internal/resources/inventory_test.go
Rama main · réplica de lectura del repositorio original.
package resources
import (
"errors"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
k8stesting "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
"github.com/sophotechlabs/spinoza/internal/api"
"github.com/sophotechlabs/spinoza/internal/checks"
)
func deploymentDescriptor() api.ResourceDescriptor {
return api.ResourceDescriptor{
Group: "apps",
Version: "v1",
Resource: "deployments",
Kind: "Deployment",
Namespaced: true,
}
}
func TestListNamesCarriesIdentityOwnershipAndManager(t *testing.T) {
owned := meta("apps", "v1", "Deployment", "prod", "web")
owned.OwnerReferences = []metav1.OwnerReference{{Name: "web-app"}}
owned.Labels = map[string]string{"helm.toolkit.fluxcd.io/name": "web"}
handmade := meta("apps", "v1", "Deployment", "staging", "api")
handmade.Labels = map[string]string{"app.kubernetes.io/managed-by": "Helm"}
manager := NewManager(t.Context(), Deps{Metadata: fakeMeta(t, owned, handmade)})
items, err := manager.ListNames(t.Context(), deploymentDescriptor())
if err != nil {
t.Fatalf("list names: %v", err)
}
if len(items) != 2 {
t.Fatalf("items = %d, want 2", len(items))
}
byName := map[string]checks.Named{}
for _, item := range items {
byName[item.Ref.Name] = item
}
web := byName["web"]
if web.Ref.Namespace != "prod" || web.Ref.Group != "apps" || web.Ref.Resource != "deployments" {
t.Fatalf("web ref = %+v", web.Ref)
}
if !web.Owned || web.Manager != "Flux" {
t.Fatalf("web = owned:%t manager:%q", web.Owned, web.Manager)
}
apiDeployment := byName["api"]
if apiDeployment.Owned || apiDeployment.Manager != "Helm" {
t.Fatalf("api = owned:%t manager:%q", apiDeployment.Owned, apiDeployment.Manager)
}
}
func TestListNamesReturnsMetadataFailures(t *testing.T) {
client := fakeMeta(t)
client.PrependReactor("list", "deployments", func(k8stesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("deployment metadata is forbidden")
})
manager := NewManager(t.Context(), Deps{Metadata: client})
_, err := manager.ListNames(t.Context(), deploymentDescriptor())
if err == nil || err.Error() != "deployment metadata is forbidden" {
t.Fatalf("error = %v", err)
}
}
func TestScanReturnsIndependentObjectsFromEveryNamespace(t *testing.T) {
client := newClient(
t,
newDeployment("prod", "web"),
newDeployment("staging", "api"),
)
manager := NewManager(t.Context(), Deps{Dynamic: client})
items, err := manager.Scan(t.Context(), deploymentDescriptor())
if err != nil {
t.Fatalf("scan: %v", err)
}
if len(items) != 2 {
t.Fatalf("items = %d, want 2", len(items))
}
namespaces := map[string]bool{}
for _, item := range items {
namespaces[item.GetNamespace()] = true
}
if !namespaces["prod"] || !namespaces["staging"] {
t.Fatalf("namespaces = %v", namespaces)
}
firstName := items[0].GetName()
items[1].SetName("changed")
if items[0].GetName() != firstName {
t.Fatal("scan results shared object storage")
}
}
func TestScanReturnsDynamicClientFailures(t *testing.T) {
client := newClient(t)
client.PrependReactor("list", "deployments", func(k8stesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("deployments are unavailable")
})
manager := NewManager(t.Context(), Deps{Dynamic: client})
_, err := manager.Scan(t.Context(), deploymentDescriptor())
if err == nil || err.Error() != "deployments are unavailable" {
t.Fatalf("error = %v", err)
}
}
func TestListAllSkipsObjectsItCannotTurnIntoRows(t *testing.T) {
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
if err := indexer.Add(newDeployment("prod", "web")); err != nil {
t.Fatalf("add deployment: %v", err)
}
if err := indexer.Add(&corev1.Pod{Name: "typed", Namespace: "prod"}); err != nil {
t.Fatalf("add typed pod: %v", err)
}
lister := cache.NewGenericLister(indexer, schema.GroupResource{Group: "apps", Resource: "deployments"})
items, err := listAll(lister)
if err != nil {
t.Fatalf("list all: %v", err)
}
if len(items) != 1 || items[0].GetName() != "web" {
t.Fatalf("items = %+v, want only the unstructured deployment", items)
}
}
type failedGenericLister struct {
err error
}
func (f failedGenericLister) List(labels.Selector) ([]runtime.Object, error) {
return nil, f.err
}
func (f failedGenericLister) Get(string) (runtime.Object, error) {
return nil, f.err
}
func (f failedGenericLister) ByNamespace(string) cache.GenericNamespaceLister {
return nil
}
func TestListAllReturnsListerFailures(t *testing.T) {
want := errors.New("cache index failed")
_, err := listAll(failedGenericLister{err: want})
if !errors.Is(err, want) {
t.Fatalf("error = %v, want %v", err, want)
}
}
func TestListNamesUsesTheRequestedResource(t *testing.T) {
client := fakeMeta(t)
var action k8stesting.ListAction
client.PrependReactor("list", "deployments", func(got k8stesting.Action) (bool, runtime.Object, error) {
listed, ok := got.(k8stesting.ListAction)
if !ok {
t.Fatalf("action = %T, want ListAction", got)
}
action = listed
return false, nil, nil
})
manager := NewManager(t.Context(), Deps{Metadata: client})
_, err := manager.ListNames(t.Context(), deploymentDescriptor())
if err != nil {
t.Fatalf("list names: %v", err)
}
if action == nil {
t.Fatal("metadata client saw no list action")
}
if action.GetResource() != depGVR {
t.Fatalf("resource = %s, want %s", action.GetResource(), depGVR)
}
if action.GetNamespace() != metav1.NamespaceAll {
t.Fatalf("namespace = %q, want all", action.GetNamespace())
}
}