diff --git a/pkg/landscaper/executor.go b/pkg/landscaper/executor.go index e5d0dc6..a97968a 100644 --- a/pkg/landscaper/executor.go +++ b/pkg/landscaper/executor.go @@ -84,12 +84,10 @@ func (e *executor) Apply(desired, current Components) error { logrus.WithFields(logrus.Fields{"create": len(create), "update": len(update), "delete": len(delete)}).Info("Apply desired state") - if err := logDifferences(current, create, update, delete, e.stageEnabled("update"), e.stageEnabled("delete"), logrus.Infof); err != nil { - return err - } - - if e.stageEnabled("delete") { - for _, cmp := range delete { + for _, cmp := range delete { + _, cmpForcedUpdate := needForcedUpdate[cmp.Name] + if e.stageEnabled("delete") || (e.stageEnabled("update") && cmpForcedUpdate) { + logrus.Infof("Delete: %s", cmp.Name) if err := e.DeleteComponent(cmp); err != nil { logrus.WithFields(logrus.Fields{"error": err, "component": cmp}).Error("DeleteComponent failed") return err @@ -99,6 +97,9 @@ func (e *executor) Apply(desired, current Components) error { if e.stageEnabled("update") { for _, cmp := range update { + if err := logDifferences(logrus.Infof, "Update: "+cmp.Name, current[cmp.Name], cmp); err != nil { + return err + } if err := e.UpdateComponent(cmp); err != nil { logrus.WithFields(logrus.Fields{"error": err, "component": cmp}).Error("UpdateComponent failed") return err @@ -106,8 +107,13 @@ func (e *executor) Apply(desired, current Components) error { } } - if e.stageEnabled("create") { - for _, cmp := range create { + for _, cmp := range create { + _, cmpForcedUpdate := needForcedUpdate[cmp.Name] + if e.stageEnabled("create") || (e.stageEnabled("update") && cmpForcedUpdate) { + if err := logDifferences(logrus.Infof, "Create: "+cmp.Name, nil, cmp); err != nil { + return err + } + if err := e.CreateComponent(cmp); err != nil { logrus.WithFields(logrus.Fields{"error": err, "component": cmp}).Error("CreateComponent failed") return err @@ -317,46 +323,18 @@ func componentDiffText(current, desired *Component) (string, error) { }) } -// logDifferences logs the Create, Update and Delete w.r.t. current to logf -func logDifferences(current, creates, updates, deletes Components, updateStageEnabled bool, deleteStageEnabled bool, logf func(format string, args ...interface{})) error { - log := func(action string, current, desired *Component) error { - diff, err := componentDiffText(current, desired) - if err != nil { - return err - } - logf("%s", action) - if diff != "" { - logf("Diff:\n%s", diff) - } - if current != nil && desired != nil && !reflect.DeepEqual(current.SecretValues, desired.SecretValues) { - logrus.Info("Diff: secrets have changed, not shown here") - } - return nil - } - - // Log diffs only if delete is applied - if deleteStageEnabled { - for _, d := range deletes { - logf("Delete: %s", d.Name) - } +func logDifferences(logf func(format string, args ...interface{}), action string, current, desired *Component) error { + diff, err := componentDiffText(current, desired) + if err != nil { + return err } - - for _, d := range creates { - if err := log("Create: "+d.Name, nil, d); err != nil { - return err - } + logf("%s", action) + if diff != "" { + logf("Diff:\n%s", diff) } - - // Log diffs only if upadete is applied - if updateStageEnabled { - for _, d := range updates { - c := current[d.Name] - if err := log("Update: "+d.Name, c, d); err != nil { - return err - } - } + if current != nil && desired != nil && !reflect.DeepEqual(current.SecretValues, desired.SecretValues) { + logrus.Info("Diff: secrets have changed, not shown here") } - return nil } diff --git a/pkg/landscaper/executor_test.go b/pkg/landscaper/executor_test.go index d8bbc1e..271f966 100644 --- a/pkg/landscaper/executor_test.go +++ b/pkg/landscaper/executor_test.go @@ -92,6 +92,60 @@ func TestExecutorApply(t *testing.T) { } +func TestExecutorApplyWithForcedUpdatesAndDeleteCreateDisable(t *testing.T) { + chartPath := "/opt/store/whatever/path/" + + nu := newTestComponent("new-one") + nu.Namespace = "recognizable-new-one" + rem := newTestComponent("busted-one") + up := newTestComponent("updated-one") + updiff := newTestComponent("updated-one") + updiff.Configuration["FlushSize"] = 4 + updiff.SecretNames = SecretNames{"newSecret": "somethingNew"} + + updiff.SecretValues = SecretValues{ + "newSecret": []byte("somethingNew"), + } + + des := Components{nu.Name: nu, updiff.Name: updiff} + cur := Components{rem.Name: rem, up.Name: up} + + helmMock := &HelmclientMock{ + installRelease: func(chStr string, namespace string, opts ...helm.InstallOption) (*services.InstallReleaseResponse, error) { + t.Logf("installRelease %#v %#v %#v", chStr, namespace, opts) + require.Equal(t, namespace, "recognizable-new-one") // the name is hidden in the opts we cannot inspect + return nil, nil + }, + deleteRelease: func(rlsName string, opts ...helm.DeleteOption) (*services.UninstallReleaseResponse, error) { + t.Logf("deleteRelease %#v", rlsName) + require.Equal(t, rlsName, "busted-one") + return nil, nil + }, + updateRelease: func(rlsName string, chStr string, opts ...helm.UpdateOption) (*services.UpdateReleaseResponse, error) { + t.Logf("updateRelease %#v %#v %#v", rlsName, chStr, opts) + require.Equal(t, rlsName, "updated-one") + return nil, nil + }} + chartLoadMock := MockChartLoader(func(chartRef string) (*chart.Chart, string, error) { + t.Logf("MockChartLoader %#v", chartRef) + return nil, chartPath, nil + }) + secretsMock := SecretsProviderMock{ + write: func(componentName, namespace string, values SecretValues) error { + return nil + }, + delete: func(componentName, namespace string) error { + return nil + }, + } + + createDeleteDisabled := []string{"create", "delete"} + + err := NewExecutor(helmMock, chartLoadMock, secretsMock, false, false, waitTimeout, createDeleteDisabled).Apply(des, cur) + require.NoError(t, err) + +} + func TestExecutorCreate(t *testing.T) { chartPath := "/opt/store/whatever/path/" nameSpace := "spacename"