Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions internal/plan/view/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,17 +381,20 @@ func assertJSONPaths(tb testing.TB, raw []byte, wants []jsonPathWant) {
}

// assertGolden is the primary golden contract: got must equal
// testdata/golden/<name>.golden in full. A mismatch stops the test.
// testdata/golden/<name>.golden in full. A mismatch stops the test
// with "golden file %s is stale; run with -update to regenerate".
// A normal run never skips the comparison. -update rewrites the file
// from got, then the same equality still runs.
func assertGolden(t *testing.T, name, got string) {
t.Helper()
require.Equal(t, string(readGolden(t, name, got)), got)
path, want := readGolden(t, name, got)
require.Equal(t, string(want), got, "golden file %s is stale; run with -update to regenerate", path)
}

func assertJSONGolden(t *testing.T, name, got string) {
t.Helper()
require.JSONEq(t, string(readGolden(t, name, got)), got)
path, want := readGolden(t, name, got)
require.JSONEq(t, string(want), got, "golden file %s is stale; run with -update to regenerate", path)
}

func compilePlanSchema(t *testing.T) *jsonschema.Schema {
Expand All @@ -412,7 +415,7 @@ func validatePlanSchema(t *testing.T, raw []byte) {
require.NoError(t, compilePlanSchema(t).Validate(v))
}

func readGolden(t *testing.T, name, got string) []byte {
func readGolden(t *testing.T, name, got string) (string, []byte) {
t.Helper()
path := filepath.Clean(filepath.Join("testdata", "golden", name+".golden"))
if *update {
Expand All @@ -423,5 +426,5 @@ func readGolden(t *testing.T, name, got string) []byte {
if err != nil {
t.Fatalf("golden %s missing or unreadable: %v\n--- got ---\n%s", path, err, got)
}
return want
return path, want
}
3 changes: 3 additions & 0 deletions internal/plan/view/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,9 @@ func TestWriteJSON_DriftSecretRedaction(t *testing.T) {
assertJSONAt(t, buf.Bytes(), tt.before, "drift", 0, "fields", 0, "before")
validatePlanSchema(t, buf.Bytes())
require.Equal(t, "b2xk", p.Drift[0].Fields[0].Before)
require.Equal(t, "old", objectString(t, p.Drift[0].Previous.Object, "stringData", "password"))
require.Equal(t, "bmV3", objectString(t, p.Drift[0].Live.Object, "data", "password"))
require.Equal(t, "c2VjcmV0", objectString(t, p.Drift[1].Live.Object, "data", "password"))
})
}
}
Expand Down
87 changes: 87 additions & 0 deletions internal/plan/view/prepare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,93 @@ func TestPrepareRender_InvalidEnums(t *testing.T) {
}(),
wantErr: "invalid change 0 field 0 op",
},
{
name: "invalid drift action",
plan: semantic.Plan{
HelmAction: semantic.HelmNone,
Drift: []semantic.DriftChange{{
Resource: ref("ConfigMap", "app"),
}},
},
wantErr: "invalid drift 0 action",
},
{
name: "invalid drift field op",
plan: semantic.Plan{
HelmAction: semantic.HelmNone,
Drift: []semantic.DriftChange{{
Resource: ref("ConfigMap", "app"),
Action: semantic.DriftModified,
Fields: []semantic.FieldChange{{Path: "/data/key"}},
}},
},
wantErr: "invalid drift 0 field 0 op",
},
{
name: "invalid task phase",
plan: semantic.Plan{
HelmAction: semantic.HelmUpgrade,
Tasks: []semantic.TaskPlan{{
Name: "migrate",
}},
},
wantErr: "invalid task 0 phase",
},
{
name: "invalid task action",
plan: semantic.Plan{
HelmAction: semantic.HelmUpgrade,
Tasks: []semantic.TaskPlan{{
Name: "migrate",
Phase: semantic.TaskPreDeploy,
}},
},
wantErr: "invalid task 0 action",
},
{
name: "invalid definition action",
plan: semantic.Plan{
HelmAction: semantic.HelmUpgrade,
Tasks: []semantic.TaskPlan{{
Name: "migrate",
Phase: semantic.TaskPreDeploy,
Action: semantic.TaskUpdate,
Definitions: []semantic.HookDefinition{{
Resource: ref("ConfigMap", "app"),
}},
}},
},
wantErr: "invalid task 0 definition 0 action",
},
{
name: "invalid definition field op",
plan: semantic.Plan{
HelmAction: semantic.HelmUpgrade,
Tasks: []semantic.TaskPlan{{
Name: "migrate",
Phase: semantic.TaskPreDeploy,
Action: semantic.TaskUpdate,
Definitions: []semantic.HookDefinition{{
Resource: ref("ConfigMap", "app"),
Action: semantic.Update,
Fields: []semantic.FieldChange{{Path: "/data/key"}},
}},
}},
},
wantErr: "invalid task 0 definition 0 field 0 op",
},
{
name: "invalid chart crd lifecycle",
plan: semantic.Plan{
HelmAction: semantic.HelmUpgrade,
ChartCRDs: []semantic.ChartCRD{{
Source: ".deployah/crds/widgets.yaml",
Kind: "CustomResourceDefinition",
Name: "widgets.example.com",
}},
},
wantErr: "invalid chart crd 0 lifecycle",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
43 changes: 43 additions & 0 deletions internal/plan/view/redact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,49 @@ func TestSecretRedaction_OmitsPlaintext(t *testing.T) {
}
}

func TestSecretRedaction_HookDefinitionsUnchanged(t *testing.T) {
t.Parallel()
p := mustPlanWithTasks(t, semantic.HelmUpgrade, nil, []semantic.TaskPlan{{
Name: "migrate",
Phase: semantic.TaskPreDeploy,
Action: semantic.TaskUpdate,
WillRun: true,
Definitions: []semantic.HookDefinition{
{
Resource: ref("Secret", "hook-secret"),
Action: semantic.Update,
Before: snap(secretObj("hook-secret", "old-pass", "old-tok")),
After: snap(secretObj("hook-secret", "new-pass", "new-tok")),
},
{
Resource: semantic.ResourceRef{APIVersion: "v1", Kind: "Secret", Namespace: "prod", Name: "created"},
Action: semantic.Create,
After: snap(secretObj("created", "c-pass", "c-tok")),
},
{
Resource: semantic.ResourceRef{APIVersion: "v1", Kind: "Secret", Namespace: "prod", Name: "removed"},
Action: semantic.Delete,
Before: snap(secretObj("removed", "d-pass", "d-tok")),
},
},
}})
require.NoError(t, view.WriteHuman(&bytes.Buffer{}, p, view.Options{}))
require.NoError(t, view.WriteJSON(&bytes.Buffer{}, p, view.Options{}))
defs := p.Tasks[0].Definitions
require.Len(t, defs, 3)
require.Equal(t, "created", objectString(t, defs[0].After.Object, "metadata", "name"))
require.Equal(t, "c-pass", objectString(t, defs[0].After.Object, "stringData", "password"))
require.Equal(t, "c-tok", objectString(t, defs[0].After.Object, "data", "token"))
require.Equal(t, "hook-secret", objectString(t, defs[1].Before.Object, "metadata", "name"))
require.Equal(t, "old-pass", objectString(t, defs[1].Before.Object, "stringData", "password"))
require.Equal(t, "old-tok", objectString(t, defs[1].Before.Object, "data", "token"))
require.Equal(t, "new-pass", objectString(t, defs[1].After.Object, "stringData", "password"))
require.Equal(t, "new-tok", objectString(t, defs[1].After.Object, "data", "token"))
require.Equal(t, "removed", objectString(t, defs[2].Before.Object, "metadata", "name"))
require.Equal(t, "d-pass", objectString(t, defs[2].Before.Object, "stringData", "password"))
require.Equal(t, "d-tok", objectString(t, defs[2].Before.Object, "data", "token"))
}

func TestSecretRedaction_DriftDefaultAndShowSecrets(t *testing.T) {
t.Parallel()
p := secretDriftPlan(t)
Expand Down
Loading