internal/compare/compare_test.go
Rama main · réplica de lectura del repositorio original.
package compare
import (
"strings"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func deployment() *unstructured.Unstructured {
return &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]any{
"name": "web",
"namespace": "prod",
"uid": "7f1b3f2e-0000-4000-8000-000000000001",
"resourceVersion": "918273",
"generation": int64(4),
"creationTimestamp": "2026-07-29T12:43:49Z",
"selfLink": "/apis/apps/v1/namespaces/prod/deployments/web",
"managedFields": []any{map[string]any{"manager": "kubectl"}},
"labels": map[string]any{"app": "web"},
"annotations": map[string]any{
lastApplied: `{"kind":"Deployment"}`,
"deployment.kubernetes.io/note": "kept",
},
"ownerReferences": []any{map[string]any{
"apiVersion": "apps/v1",
"kind": "ReplicaSet",
"name": "web-5c9",
"uid": "7f1b3f2e-0000-4000-8000-000000000002",
}},
},
"spec": map[string]any{"replicas": int64(3)},
"status": map[string]any{"readyReplicas": int64(3)},
}}
}
func rendered(t *testing.T, item *unstructured.Unstructured) string {
t.Helper()
text, err := YAML(Normalise(item))
if err != nil {
t.Fatalf("render: %v", err)
}
return text
}
func TestTheServersOwnFieldsAreDropped(t *testing.T) {
text := rendered(t, deployment())
for _, gone := range []string{
"uid:",
"resourceVersion:",
"generation:",
"creationTimestamp:",
"selfLink:",
"managedFields:",
"status:",
lastApplied,
} {
if strings.Contains(text, gone) {
t.Fatalf("%q survived normalisation:\n%s", gone, text)
}
}
}
func TestWhatSomebodyAuthoredSurvives(t *testing.T) {
text := rendered(t, deployment())
for _, kept := range []string{
"name: web",
"namespace: prod",
"app: web",
"deployment.kubernetes.io/note: kept",
"replicas: 3",
"kind: ReplicaSet",
} {
if !strings.Contains(text, kept) {
t.Fatalf("%q was lost in normalisation:\n%s", kept, text)
}
}
}
func TestAnOwnerKeepsEverythingButItsUID(t *testing.T) {
clean := Normalise(deployment())
owners := clean.GetOwnerReferences()
if len(owners) != 1 {
t.Fatalf("owners = %d, want the one it came with", len(owners))
}
if owners[0].UID != "" {
t.Fatalf("uid = %q, want it dropped", owners[0].UID)
}
if owners[0].Name != "web-5c9" || owners[0].Kind != "ReplicaSet" {
t.Fatalf("owner = %+v, want the rest of it kept", owners[0])
}
}
func TestAnnotationsGoAwayOnlyWhenNothingIsLeft(t *testing.T) {
only := deployment()
unstructured.RemoveNestedField(only.Object, "metadata", "annotations")
only.SetAnnotations(map[string]string{lastApplied: `{"kind":"Deployment"}`})
clean := Normalise(only)
if clean.GetAnnotations() != nil {
t.Fatalf("annotations = %v, want the key removed with the map", clean.GetAnnotations())
}
}
func TestAnObjectWithNothingToStripIsUnchanged(t *testing.T) {
bare := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]any{"name": "settings"},
"data": map[string]any{"a": "1"},
}}
before, err := YAML(bare)
if err != nil {
t.Fatalf("render: %v", err)
}
after := rendered(t, bare)
if before != after {
t.Fatalf("normalisation changed an object that had nothing to strip:\n%s\n%s", before, after)
}
}
func TestTheSourceIsLeftAlone(t *testing.T) {
original := deployment()
Normalise(original)
if _, found, _ := unstructured.NestedMap(original.Object, "status"); !found {
t.Fatal("normalisation reached back into the object it was given")
}
}
func TestTwoClustersRenderTheSameManifestIdentically(t *testing.T) {
here := deployment()
there := deployment()
there.SetUID("7f1b3f2e-0000-4000-8000-00000000000f")
there.SetResourceVersion("55")
unstructured.RemoveNestedField(there.Object, "status")
if err := unstructured.SetNestedField(there.Object, "different", "status", "phase"); err != nil {
t.Fatalf("seed: %v", err)
}
if rendered(t, here) != rendered(t, there) {
t.Fatalf("the same manifest read differently:\n%s\n%s", rendered(t, here), rendered(t, there))
}
}
func TestARealDifferenceStillShows(t *testing.T) {
here := deployment()
there := deployment()
if err := unstructured.SetNestedField(there.Object, int64(5), "spec", "replicas"); err != nil {
t.Fatalf("seed: %v", err)
}
if rendered(t, here) == rendered(t, there) {
t.Fatal("a changed replica count was normalised away")
}
}
func TestKeysComeOutInAStableOrder(t *testing.T) {
first := rendered(t, deployment())
second := rendered(t, deployment())
if first != second {
t.Fatal("two renders of the same object differ, so a diff would be noise")
}
}
func TestRenderedTakesRawYamlThroughTheSamePath(t *testing.T) {
raw, err := YAML(deployment())
if err != nil {
t.Fatalf("render: %v", err)
}
got, renderErr := Rendered(raw, false)
if renderErr != nil {
t.Fatalf("rendered: %v", renderErr)
}
if got != rendered(t, deployment()) {
t.Fatal("yaml in and object in took different paths")
}
}
func TestRenderedKeepsEverythingWhenAsked(t *testing.T) {
raw, err := YAML(deployment())
if err != nil {
t.Fatalf("render: %v", err)
}
got, renderErr := Rendered(raw, true)
if renderErr != nil {
t.Fatalf("rendered: %v", renderErr)
}
if got != raw {
t.Fatal("the raw form was changed on its way through")
}
}
func TestSomethingThatIsNotYamlIsRefused(t *testing.T) {
_, err := Rendered("\tnot: [yaml", false)
if err == nil {
t.Fatal("expected unreadable yaml to be refused")
}
if !strings.Contains(err.Error(), "could not be read as yaml") {
t.Fatalf("error = %v, want it to say what failed", err)
}
}
func TestOrdinaryAnnotationsSurviveTheNormalising(t *testing.T) {
item := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]any{
"name": "settings",
"namespace": "demo",
"annotations": map[string]any{
"meta.helm.sh/release-name": "podinfo",
"reloader.stakater.com/auto": "true",
},
},
}}
clean := Normalise(item)
annotations := clean.GetAnnotations()
if len(annotations) != 2 {
t.Fatalf("annotations = %v, want both kept: only the kubectl blob is noise", annotations)
}
}
func TestAnObjectWithNoAnnotationsIsLeftAlone(t *testing.T) {
item := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]any{"name": "settings", "namespace": "demo"},
}}
clean := Normalise(item)
metadata, ok := clean.Object["metadata"].(map[string]any)
if !ok {
t.Fatalf("metadata = %T, want a map", clean.Object["metadata"])
}
if _, invented := metadata["annotations"]; invented {
t.Fatal("normalising invented an annotations map")
}
}
func TestOwnerReferencesThatAreNotObjectsAreLeftAlone(t *testing.T) {
item := &unstructured.Unstructured{Object: map[string]any{
"apiVersion": "v1",
"kind": "Pod",
"metadata": map[string]any{
"name": "web",
"namespace": "demo",
"ownerReferences": []any{"not an owner", map[string]any{"name": "rs", "uid": "abc"}},
},
}}
clean := Normalise(item)
owners, _, err := unstructured.NestedSlice(clean.Object, "metadata", "ownerReferences")
if err != nil {
t.Fatalf("owners: %v", err)
}
if len(owners) != 2 {
t.Fatalf("owners = %v, want both entries kept", owners)
}
kept, ok := owners[1].(map[string]any)
if !ok {
t.Fatalf("owner = %T, want the map still there", owners[1])
}
if _, carries := kept["uid"]; carries {
t.Fatalf("owner = %v, want the uid dropped", kept)
}
}