Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #914 from laverya/fix-randomstring-config-chaining
Browse files Browse the repository at this point in the history
Fix randomstring config chaining
  • Loading branch information
laverya committed Apr 15, 2019
2 parents 1bce583 + d252138 commit 2253e8f
Show file tree
Hide file tree
Showing 3 changed files with 338 additions and 3 deletions.
3 changes: 3 additions & 0 deletions pkg/lifecycle/render/config/daemonresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ func (d *DaemonResolver) awaitConfigSaved(ctx context.Context, daemonExitedChan
return d.Daemon.GetCurrentConfig(), nil
case <-time.After(10 * time.Second):
debug.Log("waitingFor", "config.saved")
case <-ctx.Done():
debug.Log("event", "ctx.done")
return nil, ctx.Err()
}
}
}
322 changes: 322 additions & 0 deletions pkg/lifecycle/render/config/daemonresolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"context"
"fmt"
"testing"
"time"

Expand All @@ -13,8 +14,13 @@ import (

"github.com/replicatedhq/ship/pkg/api"
"github.com/replicatedhq/ship/pkg/lifecycle/daemon"
"github.com/replicatedhq/ship/pkg/lifecycle/daemon/headless"
"github.com/replicatedhq/ship/pkg/lifecycle/kustomize"
"github.com/replicatedhq/ship/pkg/lifecycle/render/config/resolve"
"github.com/replicatedhq/ship/pkg/state"
templates "github.com/replicatedhq/ship/pkg/templates"
"github.com/replicatedhq/ship/pkg/testing/logger"
"github.com/replicatedhq/ship/pkg/ui"
)

type daemonResolverTestCase struct {
Expand Down Expand Up @@ -129,6 +135,7 @@ func TestDaemonResolver(t *testing.T) {
viper.Set("api-port", 0)
fs := afero.Afero{Fs: afero.NewMemMapFs()}
log := &logger.TestLogger{T: t}

daemon := &daemon.ShipDaemon{
Logger: log,
WebUIFactory: daemon.WebUIFactoryFactory(log),
Expand Down Expand Up @@ -178,3 +185,318 @@ func TestDaemonResolver(t *testing.T) {
})
}
}

func TestHeadlessResolver(t *testing.T) {
tests := []daemonResolverTestCase{
{
name: "test_resolve_noitems",
release: &api.Release{
Spec: api.Spec{
Lifecycle: api.Lifecycle{
V1: []api.Step{
{
Render: &api.Render{},
},
},
},
Config: api.Config{
V1: []libyaml.ConfigGroup{},
},
},
},
inputContext: map[string]interface{}{
"foo": "bar",
},
expect: func(t *testing.T, config map[string]interface{}, e error) {
req := require.New(t)
req.NoError(e)
actual, ok := config["foo"]
req.True(ok, "Expected to find key %s in resolved config", "foo")
req.Equal("bar", actual)
},
},
{
name: "test_config_item",
release: &api.Release{
Spec: api.Spec{
Lifecycle: api.Lifecycle{
V1: []api.Step{
{
Render: &api.Render{},
},
},
},
Config: api.Config{
V1: []libyaml.ConfigGroup{
{
Items: []*libyaml.ConfigItem{
{
Name: "out",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "foo"}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "foo",
Type: "text",
ReadOnly: false,
Value: ``,
},
},
},
},
},
},
},
inputContext: map[string]interface{}{
"foo": "bar",
},
expect: func(t *testing.T, i map[string]interface{}, e error) {
req := require.New(t)
req.NoError(e)

expectContext := map[string]interface{}{
"foo": "bar",
"out": "bar",
}

req.Equal(expectContext, i)
},
},
{
name: "test_random_chain",
release: &api.Release{
Spec: api.Spec{
Lifecycle: api.Lifecycle{
V1: []api.Step{
{
Render: &api.Render{},
},
},
},
Config: api.Config{
V1: []libyaml.ConfigGroup{
{
Items: []*libyaml.ConfigItem{
{
Name: "random_1",
Type: "text",
ReadOnly: true,
Value: `{{repl RandomString 32}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_dependent",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "random_1"}}`,
},
},
},
},
},
},
},
inputContext: map[string]interface{}{},
expect: func(t *testing.T, i map[string]interface{}, e error) {
req := require.New(t)
req.NoError(e)

random1, exists := i["random_1"]
req.True(exists, "'random_1' should exist")

randomDependent, exists := i["random_dependent"]
req.True(exists, "'random_dependent' should exist")

req.Equal(randomDependent, random1)
},
},
{
name: "test_deep_random_chain",
release: &api.Release{
Spec: api.Spec{
Lifecycle: api.Lifecycle{
V1: []api.Step{
{
Render: &api.Render{},
},
},
},
Config: api.Config{
V1: []libyaml.ConfigGroup{
{
Items: []*libyaml.ConfigItem{
{
Name: "random_1",
Type: "text",
ReadOnly: true,
Value: `{{repl RandomString 32}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_dependent",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "random_1"}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_dependent_child",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "random_dependent"}}+{{repl ConfigOption "random_dependent"}}`,
},
},
},
},
},
},
},
inputContext: map[string]interface{}{},
expect: func(t *testing.T, i map[string]interface{}, e error) {
req := require.New(t)
req.NoError(e)

random1, exists := i["random_1"]
req.True(exists, "'random_1' should exist")

randomDependent, exists := i["random_dependent"]
req.True(exists, "'random_dependent' should exist")

randomDependentChild, exists := i["random_dependent_child"]
req.True(exists, "'random_dependent_child' should exist")

req.Equal(randomDependentChild, fmt.Sprintf("%s+%s", randomDependent, randomDependent), "constructed child should match")
req.Equal(randomDependent, random1, "raw child should match")
},
},
{
name: "ensure_randomstrings_differ",
release: &api.Release{
Spec: api.Spec{
Lifecycle: api.Lifecycle{
V1: []api.Step{
{
Render: &api.Render{},
},
},
},
Config: api.Config{
V1: []libyaml.ConfigGroup{
{
Items: []*libyaml.ConfigItem{
{
Name: "random_1",
Type: "text",
ReadOnly: true,
Value: `{{repl RandomString 32}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_dependent",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "random_1"}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_2",
Type: "text",
ReadOnly: true,
Value: `{{repl RandomString 32}}`,
},
},
},
{
Items: []*libyaml.ConfigItem{
{
Name: "random_dependent_2",
Type: "text",
ReadOnly: true,
Value: `{{repl ConfigOption "random_2"}}`,
},
},
},
},
},
},
},
inputContext: map[string]interface{}{},
expect: func(t *testing.T, i map[string]interface{}, e error) {
req := require.New(t)
req.NoError(e)

random1, exists := i["random_1"]
req.True(exists, "'random_1' should exist")

randomDependent, exists := i["random_dependent"]
req.True(exists, "'random_dependent' should exist")

req.Equal(randomDependent, random1)

random2, exists := i["random_2"]
req.True(exists, "'random_2' should exist")

randomDependent2, exists := i["random_dependent_2"]
req.True(exists, "'random_dependent_2' should exist")

req.Equal(randomDependent2, random2)

req.NotEqual(random1, random2)
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
v := viper.New()

viper.Set("api-port", 0)
fs := afero.Afero{Fs: afero.NewMemMapFs()}
log := &logger.TestLogger{T: t}

manager := state.NewManager(log, fs, v)

builderBuilder := templates.NewBuilderBuilder(log, v, manager)

renderer := resolve.NewRenderer(log, v, builderBuilder)

headlessDaemon := headless.HeadlessDaemon{
StateManager: manager,
Logger: log,
UI: ui.FromViper(v),
ConfigRenderer: renderer,
FS: fs,
ResolvedConfig: test.inputContext,
YesApplyTerraform: false,
}

resolver := &DaemonResolver{log, &headlessDaemon}

resolveContext, cancel := context.WithTimeout(context.Background(), 1*time.Second)

config, err := resolver.ResolveConfig(resolveContext, test.release, test.inputContext)

test.expect(t, config, err)
cancel()
})
}
}
Loading

0 comments on commit 2253e8f

Please sign in to comment.