pkg/ownership/manager_interleaving_test.go
Rama main · réplica de lectura del repositorio original.
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)
}
}