// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package resource import "github.com/hashicorp/consul/proto-public/pbresource" // EqualType compares two resource types for equality without reflection. func EqualType(a, b *pbresource.Type) bool { if a == b { return true } if a == nil || b == nil { return false } return a.Group == b.Group && a.GroupVersion == b.GroupVersion && a.Kind == b.Kind } // EqualTenancy compares two resource tenancies for equality without reflection. func EqualTenancy(a, b *pbresource.Tenancy) bool { if a == b { return true } if a == nil || b == nil { return false } return a.Partition == b.Partition && a.Namespace == b.Namespace } // TODO(peering/v2) add equality method peer tenancy // EqualID compares two resource IDs for equality without reflection. func EqualID(a, b *pbresource.ID) bool { if a == b { return true } if a == nil || b == nil { return false } return EqualType(a.Type, b.Type) && EqualTenancy(a.Tenancy, b.Tenancy) && a.Name == b.Name && a.Uid == b.Uid } // EqualStatus compares two statuses for equality without reflection. // // Pass true for compareUpdatedAt to compare the UpdatedAt timestamps, which you // generally *don't* want when dirty checking the status in a controller. func EqualStatus(a, b *pbresource.Status, compareUpdatedAt bool) bool { if a == b { return true } if a == nil || b == nil { return false } if a.ObservedGeneration != b.ObservedGeneration { return false } if compareUpdatedAt && !a.UpdatedAt.AsTime().Equal(b.UpdatedAt.AsTime()) { return false } if len(a.Conditions) != len(b.Conditions) { return false } for i, ac := range a.Conditions { bc := b.Conditions[i] if !EqualCondition(ac, bc) { return false } } return true } // EqualCondition compares two conditions for equality without reflection. func EqualCondition(a, b *pbresource.Condition) bool { if a == b { return true } if a == nil || b == nil { return false } return a.Type == b.Type && a.State == b.State && a.Reason == b.Reason && a.Message == b.Message && EqualReference(a.Resource, b.Resource) } // EqualReference compares two references for equality without reflection. func EqualReference(a, b *pbresource.Reference) bool { if a == b { return true } if a == nil || b == nil { return false } return EqualType(a.Type, b.Type) && EqualTenancy(a.Tenancy, b.Tenancy) && a.Name == b.Name && a.Section == b.Section } // ReferenceOrIDMatch compares two references or IDs to see if they both refer // to the same thing. // // Note that this only compares fields that are common between them as // represented by the ReferenceOrID interface and notably ignores the section // field on references and the uid field on ids. func ReferenceOrIDMatch(ref1, ref2 ReferenceOrID) bool { if ref1 == nil || ref2 == nil { return false } return EqualType(ref1.GetType(), ref2.GetType()) && EqualTenancy(ref1.GetTenancy(), ref2.GetTenancy()) && ref1.GetName() == ref2.GetName() } // EqualStatusMap compares two status maps for equality without reflection. func EqualStatusMap(a, b map[string]*pbresource.Status) bool { if len(a) != len(b) { return false } compared := make(map[string]struct{}) for k, av := range a { bv, ok := b[k] if !ok { return false } if !EqualStatus(av, bv, true) { return false } compared[k] = struct{}{} } for k, bv := range b { if _, skip := compared[k]; skip { continue } av, ok := a[k] if !ok { return false } if !EqualStatus(av, bv, true) { return false } } return true }