Ctrl K
ComunidadGuías…

pkg/ownership/manager_interleaving_test.go

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

Archivo original ↗Preguntar a KiBot
package ownership_test

import (
	"testing"

	"github.com/skyhook-io/radar/pkg/ownership"
	"github.com/skyhook-io/radar/pkg/ownership/ownershiptest"
	"github.com/skyhook-io/radar/pkg/resourceid"
	"github.com/skyhook-io/radar/pkg/topology"
)

// A manager the view read while its kind was loading, then found by the
// recorder search once loaded, leaves the answer incomplete: not none.
func TestManagerKeepsAnEarlierUnavailableRecorderIncomplete(t *testing.T) {
	b := ownershiptest.NewBuilder()
	cm := b.Add("", "ConfigMap", "shop", "settings")
	m := b.Manager(ownership.ArgoApplication, "argocd", "app", ownership.MembersRecorded, "shop", cm.Ref)
	loaded := b.World()
	loading := b.World()
	loading.Collection[ownership.ArgoApplication] = ownershiptest.Collection{State: ownershiptest.Loading}
	s := newCountingSession(t, loading)
	v := ownership.NewView(s, ownership.Unrestricted())
	if got := v.Owner(m.Ref); got.Subject.Read.State != ownership.Unavailable {
		t.Fatal("scenario: the manager must first read unavailable")
	}
	later, err := ownershiptest.Scan(loaded).Begin()
	if err != nil {
		t.Fatal(err)
	}
	s.now = later
	if got := v.Manager(cm.Ref); got.State != ownership.ManagerUnknown {
		t.Fatalf("state %s, direct %+v; want unknown", got.State, got.Direct)
	}
}

// The same through the wire projection, for an object whose manager is also
// a non-controller owner the view reads first.
func TestApplyOwnershipKeepsAnEarlierUnavailableRecorderIncomplete(t *testing.T) {
	b := ownershiptest.NewBuilder()
	cm := b.Add("", "ConfigMap", "shop", "settings")
	m := b.Manager(ownership.ArgoApplication, "shop", "app", ownership.MembersRecorded, "shop", cm.Ref)
	loaded := b.World()
	for i := range loaded.Objects {
		if loaded.Objects[i].Ref == cm.Ref {
			loaded.Objects[i].OwnerReferences = append(loaded.Objects[i].OwnerReferences, m.OwnerRef(false))
		}
	}
	loading := b.World()
	loading.Collection[ownership.ArgoApplication] = ownershiptest.Collection{State: ownershiptest.Loading}
	s := newCountingSession(t, loading)
	v := ownership.NewView(s, ownership.Unrestricted())
	fetched := s.Object(cm.Ref).Object
	v.Seed(fetched)
	later, err := ownershiptest.Scan(loaded).Begin()
	if err != nil {
		t.Fatal(err)
	}
	s.later, s.switchAt = later, "Object"
	rel := &topology.Relationships{}
	topology.ApplyOwnership(rel, v, fetched)
	if got := rel.Ownership.Manager; got == nil || got.State != "unknown" {
		t.Fatalf("manager %+v; want unknown", got)
	}
}

// A manager replaced since the view read it can't confirm membership for the
// incarnation the view holds, as Members already refuses.
func TestManagerRejectsARecordersDifferentIncarnation(t *testing.T) {
	b := ownershiptest.NewBuilder()
	cm := b.Meta(b.Add("", "ConfigMap", "shop", "settings"), nil, map[string]string{trackingID: "argocd_app:/ConfigMap:shop/settings"})
	m := b.Manager(ownership.ArgoApplication, "argocd", "app", ownership.MembersRecorded, "shop")
	w := b.World()
	s := newCountingSession(t, w)
	v := ownership.NewView(s, ownership.Unrestricted())
	v.Owner(m.Ref)
	changeManager(t, s, w, m.Ref, func(o *ownershiptest.Object) {
		o.UID = "replacement-uid"
		o.Members = []resourceid.Ref{cm.Ref}
	})
	if members := v.Members(m.Ref); members.Membership == ownership.MembersRecorded || len(members.Gaps) == 0 {
		t.Fatalf("scenario: Members must refuse the new incarnation: %+v", members)
	}
	got := v.Manager(cm.Ref)
	if got.State == ownership.ManagerAgree || checkOf(got.Direct, app("app")) != ownership.ClaimUnchecked {
		t.Fatalf("state %s, claims %+v; want the claim unchecked, membership unconfirmed", got.State, got.Direct.Claims)
	}
}

// Falling back to the nearest ancestor's claim keeps the claims farther up.
func TestManagerFallbackKeepsClaimsFartherUp(t *testing.T) {
	b := ownershiptest.NewBuilder()
	op := b.Add("example.io", "Widget", "shop", "op")
	d := b.Meta(b.Add("apps", "Deployment", "shop", "web", op.OwnerRef(true)), map[string]string{instanceLabel: "argocd_far"}, nil)
	rs := b.Meta(b.Add("apps", "ReplicaSet", "shop", "web-1", d.OwnerRef(true)), map[string]string{instanceLabel: "argocd_near"}, nil)
	pod := b.Add("", "Pod", "shop", "web-1-a", rs.OwnerRef(true))
	got := view(t, b.World(), ownership.Unrestricted()).Manager(pod.Ref)
	if got.State != ownership.ManagerClaimed || got.Via == nil || got.Via.Object != rs.Ref {
		t.Fatalf("answer %+v; want claimed via the ReplicaSet", got)
	}
	if len(got.Between) != 1 || got.Between[0].Object != d.Ref {
		t.Fatalf("between %+v; want the Deployment's claim kept", got.Between)
	}
}

// A claim naming no namespace, with no listing manager of its name, is
// unresolved: Radar says nothing of whether such a manager exists.
func TestManagerUnqualifiedClaimWithoutAMatchIsUnresolved(t *testing.T) {
	b := ownershiptest.NewBuilder()
	cm := b.Meta(b.Add("", "ConfigMap", "shop", "settings"), map[string]string{instanceLabel: "elsewhere"}, nil)
	got := view(t, b.World(), ownership.Unrestricted()).Manager(cm.Ref)
	unqualified := resourceid.Ref{Group: "argoproj.io", Kind: "Application", Name: "elsewhere"}
	if got.State != ownership.ManagerClaimed || checkOf(got.Direct, unqualified) != ownership.ClaimUnresolved {
		t.Fatalf("answer %+v; want claimed with the claim unresolved", got)
	}
}