Ctrl K
ComunidadGuías…

internal/helm/history_boundaries_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package helm

import (
	"context"
	"errors"
	"strconv"
	"strings"
	"testing"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	k8sfake "k8s.io/client-go/kubernetes/fake"
	metadatafake "k8s.io/client-go/metadata/fake"
	k8stesting "k8s.io/client-go/testing"

	"github.com/sophotechlabs/spinoza/internal/api"
)

func TestHistoryReportsAMissingMetadataClient(t *testing.T) {
	service := NewService(k8sfake.NewClientset(), nil, nil, nil, nil, api.ContextRef{})

	_, err := service.History(t.Context(), "demo", "podinfo", 0)

	if !errors.Is(err, errNoMetadata) {
		t.Fatalf("history error = %v, want the missing metadata client", err)
	}
}

func TestRevisionSelectorIncludesEveryRequestedRevision(t *testing.T) {
	selector := revisionSelector("podinfo", []int64{7, 4, 1})
	want := "owner=helm,name=podinfo,version in (7,4,1)"

	if selector != want {
		t.Fatalf("selector = %q, want %q", selector, want)
	}
}

func TestOneRefRejectsSameDriverDuplicateRevision(t *testing.T) {
	refs := []storedRef{
		{revision: 2, driver: DriverSecret, object: "sh.helm.release.v1.podinfo.v2-copy"},
		{revision: 2, driver: DriverSecret, object: "sh.helm.release.v1.podinfo.v2"},
	}

	_, err := oneRef(refs, "demo", "podinfo")

	if !errors.Is(err, errAmbiguousRevision) {
		t.Fatalf("revision error = %v, want the same-driver duplicate rejected", err)
	}
}

func TestDetailReportsARevisionThatDisappearsAfterMetadataListing(t *testing.T) {
	spec := sampleRelease()
	secret := detailSecret(spec)
	meta := metadatafake.NewSimpleMetadataClient(metaScheme(), metaOf(secret))
	service := serviceWithMeta(k8sfake.NewClientset(), meta, nil)

	_, err := service.Detail(t.Context(), "demo", "podinfo", spec.revision, resolver)

	if err == nil {
		t.Fatal("a revision missing from typed storage reported a readable detail")
	}
}

func TestDetailReportsAMetadataListFailure(t *testing.T) {
	meta := metadatafake.NewSimpleMetadataClient(metaScheme())
	meta.PrependReactor("list", "secrets", func(k8stesting.Action) (bool, runtime.Object, error) {
		return true, nil, errors.New("metadata unavailable")
	})
	service := serviceWithMeta(k8sfake.NewClientset(), meta, nil)

	_, err := service.Detail(t.Context(), "demo", "podinfo", 2, resolver)

	if err == nil || !strings.Contains(err.Error(), "metadata unavailable") {
		t.Fatalf("detail error = %v, want the metadata refusal", err)
	}
}

func TestHistoryReportsMetadataListFailures(t *testing.T) {
	for _, resource := range []string{"secrets", "configmaps"} {
		t.Run(resource, func(t *testing.T) {
			meta := metadatafake.NewSimpleMetadataClient(metaScheme())
			meta.PrependReactor("list", resource, func(k8stesting.Action) (bool, runtime.Object, error) {
				return true, nil, errors.New(resource + " list refused")
			})
			service := serviceWithMeta(k8sfake.NewClientset(), meta, nil)

			_, err := service.History(t.Context(), "demo", "podinfo", 0)

			if err == nil || !strings.Contains(err.Error(), resource+" list refused") {
				t.Fatalf("history error = %v, want the %s refusal", err, resource)
			}
		})
	}
}

func TestHistoryRejectsInvalidCoordinatesBeforeListing(t *testing.T) {
	service := NewService(k8sfake.NewClientset(), nil, nil, nil, nil, api.ContextRef{})
	for _, coordinates := range [][2]string{
		{"Not A Namespace", "podinfo"},
		{"demo", "--kubeconfig=/etc/shadow"},
	} {
		_, err := service.History(t.Context(), coordinates[0], coordinates[1], 0)

		if err == nil || errors.Is(err, errNoMetadata) {
			t.Fatalf("History(%q, %q) error = %v, want invalid coordinates", coordinates[0], coordinates[1], err)
		}
	}
}

func TestHistoryUsesTheLatestRevisionWhenNoCursorIsGiven(t *testing.T) {
	objects := make([]runtime.Object, 0, 3)
	for revision := int64(1); revision <= 3; revision++ {
		spec := sampleRelease()
		spec.revision = revision
		objects = append(objects, detailSecret(spec))
	}
	service := newService(k8sfake.NewClientset(objects...), nil, nil)

	page, err := service.History(t.Context(), "demo", "podinfo", 0)
	if err != nil {
		t.Fatalf("history: %v", err)
	}

	if len(page.Revisions) != 3 {
		t.Fatalf("history = %+v, want all three revisions", page.Revisions)
	}
	if page.Revisions[0].Revision != 3 || page.Revisions[2].Revision != 1 {
		t.Fatalf("history = %+v, want newest first", page.Revisions)
	}
	if page.Next != 0 {
		t.Fatalf("next = %d, want the end of history", page.Next)
	}
}

func TestHistoryTreatsAnOnlyMalformedRevisionAsMissing(t *testing.T) {
	bad := releaseSecret("sh.helm.release.v1.web.vbad", "not-a-number")
	service := newService(k8sfake.NewClientset(bad), nil, nil)

	_, err := service.History(t.Context(), "prod", "web", 0)

	if !errors.Is(err, ErrNoRelease) {
		t.Fatalf("history error = %v, want no usable release", err)
	}
}

func TestHistorySkipsAMalformedRevisionBesideAValidOne(t *testing.T) {
	valid := sampleRelease()
	valid.revision = 2
	bad := detailSecret(sampleRelease())
	bad.Name = "sh.helm.release.v1.podinfo.vbad"
	bad.Labels[versionLabel] = "not-a-number"
	service := newService(k8sfake.NewClientset(detailSecret(valid), bad), nil, nil)

	page, err := service.History(t.Context(), "demo", "podinfo", 0)
	if err != nil {
		t.Fatalf("history: %v", err)
	}

	if len(page.Revisions) != 1 || page.Revisions[0].Revision != 2 {
		t.Fatalf("history = %+v, want only revision 2", page.Revisions)
	}
}

func TestHistoryCanReturnAnEmptyPageBeforeTheOldestRevision(t *testing.T) {
	newest := sampleRelease()
	newest.revision = 3
	older := sampleRelease()
	older.revision = 2
	service := newService(k8sfake.NewClientset(detailSecret(newest), detailSecret(older)), nil, nil)

	page, err := service.History(t.Context(), "demo", "podinfo", 1)
	if err != nil {
		t.Fatalf("history: %v", err)
	}

	if len(page.Revisions) != 0 || page.Next != 0 {
		t.Fatalf("page = %+v, want the end of history", page)
	}
}

func TestHistoryRejectsAnOlderRevisionStoredTwice(t *testing.T) {
	newest := sampleRelease()
	newest.revision = 3
	older := sampleRelease()
	older.revision = 2
	secret := detailSecret(older)
	entry := &corev1.ConfigMap{
		Name:      secret.Name,
		Namespace: secret.Namespace,
		Labels:    secret.Labels,
		Data:      map[string]string{releaseKey: string(secret.Data[releaseKey])},
	}
	service := newService(k8sfake.NewClientset(detailSecret(newest), secret, entry), nil, nil)

	_, err := service.History(t.Context(), "demo", "podinfo", 0)

	if !errors.Is(err, errAmbiguousRevision) {
		t.Fatalf("history error = %v, want the older duplicate rejected", err)
	}
}

func TestStoredRevisionMetadataReportsATruncatedDriverPage(t *testing.T) {
	meta := metadatafake.NewSimpleMetadataClient(metaScheme())
	meta.PrependReactor("list", "secrets", func(k8stesting.Action) (bool, runtime.Object, error) {
		list := &metav1.List{}
		for revision := range 4 {
			list.Items = append(list.Items, runtime.RawExtension{Object: &metav1.PartialObjectMetadata{
				APIVersion: "v1", Kind: "Secret",
				Name:      "sh.helm.release.v1.podinfo.v" + strconv.Itoa(revision+1),
				Namespace: "demo",
				Labels: map[string]string{
					"owner": "helm", nameLabel: "podinfo", versionLabel: strconv.Itoa(revision + 1),
				},
			}})
		}
		return true, list, nil
	})
	service := serviceWithMeta(k8sfake.NewClientset(), meta, nil)

	_, err := service.storedRefs(t.Context(), "demo", releaseSelector("podinfo"), 2)

	if err == nil || !strings.Contains(err.Error(), "more than 2") {
		t.Fatalf("stored refs error = %v, want the truncation reported", err)
	}
}

func TestTypedRevisionScanRequiresAPositiveLimit(t *testing.T) {
	_, err := revisionsMatching(t.Context(), k8sfake.NewClientset(), "prod", ownerLabel, 0)

	if err == nil || !strings.Contains(err.Error(), "positive") {
		t.Fatalf("revision scan error = %v, want the invalid limit", err)
	}
}

func TestTypedRevisionScanReportsStorageListFailures(t *testing.T) {
	for _, resource := range []string{"secrets", "configmaps"} {
		t.Run(resource, func(t *testing.T) {
			client := k8sfake.NewClientset()
			client.PrependReactor("list", resource, func(k8stesting.Action) (bool, runtime.Object, error) {
				return true, nil, errors.New(resource + " list refused")
			})

			_, err := revisionsIn(t.Context(), client, "prod", "web")

			if err == nil || !strings.Contains(err.Error(), resource+" list refused") {
				t.Fatalf("revision scan error = %v, want the %s refusal", err, resource)
			}
		})
	}
}

func TestTypedRevisionScanSkipsObjectsThatAreNotReleasePayloads(t *testing.T) {
	ordinary := releaseSecret("ordinary", "1")
	ordinary.Type = corev1.SecretTypeOpaque
	validSecret := releaseSecret("sh.helm.release.v1.web.v2", "2")
	missingBody := releaseConfigMap("missing-body", "3")
	missingBody.Data = map[string]string{}
	validMap := releaseConfigMap("sh.helm.release.v1.web.v4", "4")
	client := k8sfake.NewClientset(ordinary, validSecret, missingBody, validMap)

	found, err := revisionsIn(t.Context(), client, "prod", "web")
	if err != nil {
		t.Fatalf("revisions: %v", err)
	}

	if len(found) != 2 {
		t.Fatalf("revisions = %+v, want only the two release payloads", found)
	}
	if found[0].revision != 2 || found[1].revision != 4 {
		t.Fatalf("revisions = %+v, want 2 and 4", found)
	}
}

func TestTypedRevisionScanCapsCombinedStorageDrivers(t *testing.T) {
	client := k8sfake.NewClientset(
		releaseSecret("sh.helm.release.v1.web.v1", "1"),
		releaseConfigMap("sh.helm.release.v1.web.v2", "2"),
	)

	_, err := revisionsMatching(t.Context(), client, "prod", ownerLabel, 1)

	if err == nil || !strings.Contains(err.Error(), "more than 1") {
		t.Fatalf("revision scan error = %v, want the combined object cap", err)
	}
}

func TestTypedRevisionScansCapEveryObjectTheyInspect(t *testing.T) {
	for _, test := range []struct {
		name string
		run  func(*k8sfake.Clientset) error
		objs []runtime.Object
	}{
		{
			name: "secrets",
			run: func(client *k8sfake.Clientset) error {
				_, err := revisionSecrets(t.Context(), client, "prod", ownerLabel, 1)
				return err
			},
			objs: []runtime.Object{
				releaseSecret("sh.helm.release.v1.web.v1", "1"),
				releaseSecret("sh.helm.release.v1.web.v2", "2"),
			},
		},
		{
			name: "configmaps",
			run: func(client *k8sfake.Clientset) error {
				_, err := revisionConfigMaps(t.Context(), client, "prod", ownerLabel, 1)
				return err
			},
			objs: []runtime.Object{
				releaseConfigMap("sh.helm.release.v1.web.v1", "1"),
				releaseConfigMap("sh.helm.release.v1.web.v2", "2"),
			},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			err := test.run(k8sfake.NewClientset(test.objs...))

			if err == nil || !strings.Contains(err.Error(), "more than 1") {
				t.Fatalf("scan error = %v, want the object cap", err)
			}
		})
	}
}

func TestActionsUseTypedStorageWhenMetadataIsUnavailable(t *testing.T) {
	runner := &stubRunner{}
	old := sampleRelease()
	old.revision = 1
	newest := sampleRelease()
	newest.revision = 2
	secret := detailSecret(old)
	entry := &corev1.ConfigMap{
		Name:      "sh.helm.release.v1.podinfo.v2",
		Namespace: "demo",
		Labels: map[string]string{
			"owner": "helm", "name": "podinfo", versionLabel: "2",
		},
		Data: map[string]string{releaseKey: detailPayload(newest)},
	}
	service := NewService(
		k8sfake.NewClientset(secret, entry),
		nil,
		runner,
		nil,
		nil,
		api.ContextRef{Name: "kind-spinoza"},
	)

	_, err := service.Uninstall(context.Background(), "demo", "podinfo")
	if err != nil {
		t.Fatalf("uninstall: %v", err)
	}

	if len(runner.envs) != 1 || len(runner.envs[0]) != 1 || runner.envs[0][0] != driverEnv+"="+DriverConfigMap {
		t.Fatalf("env = %v, want the newest typed-storage driver", runner.envs)
	}
}

func TestActionsReportTypedStorageFailuresWithoutRunningHelm(t *testing.T) {
	for _, test := range []struct {
		name    string
		client  func() *k8sfake.Clientset
		missing bool
	}{
		{
			name: "storage list failure",
			client: func() *k8sfake.Clientset {
				client := k8sfake.NewClientset()
				client.PrependReactor("list", "secrets", func(k8stesting.Action) (bool, runtime.Object, error) {
					return true, nil, errors.New("typed storage unavailable")
				})
				return client
			},
		},
		{
			name: "missing release",
			client: func() *k8sfake.Clientset {
				return k8sfake.NewClientset()
			},
			missing: true,
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			runner := &stubRunner{}
			service := NewService(
				test.client(),
				nil,
				runner,
				nil,
				nil,
				api.ContextRef{Name: "kind-spinoza"},
			)

			_, err := service.Uninstall(t.Context(), "demo", "podinfo")

			if err == nil {
				t.Fatal("uninstall succeeded without a usable storage driver")
			}
			if test.missing && !errors.Is(err, ErrNoRelease) {
				t.Fatalf("uninstall error = %v, want a missing release", err)
			}
			if !test.missing && !strings.Contains(err.Error(), "typed storage unavailable") {
				t.Fatalf("uninstall error = %v, want the storage refusal", err)
			}
			if len(runner.args) != 0 {
				t.Fatalf("helm ran %d times without a usable storage driver", len(runner.args))
			}
		})
	}
}

func TestActionsReportMetadataFailureWithoutRunningHelm(t *testing.T) {
	meta := metadatafake.NewSimpleMetadataClient(metaScheme())
	meta.PrependReactor("list", "secrets", func(k8stesting.Action) (bool, runtime.Object, error) {
		return true, nil, errors.New("metadata unavailable")
	})
	runner := &stubRunner{}
	service := NewService(
		k8sfake.NewClientset(),
		meta,
		runner,
		nil,
		nil,
		api.ContextRef{Name: "kind-spinoza"},
	)

	_, err := service.Uninstall(t.Context(), "demo", "podinfo")

	if err == nil || !strings.Contains(err.Error(), "metadata unavailable") {
		t.Fatalf("uninstall error = %v, want the metadata refusal", err)
	}
	if len(runner.args) != 0 {
		t.Fatalf("helm ran %d times after metadata failed", len(runner.args))
	}
}

func TestActionsRejectAmbiguousTypedStorageWithoutMetadata(t *testing.T) {
	runner := &stubRunner{}
	spec := sampleRelease()
	secret := detailSecret(spec)
	entry := &corev1.ConfigMap{
		Name:      secret.Name,
		Namespace: secret.Namespace,
		Labels:    secret.Labels,
		Data:      map[string]string{releaseKey: string(secret.Data[releaseKey])},
	}
	service := NewService(
		k8sfake.NewClientset(secret, entry),
		nil,
		runner,
		nil,
		nil,
		api.ContextRef{Name: "kind-spinoza"},
	)

	_, err := service.Uninstall(context.Background(), "demo", "podinfo")

	if !errors.Is(err, errAmbiguousRevision) {
		t.Fatalf("uninstall error = %v, want ambiguous storage", err)
	}
	if len(runner.args) != 0 {
		t.Fatalf("helm ran %d times for ambiguous storage", len(runner.args))
	}
}