diff --git a/pkg/lifecycle/daemon/routes_navcycle.go b/pkg/lifecycle/daemon/routes_navcycle.go index a55c97942..b130f105c 100644 --- a/pkg/lifecycle/daemon/routes_navcycle.go +++ b/pkg/lifecycle/daemon/routes_navcycle.go @@ -157,8 +157,14 @@ func (d *NavcycleRoutes) getRequiredButIncompleteStepFor(requires []string) (str return "", nil } -func (d *NavcycleRoutes) hydrateAndSend(step daemontypes.Step, c *gin.Context) { - result, err := d.hydrateStep(step) +func (d *NavcycleRoutes) hydrateAndSend(step api.Step, c *gin.Context) { + step, err := d.buildStepContents(step) + if err != nil { + c.AbortWithError(500, err) + return + } + + result, err := d.hydrateStep(daemontypes.NewStep(step)) if err != nil { c.AbortWithError(500, err) return diff --git a/pkg/lifecycle/daemon/routes_navcycle_completestep.go b/pkg/lifecycle/daemon/routes_navcycle_completestep.go index 4f5f960f7..f59411149 100644 --- a/pkg/lifecycle/daemon/routes_navcycle_completestep.go +++ b/pkg/lifecycle/daemon/routes_navcycle_completestep.go @@ -47,7 +47,7 @@ func (d *NavcycleRoutes) completeStep(c *gin.Context) { // hack, give it 10 ms in case its an instant step. Hydrate and send will read progress from the syncMap time.Sleep(10 * time.Millisecond) - d.hydrateAndSend(daemontypes.NewStep(step), c) + d.hydrateAndSend(step, c) go d.handleAsync(errChan, debug, step, stepID) return } diff --git a/pkg/lifecycle/daemon/routes_navcycle_getstep.go b/pkg/lifecycle/daemon/routes_navcycle_getstep.go index 93b2ae669..3c0ade350 100644 --- a/pkg/lifecycle/daemon/routes_navcycle_getstep.go +++ b/pkg/lifecycle/daemon/routes_navcycle_getstep.go @@ -9,6 +9,7 @@ import ( "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" "github.com/pkg/errors" + "github.com/replicatedhq/ship/pkg/api" "github.com/replicatedhq/ship/pkg/constants" "github.com/replicatedhq/ship/pkg/lifecycle/daemon/daemontypes" "github.com/replicatedhq/ship/pkg/lifecycle/render/helm" @@ -24,6 +25,12 @@ func (d *NavcycleRoutes) getStep(c *gin.Context) { return } + step, err := d.buildStepContents(step) + if err != nil { + level.Error(d.Logger).Log("event", "getStep.buildContents.fail", "err", err) + return + } + if preExecuteFunc, exists := d.PreExecuteFuncMap[step.Shared().ID]; exists { if err := preExecuteFunc(context.Background(), step); err != nil { level.Error(d.Logger).Log("event", "preExecute.fail", "err", err) @@ -34,7 +41,7 @@ func (d *NavcycleRoutes) getStep(c *gin.Context) { delete(d.PreExecuteFuncMap, step.ShortName()) } - d.hydrateAndSend(daemontypes.NewStep(step), c) + d.hydrateAndSend(step, c) return } } @@ -42,26 +49,50 @@ func (d *NavcycleRoutes) getStep(c *gin.Context) { d.errNotFound(c) } -func (d *NavcycleRoutes) hydrateStep(step daemontypes.Step) (*daemontypes.StepResponse, error) { - debug := level.Debug(log.With(d.Logger, "method", "hydrateStep")) - +func (d *NavcycleRoutes) buildStepContents(step api.Step) (api.Step, error) { currentState, err := d.StateManager.TryLoad() if err != nil { level.Error(d.Logger).Log("event", "tryLoad.fail", "err", err) - return nil, errors.Wrap(err, "load state") + return api.Step{}, errors.Wrap(err, "load state") } if step.Kustomize != nil { builder, err := d.BuilderBuilder.FullBuilder(d.Release.Metadata, d.Release.Spec.Config.V1, currentState.CurrentConfig()) if err != nil { - return nil, errors.Wrap(err, "create kustomize template builder") + return api.Step{}, errors.Wrap(err, "create kustomize template builder") + } + renderedBasePath, err := builder.String(step.Kustomize.Base) + if err != nil { + return api.Step{}, errors.Wrap(err, "render kustomize basepath template") + } + step.Kustomize.Base = renderedBasePath + } + + if step.Message != nil { + builder, err := d.BuilderBuilder.FullBuilder(d.Release.Metadata, d.Release.Spec.Config.V1, currentState.CurrentConfig()) + if err != nil { + return api.Step{}, errors.Wrap(err, "create message template builder") } - renderedBasePath, err := builder.String(step.Kustomize.BasePath) + renderedContents, err := builder.String(step.Message.Contents) if err != nil { - return nil, errors.Wrap(err, "render kusstomize basepath contents") + return api.Step{}, errors.Wrap(err, "render message contents") } - step.Kustomize.BasePath = renderedBasePath + step.Message.Contents = renderedContents + } + + return step, nil +} +func (d *NavcycleRoutes) hydrateStep(step daemontypes.Step) (*daemontypes.StepResponse, error) { + debug := level.Debug(log.With(d.Logger, "method", "hydrateStep")) + + currentState, err := d.StateManager.TryLoad() + if err != nil { + level.Error(d.Logger).Log("event", "tryLoad.fail", "err", err) + return nil, errors.Wrap(err, "load state") + } + + if step.Kustomize != nil { tree, err := d.TreeLoader.LoadTree(step.Kustomize.BasePath) if err != nil { level.Error(d.Logger).Log("event", "loadTree.fail", "err", err) @@ -93,18 +124,6 @@ func (d *NavcycleRoutes) hydrateStep(step daemontypes.Step) (*daemontypes.StepRe step.HelmValues.Namespace = namespace } - if step.Message != nil { - builder, err := d.BuilderBuilder.FullBuilder(d.Release.Metadata, d.Release.Spec.Config.V1, currentState.CurrentConfig()) - if err != nil { - return nil, errors.Wrap(err, "create message template builder") - } - rendered, err := builder.String(step.Source.Message.Contents) - if err != nil { - return nil, errors.Wrap(err, "render message contents") - } - step.Message.Contents = rendered - } - result := &daemontypes.StepResponse{ CurrentStep: step, Phase: step.Source.ShortName(), diff --git a/pkg/lifecycle/daemon/routes_navcycle_getstep_test.go b/pkg/lifecycle/daemon/routes_navcycle_getstep_test.go index b31756190..850bf4962 100644 --- a/pkg/lifecycle/daemon/routes_navcycle_getstep_test.go +++ b/pkg/lifecycle/daemon/routes_navcycle_getstep_test.go @@ -407,7 +407,7 @@ func TestHydrateActions(t *testing.T) { func TestHydrateStep(t *testing.T) { tests := []struct { name string - step daemontypes.Step + step api.Step state state2.State fs map[string]string release *api.Release @@ -415,14 +415,14 @@ func TestHydrateStep(t *testing.T) { }{ { name: "message", - step: daemontypes.NewStep(api.Step{ + step: api.Step{ Message: &api.Message{ Contents: "hey there {{repl Installation \"customer_id\"}} {{repl ConfigOption \"spam\"}}", StepShared: api.StepShared{ ID: "foo", }, }, - }), + }, release: &api.Release{ Metadata: api.ReleaseMetadata{ CustomerID: "12345", @@ -447,7 +447,7 @@ func TestHydrateStep(t *testing.T) { CurrentStep: daemontypes.Step{ Source: api.Step{ Message: &api.Message{ - Contents: "hey there {{repl Installation \"customer_id\"}} {{repl ConfigOption \"spam\"}}", + Contents: "hey there 12345 eggs", StepShared: api.StepShared{ ID: "foo", }, @@ -487,6 +487,7 @@ func TestHydrateStep(t *testing.T) { if test.state != nil { mockState.EXPECT().TryLoad().Return(test.state, nil) + mockState.EXPECT().TryLoad().Return(test.state, nil) } v2 := &NavcycleRoutes{ @@ -502,7 +503,10 @@ func TestHydrateStep(t *testing.T) { Release: test.release, } - response, err := v2.hydrateStep(test.step) + builtStep, err := v2.buildStepContents(test.step) + req.NoError(err) + + response, err := v2.hydrateStep(daemontypes.NewStep(builtStep)) req.NoError(err, "hydrate step") req.Equal(test.want, response) }) @@ -512,7 +516,7 @@ func TestHydrateStep(t *testing.T) { func TestHydrateTemplatedKustomizeStep(t *testing.T) { tests := []struct { name string - step daemontypes.Step + step api.Step state state2.State fs map[string]string release *api.Release @@ -520,7 +524,7 @@ func TestHydrateTemplatedKustomizeStep(t *testing.T) { }{ { name: "kustomize", - step: daemontypes.NewStep(api.Step{ + step: api.Step{ Kustomize: &api.Kustomize{ Base: "{{repl ToUpper \"abcdef\"}}", Dest: "more.yaml", @@ -529,7 +533,7 @@ func TestHydrateTemplatedKustomizeStep(t *testing.T) { ID: "bar", }, }, - }), + }, release: &api.Release{ Metadata: api.ReleaseMetadata{ CustomerID: "12345", @@ -554,7 +558,7 @@ func TestHydrateTemplatedKustomizeStep(t *testing.T) { CurrentStep: daemontypes.Step{ Source: api.Step{ Kustomize: &api.Kustomize{ - Base: "{{repl ToUpper \"abcdef\"}}", + Base: "ABCDEF", Dest: "more.yaml", Overlay: "overlay/mine", StepShared: api.StepShared{ @@ -612,6 +616,7 @@ func TestHydrateTemplatedKustomizeStep(t *testing.T) { if test.state != nil { mockState.EXPECT().TryLoad().Return(test.state, nil) mockState.EXPECT().TryLoad().Return(test.state, nil) + mockState.EXPECT().TryLoad().Return(test.state, nil) } treeLoader := filetree.NewLoader(mockFs, testLogger, mockState) @@ -633,7 +638,10 @@ func TestHydrateTemplatedKustomizeStep(t *testing.T) { err := mockFs.MkdirAll("ABCDEF", 0755) req.NoError(err, "mkdir") - response, err := v2.hydrateStep(test.step) + builtStep, err := v2.buildStepContents(test.step) + req.NoError(err) + + response, err := v2.hydrateStep(daemontypes.NewStep(builtStep)) req.NoError(err, "hydrate templated kustomize step") req.Equal(test.want, response) })