Run golangci-lint run --fix

This commit is entirely generated by earthly +reviewable

Signed-off-by: Nic Cope <nicc@rk0n.org>
This commit is contained in:
Nic Cope 2025-07-03 12:51:13 -07:00
parent aad05b013a
commit 678177c524
85 changed files with 812 additions and 86 deletions

View File

@ -126,6 +126,7 @@ func IsSystemConditionType(t ConditionType) bool {
case TypeReady, TypeSynced, TypeHealthy: case TypeReady, TypeSynced, TypeHealthy:
return true return true
} }
return false return false
} }
@ -150,6 +151,7 @@ type ConditionedStatus struct {
func NewConditionedStatus(c ...Condition) *ConditionedStatus { func NewConditionedStatus(c ...Condition) *ConditionedStatus {
s := &ConditionedStatus{} s := &ConditionedStatus{}
s.SetConditions(c...) s.SetConditions(c...)
return s return s
} }
@ -171,6 +173,7 @@ func (s *ConditionedStatus) GetCondition(ct ConditionType) Condition {
func (s *ConditionedStatus) SetConditions(c ...Condition) { func (s *ConditionedStatus) SetConditions(c ...Condition) {
for _, cond := range c { for _, cond := range c {
exists := false exists := false
for i, existing := range s.Conditions { for i, existing := range s.Conditions {
if existing.Type != cond.Type { if existing.Type != cond.Type {
continue continue
@ -184,6 +187,7 @@ func (s *ConditionedStatus) SetConditions(c ...Condition) {
s.Conditions[i] = cond s.Conditions[i] = cond
exists = true exists = true
} }
if !exists { if !exists {
s.Conditions = append(s.Conditions, cond) s.Conditions = append(s.Conditions, cond)
} }

View File

@ -72,6 +72,7 @@ func (in *ConnectionSecretMetadata) SetOwnerUID(uid types.UID) {
if in.Labels == nil { if in.Labels == nil {
in.Labels = map[string]string{} in.Labels = map[string]string{}
} }
in.Labels[LabelKeyOwnerUID] = string(uid) in.Labels[LabelKeyOwnerUID] = string(uid)
} }
@ -80,6 +81,7 @@ func (in *ConnectionSecretMetadata) GetOwnerUID() string {
if u, ok := in.Labels[LabelKeyOwnerUID]; ok { if u, ok := in.Labels[LabelKeyOwnerUID]; ok {
return u return u
} }
return "" return ""
} }

View File

@ -40,9 +40,11 @@ func (mo *MergeOptions) MergoConfiguration() []func(*mergo.Config) {
if mo.KeepMapValues != nil && *mo.KeepMapValues { if mo.KeepMapValues != nil && *mo.KeepMapValues {
config = config[:0] config = config[:0]
} }
if mo.AppendSlice != nil && *mo.AppendSlice { if mo.AppendSlice != nil && *mo.AppendSlice {
config = append(config, mergo.WithAppendSlice) config = append(config, mergo.WithAppendSlice)
} }
return config return config
} }

View File

@ -33,12 +33,15 @@ func (arr mergoOptArr) names() []string {
for i, opt := range arr { for i, opt := range arr {
names[i] = runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name() names[i] = runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name()
} }
sort.Strings(names) sort.Strings(names)
return names return names
} }
func TestMergoConfiguration(t *testing.T) { func TestMergoConfiguration(t *testing.T) {
valTrue := true valTrue := true
tests := map[string]struct { tests := map[string]struct {
mo *MergeOptions mo *MergeOptions
want mergoOptArr want mergoOptArr

View File

@ -101,6 +101,7 @@ func (p *Policy) IsResolutionPolicyOptional() bool {
if p == nil || p.Resolution == nil { if p == nil || p.Resolution == nil {
return false return false
} }
return *p.Resolution == ResolutionPolicyOptional return *p.Resolution == ResolutionPolicyOptional
} }
@ -109,6 +110,7 @@ func (p *Policy) IsResolvePolicyAlways() bool {
if p == nil || p.Resolve == nil { if p == nil || p.Resolve == nil {
return false return false
} }
return *p.Resolve == ResolvePolicyAlways return *p.Resolve == ResolvePolicyAlways
} }

View File

@ -36,12 +36,14 @@ const (
func LoadMTLSConfig(caPath, certPath, keyPath string, isServer bool) (*tls.Config, error) { func LoadMTLSConfig(caPath, certPath, keyPath string, isServer bool) (*tls.Config, error) {
tlsCertFilePath := filepath.Clean(certPath) tlsCertFilePath := filepath.Clean(certPath)
tlsKeyFilePath := filepath.Clean(keyPath) tlsKeyFilePath := filepath.Clean(keyPath)
certificate, err := tls.LoadX509KeyPair(tlsCertFilePath, tlsKeyFilePath) certificate, err := tls.LoadX509KeyPair(tlsCertFilePath, tlsKeyFilePath)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errLoadCert) return nil, errors.Wrap(err, errLoadCert)
} }
caCertFilePath := filepath.Clean(caPath) caCertFilePath := filepath.Clean(caPath)
ca, err := os.ReadFile(caCertFilePath) ca, err := os.ReadFile(caCertFilePath)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errLoadCA) return nil, errors.Wrap(err, errLoadCA)

View File

@ -27,10 +27,12 @@ func TestLoad(t *testing.T) {
certsFolderPath string certsFolderPath string
requireClientValidation bool requireClientValidation bool
} }
type want struct { type want struct {
err error err error
out *tls.Config out *tls.Config
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -92,16 +94,16 @@ func TestLoad(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
certsFolderPath := tc.args.certsFolderPath certsFolderPath := tc.certsFolderPath
requireClient := tc.args.requireClientValidation requireClient := tc.requireClientValidation
cfg, err := LoadMTLSConfig(filepath.Join(certsFolderPath, caCertFileName), filepath.Join(certsFolderPath, tlsCertFileName), filepath.Join(certsFolderPath, tlsKeyFileName), requireClient) cfg, err := LoadMTLSConfig(filepath.Join(certsFolderPath, caCertFileName), filepath.Join(certsFolderPath, tlsCertFileName), filepath.Join(certsFolderPath, tlsKeyFileName), requireClient)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nLoad(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nLoad(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if requireClient { if requireClient {
if diff := cmp.Diff(tc.want.out.ClientAuth, cfg.ClientAuth); diff != "" { if diff := cmp.Diff(tc.out.ClientAuth, cfg.ClientAuth); diff != "" {
t.Errorf("\n%s\nLoad(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nLoad(...): -want, +got:\n%s", tc.reason, diff)
} }
} }

View File

@ -68,5 +68,6 @@ func (c *observedGenerationPropagationConditionSet) MarkConditions(condition ...
for i := range condition { for i := range condition {
condition[i].ObservedGeneration = c.o.GetGeneration() condition[i].ObservedGeneration = c.o.GetGeneration()
} }
c.o.SetConditions(condition...) c.o.SetConditions(condition...)
} }

View File

@ -80,6 +80,7 @@ func TestOGConditionSetMark(t *testing.T) {
ut := newManaged(42, tt.start...) ut := newManaged(42, tt.start...)
c := manager.For(ut) c := manager.For(ut)
c.MarkConditions(tt.mark...) c.MarkConditions(tt.mark...)
if diff := cmp.Diff(tt.want, ut.Conditions, test.EquateConditions(), cmpopts.EquateApproxTime(1*time.Second)); diff != "" { if diff := cmp.Diff(tt.want, ut.Conditions, test.EquateConditions(), cmpopts.EquateApproxTime(1*time.Second)); diff != "" {
t.Errorf("\nReason: %s\n-want, +got:\n%s", tt.reason, diff) t.Errorf("\nReason: %s\n-want, +got:\n%s", tt.reason, diff)
} }
@ -129,5 +130,6 @@ func newManaged(generation int64, conditions ...xpv1.Condition) *fake.Managed {
mg := &fake.Managed{} mg := &fake.Managed{}
mg.Generation = generation mg.Generation = generation
mg.SetConditions(conditions...) mg.SetConditions(conditions...)
return mg return mg
} }

View File

@ -74,10 +74,13 @@ func (s *StoreConfig) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (s *StoreConfig) DeepCopyObject() runtime.Object { func (s *StoreConfig) DeepCopyObject() runtime.Object {
out := &StoreConfig{} out := &StoreConfig{}
j, err := json.Marshal(s) j, err := json.Marshal(s)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }

View File

@ -115,6 +115,7 @@ func (m *DetailsManager) PublishConnection(ctx context.Context, so resource.Conn
} }
changed, err := ss.WriteKeyValues(ctx, store.NewSecret(so, store.KeyValues(conn)), SecretToWriteMustBeOwnedBy(so)) changed, err := ss.WriteKeyValues(ctx, store.NewSecret(so, store.KeyValues(conn)), SecretToWriteMustBeOwnedBy(so))
return changed, errors.Wrap(err, errWriteStore) return changed, errors.Wrap(err, errWriteStore)
} }
@ -149,6 +150,7 @@ func (m *DetailsManager) FetchConnection(ctx context.Context, so resource.Connec
} }
s := &store.Secret{} s := &store.Secret{}
return managed.ConnectionDetails(s.Data), errors.Wrap(ss.ReadKeyValues(ctx, store.ScopedName{Name: p.Name, Scope: so.GetNamespace()}, s), errReadStore) return managed.ConnectionDetails(s.Data), errors.Wrap(ss.ReadKeyValues(ctx, store.ScopedName{Name: p.Name, Scope: so.GetNamespace()}, s), errReadStore)
} }
@ -185,6 +187,7 @@ func (m *DetailsManager) PropagateConnection(ctx context.Context, to resource.Lo
} }
changed, err := ssTo.WriteKeyValues(ctx, store.NewSecret(to, sFrom.Data), SecretToWriteMustBeOwnedBy(to)) changed, err := ssTo.WriteKeyValues(ctx, store.NewSecret(to, sFrom.Data), SecretToWriteMustBeOwnedBy(to))
return changed, errors.Wrap(err, errWriteStore) return changed, errors.Wrap(err, errWriteStore)
} }
@ -217,5 +220,6 @@ func secretMustBeOwnedBy(so metav1.Object, secret *store.Secret) error {
if secret.Metadata == nil || secret.Metadata.GetOwnerUID() != string(so.GetUID()) { if secret.Metadata == nil || secret.Metadata.GetOwnerUID() != string(so.GetUID()) {
return errors.Errorf(errFmtNotOwnedBy, string(so.GetUID())) return errors.Errorf(errFmtNotOwnedBy, string(so.GetUID()))
} }
return nil return nil
} }

View File

@ -144,10 +144,10 @@ func TestManagerConnectStore(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
m := NewDetailsManager(tc.args.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.args.sb)) m := NewDetailsManager(tc.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.sb))
_, err := m.connectStore(context.Background(), tc.args.p) _, err := m.connectStore(context.Background(), tc.p)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nm.connectStore(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.connectStore(...): -want error, +got error:\n%s", tc.reason, diff)
} }
}) })
@ -289,13 +289,14 @@ func TestManagerPublishConnection(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
m := NewDetailsManager(tc.args.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.args.sb)) m := NewDetailsManager(tc.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.sb))
published, err := m.PublishConnection(context.Background(), tc.args.so, tc.args.conn) published, err := m.PublishConnection(context.Background(), tc.so, tc.conn)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nm.publishConnection(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.publishConnection(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.published, published); diff != "" {
if diff := cmp.Diff(tc.published, published); diff != "" {
t.Errorf("\nReason: %s\nm.publishConnection(...): -want published, +got published:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.publishConnection(...): -want published, +got published:\n%s", tc.reason, diff)
} }
}) })
@ -489,10 +490,10 @@ func TestManagerUnpublishConnection(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
m := NewDetailsManager(tc.args.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.args.sb)) m := NewDetailsManager(tc.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.sb))
err := m.UnpublishConnection(context.Background(), tc.args.so, tc.args.conn) err := m.UnpublishConnection(context.Background(), tc.so, tc.conn)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nm.unpublishConnection(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.unpublishConnection(...): -want error, +got error:\n%s", tc.reason, diff)
} }
}) })
@ -632,13 +633,14 @@ func TestManagerFetchConnection(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
m := NewDetailsManager(tc.args.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.args.sb)) m := NewDetailsManager(tc.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.sb))
got, err := m.FetchConnection(context.Background(), tc.args.so) got, err := m.FetchConnection(context.Background(), tc.so)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nm.FetchConnection(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.FetchConnection(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.conn, got); diff != "" {
if diff := cmp.Diff(tc.conn, got); diff != "" {
t.Errorf("\nReason: %s\nm.FetchConnection(...): -want connDetails, +got connDetails:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.FetchConnection(...): -want connDetails, +got connDetails:\n%s", tc.reason, diff)
} }
}) })
@ -1213,13 +1215,14 @@ func TestManagerPropagateConnection(t *testing.T) {
} }
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
m := NewDetailsManager(tc.args.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.args.sb)) m := NewDetailsManager(tc.c, resourcefake.GVK(&fake.StoreConfig{}), WithStoreBuilder(tc.sb))
got, err := m.PropagateConnection(context.Background(), tc.args.to, tc.args.from) got, err := m.PropagateConnection(context.Background(), tc.to, tc.from)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nm.PropagateConnection(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.PropagateConnection(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.propagated, got); diff != "" {
if diff := cmp.Diff(tc.propagated, got); diff != "" {
t.Errorf("\nReason: %s\nm.PropagateConnection(...): -want propagated, +got propagated:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nm.PropagateConnection(...): -want propagated, +got propagated:\n%s", tc.reason, diff)
} }
}) })
@ -1231,6 +1234,7 @@ func fakeStoreBuilderFn(ss fake.SecretStore) StoreBuilderFn {
if *cfg.Type == fakeStore { if *cfg.Type == fakeStore {
return &ss, nil return &ss, nil
} }
return nil, errors.Errorf(errFmtUnknownSecretStore, *cfg.Type) return nil, errors.Errorf(errFmtUnknownSecretStore, *cfg.Type)
} }
} }

View File

@ -83,10 +83,12 @@ func buildClient(ctx context.Context, local client.Client, cfg v1.SecretStoreCon
if err != nil { if err != nil {
return nil, errors.Wrap(err, errExtractKubernetesAuthCreds) return nil, errors.Wrap(err, errExtractKubernetesAuthCreds)
} }
config, err := clientcmd.RESTConfigFromKubeConfig(kfg) config, err := clientcmd.RESTConfigFromKubeConfig(kfg)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errBuildRestConfig) return nil, errors.Wrap(err, errBuildRestConfig)
} }
return client.New(config, client.Options{}) return client.New(config, client.Options{})
} }
@ -96,12 +98,14 @@ func (ss *SecretStore) ReadKeyValues(ctx context.Context, n store.ScopedName, s
if err := ss.client.Get(ctx, types.NamespacedName{Name: n.Name, Namespace: ss.namespaceForSecret(n)}, ks); resource.IgnoreNotFound(err) != nil { if err := ss.client.Get(ctx, types.NamespacedName{Name: n.Name, Namespace: ss.namespaceForSecret(n)}, ks); resource.IgnoreNotFound(err) != nil {
return errors.Wrap(err, errGetSecret) return errors.Wrap(err, errGetSecret)
} }
s.Data = ks.Data s.Data = ks.Data
s.Metadata = &v1.ConnectionSecretMetadata{ s.Metadata = &v1.ConnectionSecretMetadata{
Labels: ks.Labels, Labels: ks.Labels,
Annotations: ks.Annotations, Annotations: ks.Annotations,
Type: &ks.Type, Type: &ks.Type,
} }
return nil return nil
} }
@ -118,6 +122,7 @@ func (ss *SecretStore) WriteKeyValues(ctx context.Context, s *store.Secret, wo .
if s.Metadata != nil { if s.Metadata != nil {
ks.Labels = s.Metadata.Labels ks.Labels = s.Metadata.Labels
ks.Annotations = s.Metadata.Annotations ks.Annotations = s.Metadata.Annotations
if s.Metadata.Type != nil { if s.Metadata.Type != nil {
ks.Type = *s.Metadata.Type ks.Type = *s.Metadata.Type
@ -136,9 +141,11 @@ func (ss *SecretStore) WriteKeyValues(ctx context.Context, s *store.Secret, wo .
// The update was not allowed because it was a no-op. // The update was not allowed because it was a no-op.
return false, nil return false, nil
} }
if err != nil { if err != nil {
return false, errors.Wrap(err, errApplySecret) return false, errors.Wrap(err, errApplySecret)
} }
return true, nil return true, nil
} }
@ -156,11 +163,13 @@ func (ss *SecretStore) DeleteKeyValues(ctx context.Context, s *store.Secret, do
// deletion, I opted for unifying both instead of adding conditional logic // deletion, I opted for unifying both instead of adding conditional logic
// like add owner references if not remote and not call delete etc. // like add owner references if not remote and not call delete etc.
ks := &corev1.Secret{} ks := &corev1.Secret{}
err := ss.client.Get(ctx, types.NamespacedName{Name: s.Name, Namespace: ss.namespaceForSecret(s.ScopedName)}, ks) err := ss.client.Get(ctx, types.NamespacedName{Name: s.Name, Namespace: ss.namespaceForSecret(s.ScopedName)}, ks)
if kerrors.IsNotFound(err) { if kerrors.IsNotFound(err) {
// Secret already deleted, nothing to do. // Secret already deleted, nothing to do.
return nil return nil
} }
if err != nil { if err != nil {
return errors.Wrap(err, errGetSecret) return errors.Wrap(err, errGetSecret)
} }
@ -175,6 +184,7 @@ func (ss *SecretStore) DeleteKeyValues(ctx context.Context, s *store.Secret, do
for k := range s.Data { for k := range s.Data {
delete(ks.Data, k) delete(ks.Data, k)
} }
if len(s.Data) == 0 || len(ks.Data) == 0 { if len(s.Data) == 0 || len(ks.Data) == 0 {
// Secret is deleted only if: // Secret is deleted only if:
// - No kv to delete specified as input // - No kv to delete specified as input
@ -189,6 +199,7 @@ func (ss *SecretStore) namespaceForSecret(n store.ScopedName) string {
if n.Scope == "" { if n.Scope == "" {
return ss.defaultNamespace return ss.defaultNamespace
} }
return n.Scope return n.Scope
} }
@ -244,6 +255,7 @@ func applyOptions(wo ...store.WriteOption) []resource.ApplyOption {
desiredSecret.Data = ds.Data desiredSecret.Data = ds.Data
desiredSecret.Labels = ds.Metadata.Labels desiredSecret.Labels = ds.Metadata.Labels
desiredSecret.Annotations = ds.Metadata.Annotations desiredSecret.Annotations = ds.Metadata.Annotations
if ds.Metadata.Type != nil { if ds.Metadata.Type != nil {
desiredSecret.Type = *ds.Metadata.Type desiredSecret.Type = *ds.Metadata.Type
@ -252,5 +264,6 @@ func applyOptions(wo ...store.WriteOption) []resource.ApplyOption {
return nil return nil
} }
} }
return ao return ao
} }

View File

@ -71,6 +71,7 @@ func TestSecretStoreReadKeyValues(t *testing.T) {
client resource.ClientApplicator client resource.ClientApplicator
n store.ScopedName n store.ScopedName
} }
type want struct { type want struct {
result store.KeyValues result store.KeyValues
err error err error
@ -139,17 +140,18 @@ func TestSecretStoreReadKeyValues(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
} }
s := &store.Secret{} s := &store.Secret{}
s.ScopedName = tc.args.n s.ScopedName = tc.n
err := ss.ReadKeyValues(context.Background(), tc.args.n, s)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { err := ss.ReadKeyValues(context.Background(), tc.n, s)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.ReadKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.ReadKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.result, s.Data); diff != "" { if diff := cmp.Diff(tc.result, s.Data); diff != "" {
t.Errorf("\n%s\nss.ReadKeyValues(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.ReadKeyValues(...): -want, +got:\n%s", tc.reason, diff)
} }
}) })
@ -158,6 +160,7 @@ func TestSecretStoreReadKeyValues(t *testing.T) {
func TestSecretStoreWriteKeyValues(t *testing.T) { func TestSecretStoreWriteKeyValues(t *testing.T) {
secretTypeOpaque := corev1.SecretTypeOpaque secretTypeOpaque := corev1.SecretTypeOpaque
type args struct { type args struct {
client resource.ClientApplicator client resource.ClientApplicator
defaultNamespace string defaultNamespace string
@ -165,6 +168,7 @@ func TestSecretStoreWriteKeyValues(t *testing.T) {
wo []store.WriteOption wo []store.WriteOption
} }
type want struct { type want struct {
changed bool changed bool
err error err error
@ -465,14 +469,16 @@ func TestSecretStoreWriteKeyValues(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
defaultNamespace: tc.args.defaultNamespace, defaultNamespace: tc.defaultNamespace,
} }
changed, err := ss.WriteKeyValues(context.Background(), tc.args.secret, tc.args.wo...)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { changed, err := ss.WriteKeyValues(context.Background(), tc.secret, tc.wo...)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.WriteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.WriteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.changed, changed); diff != "" {
if diff := cmp.Diff(tc.changed, changed); diff != "" {
t.Errorf("\n%s\nss.WriteKeyValues(...): -want changed, +got changed:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.WriteKeyValues(...): -want changed, +got changed:\n%s", tc.reason, diff)
} }
}) })
@ -487,6 +493,7 @@ func TestSecretStoreDeleteKeyValues(t *testing.T) {
do []store.DeleteOption do []store.DeleteOption
} }
type want struct { type want struct {
err error err error
} }
@ -655,11 +662,12 @@ func TestSecretStoreDeleteKeyValues(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
defaultNamespace: tc.args.defaultNamespace, defaultNamespace: tc.defaultNamespace,
} }
err := ss.DeleteKeyValues(context.Background(), tc.args.secret, tc.args.do...)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { err := ss.DeleteKeyValues(context.Background(), tc.secret, tc.do...)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.DeleteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.DeleteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
}) })
@ -671,6 +679,7 @@ func TestNewSecretStore(t *testing.T) {
client resource.ClientApplicator client resource.ClientApplicator
cfg v1.SecretStoreConfig cfg v1.SecretStoreConfig
} }
type want struct { type want struct {
err error err error
} }
@ -836,8 +845,8 @@ users:
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
_, err := NewSecretStore(context.Background(), tc.args.client, nil, tc.args.cfg) _, err := NewSecretStore(context.Background(), tc.client, nil, tc.cfg)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nNewSecretStore(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nNewSecretStore(...): -want error, +got error:\n%s", tc.reason, diff)
} }
}) })

View File

@ -53,6 +53,7 @@ type SecretStore struct {
// NewSecretStore returns a new External SecretStore. // NewSecretStore returns a new External SecretStore.
func NewSecretStore(_ context.Context, kube client.Client, tcfg *tls.Config, cfg v1.SecretStoreConfig) (*SecretStore, error) { func NewSecretStore(_ context.Context, kube client.Client, tcfg *tls.Config, cfg v1.SecretStoreConfig) (*SecretStore, error) {
creds := credentials.NewTLS(tcfg) creds := credentials.NewTLS(tcfg)
conn, err := grpc.NewClient(cfg.Plugin.Endpoint, grpc.WithTransportCredentials(creds)) conn, err := grpc.NewClient(cfg.Plugin.Endpoint, grpc.WithTransportCredentials(creds))
if err != nil { if err != nil {
return nil, errors.Wrapf(err, errFmtCannotDial, cfg.Plugin.Endpoint) return nil, errors.Wrapf(err, errFmtCannotDial, cfg.Plugin.Endpoint)
@ -81,6 +82,7 @@ func (ss *SecretStore) ReadKeyValues(ctx context.Context, n store.ScopedName, s
} }
respSecretData := respSecret.GetData() respSecretData := respSecret.GetData()
s.Data = make(map[string][]byte, len(respSecretData)) s.Data = make(map[string][]byte, len(respSecretData))
for d := range respSecretData { for d := range respSecretData {
s.Data[d] = respSecretData[d] s.Data[d] = respSecretData[d]
@ -89,6 +91,7 @@ func (ss *SecretStore) ReadKeyValues(ctx context.Context, n store.ScopedName, s
respSecretMetadata := respSecret.GetMetadata() respSecretMetadata := respSecret.GetMetadata()
if len(respSecretMetadata) != 0 { if len(respSecretMetadata) != 0 {
s.Metadata = new(v1.ConnectionSecretMetadata) s.Metadata = new(v1.ConnectionSecretMetadata)
s.Metadata.Labels = make(map[string]string, len(respSecretMetadata)) s.Metadata.Labels = make(map[string]string, len(respSecretMetadata))
for k, v := range respSecretMetadata { for k, v := range respSecretMetadata {
s.Metadata.Labels[k] = v s.Metadata.Labels[k] = v
@ -102,6 +105,7 @@ func (ss *SecretStore) ReadKeyValues(ctx context.Context, n store.ScopedName, s
func (ss *SecretStore) WriteKeyValues(ctx context.Context, s *store.Secret, _ ...store.WriteOption) (changed bool, err error) { func (ss *SecretStore) WriteKeyValues(ctx context.Context, s *store.Secret, _ ...store.WriteOption) (changed bool, err error) {
sec := &essproto.Secret{} sec := &essproto.Secret{}
sec.ScopedName = ss.getScopedName(s.ScopedName) sec.ScopedName = ss.getScopedName(s.ScopedName)
sec.Data = make(map[string][]byte, len(s.Data)) sec.Data = make(map[string][]byte, len(s.Data))
for k, v := range s.Data { for k, v := range s.Data {
sec.Data[k] = v sec.Data[k] = v
@ -141,5 +145,6 @@ func (ss *SecretStore) getScopedName(n store.ScopedName) string {
if n.Scope == "" { if n.Scope == "" {
n.Scope = ss.defaultScope n.Scope = ss.defaultScope
} }
return filepath.Join(n.Scope, n.Name) return filepath.Join(n.Scope, n.Name)
} }

View File

@ -44,10 +44,12 @@ func TestReadKeyValues(t *testing.T) {
sn store.ScopedName sn store.ScopedName
client ess.ExternalSecretStorePluginServiceClient client ess.ExternalSecretStorePluginServiceClient
} }
type want struct { type want struct {
out *store.Secret out *store.Secret
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -123,7 +125,7 @@ func TestReadKeyValues(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
config: &v1.Config{ config: &v1.Config{
APIVersion: "v1alpha1", APIVersion: "v1alpha1",
Kind: "VaultConfig", Kind: "VaultConfig",
@ -132,13 +134,12 @@ func TestReadKeyValues(t *testing.T) {
} }
s := &store.Secret{} s := &store.Secret{}
err := ss.ReadKeyValues(ctx, tc.args.sn, s) err := ss.ReadKeyValues(ctx, tc.sn, s)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.ReadKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.ReadKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.out, s); diff != "" { if diff := cmp.Diff(tc.out, s); diff != "" {
t.Errorf("\n%s\nss.ReadKeyValues(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.ReadKeyValues(...): -want, +got:\n%s", tc.reason, diff)
} }
}) })
@ -149,10 +150,12 @@ func TestWriteKeyValues(t *testing.T) {
type args struct { type args struct {
client ess.ExternalSecretStorePluginServiceClient client ess.ExternalSecretStorePluginServiceClient
} }
type want struct { type want struct {
isChanged bool isChanged bool
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -195,7 +198,7 @@ func TestWriteKeyValues(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
config: &v1.Config{ config: &v1.Config{
APIVersion: "v1alpha1", APIVersion: "v1alpha1",
Kind: "VaultConfig", Kind: "VaultConfig",
@ -205,12 +208,11 @@ func TestWriteKeyValues(t *testing.T) {
s := &store.Secret{} s := &store.Secret{}
isChanged, err := ss.WriteKeyValues(ctx, s) isChanged, err := ss.WriteKeyValues(ctx, s)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.WriteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.WriteKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.isChanged, isChanged); diff != "" { if diff := cmp.Diff(tc.isChanged, isChanged); diff != "" {
t.Errorf("\n%s\nss.WriteKeyValues(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.WriteKeyValues(...): -want, +got:\n%s", tc.reason, diff)
} }
}) })
@ -221,9 +223,11 @@ func TestDeleteKeyValues(t *testing.T) {
type args struct { type args struct {
client ess.ExternalSecretStorePluginServiceClient client ess.ExternalSecretStorePluginServiceClient
} }
type want struct { type want struct {
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -260,7 +264,7 @@ func TestDeleteKeyValues(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ss := &SecretStore{ ss := &SecretStore{
client: tc.args.client, client: tc.client,
config: &v1.Config{ config: &v1.Config{
APIVersion: "v1alpha1", APIVersion: "v1alpha1",
Kind: "VaultConfig", Kind: "VaultConfig",
@ -270,8 +274,7 @@ func TestDeleteKeyValues(t *testing.T) {
s := &store.Secret{} s := &store.Secret{}
err := ss.DeleteKeyValues(ctx, s) err := ss.DeleteKeyValues(ctx, s)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nss.DeletKeyValues(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nss.DeletKeyValues(...): -want error, +got error:\n%s", tc.reason, diff)
} }
}) })

View File

@ -43,6 +43,7 @@ type ScopedName struct {
// A Secret is an entity representing a set of sensitive Key Values. // A Secret is an entity representing a set of sensitive Key Values.
type Secret struct { type Secret struct {
ScopedName ScopedName
Metadata *v1.ConnectionSecretMetadata Metadata *v1.ConnectionSecretMetadata
Data KeyValues Data KeyValues
} }
@ -53,11 +54,14 @@ func NewSecret(so SecretOwner, data KeyValues) *Secret {
if so.GetPublishConnectionDetailsTo() == nil { if so.GetPublishConnectionDetailsTo() == nil {
return nil return nil
} }
p := so.GetPublishConnectionDetailsTo() p := so.GetPublishConnectionDetailsTo()
if p.Metadata == nil { if p.Metadata == nil {
p.Metadata = &v1.ConnectionSecretMetadata{} p.Metadata = &v1.ConnectionSecretMetadata{}
} }
p.Metadata.SetOwnerUID(so.GetUID()) p.Metadata.SetOwnerUID(so.GetUID())
return &Secret{ return &Secret{
ScopedName: ScopedName{ ScopedName: ScopedName{
Name: p.Name, Name: p.Name,
@ -73,6 +77,7 @@ func (s *Secret) GetOwner() string {
if s.Metadata == nil { if s.Metadata == nil {
return "" return ""
} }
return s.Metadata.GetOwnerUID() return s.Metadata.GetOwnerUID()
} }
@ -81,6 +86,7 @@ func (s *Secret) GetLabels() map[string]string {
if s.Metadata == nil { if s.Metadata == nil {
return nil return nil
} }
return s.Metadata.Labels return s.Metadata.Labels
} }

View File

@ -43,5 +43,6 @@ func RuntimeStoreBuilder(ctx context.Context, local client.Client, tcfg *tls.Con
case v1.SecretStorePlugin: case v1.SecretStorePlugin:
return plugin.NewSecretStore(ctx, local, tcfg, cfg) return plugin.NewSecretStore(ctx, local, tcfg, cfg)
} }
return nil, errors.Errorf(errFmtUnknownSecretStore, *cfg.Type) return nil, errors.Errorf(errFmtUnknownSecretStore, *cfg.Type)
} }

View File

@ -85,6 +85,7 @@ func WithMessage(err error, message string) error {
if err == nil { if err == nil {
return nil return nil
} }
return fmt.Errorf("%s: %w", message, err) return fmt.Errorf("%s: %w", message, err)
} }
@ -94,6 +95,7 @@ func WithMessagef(err error, format string, args ...any) error {
if err == nil { if err == nil {
return nil return nil
} }
return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err) return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)
} }
@ -120,6 +122,7 @@ func Cause(err error) error {
if !ok { if !ok {
return err return err
} }
err = w.Unwrap() err = w.Unwrap()
} }
@ -146,6 +149,7 @@ func Join(errs ...error) MultiError {
if err == nil { if err == nil {
return nil return nil
} }
return multiError{aggregate: err} return multiError{aggregate: err}
} }

View File

@ -29,6 +29,7 @@ func TestWrap(t *testing.T) {
err error err error
message string message string
} }
cases := map[string]struct { cases := map[string]struct {
args args args args
want error want error
@ -65,6 +66,7 @@ func TestWrapf(t *testing.T) {
message string message string
args []any args []any
} }
cases := map[string]struct { cases := map[string]struct {
args args args args
want error want error

View File

@ -30,6 +30,7 @@ func SilentlyRequeueOnConflict(result reconcile.Result, err error) (reconcile.Re
if kerrors.IsConflict(Cause(err)) { if kerrors.IsConflict(Cause(err)) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
return result, err return result, err
} }

View File

@ -33,10 +33,12 @@ func TestSilentlyRequeueOnConflict(t *testing.T) {
result reconcile.Result result reconcile.Result
err error err error
} }
type want struct { type want struct {
result reconcile.Result result reconcile.Result
err error err error
} }
tests := []struct { tests := []struct {
reason string reason string
args args args args
@ -91,6 +93,7 @@ func TestSilentlyRequeueOnConflict(t *testing.T) {
if diff := cmp.Diff(tt.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tt.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nIgnoreConflict(...): -want error, +got error:\n%s", tt.reason, diff) t.Errorf("\n%s\nIgnoreConflict(...): -want error, +got error:\n%s", tt.reason, diff)
} }
if diff := cmp.Diff(tt.want.result, got); diff != "" { if diff := cmp.Diff(tt.want.result, got); diff != "" {
t.Errorf("\n%s\nIgnoreConflict(...): -want result, +got result:\n%s", tt.reason, diff) t.Errorf("\n%s\nIgnoreConflict(...): -want result, +got result:\n%s", tt.reason, diff)
} }

View File

@ -52,6 +52,7 @@ func Normal(r Reason, message string, keysAndValues ...string) Event {
Annotations: map[string]string{}, Annotations: map[string]string{},
} }
sliceMap(keysAndValues, e.Annotations) sliceMap(keysAndValues, e.Annotations)
return e return e
} }
@ -64,6 +65,7 @@ func Warning(r Reason, err error, keysAndValues ...string) Event {
Annotations: map[string]string{}, Annotations: map[string]string{},
} }
sliceMap(keysAndValues, e.Annotations) sliceMap(keysAndValues, e.Annotations)
return e return e
} }
@ -97,7 +99,9 @@ func (r *APIRecorder) WithAnnotations(keysAndValues ...string) Recorder {
for k, v := range r.annotations { for k, v := range r.annotations {
ar.annotations[k] = v ar.annotations[k] = v
} }
sliceMap(keysAndValues, ar.annotations) sliceMap(keysAndValues, ar.annotations)
return ar return ar
} }

View File

@ -28,6 +28,7 @@ func TestSliceMap(t *testing.T) {
from []string from []string
to map[string]string to map[string]string
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args

View File

@ -33,9 +33,11 @@ type Flags struct {
// Enable a feature flag. // Enable a feature flag.
func (fs *Flags) Enable(f Flag) { func (fs *Flags) Enable(f Flag) {
fs.m.Lock() fs.m.Lock()
if fs.enabled == nil { if fs.enabled == nil {
fs.enabled = make(map[Flag]bool) fs.enabled = make(map[Flag]bool)
} }
fs.enabled[f] = true fs.enabled[f] = true
fs.m.Unlock() fs.m.Unlock()
} }
@ -45,7 +47,9 @@ func (fs *Flags) Enabled(f Flag) bool {
if fs == nil { if fs == nil {
return false return false
} }
fs.m.RLock() fs.m.RLock()
defer fs.m.RUnlock() defer fs.m.RUnlock()
return fs.enabled[f] return fs.enabled[f]
} }

View File

@ -82,6 +82,7 @@ func (sg Segments) String() string {
b.WriteString(fmt.Sprintf("[%s]", s.Field)) b.WriteString(fmt.Sprintf("[%s]", s.Field))
continue continue
} }
b.WriteString(fmt.Sprintf(".%s", s.Field)) b.WriteString(fmt.Sprintf(".%s", s.Field))
case SegmentIndex: case SegmentIndex:
b.WriteString(fmt.Sprintf("[%d]", s.Index)) b.WriteString(fmt.Sprintf("[%d]", s.Index))
@ -120,6 +121,7 @@ func Parse(path string) (Segments, error) {
go l.run() go l.run()
segments := make(Segments, 0, 1) segments := make(Segments, 0, 1)
for i := range l.items { for i := range l.items {
switch i.typ { //nolint:exhaustive // We're only worried about names, not separators. switch i.typ { //nolint:exhaustive // We're only worried about names, not separators.
case itemField: case itemField:
@ -130,6 +132,7 @@ func Parse(path string) (Segments, error) {
return nil, errors.Errorf("%s at position %d", i.val, i.pos) return nil, errors.Errorf("%s at position %d", i.val, i.pos)
} }
} }
return segments, nil return segments, nil
} }
@ -174,6 +177,7 @@ func (l *lexer) run() {
for state := lexField; state != nil; { for state := lexField; state != nil; {
state = state(l) state = state(l)
} }
close(l.items) close(l.items)
} }
@ -182,7 +186,9 @@ func (l *lexer) emit(t itemType) {
if l.pos <= l.start { if l.pos <= l.start {
return return
} }
l.items <- item{typ: t, pos: l.start, val: l.input[l.start:l.pos]} l.items <- item{typ: t, pos: l.start, val: l.input[l.start:l.pos]}
l.start = l.pos l.start = l.pos
} }
@ -202,12 +208,14 @@ func lexField(l *lexer) stateFn {
case leftBracket: case leftBracket:
l.pos += i l.pos += i
l.emit(itemField) l.emit(itemField)
return lexLeftBracket return lexLeftBracket
// A period indicates the end of the field name. // A period indicates the end of the field name.
case period: case period:
l.pos += i l.pos += i
l.emit(itemField) l.emit(itemField)
return lexPeriod return lexPeriod
} }
} }
@ -216,6 +224,7 @@ func lexField(l *lexer) stateFn {
l.pos = len(l.input) l.pos = len(l.input)
l.emit(itemField) l.emit(itemField)
l.emit(itemEOL) l.emit(itemEOL)
return nil return nil
} }
@ -234,6 +243,7 @@ func lexPeriod(l *lexer) stateFn {
if r == period { if r == period {
return l.errorf(l.pos, "unexpected %q", period) return l.errorf(l.pos, "unexpected %q", period)
} }
if r == leftBracket { if r == leftBracket {
return l.errorf(l.pos, "unexpected %q", leftBracket) return l.errorf(l.pos, "unexpected %q", leftBracket)
} }
@ -249,6 +259,7 @@ func lexLeftBracket(l *lexer) stateFn {
l.pos += utf8.RuneLen(leftBracket) l.pos += utf8.RuneLen(leftBracket)
l.emit(itemLeftBracket) l.emit(itemLeftBracket)
return lexFieldOrIndex return lexFieldOrIndex
} }
@ -272,11 +283,13 @@ func lexFieldOrIndex(l *lexer) stateFn {
// Periods are not considered field separators when we're inside brackets. // Periods are not considered field separators when we're inside brackets.
l.pos += rbi l.pos += rbi
l.emit(itemFieldOrIndex) l.emit(itemFieldOrIndex)
return lexRightBracket return lexRightBracket
} }
func lexRightBracket(l *lexer) stateFn { func lexRightBracket(l *lexer) stateFn {
l.pos += utf8.RuneLen(rightBracket) l.pos += utf8.RuneLen(rightBracket)
l.emit(itemRightBracket) l.emit(itemRightBracket)
return lexField return lexField
} }

View File

@ -299,6 +299,7 @@ func TestParse(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\nParse(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\nParse(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.s, got); diff != "" { if diff := cmp.Diff(tc.want.s, got); diff != "" {
t.Errorf("\nParse(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\nParse(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }

View File

@ -57,6 +57,7 @@ func merge(dst, src any, mergeOptions *xpv1.MergeOptions) (any, error) {
// because mergo currently supports merging only maps or structs, // because mergo currently supports merging only maps or structs,
// we wrap the argument to be passed to mergo.Merge in a map. // we wrap the argument to be passed to mergo.Merge in a map.
const keyArg = "arg" const keyArg = "arg"
argWrap := func(arg any) map[string]any { argWrap := func(arg any) map[string]any {
return map[string]any{ return map[string]any{
keyArg: arg, keyArg: arg,
@ -77,6 +78,7 @@ func merge(dst, src any, mergeOptions *xpv1.MergeOptions) (any, error) {
if err := mergo.Merge(&mDst, argWrap(src), mergeOptions.MergoConfiguration()...); err != nil { if err := mergo.Merge(&mDst, argWrap(src), mergeOptions.MergoConfiguration()...); err != nil {
return nil, errors.Wrap(err, errInvalidMerge) return nil, errors.Wrap(err, errInvalidMerge)
} }
return mDst[keyArg], nil return mDst[keyArg], nil
} }
@ -85,9 +87,11 @@ func removeSourceDuplicates(dst, src any) any {
if sliceDst.Kind() == reflect.Ptr { if sliceDst.Kind() == reflect.Ptr {
sliceDst = sliceDst.Elem() sliceDst = sliceDst.Elem()
} }
if sliceSrc.Kind() == reflect.Ptr { if sliceSrc.Kind() == reflect.Ptr {
sliceSrc = sliceSrc.Elem() sliceSrc = sliceSrc.Elem()
} }
if sliceDst.Kind() != reflect.Slice || sliceSrc.Kind() != reflect.Slice { if sliceDst.Kind() != reflect.Slice || sliceSrc.Kind() != reflect.Slice {
return src return src
} }
@ -95,6 +99,7 @@ func removeSourceDuplicates(dst, src any) any {
result := reflect.New(sliceSrc.Type()).Elem() // we will not modify src result := reflect.New(sliceSrc.Type()).Elem() // we will not modify src
for i := range sliceSrc.Len() { for i := range sliceSrc.Len() {
itemSrc := sliceSrc.Index(i) itemSrc := sliceSrc.Index(i)
found := false found := false
for j := 0; j < sliceDst.Len() && !found; j++ { for j := 0; j < sliceDst.Len() && !found; j++ {
// if src item is found in the dst array // if src item is found in the dst array
@ -102,10 +107,12 @@ func removeSourceDuplicates(dst, src any) any {
found = true found = true
} }
} }
if !found { if !found {
// then put src item into result // then put src item into result
result = reflect.Append(result, itemSrc) result = reflect.Append(result, itemSrc)
} }
} }
return result.Interface() return result.Interface()
} }

View File

@ -36,6 +36,7 @@ func TestMergeValue(t *testing.T) {
valSrc2 = "e1-from-source-2" valSrc2 = "e1-from-source-2"
valDst = "e1-from-destination" valDst = "e1-from-destination"
) )
formatArr := func(arr []string) string { formatArr := func(arr []string) string {
return fmt.Sprintf(`{"%s": ["%s"]}`, pathTest, strings.Join(arr, `", "`)) return fmt.Sprintf(`{"%s": ["%s"]}`, pathTest, strings.Join(arr, `", "`))
} }
@ -59,15 +60,18 @@ func TestMergeValue(t *testing.T) {
type fields struct { type fields struct {
object map[string]any object map[string]any
} }
type args struct { type args struct {
path string path string
value any value any
mo *xpv1.MergeOptions mo *xpv1.MergeOptions
} }
type want struct { type want struct {
serialized string serialized string
err error err error
} }
tests := map[string]struct { tests := map[string]struct {
reason string reason string
fields fields fields fields
@ -199,11 +203,13 @@ func TestMergeValue(t *testing.T) {
p := &Paved{ p := &Paved{
object: tc.fields.object, object: tc.fields.object,
} }
err := p.MergeValue(tc.args.path, tc.args.value, tc.args.mo) err := p.MergeValue(tc.args.path, tc.args.value, tc.args.mo)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.MergeValue(%s, %v): %s: -want error, +got error:\n%s", t.Fatalf("\np.MergeValue(%s, %v): %s: -want error, +got error:\n%s",
tc.args.path, tc.args.value, tc.reason, diff) tc.args.path, tc.args.value, tc.reason, diff)
} }
if diff := cmp.Diff(want, p.object); diff != "" { if diff := cmp.Diff(want, p.object); diff != "" {
t.Fatalf("\np.MergeValue(%s, %v): %s: -want, +got:\n%s", t.Fatalf("\np.MergeValue(%s, %v): %s: -want, +got:\n%s",
tc.args.path, tc.args.value, tc.reason, diff) tc.args.path, tc.args.value, tc.reason, diff)

View File

@ -44,6 +44,7 @@ func IsNotFound(err error) bool {
_, ok := cause.(interface { _, ok := cause.(interface {
IsNotFound() bool IsNotFound() bool
}) })
return ok return ok
} }
@ -100,6 +101,7 @@ func (p *Paved) UnstructuredContent() map[string]any {
if p.object == nil { if p.object == nil {
return make(map[string]any) return make(map[string]any)
} }
return p.object return p.object
} }
@ -115,18 +117,22 @@ func (p *Paved) getValue(s Segments) (any, error) {
func getValueFromInterface(it any, s Segments) (any, error) { func getValueFromInterface(it any, s Segments) (any, error) {
for i, current := range s { for i, current := range s {
final := i == len(s)-1 final := i == len(s)-1
switch current.Type { switch current.Type {
case SegmentIndex: case SegmentIndex:
array, ok := it.([]any) array, ok := it.([]any)
if !ok { if !ok {
return nil, errors.Errorf("%s: not an array", s[:i]) return nil, errors.Errorf("%s: not an array", s[:i])
} }
if current.Index >= uint(len(array)) { if current.Index >= uint(len(array)) {
return nil, notFoundError{errors.Errorf("%s: no such element", s[:i+1])} return nil, notFoundError{errors.Errorf("%s: no such element", s[:i+1])}
} }
if final { if final {
return array[current.Index], nil return array[current.Index], nil
} }
it = array[current.Index] it = array[current.Index]
case SegmentField: case SegmentField:
switch object := it.(type) { switch object := it.(type) {
@ -135,9 +141,11 @@ func getValueFromInterface(it any, s Segments) (any, error) {
if !ok { if !ok {
return nil, notFoundError{errors.Errorf("%s: no such field", s[:i+1])} return nil, notFoundError{errors.Errorf("%s: no such field", s[:i+1])}
} }
if final { if final {
return v, nil return v, nil
} }
it = object[current.Field] it = object[current.Field]
case nil: case nil:
return nil, notFoundError{errors.Errorf("%s: expected map, got nil", s[:i])} return nil, notFoundError{errors.Errorf("%s: expected map, got nil", s[:i])}
@ -165,14 +173,17 @@ func (p *Paved) ExpandWildcards(path string) ([]string, error) {
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "cannot parse path %q", path) return nil, errors.Wrapf(err, "cannot parse path %q", path)
} }
segmentsArray, err := expandWildcards(p.object, segments) segmentsArray, err := expandWildcards(p.object, segments)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "cannot expand wildcards for segments: %q", segments) return nil, errors.Wrapf(err, "cannot expand wildcards for segments: %q", segments)
} }
paths := make([]string, len(segmentsArray)) paths := make([]string, len(segmentsArray))
for i, s := range segmentsArray { for i, s := range segmentsArray {
paths[i] = s.String() paths[i] = s.String()
} }
return paths, nil return paths, nil
} }
@ -180,7 +191,9 @@ func expandWildcards(data any, segments Segments) ([]Segments, error) { //nolint
// Even complexity turns out to be high, it is mostly because we have duplicate // Even complexity turns out to be high, it is mostly because we have duplicate
// logic for arrays and maps and a couple of error handling. // logic for arrays and maps and a couple of error handling.
var res []Segments var res []Segments
it := data it := data
for i, current := range segments { for i, current := range segments {
// wildcards are regular fields with "*" as string // wildcards are regular fields with "*" as string
if current.Type == SegmentField && current.Field == wildcard { if current.Type == SegmentField && current.Field == wildcard {
@ -190,10 +203,12 @@ func expandWildcards(data any, segments Segments) ([]Segments, error) { //nolint
expanded := make(Segments, len(segments)) expanded := make(Segments, len(segments))
copy(expanded, segments) copy(expanded, segments)
expanded = append(append(expanded[:i], FieldOrIndex(strconv.Itoa(ix))), expanded[i+1:]...) expanded = append(append(expanded[:i], FieldOrIndex(strconv.Itoa(ix))), expanded[i+1:]...)
r, err := expandWildcards(data, expanded) r, err := expandWildcards(data, expanded)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "%q: cannot expand wildcards", expanded) return nil, errors.Wrapf(err, "%q: cannot expand wildcards", expanded)
} }
res = append(res, r...) res = append(res, r...)
} }
case map[string]any: case map[string]any:
@ -201,10 +216,12 @@ func expandWildcards(data any, segments Segments) ([]Segments, error) { //nolint
expanded := make(Segments, len(segments)) expanded := make(Segments, len(segments))
copy(expanded, segments) copy(expanded, segments)
expanded = append(append(expanded[:i], Field(k)), expanded[i+1:]...) expanded = append(append(expanded[:i], Field(k)), expanded[i+1:]...)
r, err := expandWildcards(data, expanded) r, err := expandWildcards(data, expanded)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "%q: cannot expand wildcards", expanded) return nil, errors.Wrapf(err, "%q: cannot expand wildcards", expanded)
} }
res = append(res, r...) res = append(res, r...)
} }
case nil: case nil:
@ -212,17 +229,22 @@ func expandWildcards(data any, segments Segments) ([]Segments, error) { //nolint
default: default:
return nil, errors.Errorf("%q: unexpected wildcard usage", segments[:i]) return nil, errors.Errorf("%q: unexpected wildcard usage", segments[:i])
} }
return res, nil return res, nil
} }
var err error var err error
it, err = getValueFromInterface(data, segments[:i+1]) it, err = getValueFromInterface(data, segments[:i+1])
if IsNotFound(err) { if IsNotFound(err) {
return nil, nil return nil, nil
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
return append(res, segments), nil return append(res, segments), nil
} }
@ -242,10 +264,12 @@ func (p *Paved) GetValueInto(path string, out any) error {
if err != nil { if err != nil {
return err return err
} }
js, err := json.Marshal(val) js, err := json.Marshal(val)
if err != nil { if err != nil {
return errors.Wrap(err, "cannot marshal value to JSON") return errors.Wrap(err, "cannot marshal value to JSON")
} }
return errors.Wrap(json.Unmarshal(js, out), "cannot unmarshal value from JSON") return errors.Wrap(json.Unmarshal(js, out), "cannot unmarshal value from JSON")
} }
@ -260,6 +284,7 @@ func (p *Paved) GetString(path string) (string, error) {
if !ok { if !ok {
return "", errors.Errorf("%s: not a string", path) return "", errors.Errorf("%s: not a string", path)
} }
return s, nil return s, nil
} }
@ -281,6 +306,7 @@ func (p *Paved) GetStringArray(path string) ([]string, error) {
if !ok { if !ok {
return nil, errors.Errorf("%s: not an array of strings", path) return nil, errors.Errorf("%s: not an array of strings", path)
} }
sa[i] = s sa[i] = s
} }
@ -305,6 +331,7 @@ func (p *Paved) GetStringObject(path string) (map[string]string, error) {
if !ok { if !ok {
return nil, errors.Errorf("%s: not an object with string field values", path) return nil, errors.Errorf("%s: not an object with string field values", path)
} }
so[k] = s so[k] = s
} }
@ -322,6 +349,7 @@ func (p *Paved) GetBool(path string) (bool, error) {
if !ok { if !ok {
return false, errors.Errorf("%s: not a bool", path) return false, errors.Errorf("%s: not a bool", path)
} }
return b, nil return b, nil
} }
@ -336,6 +364,7 @@ func (p *Paved) GetInteger(path string) (int64, error) {
if !ok { if !ok {
return 0, errors.Errorf("%s: not a (int64) number", path) return 0, errors.Errorf("%s: not a (int64) number", path)
} }
return f, nil return f, nil
} }
@ -354,6 +383,7 @@ func (p *Paved) setValue(s Segments, value any) error {
} }
var in any = p.object var in any = p.object
for i, current := range s { for i, current := range s {
final := i == len(s)-1 final := i == len(s)-1
@ -393,13 +423,16 @@ func (p *Paved) setValue(s Segments, value any) error {
func toValidJSON(value any) (any, error) { func toValidJSON(value any) (any, error) {
var v any var v any
j, err := json.Marshal(value) j, err := json.Marshal(value)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "cannot marshal value to JSON") return nil, errors.Wrap(err, "cannot marshal value to JSON")
} }
if err := json.Unmarshal(j, &v); err != nil { if err := json.Unmarshal(j, &v); err != nil {
return nil, errors.Wrap(err, "cannot unmarshal value from JSON") return nil, errors.Wrap(err, "cannot unmarshal value from JSON")
} }
return v, nil return v, nil
} }
@ -413,6 +446,7 @@ func prepareElement(array []any, current, next Segment) {
case SegmentField: case SegmentField:
array[current.Index] = make(map[string]any) array[current.Index] = make(map[string]any)
} }
return return
} }
@ -444,6 +478,7 @@ func prepareField(object map[string]any, current, next Segment) {
case SegmentField: case SegmentField:
object[current.Field] = make(map[string]any) object[current.Field] = make(map[string]any)
} }
return return
} }
@ -471,6 +506,7 @@ func (p *Paved) SetValue(path string, value any) error {
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot parse path %q", path) return errors.Wrapf(err, "cannot parse path %q", path)
} }
return p.setValue(segments, value) return p.setValue(segments, value)
} }
@ -478,11 +514,13 @@ func (p *Paved) validateSegments(s Segments) error {
if !p.maxFieldPathIndexEnabled() { if !p.maxFieldPathIndexEnabled() {
return nil return nil
} }
for _, segment := range s { for _, segment := range s {
if segment.Type == SegmentIndex && segment.Index > p.maxFieldPathIndex { if segment.Type == SegmentIndex && segment.Index > p.maxFieldPathIndex {
return errors.Errorf("index %v is greater than max allowed index %d", segment.Index, p.maxFieldPathIndex) return errors.Errorf("index %v is greater than max allowed index %d", segment.Index, p.maxFieldPathIndex)
} }
} }
return nil return nil
} }
@ -511,6 +549,7 @@ func (p *Paved) DeleteField(path string) error {
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot parse path %q", path) return errors.Wrapf(err, "cannot parse path %q", path)
} }
return p.delete(segments) return p.delete(segments)
} }
@ -522,10 +561,14 @@ func (p *Paved) delete(segments Segments) error { //nolint:gocognit // See note
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot delete %s", segments) return errors.Wrapf(err, "cannot delete %s", segments)
} }
p.object = o.(map[string]any) //nolint:forcetypeassert // We're deleting from the root of the paved object, which is always a map[string]any. p.object = o.(map[string]any) //nolint:forcetypeassert // We're deleting from the root of the paved object, which is always a map[string]any.
return nil return nil
} }
var in any = p.object var in any = p.object
for i, current := range segments { for i, current := range segments {
// beforeLast is true for the element before the last one because // beforeLast is true for the element before the last one because
// slices cannot be changed in place and Go does not allow // slices cannot be changed in place and Go does not allow
@ -535,6 +578,7 @@ func (p *Paved) delete(segments Segments) error { //nolint:gocognit // See note
// until the element before the last one as opposed to // until the element before the last one as opposed to
// Set/Get functions in this file. // Set/Get functions in this file.
beforeLast := i == len(segments)-2 beforeLast := i == len(segments)-2
switch current.Type { switch current.Type {
case SegmentIndex: case SegmentIndex:
array, ok := in.([]any) array, ok := in.([]any)
@ -552,7 +596,9 @@ func (p *Paved) delete(segments Segments) error { //nolint:gocognit // See note
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot delete %s", segments) return errors.Wrapf(err, "cannot delete %s", segments)
} }
array[current.Index] = o array[current.Index] = o
return nil return nil
} }
@ -573,13 +619,16 @@ func (p *Paved) delete(segments Segments) error { //nolint:gocognit // See note
if err != nil { if err != nil {
return errors.Wrapf(err, "cannot delete %s", segments) return errors.Wrapf(err, "cannot delete %s", segments)
} }
object[current.Field] = o object[current.Field] = o
return nil return nil
} }
in = object[current.Field] in = object[current.Field]
} }
} }
return nil return nil
} }
@ -593,20 +642,26 @@ func deleteField(obj any, s Segment) (any, error) {
if !ok { if !ok {
return nil, errors.New("not an array") return nil, errors.New("not an array")
} }
if len(array) == 0 || uint(len(array)) <= s.Index { if len(array) == 0 || uint(len(array)) <= s.Index {
return array, nil return array, nil
} }
for i := s.Index; i < uint(len(array))-1; i++ { for i := s.Index; i < uint(len(array))-1; i++ {
array[i] = array[i+1] array[i] = array[i+1]
} }
return array[:len(array)-1], nil return array[:len(array)-1], nil
case SegmentField: case SegmentField:
object, ok := obj.(map[string]any) object, ok := obj.(map[string]any)
if !ok { if !ok {
return nil, errors.New("not an object") return nil, errors.New("not an object")
} }
delete(object, s.Field) delete(object, s.Field)
return object, nil return object, nil
} }
return nil, nil return nil, nil
} }

View File

@ -68,6 +68,7 @@ func TestGetValue(t *testing.T) {
value any value any
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -181,6 +182,7 @@ func TestGetValue(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetValue(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetValue(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetValue(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetValue(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -201,10 +203,12 @@ func TestGetValueInto(t *testing.T) {
path string path string
out any out any
} }
type want struct { type want struct {
out any out any
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
data []byte data []byte
@ -257,6 +261,7 @@ func TestGetValueInto(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetValueInto(%s): %s: -want error, +got error:\n%s", tc.args.path, tc.reason, diff) t.Fatalf("\np.GetValueInto(%s): %s: -want error, +got error:\n%s", tc.args.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.out, tc.args.out); diff != "" { if diff := cmp.Diff(tc.want.out, tc.args.out); diff != "" {
t.Errorf("\np.GetValueInto(%s): %s: -want, +got:\n%s", tc.args.path, tc.reason, diff) t.Errorf("\np.GetValueInto(%s): %s: -want, +got:\n%s", tc.args.path, tc.reason, diff)
} }
@ -269,6 +274,7 @@ func TestGetString(t *testing.T) {
value string value string
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -310,6 +316,7 @@ func TestGetString(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetString(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetString(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetString(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetString(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -322,6 +329,7 @@ func TestGetStringArray(t *testing.T) {
value []string value []string
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -371,6 +379,7 @@ func TestGetStringArray(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetStringArray(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetStringArray(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetStringArray(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetStringArray(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -383,6 +392,7 @@ func TestGetStringObject(t *testing.T) {
value map[string]string value map[string]string
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -432,6 +442,7 @@ func TestGetStringObject(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetStringObject(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetStringObject(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetStringObject(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetStringObject(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -444,6 +455,7 @@ func TestGetBool(t *testing.T) {
value bool value bool
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -485,6 +497,7 @@ func TestGetBool(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetBool(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetBool(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetBool(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetBool(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -497,6 +510,7 @@ func TestGetInteger(t *testing.T) {
value int64 value int64
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -538,6 +552,7 @@ func TestGetInteger(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.GetNumber(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.GetNumber(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.value, got); diff != "" { if diff := cmp.Diff(tc.want.value, got); diff != "" {
t.Errorf("\np.GetNumber(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff) t.Errorf("\np.GetNumber(%s): %s: -want, +got:\n%s", tc.path, tc.reason, diff)
} }
@ -551,10 +566,12 @@ func TestSetValue(t *testing.T) {
value any value any
opts []PavedOption opts []PavedOption
} }
type want struct { type want struct {
object map[string]any object map[string]any
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
data []byte data []byte
@ -814,6 +831,7 @@ func TestSetValue(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.SetValue(%s, %v): %s: -want error, +got error:\n%s", tc.args.path, tc.args.value, tc.reason, diff) t.Fatalf("\np.SetValue(%s, %v): %s: -want error, +got error:\n%s", tc.args.path, tc.args.value, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.object, p.object); diff != "" { if diff := cmp.Diff(tc.want.object, p.object); diff != "" {
t.Fatalf("\np.SetValue(%s, %v): %s: -want, +got:\n%s", tc.args.path, tc.args.value, tc.reason, diff) t.Fatalf("\np.SetValue(%s, %v): %s: -want, +got:\n%s", tc.args.path, tc.args.value, tc.reason, diff)
} }
@ -826,6 +844,7 @@ func TestExpandWildcards(t *testing.T) {
expanded []string expanded []string
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
path string path string
@ -979,6 +998,7 @@ func TestExpandWildcards(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.ExpandWildcards(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff) t.Fatalf("\np.ExpandWildcards(%s): %s: -want error, +got error:\n%s", tc.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.expanded, got, cmpopts.SortSlices(func(x, y string) bool { if diff := cmp.Diff(tc.want.expanded, got, cmpopts.SortSlices(func(x, y string) bool {
return x < y return x < y
})); diff != "" { })); diff != "" {
@ -992,10 +1012,12 @@ func TestDeleteField(t *testing.T) {
type args struct { type args struct {
path string path string
} }
type want struct { type want struct {
object map[string]any object map[string]any
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
data []byte data []byte
@ -1267,6 +1289,7 @@ func TestDeleteField(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Fatalf("\np.DeleteField(%s): %s: -want error, +got error:\n%s", tc.args.path, tc.reason, diff) t.Fatalf("\np.DeleteField(%s): %s: -want error, +got error:\n%s", tc.args.path, tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.object, p.object); diff != "" { if diff := cmp.Diff(tc.want.object, p.object); diff != "" {
t.Fatalf("\np.DeleteField(%s): %s: -want, +got:\n%s", tc.args.path, tc.reason, diff) t.Fatalf("\np.DeleteField(%s): %s: -want, +got:\n%s", tc.args.path, tc.reason, diff)
} }

View File

@ -49,6 +49,7 @@ func (l *requestThrottlingFilter) klogToLogrLevel(klogLvl int) int {
if klogLvl >= 3 { if klogLvl >= 3 {
return klogLvl - 3 return klogLvl - 3
} }
return 0 return 0
} }

View File

@ -70,6 +70,7 @@ const (
// See https://github.com/crossplane/crossplane-runtime/issues/49 // See https://github.com/crossplane/crossplane-runtime/issues/49
func ReferenceTo(o metav1.Object, of schema.GroupVersionKind) *corev1.ObjectReference { func ReferenceTo(o metav1.Object, of schema.GroupVersionKind) *corev1.ObjectReference {
v, k := of.ToAPIVersionAndKind() v, k := of.ToAPIVersionAndKind()
return &corev1.ObjectReference{ return &corev1.ObjectReference{
APIVersion: v, APIVersion: v,
Kind: k, Kind: k,
@ -83,6 +84,7 @@ func ReferenceTo(o metav1.Object, of schema.GroupVersionKind) *corev1.ObjectRefe
// presumed to be of the supplied group, version, and kind. // presumed to be of the supplied group, version, and kind.
func TypedReferenceTo(o metav1.Object, of schema.GroupVersionKind) *xpv1.TypedReference { func TypedReferenceTo(o metav1.Object, of schema.GroupVersionKind) *xpv1.TypedReference {
v, k := of.ToAPIVersionAndKind() v, k := of.ToAPIVersionAndKind()
return &xpv1.TypedReference{ return &xpv1.TypedReference{
APIVersion: v, APIVersion: v,
Kind: k, Kind: k,
@ -108,6 +110,7 @@ func AsController(r *xpv1.TypedReference) metav1.OwnerReference {
ref := AsOwner(r) ref := AsOwner(r)
ref.Controller = &t ref.Controller = &t
ref.BlockOwnerDeletion = &t ref.BlockOwnerDeletion = &t
return ref return ref
} }
@ -139,9 +142,11 @@ func AddOwnerReference(o metav1.Object, r metav1.OwnerReference) {
if refs[i].UID == r.UID { if refs[i].UID == r.UID {
refs[i] = r refs[i] = r
o.SetOwnerReferences(refs) o.SetOwnerReferences(refs)
return return
} }
} }
o.SetOwnerReferences(append(refs, r)) o.SetOwnerReferences(append(refs, r))
} }
@ -154,6 +159,7 @@ func AddControllerReference(o metav1.Object, r metav1.OwnerReference) error {
} }
AddOwnerReference(o, r) AddOwnerReference(o, r)
return nil return nil
} }
@ -165,6 +171,7 @@ func AddFinalizer(o metav1.Object, finalizer string) {
return return
} }
} }
o.SetFinalizers(append(f, finalizer)) o.SetFinalizers(append(f, finalizer))
} }
@ -176,6 +183,7 @@ func RemoveFinalizer(o metav1.Object, finalizer string) {
f = append(f[:i], f[i+1:]...) f = append(f[:i], f[i+1:]...)
} }
} }
o.SetFinalizers(f) o.SetFinalizers(f)
} }
@ -187,6 +195,7 @@ func FinalizerExists(o metav1.Object, finalizer string) bool {
return true return true
} }
} }
return false return false
} }
@ -197,9 +206,11 @@ func AddLabels(o metav1.Object, labels map[string]string) {
o.SetLabels(labels) o.SetLabels(labels)
return return
} }
for k, v := range labels { for k, v := range labels {
l[k] = v l[k] = v
} }
o.SetLabels(l) o.SetLabels(l)
} }
@ -209,9 +220,11 @@ func RemoveLabels(o metav1.Object, labels ...string) {
if l == nil { if l == nil {
return return
} }
for _, k := range labels { for _, k := range labels {
delete(l, k) delete(l, k)
} }
o.SetLabels(l) o.SetLabels(l)
} }
@ -222,9 +235,11 @@ func AddAnnotations(o metav1.Object, annotations map[string]string) {
o.SetAnnotations(annotations) o.SetAnnotations(annotations)
return return
} }
for k, v := range annotations { for k, v := range annotations {
a[k] = v a[k] = v
} }
o.SetAnnotations(a) o.SetAnnotations(a)
} }
@ -234,9 +249,11 @@ func RemoveAnnotations(o metav1.Object, annotations ...string) {
if a == nil { if a == nil {
return return
} }
for _, k := range annotations { for _, k := range annotations {
delete(a, k) delete(a, k)
} }
o.SetAnnotations(a) o.SetAnnotations(a)
} }
@ -267,10 +284,12 @@ func SetExternalName(o metav1.Object, name string) {
// was most recently pending creation. // was most recently pending creation.
func GetExternalCreatePending(o metav1.Object) time.Time { func GetExternalCreatePending(o metav1.Object) time.Time {
a := o.GetAnnotations()[AnnotationKeyExternalCreatePending] a := o.GetAnnotations()[AnnotationKeyExternalCreatePending]
t, err := time.Parse(time.RFC3339, a) t, err := time.Parse(time.RFC3339, a)
if err != nil { if err != nil {
return time.Time{} return time.Time{}
} }
return t return t
} }
@ -284,10 +303,12 @@ func SetExternalCreatePending(o metav1.Object, t time.Time) {
// was most recently created. // was most recently created.
func GetExternalCreateSucceeded(o metav1.Object) time.Time { func GetExternalCreateSucceeded(o metav1.Object) time.Time {
a := o.GetAnnotations()[AnnotationKeyExternalCreateSucceeded] a := o.GetAnnotations()[AnnotationKeyExternalCreateSucceeded]
t, err := time.Parse(time.RFC3339, a) t, err := time.Parse(time.RFC3339, a)
if err != nil { if err != nil {
return time.Time{} return time.Time{}
} }
return t return t
} }
@ -301,10 +322,12 @@ func SetExternalCreateSucceeded(o metav1.Object, t time.Time) {
// recently failed to create. // recently failed to create.
func GetExternalCreateFailed(o metav1.Object) time.Time { func GetExternalCreateFailed(o metav1.Object) time.Time {
a := o.GetAnnotations()[AnnotationKeyExternalCreateFailed] a := o.GetAnnotations()[AnnotationKeyExternalCreateFailed]
t, err := time.Parse(time.RFC3339, a) t, err := time.Parse(time.RFC3339, a)
if err != nil { if err != nil {
return time.Time{} return time.Time{}
} }
return t return t
} }
@ -344,6 +367,7 @@ func ExternalCreateSucceededDuring(o metav1.Object, d time.Duration) bool {
if t.IsZero() { if t.IsZero() {
return false return false
} }
return time.Since(t) < d return time.Since(t) < d
} }

View File

@ -46,6 +46,7 @@ func TestReferenceTo(t *testing.T) {
o metav1.Object o metav1.Object
of schema.GroupVersionKind of schema.GroupVersionKind
} }
tests := map[string]struct { tests := map[string]struct {
args args
want *corev1.ObjectReference want *corev1.ObjectReference
@ -77,7 +78,7 @@ func TestReferenceTo(t *testing.T) {
for name, tc := range tests { for name, tc := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
got := ReferenceTo(tc.args.o, tc.args.of) got := ReferenceTo(tc.o, tc.of)
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("ReferenceTo(): -want, +got:\n%s", diff) t.Errorf("ReferenceTo(): -want, +got:\n%s", diff)
} }
@ -90,6 +91,7 @@ func TestTypedReferenceTo(t *testing.T) {
o metav1.Object o metav1.Object
of schema.GroupVersionKind of schema.GroupVersionKind
} }
tests := map[string]struct { tests := map[string]struct {
args args
want *xpv1.TypedReference want *xpv1.TypedReference
@ -120,7 +122,7 @@ func TestTypedReferenceTo(t *testing.T) {
for name, tc := range tests { for name, tc := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
got := TypedReferenceTo(tc.args.o, tc.args.of) got := TypedReferenceTo(tc.o, tc.of)
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("TypedReferenceTo(): -want, +got:\n%s", diff) t.Errorf("TypedReferenceTo(): -want, +got:\n%s", diff)
} }
@ -895,6 +897,7 @@ func TestSetExternalName(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
SetExternalName(tc.o, tc.name) SetExternalName(tc.o, tc.name)
if diff := cmp.Diff(tc.want, tc.o); diff != "" { if diff := cmp.Diff(tc.want, tc.o); diff != "" {
t.Errorf("SetExternalName(...): -want, +got:\n%s", diff) t.Errorf("SetExternalName(...): -want, +got:\n%s", diff)
} }
@ -947,6 +950,7 @@ func TestSetExternalCreatePending(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
SetExternalCreatePending(tc.o, tc.t) SetExternalCreatePending(tc.o, tc.t)
if diff := cmp.Diff(tc.want, tc.o); diff != "" { if diff := cmp.Diff(tc.want, tc.o); diff != "" {
t.Errorf("SetExternalCreatePending(...): -want, +got:\n%s", diff) t.Errorf("SetExternalCreatePending(...): -want, +got:\n%s", diff)
} }
@ -999,6 +1003,7 @@ func TestSetExternalCreateSucceeded(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
SetExternalCreateSucceeded(tc.o, tc.t) SetExternalCreateSucceeded(tc.o, tc.t)
if diff := cmp.Diff(tc.want, tc.o); diff != "" { if diff := cmp.Diff(tc.want, tc.o); diff != "" {
t.Errorf("SetExternalCreateSucceeded(...): -want, +got:\n%s", diff) t.Errorf("SetExternalCreateSucceeded(...): -want, +got:\n%s", diff)
} }
@ -1051,6 +1056,7 @@ func TestSetExternalCreateFailed(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
SetExternalCreateFailed(tc.o, tc.t) SetExternalCreateFailed(tc.o, tc.t)
if diff := cmp.Diff(tc.want, tc.o); diff != "" { if diff := cmp.Diff(tc.want, tc.o); diff != "" {
t.Errorf("SetExternalCreateFailed(...): -want, +got:\n%s", diff) t.Errorf("SetExternalCreateFailed(...): -want, +got:\n%s", diff)
} }

View File

@ -62,6 +62,7 @@ func SkipDirs() FilterFn {
if info.IsDir() { if info.IsDir() {
return true, nil return true, nil
} }
return false, nil return false, nil
} }
} }
@ -79,6 +80,7 @@ func SkipNotYAML() FilterFn {
if filepath.Ext(path) != ".yaml" && filepath.Ext(path) != ".yml" { if filepath.Ext(path) != ".yaml" && filepath.Ext(path) != ".yml" {
return true, nil return true, nil
} }
return false, nil return false, nil
} }
} }
@ -92,18 +94,23 @@ func NewFsReadCloser(fs afero.Fs, dir string, fns ...FilterFn) (*FsReadCloser, e
if err != nil { if err != nil {
return err return err
} }
for _, fn := range fns { for _, fn := range fns {
filter, err := fn(path, info) filter, err := fn(path, info)
if err != nil { if err != nil {
return err return err
} }
if filter { if filter {
return nil return nil
} }
} }
paths = append(paths, path) paths = append(paths, path)
return nil return nil
}) })
return &FsReadCloser{ return &FsReadCloser{
fs: fs, fs: fs,
dir: dir, dir: dir,
@ -121,24 +128,31 @@ func (r *FsReadCloser) Read(p []byte) (n int, err error) {
r.position = 0 r.position = 0
r.wroteBreak = false r.wroteBreak = false
n = copy(p, "\n---\n") n = copy(p, "\n---\n")
return n, nil return n, nil
} }
if r.index == len(r.paths) { if r.index == len(r.paths) {
return 0, io.EOF return 0, io.EOF
} }
if r.writeBreak { if r.writeBreak {
n = copy(p, "\n...\n") n = copy(p, "\n...\n")
r.writeBreak = false r.writeBreak = false
r.wroteBreak = true r.wroteBreak = true
return n, nil return n, nil
} }
b, err := afero.ReadFile(r.fs, r.paths[r.index]) b, err := afero.ReadFile(r.fs, r.paths[r.index])
n = copy(p, b[r.position:]) n = copy(p, b[r.position:])
r.position += n r.position += n
if errors.Is(err, io.EOF) || n == 0 { if errors.Is(err, io.EOF) || n == 0 {
r.writeBreak = true r.writeBreak = true
err = nil err = nil
} }
return n, err return n, err
} }
@ -155,6 +169,7 @@ func (r *FsReadCloser) Annotate() any {
if index == len(r.paths) { if index == len(r.paths) {
index-- index--
} }
return FsReadCloserAnnotation{ return FsReadCloserAnnotation{
path: r.paths[index], path: r.paths[index],
position: r.position, position: r.position,

View File

@ -78,6 +78,7 @@ func (l *PackageLinter) Lint(pkg Lintable) error {
return err return err
} }
} }
for _, o := range pkg.GetMeta() { for _, o := range pkg.GetMeta() {
for _, fn := range l.perMeta { for _, fn := range l.perMeta {
if err := fn(o); err != nil { if err := fn(o); err != nil {
@ -85,6 +86,7 @@ func (l *PackageLinter) Lint(pkg Lintable) error {
} }
} }
} }
for _, o := range pkg.GetObjects() { for _, o := range pkg.GetObjects() {
for _, fn := range l.perObject { for _, fn := range l.perObject {
if err := fn(o); err != nil { if err := fn(o); err != nil {
@ -92,6 +94,7 @@ func (l *PackageLinter) Lint(pkg Lintable) error {
} }
} }
} }
return nil return nil
} }
@ -100,16 +103,20 @@ func (l *PackageLinter) Lint(pkg Lintable) error {
func Or(linters ...ObjectLinterFn) ObjectLinterFn { func Or(linters ...ObjectLinterFn) ObjectLinterFn {
return func(o runtime.Object) error { return func(o runtime.Object) error {
var errs []string var errs []string
for _, l := range linters { for _, l := range linters {
if l == nil { if l == nil {
return errors.New(errNilLinterFn) return errors.New(errNilLinterFn)
} }
err := l(o) err := l(o)
if err == nil { if err == nil {
return nil return nil
} }
errs = append(errs, err.Error()) errs = append(errs, err.Error())
} }
return errors.Errorf(errOrFmt, strings.Join(errs, ", ")) return errors.Errorf(errOrFmt, strings.Join(errs, ", "))
} }
} }

View File

@ -119,7 +119,6 @@ func TestLinter(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
err := tc.args.linter.Lint(tc.args.pkg) err := tc.args.linter.Lint(tc.args.pkg)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nl.Lint(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nl.Lint(...): -want error, +got error:\n%s", tc.reason, diff)
} }
@ -175,7 +174,6 @@ func TestOr(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
err := Or(tc.args.one, tc.args.two)(crd) err := Or(tc.args.one, tc.args.two)(crd)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nOr(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nOr(...): -want error, +got error:\n%s", tc.reason, diff)
} }

View File

@ -105,21 +105,27 @@ func (p *PackageParser) Parse(_ context.Context, reader io.ReadCloser) (*Package
if reader == nil { if reader == nil {
return pkg, nil return pkg, nil
} }
defer func() { _ = reader.Close() }() defer func() { _ = reader.Close() }()
yr := yaml.NewYAMLReader(bufio.NewReader(reader)) yr := yaml.NewYAMLReader(bufio.NewReader(reader))
dm := json.NewSerializerWithOptions(json.DefaultMetaFactory, p.metaScheme, p.metaScheme, json.SerializerOptions{Yaml: true}) dm := json.NewSerializerWithOptions(json.DefaultMetaFactory, p.metaScheme, p.metaScheme, json.SerializerOptions{Yaml: true})
do := json.NewSerializerWithOptions(json.DefaultMetaFactory, p.objScheme, p.objScheme, json.SerializerOptions{Yaml: true}) do := json.NewSerializerWithOptions(json.DefaultMetaFactory, p.objScheme, p.objScheme, json.SerializerOptions{Yaml: true})
for { for {
content, err := yr.Read() content, err := yr.Read()
if err != nil && !errors.Is(err, io.EOF) { if err != nil && !errors.Is(err, io.EOF) {
return pkg, err return pkg, err
} }
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
break break
} }
if isEmptyYAML(content) { if isEmptyYAML(content) {
continue continue
} }
m, _, err := dm.Decode(content, nil, nil) m, _, err := dm.Decode(content, nil, nil)
if err != nil { if err != nil {
// NOTE(hasheddan): we only try to decode with object scheme if the // NOTE(hasheddan): we only try to decode with object scheme if the
@ -127,15 +133,20 @@ func (p *PackageParser) Parse(_ context.Context, reader io.ReadCloser) (*Package
if !runtime.IsNotRegisteredError(err) { if !runtime.IsNotRegisteredError(err) {
return pkg, annotateErr(err, reader) return pkg, annotateErr(err, reader)
} }
o, _, err := do.Decode(content, nil, nil) o, _, err := do.Decode(content, nil, nil)
if err != nil { if err != nil {
return pkg, annotateErr(err, reader) return pkg, annotateErr(err, reader)
} }
pkg.objects = append(pkg.objects, o) pkg.objects = append(pkg.objects, o)
continue continue
} }
pkg.meta = append(pkg.meta, m) pkg.meta = append(pkg.meta, m)
} }
return pkg, nil return pkg, nil
} }
@ -151,6 +162,7 @@ func isEmptyYAML(y []byte) bool {
return false return false
} }
} }
return true return true
} }
@ -159,6 +171,7 @@ func annotateErr(err error, reader io.ReadCloser) error {
if anno, ok := reader.(AnnotatedReadCloser); ok { if anno, ok := reader.(AnnotatedReadCloser); ok {
return errors.Wrapf(err, "%+v", anno.Annotate()) return errors.Wrapf(err, "%+v", anno.Annotate())
} }
return err return err
} }
@ -184,6 +197,7 @@ func NewPodLogBackend(bo ...BackendOption) *PodLogBackend {
for _, o := range bo { for _, o := range bo {
o(p) o(p)
} }
return p return p
} }
@ -192,11 +206,14 @@ func (p *PodLogBackend) Init(ctx context.Context, bo ...BackendOption) (io.ReadC
for _, o := range bo { for _, o := range bo {
o(p) o(p)
} }
logs := p.client.CoreV1().Pods(p.namespace).GetLogs(p.name, &corev1.PodLogOptions{}) logs := p.client.CoreV1().Pods(p.namespace).GetLogs(p.name, &corev1.PodLogOptions{})
reader, err := logs.Stream(ctx) reader, err := logs.Stream(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return reader, nil return reader, nil
} }
@ -207,6 +224,7 @@ func PodName(name string) BackendOption {
if !ok { if !ok {
return return
} }
pl.name = name pl.name = name
} }
} }
@ -218,6 +236,7 @@ func PodNamespace(namespace string) BackendOption {
if !ok { if !ok {
return return
} }
pl.namespace = namespace pl.namespace = namespace
} }
} }
@ -229,6 +248,7 @@ func PodClient(client kubernetes.Interface) BackendOption {
if !ok { if !ok {
return return
} }
pl.client = client pl.client = client
} }
} }
@ -261,6 +281,7 @@ func NewFsBackend(fs afero.Fs, bo ...BackendOption) *FsBackend {
for _, o := range bo { for _, o := range bo {
o(f) o(f)
} }
return f return f
} }
@ -269,6 +290,7 @@ func (p *FsBackend) Init(_ context.Context, bo ...BackendOption) (io.ReadCloser,
for _, o := range bo { for _, o := range bo {
o(p) o(p)
} }
return NewFsReadCloser(p.fs, p.dir, p.skips...) return NewFsReadCloser(p.fs, p.dir, p.skips...)
} }
@ -279,6 +301,7 @@ func FsDir(dir string) BackendOption {
if !ok { if !ok {
return return
} }
f.dir = dir f.dir = dir
} }
} }
@ -290,6 +313,7 @@ func FsFilters(skips ...FilterFn) BackendOption {
if !ok { if !ok {
return return
} }
f.skips = skips f.skips = skips
} }
} }
@ -311,5 +335,6 @@ func (p *EchoBackend) Init(_ context.Context, bo ...BackendOption) (io.ReadClose
for _, o := range bo { for _, o := range bo {
o(p) o(p)
} }
return io.NopCloser(strings.NewReader(p.echo)), nil return io.NopCloser(strings.NewReader(p.echo)), nil
} }

View File

@ -195,18 +195,22 @@ func TestParser(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("backend.Init(...): unexpected error: %s", err) t.Errorf("backend.Init(...): unexpected error: %s", err)
} }
pkg, err := tc.parser.Parse(context.TODO(), r) pkg, err := tc.parser.Parse(context.TODO(), r)
if err != nil && !tc.wantErr { if err != nil && !tc.wantErr {
t.Errorf("parser.Parse(...): unexpected error: %s", err) t.Errorf("parser.Parse(...): unexpected error: %s", err)
} }
if tc.wantErr { if tc.wantErr {
return return
} }
if diff := cmp.Diff(tc.pkg.GetObjects(), pkg.GetObjects(), cmpopts.SortSlices(func(i, j runtime.Object) bool { if diff := cmp.Diff(tc.pkg.GetObjects(), pkg.GetObjects(), cmpopts.SortSlices(func(i, j runtime.Object) bool {
return i.GetObjectKind().GroupVersionKind().String() > j.GetObjectKind().GroupVersionKind().String() return i.GetObjectKind().GroupVersionKind().String() > j.GetObjectKind().GroupVersionKind().String()
})); diff != "" { })); diff != "" {
t.Errorf("Objects: -want, +got:\n%s", diff) t.Errorf("Objects: -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.pkg.GetMeta(), pkg.GetMeta(), cmpopts.SortSlices(func(i, j runtime.Object) bool { if diff := cmp.Diff(tc.pkg.GetMeta(), pkg.GetMeta(), cmpopts.SortSlices(func(i, j runtime.Object) bool {
return i.GetObjectKind().GroupVersionKind().String() > j.GetObjectKind().GroupVersionKind().String() return i.GetObjectKind().GroupVersionKind().String() > j.GetObjectKind().GroupVersionKind().String()
})); diff != "" { })); diff != "" {
@ -220,9 +224,11 @@ func TestCleanYAML(t *testing.T) {
type args struct { type args struct {
in []byte in []byte
} }
type want struct { type want struct {
out bool out bool
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args

View File

@ -53,7 +53,9 @@ func (s Settings) Generate() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
pw[i] = s.CharacterSet[n.Int64()] pw[i] = s.CharacterSet[n.Int64()]
} }
return string(pw), nil return string(pw), nil
} }

View File

@ -8,12 +8,13 @@ import (
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
// ¯\_(ツ)_/¯ // ¯\_(ツ)_/¯
want := "aaa" want := "aaa"
got, err := Settings{CharacterSet: "a", Length: 3}.Generate() got, err := Settings{CharacterSet: "a", Length: 3}.Generate()
if diff := cmp.Diff(want, got); diff != "" { if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("Generate(): -want, +got:\n%s", diff) t.Errorf("Generate(): -want, +got:\n%s", diff)
} }
if err != nil { if err != nil {
t.Errorf("Generate: %s\n", err) t.Errorf("Generate: %s\n", err)
} }

View File

@ -52,5 +52,6 @@ func LimitRESTConfig(cfg *rest.Config, rps int) *rest.Config {
out := rest.CopyConfig(cfg) out := rest.CopyConfig(cfg)
out.QPS = float32(rps * 5) out.QPS = float32(rps * 5)
out.Burst = rps * 10 out.Burst = rps * 10
return out return out
} }

View File

@ -56,7 +56,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
if d := r.when(req); d > 0 { if d := r.when(req); d > 0 {
return reconcile.Result{RequeueAfter: d}, nil return reconcile.Result{RequeueAfter: d}, nil
} }
r.limit.Forget(item) r.limit.Forget(item)
return r.inner.Reconcile(ctx, req) return r.inner.Reconcile(ctx, req)
} }
@ -78,6 +80,7 @@ func (r *Reconciler) when(req reconcile.Request) time.Duration {
r.limitedL.Lock() r.limitedL.Lock()
delete(r.limited, item) delete(r.limited, item)
r.limitedL.Unlock() r.limitedL.Unlock()
return 0 return 0
} }

View File

@ -41,6 +41,7 @@ func TestReconcile(t *testing.T) {
ctx context.Context ctx context.Context
req reconcile.Request req reconcile.Request
} }
type want struct { type want struct {
res reconcile.Result res reconcile.Result
err error err error
@ -101,6 +102,7 @@ func TestReconcile(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("%s\nr.Reconcile(...): -want, +got error:\n%s", tc.reason, diff) t.Errorf("%s\nr.Reconcile(...): -want, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.res, got); diff != "" { if diff := cmp.Diff(tc.want.res, got); diff != "" {
t.Errorf("%s\nr.Reconcile(...): -want, +got result:\n%s", tc.reason, diff) t.Errorf("%s\nr.Reconcile(...): -want, +got result:\n%s", tc.reason, diff)
} }

View File

@ -70,7 +70,9 @@ func (a *NameAsExternalName) Initialize(ctx context.Context, mg resource.Managed
if meta.GetExternalName(mg) != "" { if meta.GetExternalName(mg) != "" {
return nil return nil
} }
meta.SetExternalName(mg, mg.GetName()) meta.SetExternalName(mg, mg.GetName())
return errors.Wrap(a.client.Update(ctx, mg), errUpdateManaged) return errors.Wrap(a.client.Update(ctx, mg), errUpdateManaged)
} }
@ -103,6 +105,7 @@ func (a *APISecretPublisher) PublishConnection(ctx context.Context, o resource.C
s := resource.ConnectionSecretFor(o, resource.MustGetKind(o, a.typer)) s := resource.ConnectionSecretFor(o, resource.MustGetKind(o, a.typer))
s.Data = c s.Data = c
err := a.secret.Apply(ctx, s, err := a.secret.Apply(ctx, s,
resource.ConnectionSecretMustBeControllableBy(o.GetUID()), resource.ConnectionSecretMustBeControllableBy(o.GetUID()),
resource.AllowUpdateIf(func(current, desired runtime.Object) bool { resource.AllowUpdateIf(func(current, desired runtime.Object) bool {
@ -116,6 +119,7 @@ func (a *APISecretPublisher) PublishConnection(ctx context.Context, o resource.C
// The update was not allowed because it was a no-op. // The update was not allowed because it was a no-op.
return false, nil return false, nil
} }
if err != nil { if err != nil {
return false, errors.Wrap(err, errCreateOrUpdateSecret) return false, errors.Wrap(err, errCreateOrUpdateSecret)
} }
@ -153,15 +157,19 @@ func prepareJSONMerge(existing, resolved runtime.Object) ([]byte, error) {
// in the first place, instead of an unmarshal/marshal from the prepared // in the first place, instead of an unmarshal/marshal from the prepared
// patch []byte later. // patch []byte later.
existing.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{}) existing.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{})
eBuff, err := json.Marshal(existing) eBuff, err := json.Marshal(existing)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMarshalExisting) return nil, errors.Wrap(err, errMarshalExisting)
} }
rBuff, err := json.Marshal(resolved) rBuff, err := json.Marshal(resolved)
if err != nil { if err != nil {
return nil, errors.Wrap(err, errMarshalResolved) return nil, errors.Wrap(err, errMarshalResolved)
} }
patch, err := jsonpatch.CreateMergePatch(eBuff, rBuff) patch, err := jsonpatch.CreateMergePatch(eBuff, rBuff)
return patch, errors.Wrap(err, errPreparePatch) return patch, errors.Wrap(err, errPreparePatch)
} }
@ -177,6 +185,7 @@ func (a *APISimpleReferenceResolver) ResolveReferences(ctx context.Context, mg r
} }
existing := mg.DeepCopyObject() existing := mg.DeepCopyObject()
if err := rr.ResolveReferences(ctx, a.client); err != nil { if err := rr.ResolveReferences(ctx, a.client); err != nil {
return errors.Wrap(err, errResolveReferences) return errors.Wrap(err, errResolveReferences)
} }
@ -190,6 +199,7 @@ func (a *APISimpleReferenceResolver) ResolveReferences(ctx context.Context, mg r
if err != nil { if err != nil {
return err return err
} }
return errors.Wrap(a.client.Patch(ctx, mg, client.RawPatch(types.ApplyPatchType, patch), client.FieldOwner(fieldOwnerAPISimpleRefResolver), client.ForceOwnership), errPatchManaged) return errors.Wrap(a.client.Patch(ctx, mg, client.RawPatch(types.ApplyPatchType, patch), client.FieldOwner(fieldOwnerAPISimpleRefResolver), client.ForceOwnership), errPatchManaged)
} }
@ -221,9 +231,12 @@ func (u *RetryingCriticalAnnotationUpdater) UpdateCriticalAnnotations(ctx contex
if getErr := u.client.Get(ctx, client.ObjectKeyFromObject(o), o); getErr != nil { if getErr := u.client.Get(ctx, client.ObjectKeyFromObject(o), o); getErr != nil {
return getErr return getErr
} }
meta.AddAnnotations(o, a) meta.AddAnnotations(o, a)
} }
return err return err
}) })
return errors.Wrap(err, errUpdateCriticalAnnotations) return errors.Wrap(err, errUpdateCriticalAnnotations)
} }

View File

@ -106,10 +106,12 @@ func TestNameAsExternalName(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
api := NewNameAsExternalName(tc.client) api := NewNameAsExternalName(tc.client)
err := api.Initialize(tc.args.ctx, tc.args.mg) err := api.Initialize(tc.args.ctx, tc.args.mg)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff) t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.mg, tc.args.mg, test.EquateConditions()); diff != "" { if diff := cmp.Diff(tc.want.mg, tc.args.mg, test.EquateConditions()); diff != "" {
t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff) t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff)
} }
@ -144,6 +146,7 @@ func TestAPISecretPublisher(t *testing.T) {
err error err error
published bool published bool
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
fields fields fields fields
@ -223,10 +226,12 @@ func TestAPISecretPublisher(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
a := &APISecretPublisher{tc.fields.secret, tc.fields.typer} a := &APISecretPublisher{tc.fields.secret, tc.fields.typer}
got, gotErr := a.PublishConnection(tc.args.ctx, tc.args.mg, tc.args.c) got, gotErr := a.PublishConnection(tc.args.ctx, tc.args.mg, tc.args.c)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nPublish(...): -wantErr, +gotErr:\n%s", tc.reason, diff) t.Errorf("\n%s\nPublish(...): -wantErr, +gotErr:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.published, got); diff != "" { if diff := cmp.Diff(tc.want.published, got); diff != "" {
t.Errorf("\n%s\nPublish(...): -wantPublished, +gotPublished:\n%s", tc.reason, diff) t.Errorf("\n%s\nPublish(...): -wantPublished, +gotPublished:\n%s", tc.reason, diff)
} }
@ -347,6 +352,7 @@ func TestResolveReferences(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
r := NewAPISimpleReferenceResolver(tc.c) r := NewAPISimpleReferenceResolver(tc.c)
got := r.ResolveReferences(tc.args.ctx, tc.args.mg) got := r.ResolveReferences(tc.args.ctx, tc.args.mg)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nr.ResolveReferences(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nr.ResolveReferences(...): -want, +got:\n%s", tc.reason, diff)
@ -360,6 +366,7 @@ func TestPrepareJSONMerge(t *testing.T) {
existing runtime.Object existing runtime.Object
resolved runtime.Object resolved runtime.Object
} }
type want struct { type want struct {
patch string patch string
err error err error
@ -392,6 +399,7 @@ func TestPrepareJSONMerge(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nprepareJSONMerge(...): -wantErr, +gotErr:\n%s", tc.reason, diff) t.Errorf("\n%s\nprepareJSONMerge(...): -wantErr, +gotErr:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.patch, string(patch)); diff != "" { if diff := cmp.Diff(tc.want.patch, string(patch)); diff != "" {
t.Errorf("\n%s\nprepareJSONMerge(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nprepareJSONMerge(...): -want, +got:\n%s", tc.reason, diff)
} }
@ -406,6 +414,7 @@ func TestRetryingCriticalAnnotationUpdater(t *testing.T) {
ctx context.Context ctx context.Context
o client.Object o client.Object
} }
type want struct { type want struct {
err error err error
o client.Object o client.Object
@ -494,10 +503,12 @@ func TestRetryingCriticalAnnotationUpdater(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
u := NewRetryingCriticalAnnotationUpdater(tc.c) u := NewRetryingCriticalAnnotationUpdater(tc.c)
got := u.UpdateCriticalAnnotations(tc.args.ctx, tc.args.o) got := u.UpdateCriticalAnnotations(tc.args.ctx, tc.args.o)
if diff := cmp.Diff(tc.want.err, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, got, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nu.UpdateCriticalAnnotations(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nu.UpdateCriticalAnnotations(...): -want, +got:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" { if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" {
t.Errorf("\n%s\nu.UpdateCriticalAnnotations(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nu.UpdateCriticalAnnotations(...): -want, +got:\n%s", tc.reason, diff)
} }

View File

@ -119,6 +119,7 @@ func (g *GRPCChangeLogger) Log(ctx context.Context, managed resource.Managed, op
// send everything we've got to the change log service // send everything we've got to the change log service
_, err = g.client.SendChangeLog(sendCtx, &v1alpha1.SendChangeLogRequest{Entry: entry}, grpc.WaitForReady(true)) _, err = g.client.SendChangeLog(sendCtx, &v1alpha1.SendChangeLogRequest{Entry: entry}, grpc.WaitForReady(true))
return errors.Wrap(err, "cannot send change log entry") return errors.Wrap(err, "cannot send change log entry")
} }

View File

@ -52,6 +52,7 @@ func (c *changeLogServiceClient) SendChangeLog(ctx context.Context, in *v1alpha1
if c.sendFn != nil { if c.sendFn != nil {
return c.sendFn(ctx, in, opts...) return c.sendFn(ctx, in, opts...)
} }
return nil, nil return nil, nil
} }
@ -167,6 +168,7 @@ func mustObjectAsProtobufStruct(o runtime.Object) *structpb.Struct {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return s return s
} }
@ -183,6 +185,7 @@ func equateApproxTimepb(margin time.Duration) []cmp.Option {
a, b := p.Last().Values() a, b := p.Last().Values()
return msgIsTimestamp(a) && msgIsTimestamp(b) return msgIsTimestamp(a) && msgIsTimestamp(b)
} }
return false return false
}, },
cmp.Transformer("timestamppb", func(t protocmp.Message) time.Time { cmp.Transformer("timestamppb", func(t protocmp.Message) time.Time {

View File

@ -116,10 +116,12 @@ func (r *MRMetricRecorder) recordFirstTimeReconciled(managed resource.Managed) {
func (r *MRMetricRecorder) recordDrift(managed resource.Managed) { func (r *MRMetricRecorder) recordDrift(managed resource.Managed) {
name := managed.GetName() name := managed.GetName()
last, ok := r.lastObservation.Load(name) last, ok := r.lastObservation.Load(name)
if !ok { if !ok {
return return
} }
lt, ok := last.(time.Time) lt, ok := last.(time.Time)
if !ok { if !ok {
return return
@ -142,6 +144,7 @@ func (r *MRMetricRecorder) recordFirstTimeReady(managed resource.Managed) {
if !ok { if !ok {
return return
} }
r.mrFirstTimeReady.With(getLabels(managed)).Observe(time.Since(managed.GetCreationTimestamp().Time).Seconds()) r.mrFirstTimeReady.With(getLabels(managed)).Observe(time.Since(managed.GetCreationTimestamp().Time).Seconds())
r.firstObservation.Delete(managed.GetName()) r.firstObservation.Delete(managed.GetName())
} }

View File

@ -139,6 +139,7 @@ func (m *ManagementPoliciesResolver) Validate() error {
return nil return nil
} }
} }
return fmt.Errorf(errFmtManagementPolicyNotSupported, m.managementPolicies.UnsortedList()) return fmt.Errorf(errFmtManagementPolicyNotSupported, m.managementPolicies.UnsortedList())
} }
@ -148,6 +149,7 @@ func (m *ManagementPoliciesResolver) IsPaused() bool {
if !m.enabled { if !m.enabled {
return false return false
} }
return m.managementPolicies.Len() == 0 return m.managementPolicies.Len() == 0
} }
@ -157,6 +159,7 @@ func (m *ManagementPoliciesResolver) ShouldCreate() bool {
if !m.enabled { if !m.enabled {
return true return true
} }
return m.managementPolicies.HasAny(xpv1.ManagementActionCreate, xpv1.ManagementActionAll) return m.managementPolicies.HasAny(xpv1.ManagementActionCreate, xpv1.ManagementActionAll)
} }
@ -166,6 +169,7 @@ func (m *ManagementPoliciesResolver) ShouldUpdate() bool {
if !m.enabled { if !m.enabled {
return true return true
} }
return m.managementPolicies.HasAny(xpv1.ManagementActionUpdate, xpv1.ManagementActionAll) return m.managementPolicies.HasAny(xpv1.ManagementActionUpdate, xpv1.ManagementActionAll)
} }
@ -175,6 +179,7 @@ func (m *ManagementPoliciesResolver) ShouldLateInitialize() bool {
if !m.enabled { if !m.enabled {
return true return true
} }
return m.managementPolicies.HasAny(xpv1.ManagementActionLateInitialize, xpv1.ManagementActionAll) return m.managementPolicies.HasAny(xpv1.ManagementActionLateInitialize, xpv1.ManagementActionAll)
} }
@ -185,6 +190,7 @@ func (m *ManagementPoliciesResolver) ShouldOnlyObserve() bool {
if !m.enabled { if !m.enabled {
return false return false
} }
return m.managementPolicies.Equal(sets.New[xpv1.ManagementAction](xpv1.ManagementActionObserve)) return m.managementPolicies.Equal(sets.New[xpv1.ManagementAction](xpv1.ManagementActionObserve))
} }

View File

@ -32,15 +32,18 @@ type PublisherChain []ConnectionPublisher
// encounters, if any. // encounters, if any.
func (pc PublisherChain) PublishConnection(ctx context.Context, o resource.ConnectionSecretOwner, c ConnectionDetails) (bool, error) { func (pc PublisherChain) PublishConnection(ctx context.Context, o resource.ConnectionSecretOwner, c ConnectionDetails) (bool, error) {
published := false published := false
for _, p := range pc { for _, p := range pc {
pb, err := p.PublishConnection(ctx, o, c) pb, err := p.PublishConnection(ctx, o, c)
if err != nil { if err != nil {
return published, err return published, err
} }
if pb { if pb {
published = true published = true
} }
} }
return published, nil return published, nil
} }
@ -52,6 +55,7 @@ func (pc PublisherChain) UnpublishConnection(ctx context.Context, o resource.Con
return err return err
} }
} }
return nil return nil
} }
@ -65,6 +69,7 @@ func (m *DisabledSecretStoreManager) PublishConnection(_ context.Context, so res
if so.GetPublishConnectionDetailsTo() != nil { if so.GetPublishConnectionDetailsTo() != nil {
return false, errors.New(errSecretStoreDisabled) return false, errors.New(errSecretStoreDisabled)
} }
return false, nil return false, nil
} }
@ -74,5 +79,6 @@ func (m *DisabledSecretStoreManager) UnpublishConnection(_ context.Context, so r
if so.GetPublishConnectionDetailsTo() != nil { if so.GetPublishConnectionDetailsTo() != nil {
return errors.New(errSecretStoreDisabled) return errors.New(errSecretStoreDisabled)
} }
return nil return nil
} }

View File

@ -109,6 +109,7 @@ func TestPublisherChain(t *testing.T) {
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
t.Errorf("Publish(...): -want, +got:\n%s", diff) t.Errorf("Publish(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.published, got); diff != "" { if diff := cmp.Diff(tc.want.published, got); diff != "" {
t.Errorf("Publish(...): -wantPublished, +gotPublished:\n%s", diff) t.Errorf("Publish(...): -wantPublished, +gotPublished:\n%s", diff)
} }
@ -120,6 +121,7 @@ func TestDisabledSecretStorePublish(t *testing.T) {
type args struct { type args struct {
mg resource.Managed mg resource.Managed
} }
type want struct { type want struct {
published bool published bool
err error err error
@ -151,10 +153,12 @@ func TestDisabledSecretStorePublish(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ss := &DisabledSecretStoreManager{} ss := &DisabledSecretStoreManager{}
got, gotErr := ss.PublishConnection(context.Background(), tc.args.mg, nil) got, gotErr := ss.PublishConnection(context.Background(), tc.args.mg, nil)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
t.Errorf("Publish(...): -want, +got:\n%s", diff) t.Errorf("Publish(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.published, got); diff != "" { if diff := cmp.Diff(tc.want.published, got); diff != "" {
t.Errorf("Publish(...): -wantPublished, +gotPublished:\n%s", diff) t.Errorf("Publish(...): -wantPublished, +gotPublished:\n%s", diff)
} }
@ -166,6 +170,7 @@ func TestDisabledSecretStoreUnpublish(t *testing.T) {
type args struct { type args struct {
mg resource.Managed mg resource.Managed
} }
type want struct { type want struct {
err error err error
} }
@ -196,6 +201,7 @@ func TestDisabledSecretStoreUnpublish(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ss := &DisabledSecretStoreManager{} ss := &DisabledSecretStoreManager{}
gotErr := ss.UnpublishConnection(context.Background(), tc.args.mg, nil) gotErr := ss.UnpublishConnection(context.Background(), tc.args.mg, nil)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
t.Errorf("Publish(...): -want, +got:\n%s", diff) t.Errorf("Publish(...): -want, +got:\n%s", diff)

View File

@ -199,6 +199,7 @@ func (cc InitializerChain) Initialize(ctx context.Context, mg resource.Managed)
return err return err
} }
} }
return nil return nil
} }
@ -823,7 +824,6 @@ func NewReconciler(m manager.Manager, of resource.ManagedKind, o ...ReconcilerOp
func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (result reconcile.Result, err error) { //nolint:gocognit // See note below. func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (result reconcile.Result, err error) { //nolint:gocognit // See note below.
// NOTE(negz): This method is a well over our cyclomatic complexity goal. // NOTE(negz): This method is a well over our cyclomatic complexity goal.
// Be wary of adding additional complexity. // Be wary of adding additional complexity.
defer func() { result, err = errors.SilentlyRequeueOnConflict(result, err) }() defer func() { result, err = errors.SilentlyRequeueOnConflict(result, err) }()
log := r.log.WithValues("request", req) log := r.log.WithValues("request", req)
@ -886,11 +886,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// that is not supported by the controller. // that is not supported by the controller.
if err := policy.Validate(); err != nil { if err := policy.Validate(); err != nil {
log.Debug(err.Error()) log.Debug(err.Error())
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonManagementPolicyInvalid, err)) record.Event(managed, event.Warning(reasonManagementPolicyInvalid, err))
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -911,23 +914,30 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// condition. If not, we requeue explicitly, which will trigger // condition. If not, we requeue explicitly, which will trigger
// backoff. // backoff.
log.Debug("Cannot unpublish connection details", "error", err) log.Debug("Cannot unpublish connection details", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotUnpublish, err)) record.Event(managed, event.Warning(reasonCannotUnpublish, err))
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err)) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
if err := r.managed.RemoveFinalizer(ctx, managed); err != nil { if err := r.managed.RemoveFinalizer(ctx, managed); err != nil {
// If this is the first time we encounter this issue we'll be // If this is the first time we encounter this issue we'll be
// requeued implicitly when we update our status with the new error // requeued implicitly when we update our status with the new error
// condition. If not, we requeue explicitly, which will trigger // condition. If not, we requeue explicitly, which will trigger
// backoff. // backoff.
log.Debug("Cannot remove managed resource finalizer", "error", err) log.Debug("Cannot remove managed resource finalizer", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err)) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -937,6 +947,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// longer exist and thus there is no point trying to update its status. // longer exist and thus there is no point trying to update its status.
r.metricRecorder.recordDeleted(managed) r.metricRecorder.recordDeleted(managed)
log.Debug("Successfully deleted managed resource") log.Debug("Successfully deleted managed resource")
return reconcile.Result{Requeue: false}, nil return reconcile.Result{Requeue: false}, nil
} }
@ -945,11 +956,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// implicitly when we update our status with the new error condition. If // implicitly when we update our status with the new error condition. If
// not, we requeue explicitly, which will trigger backoff. // not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot initialize managed resource", "error", err) log.Debug("Cannot initialize managed resource", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotInitialize, err)) record.Event(managed, event.Warning(reasonCannotInitialize, err))
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -963,8 +977,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
log.Debug(errCreateIncomplete) log.Debug(errCreateIncomplete)
record.Event(managed, event.Warning(reasonCannotInitialize, errors.New(errCreateIncomplete))) record.Event(managed, event.Warning(reasonCannotInitialize, errors.New(errCreateIncomplete)))
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.New(errCreateIncomplete))) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.New(errCreateIncomplete)))
return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
log.Debug("Cannot determine creation result, but proceeding due to deterministic external name") log.Debug("Cannot determine creation result, but proceeding due to deterministic external name")
} }
@ -985,11 +1001,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// requeued implicitly due to the status update. If not, we want // requeued implicitly due to the status update. If not, we want
// requeue explicitly, which will trigger backoff. // requeue explicitly, which will trigger backoff.
log.Debug("Cannot resolve managed resource references", "error", err) log.Debug("Cannot resolve managed resource references", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotResolveRefs, err)) record.Event(managed, event.Warning(reasonCannotResolveRefs, err))
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
} }
@ -1002,13 +1021,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// condition. If not, we requeue explicitly, which will trigger // condition. If not, we requeue explicitly, which will trigger
// backoff. // backoff.
log.Debug("Cannot connect to provider", "error", err) log.Debug("Cannot connect to provider", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotConnect, err)) record.Event(managed, event.Warning(reasonCannotConnect, err))
status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileConnect))) status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileConnect)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
defer func() { defer func() {
if err := r.external.Disconnect(ctx); err != nil { if err := r.external.Disconnect(ctx); err != nil {
log.Debug("Cannot disconnect from provider", "error", err) log.Debug("Cannot disconnect from provider", "error", err)
@ -1030,11 +1053,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// error condition. If not, we requeue explicitly, which will // error condition. If not, we requeue explicitly, which will
// trigger backoff. // trigger backoff.
log.Debug("Cannot observe external resource", "error", err) log.Debug("Cannot observe external resource", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotObserve, err)) record.Event(managed, event.Warning(reasonCannotObserve, err))
status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileObserve))) status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileObserve)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1043,6 +1069,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
if !observation.ResourceExists && policy.ShouldOnlyObserve() { if !observation.ResourceExists && policy.ShouldOnlyObserve() {
record.Event(managed, event.Warning(reasonCannotObserve, errors.New(errExternalResourceNotExist))) record.Event(managed, event.Warning(reasonCannotObserve, errors.New(errExternalResourceNotExist)))
status.MarkConditions(xpv1.ReconcileError(errors.Wrap(errors.New(errExternalResourceNotExist), errReconcileObserve))) status.MarkConditions(xpv1.ReconcileError(errors.Wrap(errors.New(errExternalResourceNotExist), errReconcileObserve)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1054,6 +1081,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
if !observation.ResourceExists && meta.ExternalCreateSucceededDuring(managed, r.creationGracePeriod) { if !observation.ResourceExists && meta.ExternalCreateSucceededDuring(managed, r.creationGracePeriod) {
log.Debug("Waiting for external resource existence to be confirmed") log.Debug("Waiting for external resource existence to be confirmed")
record.Event(managed, event.Normal(reasonPending, "Waiting for external resource existence to be confirmed")) record.Event(managed, event.Normal(reasonPending, "Waiting for external resource existence to be confirmed"))
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
@ -1076,11 +1104,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// status with the new error condition. If not, we want requeue // status with the new error condition. If not, we want requeue
// explicitly, which will trigger backoff. // explicitly, which will trigger backoff.
log.Debug("Cannot delete external resource", "error", err) log.Debug("Cannot delete external resource", "error", err)
if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_DELETE, err, deletion.AdditionalDetails); err != nil { if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_DELETE, err, deletion.AdditionalDetails); err != nil {
log.Info(errRecordChangeLog, "error", err) log.Info(errRecordChangeLog, "error", err)
} }
record.Event(managed, event.Warning(reasonCannotDelete, err)) record.Event(managed, event.Warning(reasonCannotDelete, err))
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(errors.Wrap(err, errReconcileDelete))) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(errors.Wrap(err, errReconcileDelete)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1092,36 +1123,47 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// unpublish and finalize. If it still exists we'll re-enter this // unpublish and finalize. If it still exists we'll re-enter this
// block and try again. // block and try again.
log.Debug("Successfully requested deletion of external resource") log.Debug("Successfully requested deletion of external resource")
if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_DELETE, nil, deletion.AdditionalDetails); err != nil { if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_DELETE, nil, deletion.AdditionalDetails); err != nil {
log.Info(errRecordChangeLog, "error", err) log.Info(errRecordChangeLog, "error", err)
} }
record.Event(managed, event.Normal(reasonDeleted, "Successfully requested deletion of external resource")) record.Event(managed, event.Normal(reasonDeleted, "Successfully requested deletion of external resource"))
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileSuccess()) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileSuccess())
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
if err := r.managed.UnpublishConnection(ctx, managed, observation.ConnectionDetails); err != nil { if err := r.managed.UnpublishConnection(ctx, managed, observation.ConnectionDetails); err != nil {
// If this is the first time we encounter this issue we'll be // If this is the first time we encounter this issue we'll be
// requeued implicitly when we update our status with the new error // requeued implicitly when we update our status with the new error
// condition. If not, we requeue explicitly, which will trigger // condition. If not, we requeue explicitly, which will trigger
// backoff. // backoff.
log.Debug("Cannot unpublish connection details", "error", err) log.Debug("Cannot unpublish connection details", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotUnpublish, err)) record.Event(managed, event.Warning(reasonCannotUnpublish, err))
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err)) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
if err := r.managed.RemoveFinalizer(ctx, managed); err != nil { if err := r.managed.RemoveFinalizer(ctx, managed); err != nil {
// If this is the first time we encounter this issue we'll be // If this is the first time we encounter this issue we'll be
// requeued implicitly when we update our status with the new error // requeued implicitly when we update our status with the new error
// condition. If not, we requeue explicitly, which will trigger // condition. If not, we requeue explicitly, which will trigger
// backoff. // backoff.
log.Debug("Cannot remove managed resource finalizer", "error", err) log.Debug("Cannot remove managed resource finalizer", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err)) status.MarkConditions(xpv1.Deleting(), xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1131,6 +1173,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// thus there is no point trying to update its status. // thus there is no point trying to update its status.
r.metricRecorder.recordDeleted(managed) r.metricRecorder.recordDeleted(managed)
log.Debug("Successfully deleted managed resource") log.Debug("Successfully deleted managed resource")
return reconcile.Result{Requeue: false}, nil return reconcile.Result{Requeue: false}, nil
} }
@ -1139,11 +1182,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// implicitly when we update our status with the new error condition. If // implicitly when we update our status with the new error condition. If
// not, we requeue explicitly, which will trigger backoff. // not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot publish connection details", "error", err) log.Debug("Cannot publish connection details", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotPublish, err)) record.Event(managed, event.Warning(reasonCannotPublish, err))
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1152,10 +1198,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// implicitly when we update our status with the new error condition. If // implicitly when we update our status with the new error condition. If
// not, we requeue explicitly, which will trigger backoff. // not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot add finalizer", "error", err) log.Debug("Cannot add finalizer", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1168,13 +1217,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// don't use the CriticalAnnotationUpdater because we _want_ the // don't use the CriticalAnnotationUpdater because we _want_ the
// update to fail if we get a 409 due to a stale version. // update to fail if we get a 409 due to a stale version.
meta.SetExternalCreatePending(managed, time.Now()) meta.SetExternalCreatePending(managed, time.Now())
if err := r.client.Update(ctx, managed); err != nil { if err := r.client.Update(ctx, managed); err != nil {
log.Debug(errUpdateManaged, "error", err) log.Debug(errUpdateManaged, "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManaged))) record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManaged)))
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errUpdateManaged))) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errUpdateManaged)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1186,6 +1239,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// issue we'll be requeued implicitly when we update our status with // issue we'll be requeued implicitly when we update our status with
// the new error condition. If not, we requeue explicitly, which will trigger backoff. // the new error condition. If not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot create external resource", "error", err) log.Debug("Cannot create external resource", "error", err)
if !kerrors.IsConflict(err) { if !kerrors.IsConflict(err) {
record.Event(managed, event.Warning(reasonCannotCreate, err)) record.Event(managed, event.Warning(reasonCannotCreate, err))
} }
@ -1197,6 +1251,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// won't know whether or not it created an external // won't know whether or not it created an external
// resource. // resource.
meta.SetExternalCreateFailed(managed, time.Now()) meta.SetExternalCreateFailed(managed, time.Now())
if err := r.managed.UpdateCriticalAnnotations(ctx, managed); err != nil { if err := r.managed.UpdateCriticalAnnotations(ctx, managed); err != nil {
log.Debug(errUpdateManagedAnnotations, "error", err) log.Debug(errUpdateManagedAnnotations, "error", err)
record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManagedAnnotations))) record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManagedAnnotations)))
@ -1211,7 +1266,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_CREATE, err, creation.AdditionalDetails); err != nil { if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_CREATE, err, creation.AdditionalDetails); err != nil {
log.Info(errRecordChangeLog, "error", err) log.Info(errRecordChangeLog, "error", err)
} }
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errReconcileCreate))) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errReconcileCreate)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1234,13 +1291,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// Create implementations are advised not to alter status, but // Create implementations are advised not to alter status, but
// we may revisit this in future. // we may revisit this in future.
meta.SetExternalCreateSucceeded(managed, time.Now()) meta.SetExternalCreateSucceeded(managed, time.Now())
if err := r.managed.UpdateCriticalAnnotations(ctx, managed); err != nil { if err := r.managed.UpdateCriticalAnnotations(ctx, managed); err != nil {
log.Debug(errUpdateManagedAnnotations, "error", err) log.Debug(errUpdateManagedAnnotations, "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManagedAnnotations))) record.Event(managed, event.Warning(reasonCannotUpdateManaged, errors.Wrap(err, errUpdateManagedAnnotations)))
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errUpdateManagedAnnotations))) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(errors.Wrap(err, errUpdateManagedAnnotations)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1249,11 +1310,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// requeued implicitly when we update our status with the new error // requeued implicitly when we update our status with the new error
// condition. If not, we requeue explicitly, which will trigger backoff. // condition. If not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot publish connection details", "error", err) log.Debug("Cannot publish connection details", "error", err)
if kerrors.IsConflict(err) { if kerrors.IsConflict(err) {
return reconcile.Result{Requeue: true}, nil return reconcile.Result{Requeue: true}, nil
} }
record.Event(managed, event.Warning(reasonCannotPublish, err)) record.Event(managed, event.Warning(reasonCannotPublish, err))
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(err)) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1264,6 +1328,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
log.Debug("Successfully requested creation of external resource") log.Debug("Successfully requested creation of external resource")
record.Event(managed, event.Normal(reasonCreated, "Successfully requested creation of external resource")) record.Event(managed, event.Normal(reasonCreated, "Successfully requested creation of external resource"))
status.MarkConditions(xpv1.Creating(), xpv1.ReconcileSuccess()) status.MarkConditions(xpv1.Creating(), xpv1.ReconcileSuccess())
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1279,6 +1344,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
log.Debug(errUpdateManaged, "error", err) log.Debug(errUpdateManaged, "error", err)
record.Event(managed, event.Warning(reasonCannotUpdateManaged, err)) record.Event(managed, event.Warning(reasonCannotUpdateManaged, err))
status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errUpdateManaged))) status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errUpdateManaged)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
} }
@ -1313,6 +1379,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
reconcileAfter := r.pollIntervalHook(managed, r.pollInterval) reconcileAfter := r.pollIntervalHook(managed, r.pollInterval)
log.Debug("Skipping update due to managementPolicies. Reconciliation succeeded", "requeue-after", time.Now().Add(reconcileAfter)) log.Debug("Skipping update due to managementPolicies. Reconciliation succeeded", "requeue-after", time.Now().Add(reconcileAfter))
status.MarkConditions(xpv1.ReconcileSuccess()) status.MarkConditions(xpv1.ReconcileSuccess())
return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1324,16 +1391,20 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
// requeued implicitly when we update our status with the new error // requeued implicitly when we update our status with the new error
// condition. If not, we requeue explicitly, which will trigger backoff. // condition. If not, we requeue explicitly, which will trigger backoff.
log.Debug("Cannot update external resource") log.Debug("Cannot update external resource")
if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_UPDATE, err, update.AdditionalDetails); err != nil { if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_UPDATE, err, update.AdditionalDetails); err != nil {
log.Info(errRecordChangeLog, "error", err) log.Info(errRecordChangeLog, "error", err)
} }
record.Event(managed, event.Warning(reasonCannotUpdate, err)) record.Event(managed, event.Warning(reasonCannotUpdate, err))
status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileUpdate))) status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileUpdate)))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
// record the drift after the successful update. // record the drift after the successful update.
r.metricRecorder.recordDrift(managed) r.metricRecorder.recordDrift(managed)
if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_UPDATE, nil, update.AdditionalDetails); err != nil { if err := r.change.Log(ctx, managedPreOp, v1alpha1.OperationType_OPERATION_TYPE_UPDATE, nil, update.AdditionalDetails); err != nil {
log.Info(errRecordChangeLog, "error", err) log.Info(errRecordChangeLog, "error", err)
} }
@ -1345,6 +1416,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
log.Debug("Cannot publish connection details", "error", err) log.Debug("Cannot publish connection details", "error", err)
record.Event(managed, event.Warning(reasonCannotPublish, err)) record.Event(managed, event.Warning(reasonCannotPublish, err))
status.MarkConditions(xpv1.ReconcileError(err)) status.MarkConditions(xpv1.ReconcileError(err))
return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }
@ -1357,5 +1429,6 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu
log.Debug("Successfully requested update of external resource", "requeue-after", time.Now().Add(reconcileAfter)) log.Debug("Successfully requested update of external resource", "requeue-after", time.Now().Add(reconcileAfter))
record.Event(managed, event.Normal(reasonUpdated, "Successfully requested update of external resource")) record.Event(managed, event.Normal(reasonUpdated, "Successfully requested update of external resource"))
status.MarkConditions(xpv1.ReconcileSuccess()) status.MarkConditions(xpv1.ReconcileSuccess())
return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus)
} }

View File

@ -2020,8 +2020,8 @@ func TestReconciler(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
r := NewReconciler(tc.args.m, tc.args.mg, tc.args.o...) r := NewReconciler(tc.args.m, tc.args.mg, tc.args.o...)
got, err := r.Reconcile(context.Background(), reconcile.Request{})
got, err := r.Reconcile(context.Background(), reconcile.Request{})
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\nReason: %s\nr.Reconcile(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\nReason: %s\nr.Reconcile(...): -want error, +got error:\n%s", tc.reason, diff)
} }
@ -2038,6 +2038,7 @@ func TestTestManagementPoliciesResolverIsPaused(t *testing.T) {
enabled bool enabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2083,6 +2084,7 @@ func TestManagementPoliciesResolverValidate(t *testing.T) {
enabled bool enabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2144,6 +2146,7 @@ func TestManagementPoliciesResolverShouldCreate(t *testing.T) {
managementPoliciesEnabled bool managementPoliciesEnabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2196,6 +2199,7 @@ func TestManagementPoliciesResolverShouldUpdate(t *testing.T) {
managementPoliciesEnabled bool managementPoliciesEnabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2248,6 +2252,7 @@ func TestManagementPoliciesResolverShouldLateInitialize(t *testing.T) {
managementPoliciesEnabled bool managementPoliciesEnabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2300,6 +2305,7 @@ func TestManagementPoliciesResolverOnlyObserve(t *testing.T) {
managementPoliciesEnabled bool managementPoliciesEnabled bool
policy xpv1.ManagementPolicies policy xpv1.ManagementPolicies
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2344,9 +2350,11 @@ func TestShouldDelete(t *testing.T) {
managementPoliciesEnabled bool managementPoliciesEnabled bool
managed resource.Managed managed resource.Managed
} }
type want struct { type want struct {
delete bool delete bool
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args args args
@ -2747,12 +2755,14 @@ func TestReconcilerChangeLogs(t *testing.T) {
func asManaged(obj client.Object, generation int64) *fake.Managed { func asManaged(obj client.Object, generation int64) *fake.Managed {
mg := obj.(*fake.Managed) mg := obj.(*fake.Managed)
mg.Generation = generation mg.Generation = generation
return mg return mg
} }
func newManaged(generation int64) *fake.Managed { func newManaged(generation int64) *fake.Managed {
mg := &fake.Managed{} mg := &fake.Managed{}
mg.Generation = generation mg.Generation = generation
return mg return mg
} }

View File

@ -20,10 +20,12 @@ func (c *typedExternalConnectDisconnectorWrapper[managed]) Connect(ctx context.C
if !ok { if !ok {
return nil, errors.Errorf(errFmtUnexpectedObjectType, mg) return nil, errors.Errorf(errFmtUnexpectedObjectType, mg)
} }
external, err := c.c.Connect(ctx, cr) external, err := c.c.Connect(ctx, cr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &typedExternalClientWrapper[managed]{c: external}, nil return &typedExternalClientWrapper[managed]{c: external}, nil
} }
@ -42,6 +44,7 @@ func (c *typedExternalClientWrapper[managed]) Observe(ctx context.Context, mg re
if !ok { if !ok {
return ExternalObservation{}, errors.Errorf(errFmtUnexpectedObjectType, mg) return ExternalObservation{}, errors.Errorf(errFmtUnexpectedObjectType, mg)
} }
return c.c.Observe(ctx, cr) return c.c.Observe(ctx, cr)
} }
@ -50,6 +53,7 @@ func (c *typedExternalClientWrapper[managed]) Create(ctx context.Context, mg res
if !ok { if !ok {
return ExternalCreation{}, errors.Errorf(errFmtUnexpectedObjectType, mg) return ExternalCreation{}, errors.Errorf(errFmtUnexpectedObjectType, mg)
} }
return c.c.Create(ctx, cr) return c.c.Create(ctx, cr)
} }
@ -58,6 +62,7 @@ func (c *typedExternalClientWrapper[managed]) Update(ctx context.Context, mg res
if !ok { if !ok {
return ExternalUpdate{}, errors.Errorf(errFmtUnexpectedObjectType, mg) return ExternalUpdate{}, errors.Errorf(errFmtUnexpectedObjectType, mg)
} }
return c.c.Update(ctx, cr) return c.c.Update(ctx, cr)
} }
@ -66,6 +71,7 @@ func (c *typedExternalClientWrapper[managed]) Delete(ctx context.Context, mg res
if !ok { if !ok {
return ExternalDelete{}, errors.Errorf(errFmtUnexpectedObjectType, mg) return ExternalDelete{}, errors.Errorf(errFmtUnexpectedObjectType, mg)
} }
return c.c.Delete(ctx, cr) return c.c.Delete(ctx, cr)
} }

View File

@ -168,6 +168,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
if err := r.client.List(ctx, l, client.MatchingLabels{xpv1.LabelKeyProviderName: pc.GetName()}); err != nil { if err := r.client.List(ctx, l, client.MatchingLabels{xpv1.LabelKeyProviderName: pc.GetName()}); err != nil {
log.Debug(errListPCUs, "error", err) log.Debug(errListPCUs, "error", err)
r.record.Event(pc, event.Warning(reasonAccount, errors.Wrap(err, errListPCUs))) r.record.Event(pc, event.Warning(reasonAccount, errors.Wrap(err, errListPCUs)))
return reconcile.Result{RequeueAfter: shortWait}, nil return reconcile.Result{RequeueAfter: shortWait}, nil
} }
@ -181,11 +182,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
if err := r.client.Delete(ctx, pcu); resource.IgnoreNotFound(err) != nil { if err := r.client.Delete(ctx, pcu); resource.IgnoreNotFound(err) != nil {
log.Debug(errDeletePCU, "error", err) log.Debug(errDeletePCU, "error", err)
r.record.Event(pc, event.Warning(reasonAccount, errors.Wrap(err, errDeletePCU))) r.record.Event(pc, event.Warning(reasonAccount, errors.Wrap(err, errDeletePCU)))
return reconcile.Result{RequeueAfter: shortWait}, nil return reconcile.Result{RequeueAfter: shortWait}, nil
} }
users-- users--
} }
} }
log = log.WithValues("usages", users) log = log.WithValues("usages", users)
if meta.WasDeleted(pc) { if meta.WasDeleted(pc) {
@ -198,10 +202,12 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
// We're watching our usages, so we'll be requeued when they go. // We're watching our usages, so we'll be requeued when they go.
pc.SetUsers(users) pc.SetUsers(users)
pc.SetConditions(Terminating().WithMessage(msg)) pc.SetConditions(Terminating().WithMessage(msg))
return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, pc), errUpdateStatus) return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, pc), errUpdateStatus)
} }
meta.RemoveFinalizer(pc, finalizer) meta.RemoveFinalizer(pc, finalizer)
if err := r.client.Update(ctx, pc); err != nil { if err := r.client.Update(ctx, pc); err != nil {
r.log.Debug(errUpdate, "error", err) r.log.Debug(errUpdate, "error", err)
return reconcile.Result{RequeueAfter: shortWait}, nil return reconcile.Result{RequeueAfter: shortWait}, nil
@ -212,6 +218,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
} }
meta.AddFinalizer(pc, finalizer) meta.AddFinalizer(pc, finalizer)
if err := r.client.Update(ctx, pc); err != nil { if err := r.client.Update(ctx, pc); err != nil {
r.log.Debug(errUpdate, "error", err) r.log.Debug(errUpdate, "error", err)
return reconcile.Result{RequeueAfter: shortWait}, nil return reconcile.Result{RequeueAfter: shortWait}, nil
@ -219,5 +226,6 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
// There's no need to requeue explicitly - we're watching all PCs. // There's no need to requeue explicitly - we're watching all PCs.
pc.SetUsers(users) pc.SetUsers(users)
return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, pc), errUpdateStatus) return reconcile.Result{Requeue: false}, errors.Wrap(r.client.Status().Update(ctx, pc), errUpdateStatus)
} }

View File

@ -50,11 +50,14 @@ func (p *ProviderConfigUsageList) GetObjectKind() schema.ObjectKind {
func (p *ProviderConfigUsageList) DeepCopyObject() runtime.Object { func (p *ProviderConfigUsageList) DeepCopyObject() runtime.Object {
out := &ProviderConfigUsageList{} out := &ProviderConfigUsageList{}
j, err := json.Marshal(p) //nolint:musttag // We're just using this to round-trip convert. j, err := json.Marshal(p) //nolint:musttag // We're just using this to round-trip convert.
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) //nolint:musttag // We're just using this to round-trip convert. _ = json.Unmarshal(j, out) //nolint:musttag // We're just using this to round-trip convert.
return out return out
} }
@ -320,8 +323,8 @@ func TestReconciler(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
r := NewReconciler(tc.args.m, tc.args.of) r := NewReconciler(tc.args.m, tc.args.of)
got, err := r.Reconcile(context.Background(), reconcile.Request{})
got, err := r.Reconcile(context.Background(), reconcile.Request{})
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nr.Reconcile(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nr.Reconcile(...): -want error, +got error:\n%s", tc.reason, diff)
} }

View File

@ -51,6 +51,7 @@ func FromPtrValue(v *string) string {
if v == nil { if v == nil {
return "" return ""
} }
return *v return *v
} }
@ -59,6 +60,7 @@ func FromFloatPtrValue(v *float64) string {
if v == nil { if v == nil {
return "" return ""
} }
return strconv.FormatFloat(*v, 'f', 0, 64) return strconv.FormatFloat(*v, 'f', 0, 64)
} }
@ -67,6 +69,7 @@ func FromIntPtrValue(v *int64) string {
if v == nil { if v == nil {
return "" return ""
} }
return strconv.FormatInt(*v, 10) return strconv.FormatInt(*v, 10)
} }
@ -75,6 +78,7 @@ func ToPtrValue(v string) *string {
if v == "" { if v == "" {
return nil return nil
} }
return &v return &v
} }
@ -83,10 +87,12 @@ func ToFloatPtrValue(v string) *float64 {
if v == "" { if v == "" {
return nil return nil
} }
vParsed, err := strconv.ParseFloat(v, 64) vParsed, err := strconv.ParseFloat(v, 64)
if err != nil { if err != nil {
return nil return nil
} }
return &vParsed return &vParsed
} }
@ -95,10 +101,12 @@ func ToIntPtrValue(v string) *int64 {
if v == "" { if v == "" {
return nil return nil
} }
vParsed, err := strconv.ParseInt(v, 10, 64) vParsed, err := strconv.ParseInt(v, 10, 64)
if err != nil { if err != nil {
return nil return nil
} }
return &vParsed return &vParsed
} }
@ -112,6 +120,7 @@ func FromPtrValues(v []*string) []string {
for i := range v { for i := range v {
res[i] = FromPtrValue(v[i]) res[i] = FromPtrValue(v[i])
} }
return res return res
} }
@ -121,6 +130,7 @@ func FromFloatPtrValues(v []*float64) []string {
for i := range v { for i := range v {
res[i] = FromFloatPtrValue(v[i]) res[i] = FromFloatPtrValue(v[i])
} }
return res return res
} }
@ -130,6 +140,7 @@ func FromIntPtrValues(v []*int64) []string {
for i := range v { for i := range v {
res[i] = FromIntPtrValue(v[i]) res[i] = FromIntPtrValue(v[i])
} }
return res return res
} }
@ -143,6 +154,7 @@ func ToPtrValues(v []string) []*string {
for i := range v { for i := range v {
res[i] = ToPtrValue(v[i]) res[i] = ToPtrValue(v[i])
} }
return res return res
} }
@ -152,6 +164,7 @@ func ToFloatPtrValues(v []string) []*float64 {
for i := range v { for i := range v {
res[i] = ToFloatPtrValue(v[i]) res[i] = ToFloatPtrValue(v[i])
} }
return res return res
} }
@ -161,6 +174,7 @@ func ToIntPtrValues(v []string) []*int64 {
for i := range v { for i := range v {
res[i] = ToIntPtrValue(v[i]) res[i] = ToIntPtrValue(v[i])
} }
return res return res
} }
@ -197,6 +211,7 @@ type ResolutionRequest struct {
// processed. // processed.
func (rr *ResolutionRequest) IsNoOp() bool { func (rr *ResolutionRequest) IsNoOp() bool {
isAlways := false isAlways := false
if rr.Selector != nil { if rr.Selector != nil {
if rr.Selector.Policy.IsResolvePolicyAlways() { if rr.Selector.Policy.IsResolvePolicyAlways() {
rr.Reference = nil rr.Reference = nil
@ -252,6 +267,7 @@ type MultiResolutionRequest struct {
// not be processed. // not be processed.
func (rr *MultiResolutionRequest) IsNoOp() bool { func (rr *MultiResolutionRequest) IsNoOp() bool {
isAlways := false isAlways := false
if rr.Selector != nil { if rr.Selector != nil {
if rr.Selector.Policy.IsResolvePolicyAlways() { if rr.Selector.Policy.IsResolvePolicyAlways() {
rr.References = nil rr.References = nil
@ -331,10 +347,12 @@ func (r *APIResolver) Resolve(ctx context.Context, req ResolutionRequest) (Resol
if kerrors.IsNotFound(err) { if kerrors.IsNotFound(err) {
return ResolutionResponse{}, getResolutionError(req.Reference.Policy, errors.Wrap(err, errGetManaged)) return ResolutionResponse{}, getResolutionError(req.Reference.Policy, errors.Wrap(err, errGetManaged))
} }
return ResolutionResponse{}, errors.Wrap(err, errGetManaged) return ResolutionResponse{}, errors.Wrap(err, errGetManaged)
} }
rsp := ResolutionResponse{ResolvedValue: req.Extract(req.To.Managed), ResolvedReference: req.Reference} rsp := ResolutionResponse{ResolvedValue: req.Extract(req.To.Managed), ResolvedReference: req.Reference}
return rsp, getResolutionError(req.Reference.Policy, rsp.Validate()) return rsp, getResolutionError(req.Reference.Policy, rsp.Validate())
} }
@ -350,6 +368,7 @@ func (r *APIResolver) Resolve(ctx context.Context, req ResolutionRequest) (Resol
} }
rsp := ResolutionResponse{ResolvedValue: req.Extract(to), ResolvedReference: &xpv1.Reference{Name: to.GetName()}} rsp := ResolutionResponse{ResolvedValue: req.Extract(to), ResolvedReference: &xpv1.Reference{Name: to.GetName()}}
return rsp, getResolutionError(req.Selector.Policy, rsp.Validate()) return rsp, getResolutionError(req.Selector.Policy, rsp.Validate())
} }
@ -375,14 +394,17 @@ func (r *APIResolver) ResolveMultiple(ctx context.Context, req MultiResolutionRe
if kerrors.IsNotFound(err) { if kerrors.IsNotFound(err) {
return MultiResolutionResponse{}, getResolutionError(req.References[i].Policy, errors.Wrap(err, errGetManaged)) return MultiResolutionResponse{}, getResolutionError(req.References[i].Policy, errors.Wrap(err, errGetManaged))
} }
return MultiResolutionResponse{}, errors.Wrap(err, errGetManaged) return MultiResolutionResponse{}, errors.Wrap(err, errGetManaged)
} }
valueMap[req.Extract(req.To.Managed)] = req.References[i] valueMap[req.Extract(req.To.Managed)] = req.References[i]
} }
sortedKeys, sortedRefs := sortMapByKeys(valueMap) sortedKeys, sortedRefs := sortMapByKeys(valueMap)
rsp := MultiResolutionResponse{ResolvedValues: sortedKeys, ResolvedReferences: sortedRefs} rsp := MultiResolutionResponse{ResolvedValues: sortedKeys, ResolvedReferences: sortedRefs}
return rsp, rsp.Validate() return rsp, rsp.Validate()
} }
@ -403,6 +425,7 @@ func (r *APIResolver) ResolveMultiple(ctx context.Context, req MultiResolutionRe
sortedKeys, sortedRefs := sortMapByKeys(valueMap) sortedKeys, sortedRefs := sortMapByKeys(valueMap)
rsp := MultiResolutionResponse{ResolvedValues: sortedKeys, ResolvedReferences: sortedRefs} rsp := MultiResolutionResponse{ResolvedValues: sortedKeys, ResolvedReferences: sortedRefs}
return rsp, getResolutionError(req.Selector.Policy, rsp.Validate()) return rsp, getResolutionError(req.Selector.Policy, rsp.Validate())
} }
@ -410,15 +433,18 @@ func getResolutionError(p *xpv1.Policy, err error) error {
if !p.IsResolutionPolicyOptional() { if !p.IsResolutionPolicyOptional() {
return err return err
} }
return nil return nil
} }
func sortMapByKeys(m map[string]xpv1.Reference) ([]string, []xpv1.Reference) { func sortMapByKeys(m map[string]xpv1.Reference) ([]string, []xpv1.Reference) {
keys := slices.Sorted(maps.Keys(m)) keys := slices.Sorted(maps.Keys(m))
values := make([]xpv1.Reference, 0, len(keys)) values := make([]xpv1.Reference, 0, len(keys))
for _, k := range keys { for _, k := range keys {
values = append(values, m[k]) values = append(values, m[k])
} }
return keys, values return keys, values
} }
@ -429,5 +455,6 @@ func ControllersMustMatch(s *xpv1.Selector) bool {
if s == nil { if s == nil {
return false return false
} }
return s.MatchControllerRef != nil && *s.MatchControllerRef return s.MatchControllerRef != nil && *s.MatchControllerRef
} }

View File

@ -157,10 +157,12 @@ func TestResolve(t *testing.T) {
ctx context.Context ctx context.Context
req ResolutionRequest req ResolutionRequest
} }
type want struct { type want struct {
rsp ResolutionResponse rsp ResolutionResponse
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
c client.Reader c client.Reader
@ -494,10 +496,12 @@ func TestResolve(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
r := NewAPIResolver(tc.c, tc.from) r := NewAPIResolver(tc.c, tc.from)
got, err := r.Resolve(tc.args.ctx, tc.args.req) got, err := r.Resolve(tc.args.ctx, tc.args.req)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nControllersMustMatch(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nControllersMustMatch(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.rsp, got); diff != "" { if diff := cmp.Diff(tc.want.rsp, got); diff != "" {
t.Errorf("\n%s\nControllersMustMatch(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nControllersMustMatch(...): -want, +got:\n%s", tc.reason, diff)
} }
@ -530,10 +534,12 @@ func TestResolveMultiple(t *testing.T) {
ctx context.Context ctx context.Context
req MultiResolutionRequest req MultiResolutionRequest
} }
type want struct { type want struct {
rsp MultiResolutionResponse rsp MultiResolutionResponse
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
c client.Reader c client.Reader
@ -899,10 +905,12 @@ func TestResolveMultiple(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
r := NewAPIResolver(tc.c, tc.from) r := NewAPIResolver(tc.c, tc.from)
got, err := r.ResolveMultiple(tc.args.ctx, tc.args.req) got, err := r.ResolveMultiple(tc.args.ctx, tc.args.req)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nControllersMustMatch(...): -want error, +got error:\n%s", tc.reason, diff) t.Errorf("\n%s\nControllersMustMatch(...): -want error, +got error:\n%s", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.rsp, got, cmpopts.EquateEmpty()); diff != "" { if diff := cmp.Diff(tc.want.rsp, got, cmpopts.EquateEmpty()); diff != "" {
t.Errorf("\n%s\nControllersMustMatch(...): -want, +got:\n%s", tc.reason, diff) t.Errorf("\n%s\nControllersMustMatch(...): -want, +got:\n%s", tc.reason, diff)
} }

View File

@ -67,6 +67,7 @@ func (a *APIPatchingApplicator) Apply(ctx context.Context, o client.Object, ao .
// TODO(negz): Apply ApplyOptions here too? // TODO(negz): Apply ApplyOptions here too?
return errors.Wrap(a.client.Create(ctx, o), "cannot create object") return errors.Wrap(a.client.Create(ctx, o), "cannot create object")
} }
if err != nil { if err != nil {
return errors.Wrap(err, "cannot get object") return errors.Wrap(err, "cannot get object")
} }
@ -118,6 +119,7 @@ func (a *APIUpdatingApplicator) Apply(ctx context.Context, o client.Object, ao .
// TODO(negz): Apply ApplyOptions here too? // TODO(negz): Apply ApplyOptions here too?
return errors.Wrap(a.client.Create(ctx, m), "cannot create object") return errors.Wrap(a.client.Create(ctx, m), "cannot create object")
} }
if err != nil { if err != nil {
return errors.Wrap(err, "cannot get object") return errors.Wrap(err, "cannot get object")
} }
@ -131,6 +133,7 @@ func (a *APIUpdatingApplicator) Apply(ctx context.Context, o client.Object, ao .
// NOTE(hasheddan): we must set the resource version of the desired object // NOTE(hasheddan): we must set the resource version of the desired object
// to that of the current or the update will always fail. // to that of the current or the update will always fail.
m.SetResourceVersion(current.GetResourceVersion()) m.SetResourceVersion(current.GetResourceVersion())
return errors.Wrap(a.client.Update(ctx, m), "cannot update object") return errors.Wrap(a.client.Update(ctx, m), "cannot update object")
} }
@ -163,7 +166,9 @@ func (a *APIFinalizer) AddFinalizer(ctx context.Context, obj Object) error {
if meta.FinalizerExists(obj, a.finalizer) { if meta.FinalizerExists(obj, a.finalizer) {
return nil return nil
} }
meta.AddFinalizer(obj, a.finalizer) meta.AddFinalizer(obj, a.finalizer)
return errors.Wrap(a.client.Update(ctx, obj), errUpdateObject) return errors.Wrap(a.client.Update(ctx, obj), errUpdateObject)
} }
@ -172,7 +177,9 @@ func (a *APIFinalizer) RemoveFinalizer(ctx context.Context, obj Object) error {
if !meta.FinalizerExists(obj, a.finalizer) { if !meta.FinalizerExists(obj, a.finalizer) {
return nil return nil
} }
meta.RemoveFinalizer(obj, a.finalizer) meta.RemoveFinalizer(obj, a.finalizer)
return errors.Wrap(IgnoreNotFound(a.client.Update(ctx, obj)), errUpdateObject) return errors.Wrap(IgnoreNotFound(a.client.Update(ctx, obj)), errUpdateObject)
} }

View File

@ -142,10 +142,12 @@ func TestAPIPatchingApplicator(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
a := NewAPIPatchingApplicator(tc.c) a := NewAPIPatchingApplicator(tc.c)
err := a.Apply(tc.args.ctx, tc.args.o, tc.args.ao...) err := a.Apply(tc.args.ctx, tc.args.o, tc.args.ao...)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nApply(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nApply(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" { if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" {
t.Errorf("\n%s\nApply(...): -want, +got\n%s\n", tc.reason, diff) t.Errorf("\n%s\nApply(...): -want, +got\n%s\n", tc.reason, diff)
} }
@ -157,6 +159,7 @@ func TestAPIUpdatingApplicator(t *testing.T) {
errBoom := errors.New("boom") errBoom := errors.New("boom")
desired := &object{} desired := &object{}
desired.SetName("desired") desired.SetName("desired")
current := &object{} current := &object{}
current.SetName("current") current.SetName("current")
@ -270,10 +273,12 @@ func TestAPIUpdatingApplicator(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
a := NewAPIUpdatingApplicator(tc.c) a := NewAPIUpdatingApplicator(tc.c)
err := a.Apply(tc.args.ctx, tc.args.o, tc.args.ao...) err := a.Apply(tc.args.ctx, tc.args.o, tc.args.ao...)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nApply(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nApply(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" { if diff := cmp.Diff(tc.want.o, tc.args.o); diff != "" {
t.Errorf("\n%s\nApply(...): -want, +got\n%s\n", tc.reason, diff) t.Errorf("\n%s\nApply(...): -want, +got\n%s\n", tc.reason, diff)
} }
@ -328,10 +333,12 @@ func TestManagedRemoveFinalizer(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
api := NewAPIFinalizer(tc.client, finalizer) api := NewAPIFinalizer(tc.client, finalizer)
err := api.RemoveFinalizer(tc.args.ctx, tc.args.obj) err := api.RemoveFinalizer(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("api.RemoveFinalizer(...): -want error, +got error:\n%s", diff) t.Errorf("api.RemoveFinalizer(...): -want error, +got error:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" { if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" {
t.Errorf("api.RemoveFinalizer(...) Managed: -want, +got:\n%s", diff) t.Errorf("api.RemoveFinalizer(...) Managed: -want, +got:\n%s", diff)
} }
@ -386,10 +393,12 @@ func TestAPIFinalizerAdder(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
api := NewAPIFinalizer(tc.client, finalizer) api := NewAPIFinalizer(tc.client, finalizer)
err := api.AddFinalizer(tc.args.ctx, tc.args.obj) err := api.AddFinalizer(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff) t.Errorf("api.Initialize(...): -want error, +got error:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" { if diff := cmp.Diff(tc.want.obj, tc.args.obj, test.EquateConditions()); diff != "" {
t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff) t.Errorf("api.Initialize(...) Managed: -want, +got:\n%s", diff)
} }

View File

@ -315,11 +315,14 @@ func (o *Object) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (o *Object) DeepCopyObject() runtime.Object { func (o *Object) DeepCopyObject() runtime.Object {
out := &Object{} out := &Object{}
j, err := json.Marshal(o) j, err := json.Marshal(o)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -342,11 +345,14 @@ func (m *Managed) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *Managed) DeepCopyObject() runtime.Object { func (m *Managed) DeepCopyObject() runtime.Object {
out := &Managed{} out := &Managed{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -376,11 +382,14 @@ func (m *Composite) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *Composite) DeepCopyObject() runtime.Object { func (m *Composite) DeepCopyObject() runtime.Object {
out := &Composite{} out := &Composite{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -400,11 +409,14 @@ func (m *Composed) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *Composed) DeepCopyObject() runtime.Object { func (m *Composed) DeepCopyObject() runtime.Object {
out := &Composed{} out := &Composed{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -433,11 +445,14 @@ func (m *CompositeClaim) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *CompositeClaim) DeepCopyObject() runtime.Object { func (m *CompositeClaim) DeepCopyObject() runtime.Object {
out := &CompositeClaim{} out := &CompositeClaim{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -457,6 +472,7 @@ type Manager struct {
func (m *Manager) Elected() <-chan struct{} { func (m *Manager) Elected() <-chan struct{} {
e := make(chan struct{}) e := make(chan struct{})
close(e) close(e)
return e return e
} }
@ -490,6 +506,7 @@ func GVK(o runtime.Object) schema.GroupVersionKind {
func SchemeWith(o ...runtime.Object) *runtime.Scheme { func SchemeWith(o ...runtime.Object) *runtime.Scheme {
s := runtime.NewScheme() s := runtime.NewScheme()
s.AddKnownTypes(GV, o...) s.AddKnownTypes(GV, o...)
return s return s
} }
@ -531,11 +548,14 @@ func (m *MockConnectionSecretOwner) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *MockConnectionSecretOwner) DeepCopyObject() runtime.Object { func (m *MockConnectionSecretOwner) DeepCopyObject() runtime.Object {
out := &MockConnectionSecretOwner{} out := &MockConnectionSecretOwner{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -577,11 +597,14 @@ func (m *MockLocalConnectionSecretOwner) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (m *MockLocalConnectionSecretOwner) DeepCopyObject() runtime.Object { func (m *MockLocalConnectionSecretOwner) DeepCopyObject() runtime.Object {
out := &MockLocalConnectionSecretOwner{} out := &MockLocalConnectionSecretOwner{}
j, err := json.Marshal(m) j, err := json.Marshal(m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -601,11 +624,14 @@ func (p *ProviderConfig) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (p *ProviderConfig) DeepCopyObject() runtime.Object { func (p *ProviderConfig) DeepCopyObject() runtime.Object {
out := &ProviderConfig{} out := &ProviderConfig{}
j, err := json.Marshal(p) j, err := json.Marshal(p)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -626,10 +652,13 @@ func (p *ProviderConfigUsage) GetObjectKind() schema.ObjectKind {
// DeepCopyObject returns a copy of the object as runtime.Object. // DeepCopyObject returns a copy of the object as runtime.Object.
func (p *ProviderConfigUsage) DeepCopyObject() runtime.Object { func (p *ProviderConfigUsage) DeepCopyObject() runtime.Object {
out := &ProviderConfigUsage{} out := &ProviderConfigUsage{}
j, err := json.Marshal(p) j, err := json.Marshal(p)
if err != nil { if err != nil {
panic(err) panic(err)
} }
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }

View File

@ -52,7 +52,9 @@ func (li *LateInitializer) LateInitializeStringPtr(org *string, from *string) *s
if org != nil || from == nil { if org != nil || from == nil {
return org return org
} }
li.SetChanged() li.SetChanged()
return from return from
} }
@ -61,7 +63,9 @@ func (li *LateInitializer) LateInitializeInt64Ptr(org *int64, from *int64) *int6
if org != nil || from == nil { if org != nil || from == nil {
return org return org
} }
li.SetChanged() li.SetChanged()
return from return from
} }
@ -70,7 +74,9 @@ func (li *LateInitializer) LateInitializeBoolPtr(org *bool, from *bool) *bool {
if org != nil || from == nil { if org != nil || from == nil {
return org return org
} }
li.SetChanged() li.SetChanged()
return from return from
} }
@ -80,7 +86,10 @@ func (li *LateInitializer) LateInitializeTimePtr(org *metav1.Time, from *time.Ti
if org != nil || from == nil { if org != nil || from == nil {
return org return org
} }
li.SetChanged() li.SetChanged()
t := metav1.NewTime(*from) t := metav1.NewTime(*from)
return &t return &t
} }

View File

@ -27,14 +27,17 @@ import (
func TestLateInitializeStringPtr(t *testing.T) { func TestLateInitializeStringPtr(t *testing.T) {
s1 := "desired" s1 := "desired"
s2 := "observed" s2 := "observed"
type args struct { type args struct {
org *string org *string
from *string from *string
} }
type want struct { type want struct {
result *string result *string
changed bool changed bool
} }
cases := map[string]struct { cases := map[string]struct {
args args
want want
@ -74,11 +77,13 @@ func TestLateInitializeStringPtr(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
li := NewLateInitializer() li := NewLateInitializer()
got := li.LateInitializeStringPtr(tc.org, tc.from) got := li.LateInitializeStringPtr(tc.org, tc.from)
if diff := cmp.Diff(tc.want.result, got); diff != "" { if diff := cmp.Diff(tc.result, got); diff != "" {
t.Errorf("LateInitializeStringPtr(...): -want, +got:\n%s", diff) t.Errorf("LateInitializeStringPtr(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.changed, li.IsChanged()); diff != "" {
if diff := cmp.Diff(tc.changed, li.IsChanged()); diff != "" {
t.Errorf("IsChanged(...): -want, +got:\n%s", diff) t.Errorf("IsChanged(...): -want, +got:\n%s", diff)
} }
}) })
@ -88,14 +93,17 @@ func TestLateInitializeStringPtr(t *testing.T) {
func TestLateInitializeInt64Ptr(t *testing.T) { func TestLateInitializeInt64Ptr(t *testing.T) {
i1 := int64(10) i1 := int64(10)
i2 := int64(20) i2 := int64(20)
type args struct { type args struct {
org *int64 org *int64
from *int64 from *int64
} }
type want struct { type want struct {
result *int64 result *int64
changed bool changed bool
} }
cases := map[string]struct { cases := map[string]struct {
args args
want want
@ -135,11 +143,13 @@ func TestLateInitializeInt64Ptr(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
li := NewLateInitializer() li := NewLateInitializer()
got := li.LateInitializeInt64Ptr(tc.org, tc.from) got := li.LateInitializeInt64Ptr(tc.org, tc.from)
if diff := cmp.Diff(tc.want.result, got); diff != "" { if diff := cmp.Diff(tc.result, got); diff != "" {
t.Errorf("LateInitializeBoolPtr(...): -want, +got:\n%s", diff) t.Errorf("LateInitializeBoolPtr(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.changed, li.IsChanged()); diff != "" {
if diff := cmp.Diff(tc.changed, li.IsChanged()); diff != "" {
t.Errorf("IsChanged(...): -want, +got:\n%s", diff) t.Errorf("IsChanged(...): -want, +got:\n%s", diff)
} }
}) })
@ -149,14 +159,17 @@ func TestLateInitializeInt64Ptr(t *testing.T) {
func TestLateInitializeBoolPtr(t *testing.T) { func TestLateInitializeBoolPtr(t *testing.T) {
trueVal := true trueVal := true
falseVal := false falseVal := false
type args struct { type args struct {
org *bool org *bool
from *bool from *bool
} }
type want struct { type want struct {
result *bool result *bool
changed bool changed bool
} }
cases := map[string]struct { cases := map[string]struct {
args args
want want
@ -196,11 +209,13 @@ func TestLateInitializeBoolPtr(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
li := NewLateInitializer() li := NewLateInitializer()
got := li.LateInitializeBoolPtr(tc.org, tc.from) got := li.LateInitializeBoolPtr(tc.org, tc.from)
if diff := cmp.Diff(tc.want.result, got); diff != "" { if diff := cmp.Diff(tc.result, got); diff != "" {
t.Errorf("LateInitializeBoolPtr(...): -want, +got:\n%s", diff) t.Errorf("LateInitializeBoolPtr(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.changed, li.IsChanged()); diff != "" {
if diff := cmp.Diff(tc.changed, li.IsChanged()); diff != "" {
t.Errorf("IsChanged(...): -want, +got:\n%s", diff) t.Errorf("IsChanged(...): -want, +got:\n%s", diff)
} }
}) })
@ -211,14 +226,17 @@ func TestLateInitializeTimePtr(t *testing.T) {
t1 := metav1.Now() t1 := metav1.Now()
t2 := time.Now().Add(time.Minute) t2 := time.Now().Add(time.Minute)
t2m := metav1.NewTime(t2) t2m := metav1.NewTime(t2)
type args struct { type args struct {
org *metav1.Time org *metav1.Time
from *time.Time from *time.Time
} }
type want struct { type want struct {
result *metav1.Time result *metav1.Time
changed bool changed bool
} }
cases := map[string]struct { cases := map[string]struct {
args args
want want
@ -258,11 +276,13 @@ func TestLateInitializeTimePtr(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
li := NewLateInitializer() li := NewLateInitializer()
got := li.LateInitializeTimePtr(tc.org, tc.from) got := li.LateInitializeTimePtr(tc.org, tc.from)
if diff := cmp.Diff(tc.want.result, got); diff != "" { if diff := cmp.Diff(tc.result, got); diff != "" {
t.Errorf("LateInitializeTimePtr(...): -want, +got:\n%s", diff) t.Errorf("LateInitializeTimePtr(...): -want, +got:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.changed, li.IsChanged()); diff != "" {
if diff := cmp.Diff(tc.changed, li.IsChanged()); diff != "" {
t.Errorf("IsChanged(...): -want, +got:\n%s", diff) t.Errorf("IsChanged(...): -want, +got:\n%s", diff)
} }
}) })

View File

@ -72,6 +72,7 @@ func DesiredStateChanged() predicate.Predicate {
// being able to ignore certain annotations. // being able to ignore certain annotations.
type AnnotationChangedPredicate struct { type AnnotationChangedPredicate struct {
predicate.Funcs predicate.Funcs
ignored []string ignored []string
} }
@ -80,6 +81,7 @@ func copyAnnotations(an map[string]string) map[string]string {
for k, v := range an { for k, v := range an {
r[k] = v r[k] = v
} }
return r return r
} }
@ -89,6 +91,7 @@ func (a AnnotationChangedPredicate) Update(e event.UpdateEvent) bool {
// Update event has no old object to update // Update event has no old object to update
return false return false
} }
if e.ObjectNew == nil { if e.ObjectNew == nil {
// Update event has no new object for update // Update event has no new object for update
return false return false

View File

@ -34,9 +34,11 @@ func TestDesiredStateChanged(t *testing.T) {
old client.Object old client.Object
new client.Object new client.Object
} }
type want struct { type want struct {
desiredStateChanged bool desiredStateChanged bool
} }
cases := map[string]struct { cases := map[string]struct {
args args
want want
@ -142,11 +144,11 @@ func TestDesiredStateChanged(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
got := DesiredStateChanged().Update(event.UpdateEvent{ got := DesiredStateChanged().Update(event.UpdateEvent{
ObjectOld: tc.args.old, ObjectOld: tc.old,
ObjectNew: tc.args.new, ObjectNew: tc.new,
}) })
if diff := cmp.Diff(tc.want.desiredStateChanged, got); diff != "" { if diff := cmp.Diff(tc.desiredStateChanged, got); diff != "" {
t.Errorf("DesiredStateChanged(...): -want, +got:\n%s", diff) t.Errorf("DesiredStateChanged(...): -want, +got:\n%s", diff)
} }
}) })

View File

@ -52,6 +52,7 @@ func IsMissingReference(err error) bool {
_, ok := err.(interface { _, ok := err.(interface {
MissingReference() bool MissingReference() bool
}) })
return ok return ok
} }
@ -63,6 +64,7 @@ func ExtractEnv(_ context.Context, e EnvLookupFn, s xpv1.CommonCredentialSelecto
if s.Env == nil { if s.Env == nil {
return nil, errors.New(errExtractEnv) return nil, errors.New(errExtractEnv)
} }
return []byte(e(s.Env.Name)), nil return []byte(e(s.Env.Name)), nil
} }
@ -71,6 +73,7 @@ func ExtractFs(_ context.Context, fs afero.Fs, s xpv1.CommonCredentialSelectors)
if s.Fs == nil { if s.Fs == nil {
return nil, errors.New(errExtractFs) return nil, errors.New(errExtractFs)
} }
return afero.ReadFile(fs, s.Fs.Path) return afero.ReadFile(fs, s.Fs.Path)
} }
@ -79,10 +82,12 @@ func ExtractSecret(ctx context.Context, client client.Client, s xpv1.CommonCrede
if s.SecretRef == nil { if s.SecretRef == nil {
return nil, errors.New(errExtractSecretKey) return nil, errors.New(errExtractSecretKey)
} }
secret := &corev1.Secret{} secret := &corev1.Secret{}
if err := client.Get(ctx, types.NamespacedName{Namespace: s.SecretRef.Namespace, Name: s.SecretRef.Name}, secret); err != nil { if err := client.Get(ctx, types.NamespacedName{Namespace: s.SecretRef.Namespace, Name: s.SecretRef.Name}, secret); err != nil {
return nil, errors.Wrap(err, errGetCredentialsSecret) return nil, errors.Wrap(err, errGetCredentialsSecret)
} }
return secret.Data[s.SecretRef.Key], nil return secret.Data[s.SecretRef.Key], nil
} }
@ -141,6 +146,7 @@ func (u *ProviderConfigUsageTracker) Track(ctx context.Context, mg Managed) erro
//nolint:forcetypeassert // Will always be a PCU. //nolint:forcetypeassert // Will always be a PCU.
pcu := u.of.DeepCopyObject().(ProviderConfigUsage) pcu := u.of.DeepCopyObject().(ProviderConfigUsage)
gvk := mg.GetObjectKind().GroupVersionKind() gvk := mg.GetObjectKind().GroupVersionKind()
ref := mg.GetProviderConfigReference() ref := mg.GetProviderConfigReference()
if ref == nil { if ref == nil {
return missingRefError{errors.New(errMissingPCRef)} return missingRefError{errors.New(errMissingPCRef)}
@ -163,5 +169,6 @@ func (u *ProviderConfigUsageTracker) Track(ctx context.Context, mg Managed) erro
return current.(ProviderConfigUsage).GetProviderConfigReference() != pcu.GetProviderConfigReference() return current.(ProviderConfigUsage).GetProviderConfigReference() != pcu.GetProviderConfigReference()
}), }),
) )
return errors.Wrap(Ignore(IsNotAllowed, err), errApplyPCU) return errors.Wrap(Ignore(IsNotAllowed, err), errApplyPCU)
} }

View File

@ -79,6 +79,7 @@ func TestExtractEnv(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\npc.ExtractEnv(...): -want error, +got error:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractEnv(...): -want error, +got error:\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.b, got); diff != "" { if diff := cmp.Diff(tc.want.b, got); diff != "" {
t.Errorf("\n%s\npc.ExtractEnv(...): -want, +got:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractEnv(...): -want, +got:\n%s\n", tc.reason, diff)
} }
@ -138,6 +139,7 @@ func TestExtractFs(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\npc.ExtractFs(...): -want error, +got error:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractFs(...): -want error, +got error:\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.b, got); diff != "" { if diff := cmp.Diff(tc.want.b, got); diff != "" {
t.Errorf("\n%s\npc.ExtractFs(...): -want, +got:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractFs(...): -want, +got:\n%s\n", tc.reason, diff)
} }
@ -226,6 +228,7 @@ func TestExtractSecret(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\npc.ExtractSecret(...): -want error, +got error:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractSecret(...): -want error, +got error:\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.b, got); diff != "" { if diff := cmp.Diff(tc.want.b, got); diff != "" {
t.Errorf("\n%s\npc.ExtractSecret(...): -want, +got:\n%s\n", tc.reason, diff) t.Errorf("\n%s\npc.ExtractSecret(...): -want, +got:\n%s\n", tc.reason, diff)
} }
@ -318,6 +321,7 @@ func TestTrack(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ut := &ProviderConfigUsageTracker{c: tc.fields.c, of: tc.fields.of} ut := &ProviderConfigUsageTracker{c: tc.fields.c, of: tc.fields.of}
got := ut.Track(tc.args.ctx, tc.args.mg) got := ut.Track(tc.args.ctx, tc.args.mg)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nut.Track(...): -want error, +got error:\n%s\n", tc.reason, diff) t.Errorf("\n%s\nut.Track(...): -want error, +got error:\n%s\n", tc.reason, diff)

View File

@ -128,6 +128,7 @@ func MustCreateObject(kind schema.GroupVersionKind, oc runtime.ObjectCreater) ru
if err != nil { if err != nil {
panic(err) panic(err)
} }
return obj return obj
} }
@ -139,12 +140,15 @@ func GetKind(obj runtime.Object, ot runtime.ObjectTyper) (schema.GroupVersionKin
if err != nil { if err != nil {
return schema.GroupVersionKind{}, errors.Wrap(err, "cannot get kind of supplied object") return schema.GroupVersionKind{}, errors.Wrap(err, "cannot get kind of supplied object")
} }
if unversioned { if unversioned {
return schema.GroupVersionKind{}, errors.New("supplied object is unversioned") return schema.GroupVersionKind{}, errors.New("supplied object is unversioned")
} }
if len(kinds) != 1 { if len(kinds) != 1 {
return schema.GroupVersionKind{}, errors.New("supplied object does not have exactly one kind") return schema.GroupVersionKind{}, errors.New("supplied object does not have exactly one kind")
} }
return kinds[0], nil return kinds[0], nil
} }
@ -156,6 +160,7 @@ func MustGetKind(obj runtime.Object, ot runtime.ObjectTyper) schema.GroupVersion
if err != nil { if err != nil {
panic(err) panic(err)
} }
return gvk return gvk
} }
@ -168,6 +173,7 @@ func Ignore(is ErrorIs, err error) error {
if is(err) { if is(err) {
return nil return nil
} }
return err return err
} }
@ -180,6 +186,7 @@ func IgnoreAny(err error, is ...ErrorIs) error {
return nil return nil
} }
} }
return err return err
} }
@ -215,6 +222,7 @@ type shouldRetryFunc func(error) bool
// An ApplicatorWithRetry applies changes to an object, retrying on transient failures. // An ApplicatorWithRetry applies changes to an object, retrying on transient failures.
type ApplicatorWithRetry struct { type ApplicatorWithRetry struct {
Applicator Applicator
shouldRetry shouldRetryFunc shouldRetry shouldRetryFunc
backoff wait.Backoff backoff wait.Backoff
} }
@ -285,6 +293,7 @@ func IsNotControllable(err error) bool {
_, ok := err.(interface { _, ok := err.(interface {
NotControllable() bool NotControllable() bool
}) })
return ok return ok
} }
@ -299,6 +308,7 @@ func MustBeControllableBy(u types.UID) ApplyOption {
if !ok { if !ok {
return notControllableError{errors.Errorf("existing object is missing object metadata")} return notControllableError{errors.Errorf("existing object is missing object metadata")}
} }
c := metav1.GetControllerOf(mo) c := metav1.GetControllerOf(mo)
if c == nil { if c == nil {
return nil return nil
@ -307,6 +317,7 @@ func MustBeControllableBy(u types.UID) ApplyOption {
if c.UID != u { if c.UID != u {
return notControllableError{errors.Errorf("existing object is not controlled by UID %q", u)} return notControllableError{errors.Errorf("existing object is not controlled by UID %q", u)}
} }
return nil return nil
} }
} }
@ -329,6 +340,7 @@ func ConnectionSecretMustBeControllableBy(u types.UID) ApplyOption {
if !ok { if !ok {
return errors.New("current resource is not a Secret") return errors.New("current resource is not a Secret")
} }
c := metav1.GetControllerOf(s) c := metav1.GetControllerOf(s)
switch { switch {
@ -361,6 +373,7 @@ func IsNotAllowed(err error) bool {
_, ok := err.(interface { _, ok := err.(interface {
NotAllowed() bool NotAllowed() bool
}) })
return ok return ok
} }
@ -373,6 +386,7 @@ func AllowUpdateIf(fn func(current, desired runtime.Object) bool) ApplyOption {
if fn(current, desired) { if fn(current, desired) {
return nil return nil
} }
return notAllowedError{errors.New("update not allowed")} return notAllowedError{errors.New("update not allowed")}
} }
} }
@ -386,7 +400,9 @@ func StoreCurrentRV(origRV *string) ApplyOption {
if !ok { if !ok {
return errors.New("current resource is missing object metadata") return errors.New("current resource is missing object metadata")
} }
*origRV = mo.GetResourceVersion() *origRV = mo.GetResourceVersion()
return nil return nil
} }
} }
@ -402,6 +418,7 @@ func GetExternalTags(mg Managed) map[string]string {
if mg.GetProviderConfigReference() != nil && mg.GetProviderConfigReference().Name != "" { if mg.GetProviderConfigReference() != nil && mg.GetProviderConfigReference().Name != "" {
tags[ExternalResourceTagKeyProvider] = mg.GetProviderConfigReference().Name tags[ExternalResourceTagKeyProvider] = mg.GetProviderConfigReference().Name
} }
return tags return tags
} }
@ -416,12 +433,15 @@ func FirstNAndSomeMore(n int, names []string) string {
if n <= 0 { if n <= 0 {
return fmt.Sprintf("%d", len(names)) return fmt.Sprintf("%d", len(names))
} }
if len(names) > n { if len(names) > n {
return fmt.Sprintf("%s, and %d more", strings.Join(names[:n], ", "), len(names)-n) return fmt.Sprintf("%s, and %d more", strings.Join(names[:n], ", "), len(names)-n)
} }
if len(names) == n { if len(names) == n {
return fmt.Sprintf("%s, and %s", strings.Join(names[:n-1], ", "), names[n-1]) return fmt.Sprintf("%s, and %s", strings.Join(names[:n-1], ", "), names[n-1])
} }
return strings.Join(names, ", ") return strings.Join(names, ", ")
} }
@ -431,6 +451,7 @@ func StableNAndSomeMore(n int, names []string) string {
cpy := make([]string, len(names)) cpy := make([]string, len(names))
copy(cpy, names) copy(cpy, names)
sort.Strings(cpy) sort.Strings(cpy)
return FirstNAndSomeMore(n, cpy) return FirstNAndSomeMore(n, cpy)
} }
@ -458,5 +479,6 @@ func AsProtobufStruct(o runtime.Object) (*structpb.Struct, error) {
} }
s := &structpb.Struct{} s := &structpb.Struct{}
return s, errors.Wrap(s.UnmarshalJSON(b), errUnmarshalJSON) return s, errors.Wrap(s.UnmarshalJSON(b), errUnmarshalJSON)
} }

View File

@ -181,6 +181,7 @@ func TestGetKind(t *testing.T) {
obj runtime.Object obj runtime.Object
ot runtime.ObjectTyper ot runtime.ObjectTyper
} }
type want struct { type want struct {
kind schema.GroupVersionKind kind schema.GroupVersionKind
err error err error
@ -243,6 +244,7 @@ func TestGetKind(t *testing.T) {
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" {
t.Errorf("GetKind(...): -want error, +got error:\n%s", diff) t.Errorf("GetKind(...): -want error, +got error:\n%s", diff)
} }
if diff := cmp.Diff(tc.want.kind, got); diff != "" { if diff := cmp.Diff(tc.want.kind, got); diff != "" {
t.Errorf("GetKind(...): -want, +got:\n%s", diff) t.Errorf("GetKind(...): -want, +got:\n%s", diff)
} }
@ -255,6 +257,7 @@ func TestMustCreateObject(t *testing.T) {
kind schema.GroupVersionKind kind schema.GroupVersionKind
oc runtime.ObjectCreater oc runtime.ObjectCreater
} }
cases := map[string]struct { cases := map[string]struct {
args args args args
want runtime.Object want runtime.Object
@ -285,6 +288,7 @@ func TestIgnore(t *testing.T) {
is ErrorIs is ErrorIs
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
args args args args
want error want error
@ -322,6 +326,7 @@ func TestIgnoreAny(t *testing.T) {
is []ErrorIs is []ErrorIs
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
args args args args
want error want error
@ -401,7 +406,7 @@ type object struct {
} }
func (o *object) DeepCopyObject() runtime.Object { func (o *object) DeepCopyObject() runtime.Object {
return &object{ObjectMeta: *o.ObjectMeta.DeepCopy()} return &object{ObjectMeta: *o.DeepCopy()}
} }
func TestIsNotControllable(t *testing.T) { func TestIsNotControllable(t *testing.T) {
@ -486,8 +491,8 @@ func TestMustBeControllableBy(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ao := MustBeControllableBy(tc.u) ao := MustBeControllableBy(tc.u)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nMustBeControllableBy(...)(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nMustBeControllableBy(...)(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
@ -558,8 +563,8 @@ func TestConnectionSecretMustBeControllableBy(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ao := ConnectionSecretMustBeControllableBy(tc.u) ao := ConnectionSecretMustBeControllableBy(tc.u)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nConnectionSecretMustBeControllableBy(...)(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nConnectionSecretMustBeControllableBy(...)(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
@ -600,8 +605,8 @@ func TestAllowUpdateIf(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
ao := AllowUpdateIf(tc.fn) ao := AllowUpdateIf(tc.fn)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
err := ao(tc.args.ctx, tc.args.current, tc.args.desired)
if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nAllowUpdateIf(...)(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nAllowUpdateIf(...)(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
@ -645,7 +650,6 @@ func Test_notControllableError_NotControllable(t *testing.T) {
err := notControllableError{ err := notControllableError{
errors.New("test-error"), errors.New("test-error"),
} }
if !err.NotControllable() { if !err.NotControllable() {
t.Errorf("NotControllable(): false") t.Errorf("NotControllable(): false")
} }
@ -656,7 +660,6 @@ func Test_notAllowedError_NotAllowed(t *testing.T) {
err := notAllowedError{ err := notAllowedError{
errors.New("test-error"), errors.New("test-error"),
} }
if !err.NotAllowed() { if !err.NotAllowed() {
t.Errorf("NotAllowed(): false") t.Errorf("NotAllowed(): false")
} }
@ -884,6 +887,7 @@ func TestFirstNAndSomeMore(t *testing.T) {
n int n int
names []string names []string
} }
tests := []struct { tests := []struct {
name string name string
args args args args

View File

@ -53,6 +53,7 @@ func New(opts ...Option) *Unstructured {
for _, f := range opts { for _, f := range opts {
f(c) f(c)
} }
return c return c
} }
@ -75,6 +76,7 @@ func (c *Unstructured) GetCompositionSelector() *metav1.LabelSelector {
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionSelector", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionSelector", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -89,6 +91,7 @@ func (c *Unstructured) GetCompositionReference() *corev1.ObjectReference {
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -103,6 +106,7 @@ func (c *Unstructured) GetCompositionRevisionReference() *corev1.LocalObjectRefe
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRevisionRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRevisionRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -117,6 +121,7 @@ func (c *Unstructured) GetCompositionRevisionSelector() *metav1.LabelSelector {
if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRevisionSelector", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.compositionRevisionSelector", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -136,7 +141,9 @@ func (c *Unstructured) GetCompositionUpdatePolicy() *xpv1.UpdatePolicy {
if err != nil { if err != nil {
return nil return nil
} }
out := xpv1.UpdatePolicy(p) out := xpv1.UpdatePolicy(p)
return &out return &out
} }
@ -151,7 +158,9 @@ func (c *Unstructured) GetCompositeDeletePolicy() *xpv1.CompositeDeletePolicy {
if err != nil { if err != nil {
return nil return nil
} }
out := xpv1.CompositeDeletePolicy(p) out := xpv1.CompositeDeletePolicy(p)
return &out return &out
} }
@ -161,6 +170,7 @@ func (c *Unstructured) GetResourceReference() *reference.Composite {
if err := fieldpath.Pave(c.Object).GetValueInto("spec.resourceRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.resourceRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -185,6 +195,7 @@ func (c *Unstructured) GetWriteConnectionSecretToReference() *xpv1.LocalSecretRe
if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -200,6 +211,7 @@ func (c *Unstructured) GetCondition(ct xpv1.ConditionType) xpv1.Condition {
if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil {
return xpv1.Condition{} return xpv1.Condition{}
} }
return conditioned.GetCondition(ct) return conditioned.GetCondition(ct)
} }
@ -218,6 +230,7 @@ func (c *Unstructured) GetConnectionDetailsLastPublishedTime() *metav1.Time {
if err := fieldpath.Pave(c.Object).GetValueInto("status.connectionDetails.lastPublishedTime", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("status.connectionDetails.lastPublishedTime", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -238,5 +251,6 @@ func (c *Unstructured) SetObservedGeneration(generation int64) {
func (c *Unstructured) GetObservedGeneration() int64 { func (c *Unstructured) GetObservedGeneration() int64 {
status := &xpv1.ObservedStatus{} status := &xpv1.ObservedStatus{}
_ = fieldpath.Pave(c.Object).GetValueInto("status", status) _ = fieldpath.Pave(c.Object).GetValueInto("status", status)
return status.GetObservedGeneration() return status.GetObservedGeneration()
} }

View File

@ -114,6 +114,7 @@ func TestConditions(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetConditions(tc.set...) tc.u.SetConditions(tc.set...)
got := tc.u.GetCondition(tc.get) got := tc.u.GetCondition(tc.get)
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\n%s\nu.GetCondition(%s): -want, +got:\n%s", tc.reason, tc.get, diff) t.Errorf("\n%s\nu.GetCondition(%s): -want, +got:\n%s", tc.reason, tc.get, diff)
@ -139,6 +140,7 @@ func TestCompositionSelector(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionSelector(tc.set) tc.u.SetCompositionSelector(tc.set)
got := tc.u.GetCompositionSelector() got := tc.u.GetCompositionSelector()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionSelector(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionSelector(): -want, +got:\n%s", diff)
@ -164,6 +166,7 @@ func TestCompositionReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionReference(tc.set) tc.u.SetCompositionReference(tc.set)
got := tc.u.GetCompositionReference() got := tc.u.GetCompositionReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionReference(): -want, +got:\n%s", diff)
@ -189,6 +192,7 @@ func TestCompositionRevisionReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionRevisionReference(tc.set) tc.u.SetCompositionRevisionReference(tc.set)
got := tc.u.GetCompositionRevisionReference() got := tc.u.GetCompositionRevisionReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionRevisionReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionRevisionReference(): -want, +got:\n%s", diff)
@ -214,6 +218,7 @@ func TestCompositionRevisionSelector(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionRevisionSelector(tc.set) tc.u.SetCompositionRevisionSelector(tc.set)
got := tc.u.GetCompositionRevisionSelector() got := tc.u.GetCompositionRevisionSelector()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionRevisionSelector(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionRevisionSelector(): -want, +got:\n%s", diff)
@ -239,6 +244,7 @@ func TestCompositionUpdatePolicy(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionUpdatePolicy(tc.set) tc.u.SetCompositionUpdatePolicy(tc.set)
got := tc.u.GetCompositionUpdatePolicy() got := tc.u.GetCompositionUpdatePolicy()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionUpdatePolicy(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionUpdatePolicy(): -want, +got:\n%s", diff)
@ -264,6 +270,7 @@ func TestCompositeDeletePolicy(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositeDeletePolicy(tc.set) tc.u.SetCompositeDeletePolicy(tc.set)
got := tc.u.GetCompositeDeletePolicy() got := tc.u.GetCompositeDeletePolicy()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositeDeletePolicy(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositeDeletePolicy(): -want, +got:\n%s", diff)
@ -289,6 +296,7 @@ func TestResourceReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetResourceReference(tc.set) tc.u.SetResourceReference(tc.set)
got := tc.u.GetResourceReference() got := tc.u.GetResourceReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetResourceReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetResourceReference(): -want, +got:\n%s", diff)
@ -304,6 +312,7 @@ func TestClaimReference(t *testing.T) {
u.SetNamespace(ref.Namespace) u.SetNamespace(ref.Namespace)
u.SetAPIVersion(ref.APIVersion) u.SetAPIVersion(ref.APIVersion)
u.SetKind(ref.Kind) u.SetKind(ref.Kind)
got := u.GetReference() got := u.GetReference()
if diff := cmp.Diff(ref, got); diff != "" { if diff := cmp.Diff(ref, got); diff != "" {
t.Errorf("\nu.GetClaimReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetClaimReference(): -want, +got:\n%s", diff)
@ -327,6 +336,7 @@ func TestWriteConnectionSecretToReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetWriteConnectionSecretToReference(tc.set) tc.u.SetWriteConnectionSecretToReference(tc.set)
got := tc.u.GetWriteConnectionSecretToReference() got := tc.u.GetWriteConnectionSecretToReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff)
@ -344,6 +354,7 @@ func TestConnectionDetailsLastPublishedTime(t *testing.T) {
out := &metav1.Time{} out := &metav1.Time{}
j, _ := json.Marshal(t) //nolint:errchkjson // No encoding issue in practice. j, _ := json.Marshal(t) //nolint:errchkjson // No encoding issue in practice.
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -362,6 +373,7 @@ func TestConnectionDetailsLastPublishedTime(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetConnectionDetailsLastPublishedTime(tc.set) tc.u.SetConnectionDetailsLastPublishedTime(tc.set)
got := tc.u.GetConnectionDetailsLastPublishedTime() got := tc.u.GetConnectionDetailsLastPublishedTime()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff) t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff)

View File

@ -59,6 +59,7 @@ func (c *WrapperClient) Get(ctx context.Context, key client.ObjectKey, obj clien
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Get(ctx, key, u.GetUnstructured(), opts...) return c.kube.Get(ctx, key, u.GetUnstructured(), opts...)
} }
return c.kube.Get(ctx, key, obj, opts...) return c.kube.Get(ctx, key, obj, opts...)
} }
@ -69,6 +70,7 @@ func (c *WrapperClient) List(ctx context.Context, list client.ObjectList, opts .
if u, ok := list.(ListWrapper); ok { if u, ok := list.(ListWrapper); ok {
return c.kube.List(ctx, u.GetUnstructuredList(), opts...) return c.kube.List(ctx, u.GetUnstructuredList(), opts...)
} }
return c.kube.List(ctx, list, opts...) return c.kube.List(ctx, list, opts...)
} }
@ -77,6 +79,7 @@ func (c *WrapperClient) Create(ctx context.Context, obj client.Object, opts ...c
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Create(ctx, u.GetUnstructured(), opts...) return c.kube.Create(ctx, u.GetUnstructured(), opts...)
} }
return c.kube.Create(ctx, obj, opts...) return c.kube.Create(ctx, obj, opts...)
} }
@ -85,6 +88,7 @@ func (c *WrapperClient) Delete(ctx context.Context, obj client.Object, opts ...c
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Delete(ctx, u.GetUnstructured(), opts...) return c.kube.Delete(ctx, u.GetUnstructured(), opts...)
} }
return c.kube.Delete(ctx, obj, opts...) return c.kube.Delete(ctx, obj, opts...)
} }
@ -94,6 +98,7 @@ func (c *WrapperClient) Update(ctx context.Context, obj client.Object, opts ...c
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Update(ctx, u.GetUnstructured(), opts...) return c.kube.Update(ctx, u.GetUnstructured(), opts...)
} }
return c.kube.Update(ctx, obj, opts...) return c.kube.Update(ctx, obj, opts...)
} }
@ -103,6 +108,7 @@ func (c *WrapperClient) Patch(ctx context.Context, obj client.Object, patch clie
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Patch(ctx, u.GetUnstructured(), patch, opts...) return c.kube.Patch(ctx, u.GetUnstructured(), patch, opts...)
} }
return c.kube.Patch(ctx, obj, patch, opts...) return c.kube.Patch(ctx, obj, patch, opts...)
} }
@ -111,6 +117,7 @@ func (c *WrapperClient) DeleteAllOf(ctx context.Context, obj client.Object, opts
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.DeleteAllOf(ctx, u.GetUnstructured(), opts...) return c.kube.DeleteAllOf(ctx, u.GetUnstructured(), opts...)
} }
return c.kube.DeleteAllOf(ctx, obj, opts...) return c.kube.DeleteAllOf(ctx, obj, opts...)
} }
@ -142,6 +149,7 @@ func (c *WrapperClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVer
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.GroupVersionKindFor(u.GetUnstructured()) return c.kube.GroupVersionKindFor(u.GetUnstructured())
} }
return c.kube.GroupVersionKindFor(obj) return c.kube.GroupVersionKindFor(obj)
} }
@ -150,6 +158,7 @@ func (c *WrapperClient) IsObjectNamespaced(obj runtime.Object) (bool, error) {
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.IsObjectNamespaced(u.GetUnstructured()) return c.kube.IsObjectNamespaced(u.GetUnstructured())
} }
return c.kube.IsObjectNamespaced(obj) return c.kube.IsObjectNamespaced(obj)
} }
@ -165,6 +174,7 @@ func (c *wrapperStatusClient) Create(ctx context.Context, obj, subResource clien
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Create(ctx, u.GetUnstructured(), subResource, opts...) return c.kube.Create(ctx, u.GetUnstructured(), subResource, opts...)
} }
return c.kube.Create(ctx, obj, subResource, opts...) return c.kube.Create(ctx, obj, subResource, opts...)
} }
@ -175,6 +185,7 @@ func (c *wrapperStatusClient) Update(ctx context.Context, obj client.Object, opt
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Update(ctx, u.GetUnstructured(), opts...) return c.kube.Update(ctx, u.GetUnstructured(), opts...)
} }
return c.kube.Update(ctx, obj, opts...) return c.kube.Update(ctx, obj, opts...)
} }
@ -185,5 +196,6 @@ func (c *wrapperStatusClient) Patch(ctx context.Context, obj client.Object, patc
if u, ok := obj.(Wrapper); ok { if u, ok := obj.(Wrapper); ok {
return c.kube.Patch(ctx, u.GetUnstructured(), patch, opts...) return c.kube.Patch(ctx, u.GetUnstructured(), patch, opts...)
} }
return c.kube.Patch(ctx, obj, patch, opts...) return c.kube.Patch(ctx, obj, patch, opts...)
} }

View File

@ -79,6 +79,7 @@ func TestGet(t *testing.T) {
key client.ObjectKey key client.ObjectKey
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -107,6 +108,7 @@ func TestGet(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Get(tc.args.ctx, tc.args.key, tc.args.obj) got := c.Get(tc.args.ctx, tc.args.key, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Get(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Get(...): -want error, +got error:\n %s", diff)
@ -120,6 +122,7 @@ func TestList(t *testing.T) {
ctx context.Context ctx context.Context
obj client.ObjectList obj client.ObjectList
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -150,6 +153,7 @@ func TestList(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.List(tc.args.ctx, tc.args.obj) got := c.List(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.List(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.List(...): -want error, +got error:\n %s", diff)
@ -163,6 +167,7 @@ func TestCreate(t *testing.T) {
ctx context.Context ctx context.Context
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -191,6 +196,7 @@ func TestCreate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Create(tc.args.ctx, tc.args.obj) got := c.Create(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Create(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Create(...): -want error, +got error:\n %s", diff)
@ -204,6 +210,7 @@ func TestDelete(t *testing.T) {
ctx context.Context ctx context.Context
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -232,6 +239,7 @@ func TestDelete(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Delete(tc.args.ctx, tc.args.obj) got := c.Delete(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Delete(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Delete(...): -want error, +got error:\n %s", diff)
@ -245,6 +253,7 @@ func TestUpdate(t *testing.T) {
ctx context.Context ctx context.Context
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -273,6 +282,7 @@ func TestUpdate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Update(tc.args.ctx, tc.args.obj) got := c.Update(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Update(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Update(...): -want error, +got error:\n %s", diff)
@ -287,6 +297,7 @@ func TestPatch(t *testing.T) {
obj client.Object obj client.Object
patch client.Patch patch client.Patch
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -315,6 +326,7 @@ func TestPatch(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Patch(tc.args.ctx, tc.args.obj, tc.args.patch) got := c.Patch(tc.args.ctx, tc.args.obj, tc.args.patch)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Patch(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Patch(...): -want error, +got error:\n %s", diff)
@ -328,6 +340,7 @@ func TestDeleteAllOf(t *testing.T) {
ctx context.Context ctx context.Context
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -356,6 +369,7 @@ func TestDeleteAllOf(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.DeleteAllOf(tc.args.ctx, tc.args.obj) got := c.DeleteAllOf(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.DeleteAllOf(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.DeleteAllOf(...): -want error, +got error:\n %s", diff)
@ -370,6 +384,7 @@ func TestStatusCreate(t *testing.T) {
obj client.Object obj client.Object
sub client.Object sub client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -398,6 +413,7 @@ func TestStatusCreate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Status().Create(tc.args.ctx, tc.args.obj, tc.args.sub) got := c.Status().Create(tc.args.ctx, tc.args.obj, tc.args.sub)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Status().Create(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Status().Create(...): -want error, +got error:\n %s", diff)
@ -411,6 +427,7 @@ func TestStatusUpdate(t *testing.T) {
ctx context.Context ctx context.Context
obj client.Object obj client.Object
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -439,6 +456,7 @@ func TestStatusUpdate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Status().Update(tc.args.ctx, tc.args.obj) got := c.Status().Update(tc.args.ctx, tc.args.obj)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.Status().Update(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.Status().Update(...): -want error, +got error:\n %s", diff)
@ -453,6 +471,7 @@ func TestStatusPatch(t *testing.T) {
obj client.Object obj client.Object
patch client.Patch patch client.Patch
} }
cases := map[string]struct { cases := map[string]struct {
c client.Client c client.Client
args args args args
@ -481,6 +500,7 @@ func TestStatusPatch(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
c := NewClient(tc.c) c := NewClient(tc.c)
got := c.Status().Patch(tc.args.ctx, tc.args.obj, tc.args.patch) got := c.Status().Patch(tc.args.ctx, tc.args.obj, tc.args.patch)
if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" { if diff := cmp.Diff(tc.want, got, test.EquateErrors()); diff != "" {
t.Errorf("\nc.StatusPatch(...): -want error, +got error:\n %s", diff) t.Errorf("\nc.StatusPatch(...): -want error, +got error:\n %s", diff)

View File

@ -54,6 +54,7 @@ func New(opts ...Option) *Unstructured {
for _, f := range opts { for _, f := range opts {
f(cr) f(cr)
} }
return cr return cr
} }
@ -77,6 +78,7 @@ func (cr *Unstructured) GetCondition(ct xpv1.ConditionType) xpv1.Condition {
if err := fieldpath.Pave(cr.Object).GetValueInto("status", &conditioned); err != nil { if err := fieldpath.Pave(cr.Object).GetValueInto("status", &conditioned); err != nil {
return xpv1.Condition{} return xpv1.Condition{}
} }
return conditioned.GetCondition(ct) return conditioned.GetCondition(ct)
} }
@ -95,6 +97,7 @@ func (cr *Unstructured) GetWriteConnectionSecretToReference() *xpv1.SecretRefere
if err := fieldpath.Pave(cr.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil { if err := fieldpath.Pave(cr.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -110,6 +113,7 @@ func (cr *Unstructured) OwnedBy(u types.UID) bool {
return true return true
} }
} }
return false return false
} }
@ -142,6 +146,7 @@ func NewList(opts ...ListOption) *UnstructuredList {
for _, f := range opts { for _, f := range opts {
f(cr) f(cr)
} }
return cr return cr
} }
@ -167,5 +172,6 @@ func (cr *Unstructured) SetObservedGeneration(generation int64) {
func (cr *Unstructured) GetObservedGeneration() int64 { func (cr *Unstructured) GetObservedGeneration() int64 {
status := &xpv1.ObservedStatus{} status := &xpv1.ObservedStatus{}
_ = fieldpath.Pave(cr.Object).GetValueInto("status", status) _ = fieldpath.Pave(cr.Object).GetValueInto("status", status)
return status.GetObservedGeneration() return status.GetObservedGeneration()
} }

View File

@ -114,6 +114,7 @@ func TestConditions(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetConditions(tc.set...) tc.u.SetConditions(tc.set...)
got := tc.u.GetCondition(tc.get) got := tc.u.GetCondition(tc.get)
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\n%s\nu.GetCondition(%s): -want, +got:\n%s", tc.reason, tc.get, diff) t.Errorf("\n%s\nu.GetCondition(%s): -want, +got:\n%s", tc.reason, tc.get, diff)
@ -139,6 +140,7 @@ func TestWriteConnectionSecretToReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetWriteConnectionSecretToReference(tc.set) tc.u.SetWriteConnectionSecretToReference(tc.set)
got := tc.u.GetWriteConnectionSecretToReference() got := tc.u.GetWriteConnectionSecretToReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff)

View File

@ -76,6 +76,7 @@ func New(opts ...Option) *Unstructured {
for _, f := range opts { for _, f := range opts {
f(c) f(c)
} }
return c return c
} }
@ -105,6 +106,7 @@ func (c *Unstructured) GetCompositionSelector() *metav1.LabelSelector {
if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil {
return nil return nil
} }
return out return out
} }
@ -129,6 +131,7 @@ func (c *Unstructured) GetCompositionReference() *corev1.ObjectReference {
if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil {
return nil return nil
} }
return out return out
} }
@ -153,6 +156,7 @@ func (c *Unstructured) GetCompositionRevisionReference() *corev1.LocalObjectRefe
if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil {
return nil return nil
} }
return out return out
} }
@ -177,6 +181,7 @@ func (c *Unstructured) GetCompositionRevisionSelector() *metav1.LabelSelector {
if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil {
return nil return nil
} }
return out return out
} }
@ -211,7 +216,9 @@ func (c *Unstructured) GetCompositionUpdatePolicy() *xpv1.UpdatePolicy {
if err != nil { if err != nil {
return nil return nil
} }
out := xpv1.UpdatePolicy(p) out := xpv1.UpdatePolicy(p)
return &out return &out
} }
@ -226,6 +233,7 @@ func (c *Unstructured) GetClaimReference() *reference.Claim {
if err := fieldpath.Pave(c.Object).GetValueInto("spec.claimRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.claimRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -248,6 +256,7 @@ func (c *Unstructured) GetResourceReferences() []corev1.ObjectReference {
out := &[]corev1.ObjectReference{} out := &[]corev1.ObjectReference{}
_ = fieldpath.Pave(c.Object).GetValueInto(path, out) _ = fieldpath.Pave(c.Object).GetValueInto(path, out)
return *out return *out
} }
@ -259,6 +268,7 @@ func (c *Unstructured) SetResourceReferences(refs []corev1.ObjectReference) {
} }
empty := corev1.ObjectReference{} empty := corev1.ObjectReference{}
filtered := make([]corev1.ObjectReference, 0, len(refs)) filtered := make([]corev1.ObjectReference, 0, len(refs))
for _, ref := range refs { for _, ref := range refs {
// TODO(negz): Ask muvaf to explain what this is working around. :) // TODO(negz): Ask muvaf to explain what this is working around. :)
@ -266,8 +276,10 @@ func (c *Unstructured) SetResourceReferences(refs []corev1.ObjectReference) {
if ref.String() == empty.String() { if ref.String() == empty.String() {
continue continue
} }
filtered = append(filtered, ref) filtered = append(filtered, ref)
} }
_ = fieldpath.Pave(c.Object).SetValue(path, filtered) _ = fieldpath.Pave(c.Object).SetValue(path, filtered)
} }
@ -301,6 +313,7 @@ func (c *Unstructured) GetWriteConnectionSecretToReference() *xpv1.SecretReferen
if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil return nil
} }
return out return out
} }
@ -321,6 +334,7 @@ func (c *Unstructured) GetCondition(ct xpv1.ConditionType) xpv1.Condition {
if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto("status", &conditioned); err != nil {
return xpv1.Condition{} return xpv1.Condition{}
} }
return conditioned.GetCondition(ct) return conditioned.GetCondition(ct)
} }
@ -338,6 +352,7 @@ func (c *Unstructured) GetConditions() []xpv1.Condition {
conditioned := xpv1.ConditionedStatus{} conditioned := xpv1.ConditionedStatus{}
// The path is directly `status` because conditions are inline. // The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(c.Object).GetValueInto("status", &conditioned) _ = fieldpath.Pave(c.Object).GetValueInto("status", &conditioned)
return conditioned.Conditions return conditioned.Conditions
} }
@ -352,6 +367,7 @@ func (c *Unstructured) GetConnectionDetailsLastPublishedTime() *metav1.Time {
if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil { if err := fieldpath.Pave(c.Object).GetValueInto(path, out); err != nil {
return nil return nil
} }
return out return out
} }
@ -377,6 +393,7 @@ func (c *Unstructured) SetObservedGeneration(generation int64) {
func (c *Unstructured) GetObservedGeneration() int64 { func (c *Unstructured) GetObservedGeneration() int64 {
status := &xpv1.ObservedStatus{} status := &xpv1.ObservedStatus{}
_ = fieldpath.Pave(c.Object).GetValueInto("status", status) _ = fieldpath.Pave(c.Object).GetValueInto("status", status)
return status.GetObservedGeneration() return status.GetObservedGeneration()
} }
@ -387,7 +404,9 @@ func (c *Unstructured) SetClaimConditionTypes(in ...xpv1.ConditionType) error {
if c.Schema != SchemaLegacy { if c.Schema != SchemaLegacy {
return nil return nil
} }
ts := c.GetClaimConditionTypes() ts := c.GetClaimConditionTypes()
m := make(map[xpv1.ConditionType]bool, len(ts)) m := make(map[xpv1.ConditionType]bool, len(ts))
for _, t := range ts { for _, t := range ts {
m[t] = true m[t] = true
@ -397,13 +416,17 @@ func (c *Unstructured) SetClaimConditionTypes(in ...xpv1.ConditionType) error {
if xpv1.IsSystemConditionType(t) { if xpv1.IsSystemConditionType(t) {
return errors.Errorf("cannot set system condition %s as a claim condition", t) return errors.Errorf("cannot set system condition %s as a claim condition", t)
} }
if m[t] { if m[t] {
continue continue
} }
m[t] = true m[t] = true
ts = append(ts, t) ts = append(ts, t)
} }
_ = fieldpath.Pave(c.Object).SetValue("status.claimConditionTypes", ts) _ = fieldpath.Pave(c.Object).SetValue("status.claimConditionTypes", ts)
return nil return nil
} }
@ -413,7 +436,9 @@ func (c *Unstructured) GetClaimConditionTypes() []xpv1.ConditionType {
if c.Schema != SchemaLegacy { if c.Schema != SchemaLegacy {
return nil return nil
} }
cs := []xpv1.ConditionType{} cs := []xpv1.ConditionType{}
_ = fieldpath.Pave(c.Object).GetValueInto("status.claimConditionTypes", &cs) _ = fieldpath.Pave(c.Object).GetValueInto("status.claimConditionTypes", &cs)
return cs return cs
} }

View File

@ -231,6 +231,7 @@ func TestCompositionSelector(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionSelector(tc.set) tc.u.SetCompositionSelector(tc.set)
got := tc.u.GetCompositionSelector() got := tc.u.GetCompositionSelector()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionSelector(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionSelector(): -want, +got:\n%s", diff)
@ -256,6 +257,7 @@ func TestCompositionReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionReference(tc.set) tc.u.SetCompositionReference(tc.set)
got := tc.u.GetCompositionReference() got := tc.u.GetCompositionReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionReference(): -want, +got:\n%s", diff)
@ -281,6 +283,7 @@ func TestCompositionRevisionReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionRevisionReference(tc.set) tc.u.SetCompositionRevisionReference(tc.set)
got := tc.u.GetCompositionRevisionReference() got := tc.u.GetCompositionRevisionReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionRevisionReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionRevisionReference(): -want, +got:\n%s", diff)
@ -306,6 +309,7 @@ func TestCompositionRevisionSelector(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionRevisionSelector(tc.set) tc.u.SetCompositionRevisionSelector(tc.set)
got := tc.u.GetCompositionRevisionSelector() got := tc.u.GetCompositionRevisionSelector()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionRevisionSelector(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionRevisionSelector(): -want, +got:\n%s", diff)
@ -331,6 +335,7 @@ func TestCompositionUpdatePolicy(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetCompositionUpdatePolicy(tc.set) tc.u.SetCompositionUpdatePolicy(tc.set)
got := tc.u.GetCompositionUpdatePolicy() got := tc.u.GetCompositionUpdatePolicy()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetCompositionUpdatePolicy(): -want, +got:\n%s", diff) t.Errorf("\nu.GetCompositionUpdatePolicy(): -want, +got:\n%s", diff)
@ -356,6 +361,7 @@ func TestClaimReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetClaimReference(tc.set) tc.u.SetClaimReference(tc.set)
got := tc.u.GetClaimReference() got := tc.u.GetClaimReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetClaimReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetClaimReference(): -want, +got:\n%s", diff)
@ -381,6 +387,7 @@ func TestResourceReferences(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetResourceReferences(tc.set) tc.u.SetResourceReferences(tc.set)
got := tc.u.GetResourceReferences() got := tc.u.GetResourceReferences()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetResourceReferences(): -want, +got:\n%s", diff) t.Errorf("\nu.GetResourceReferences(): -want, +got:\n%s", diff)
@ -406,6 +413,7 @@ func TestWriteConnectionSecretToReference(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetWriteConnectionSecretToReference(tc.set) tc.u.SetWriteConnectionSecretToReference(tc.set)
got := tc.u.GetWriteConnectionSecretToReference() got := tc.u.GetWriteConnectionSecretToReference()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff) t.Errorf("\nu.GetWriteConnectionSecretToReference(): -want, +got:\n%s", diff)
@ -423,6 +431,7 @@ func TestConnectionDetailsLastPublishedTime(t *testing.T) {
out := &metav1.Time{} out := &metav1.Time{}
j, _ := json.Marshal(t) //nolint:errchkjson // No encoding error in practice. j, _ := json.Marshal(t) //nolint:errchkjson // No encoding error in practice.
_ = json.Unmarshal(j, out) _ = json.Unmarshal(j, out)
return out return out
} }
@ -441,6 +450,7 @@ func TestConnectionDetailsLastPublishedTime(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc.u.SetConnectionDetailsLastPublishedTime(tc.set) tc.u.SetConnectionDetailsLastPublishedTime(tc.set)
got := tc.u.GetConnectionDetailsLastPublishedTime() got := tc.u.GetConnectionDetailsLastPublishedTime()
if diff := cmp.Diff(tc.want, got); diff != "" { if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff) t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff)

View File

@ -114,6 +114,7 @@ func (r *MRStateRecorder) Record(ctx context.Context) error {
r.metrics.Exists.With(labels).Set(float64(len(mrs))) r.metrics.Exists.With(labels).Set(float64(len(mrs)))
var numReady, numSynced float64 = 0, 0 var numReady, numSynced float64 = 0, 0
for _, o := range mrs { for _, o := range mrs {
if o.GetCondition(xpv1.TypeReady).Status == corev1.ConditionTrue { if o.GetCondition(xpv1.TypeReady).Status == corev1.ConditionTrue {
numReady++ numReady++
@ -133,6 +134,7 @@ func (r *MRStateRecorder) Record(ctx context.Context) error {
// Start records state of managed resources with given interval. // Start records state of managed resources with given interval.
func (r *MRStateRecorder) Start(ctx context.Context) error { func (r *MRStateRecorder) Start(ctx context.Context) error {
ticker := time.NewTicker(r.interval) ticker := time.NewTicker(r.interval)
for { for {
select { select {
case <-ticker.C: case <-ticker.C:

View File

@ -40,6 +40,7 @@ func EquateErrors() cmp.Option {
} }
av := reflect.ValueOf(a) av := reflect.ValueOf(a)
bv := reflect.ValueOf(b) bv := reflect.ValueOf(b)
if av.Type() != bv.Type() { if av.Type() != bv.Type() {
return false return false

View File

@ -89,6 +89,7 @@ func NewMockGetFn(err error, ofn ...ObjectFn) MockGetFn {
return err return err
} }
} }
return err return err
} }
} }
@ -101,6 +102,7 @@ func NewMockListFn(err error, ofn ...ObjectListFn) MockListFn {
return err return err
} }
} }
return err return err
} }
} }
@ -113,6 +115,7 @@ func NewMockCreateFn(err error, ofn ...ObjectFn) MockCreateFn {
return err return err
} }
} }
return err return err
} }
} }
@ -125,6 +128,7 @@ func NewMockDeleteFn(err error, ofn ...ObjectFn) MockDeleteFn {
return err return err
} }
} }
return err return err
} }
} }
@ -137,6 +141,7 @@ func NewMockDeleteAllOfFn(err error, ofn ...ObjectFn) MockDeleteAllOfFn {
return err return err
} }
} }
return err return err
} }
} }
@ -149,6 +154,7 @@ func NewMockUpdateFn(err error, ofn ...ObjectFn) MockUpdateFn {
return err return err
} }
} }
return err return err
} }
} }
@ -161,6 +167,7 @@ func NewMockPatchFn(err error, ofn ...ObjectFn) MockPatchFn {
return err return err
} }
} }
return err return err
} }
} }
@ -173,6 +180,7 @@ func NewMockSubResourceCreateFn(err error, ofn ...ObjectFn) MockSubResourceCreat
return err return err
} }
} }
return err return err
} }
} }
@ -185,6 +193,7 @@ func NewMockSubResourceUpdateFn(err error, ofn ...ObjectFn) MockSubResourceUpdat
return err return err
} }
} }
return err return err
} }
} }
@ -197,6 +206,7 @@ func NewMockSubResourcePatchFn(err error, ofn ...ObjectFn) MockSubResourcePatchF
return err return err
} }
} }
return err return err
} }
} }
@ -216,6 +226,7 @@ func NewMockGroupVersionKindForFn(err error, gvk schema.GroupVersionKind, rofn .
return gvk, err return gvk, err
} }
} }
return gvk, err return gvk, err
} }
} }
@ -228,6 +239,7 @@ func NewMockIsObjectNamespacedFn(err error, isNamespaced bool, rofn ...RuntimeOb
return isNamespaced, err return isNamespaced, err
} }
} }
return isNamespaced, err return isNamespaced, err
} }
} }

View File

@ -45,6 +45,7 @@ func NewMutator(opts ...MutatorOption) *Mutator {
for _, f := range opts { for _, f := range opts {
f(m) f(m)
} }
return m return m
} }
@ -62,5 +63,6 @@ func (m *Mutator) Default(ctx context.Context, obj runtime.Object) error {
return err return err
} }
} }
return nil return nil
} }

View File

@ -36,9 +36,11 @@ func TestDefault(t *testing.T) {
obj runtime.Object obj runtime.Object
fns []MutateFn fns []MutateFn
} }
type want struct { type want struct {
err error err error
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -71,8 +73,9 @@ func TestDefault(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
v := NewMutator(WithMutationFns(tc.fns...)) v := NewMutator(WithMutationFns(tc.fns...))
err := v.Default(context.TODO(), tc.args.obj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { err := v.Default(context.TODO(), tc.obj)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nDefault(...): -want, +got\n%s\n", tc.reason, diff) t.Errorf("\n%s\nDefault(...): -want, +got\n%s\n", tc.reason, diff)
} }
}) })

View File

@ -69,6 +69,7 @@ func NewValidator(opts ...ValidatorOption) *Validator {
for _, f := range opts { for _, f := range opts {
f(vc) f(vc)
} }
return vc return vc
} }
@ -82,38 +83,47 @@ type Validator struct {
// ValidateCreate runs functions in creation chain in order. // ValidateCreate runs functions in creation chain in order.
func (vc *Validator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { func (vc *Validator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
warnings := []string{} warnings := []string{}
for _, f := range vc.CreationChain { for _, f := range vc.CreationChain {
warns, err := f(ctx, obj) warns, err := f(ctx, obj)
if err != nil { if err != nil {
return append(warnings, warns...), err return append(warnings, warns...), err
} }
warnings = append(warnings, warns...) warnings = append(warnings, warns...)
} }
return warnings, nil return warnings, nil
} }
// ValidateUpdate runs functions in update chain in order. // ValidateUpdate runs functions in update chain in order.
func (vc *Validator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { func (vc *Validator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
warnings := []string{} warnings := []string{}
for _, f := range vc.UpdateChain { for _, f := range vc.UpdateChain {
warns, err := f(ctx, oldObj, newObj) warns, err := f(ctx, oldObj, newObj)
if err != nil { if err != nil {
return append(warnings, warns...), err return append(warnings, warns...), err
} }
warnings = append(warnings, warns...) warnings = append(warnings, warns...)
} }
return warnings, nil return warnings, nil
} }
// ValidateDelete runs functions in deletion chain in order. // ValidateDelete runs functions in deletion chain in order.
func (vc *Validator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { func (vc *Validator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
warnings := []string{} warnings := []string{}
for _, f := range vc.DeletionChain { for _, f := range vc.DeletionChain {
warns, err := f(ctx, obj) warns, err := f(ctx, obj)
if err != nil { if err != nil {
return append(warnings, warns...), err return append(warnings, warns...), err
} }
warnings = append(warnings, warns...) warnings = append(warnings, warns...)
} }
return warnings, nil return warnings, nil
} }

View File

@ -44,10 +44,12 @@ func TestValidateCreate(t *testing.T) {
obj runtime.Object obj runtime.Object
fns []ValidateCreateFn fns []ValidateCreateFn
} }
type want struct { type want struct {
err error err error
warnings admission.Warnings warnings admission.Warnings
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -107,11 +109,13 @@ func TestValidateCreate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
v := NewValidator(WithValidateCreationFns(tc.fns...)) v := NewValidator(WithValidateCreationFns(tc.fns...))
warn, err := v.ValidateCreate(context.TODO(), tc.args.obj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { warn, err := v.ValidateCreate(context.TODO(), tc.obj)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nValidateCreate(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateCreate(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
if diff := cmp.Diff(tc.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
t.Errorf("\n%s\nValidateCreate(...): -want warnings, +got warnings\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateCreate(...): -want warnings, +got warnings\n%s\n", tc.reason, diff)
} }
}) })
@ -124,10 +128,12 @@ func TestValidateUpdate(t *testing.T) {
newObj runtime.Object newObj runtime.Object
fns []ValidateUpdateFn fns []ValidateUpdateFn
} }
type want struct { type want struct {
err error err error
warnings admission.Warnings warnings admission.Warnings
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -187,11 +193,13 @@ func TestValidateUpdate(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
v := NewValidator(WithValidateUpdateFns(tc.fns...)) v := NewValidator(WithValidateUpdateFns(tc.fns...))
warn, err := v.ValidateUpdate(context.TODO(), tc.args.oldObj, tc.args.newObj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { warn, err := v.ValidateUpdate(context.TODO(), tc.oldObj, tc.newObj)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nValidateUpdate(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateUpdate(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
if diff := cmp.Diff(tc.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
t.Errorf("\n%s\nValidateUpdate(...): -want warnings, +got warnings\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateUpdate(...): -want warnings, +got warnings\n%s\n", tc.reason, diff)
} }
}) })
@ -203,10 +211,12 @@ func TestValidateDelete(t *testing.T) {
obj runtime.Object obj runtime.Object
fns []ValidateDeleteFn fns []ValidateDeleteFn
} }
type want struct { type want struct {
err error err error
warnings admission.Warnings warnings admission.Warnings
} }
cases := map[string]struct { cases := map[string]struct {
reason string reason string
args args
@ -266,11 +276,13 @@ func TestValidateDelete(t *testing.T) {
for name, tc := range cases { for name, tc := range cases {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
v := NewValidator(WithValidateDeletionFns(tc.fns...)) v := NewValidator(WithValidateDeletionFns(tc.fns...))
warn, err := v.ValidateDelete(context.TODO(), tc.args.obj)
if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { warn, err := v.ValidateDelete(context.TODO(), tc.obj)
if diff := cmp.Diff(tc.err, err, test.EquateErrors()); diff != "" {
t.Errorf("\n%s\nValidateDelete(...): -want error, +got error\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateDelete(...): -want error, +got error\n%s\n", tc.reason, diff)
} }
if diff := cmp.Diff(tc.want.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
if diff := cmp.Diff(tc.warnings, warn, cmpopts.EquateEmpty()); diff != "" {
t.Errorf("\n%s\nValidateDelete(...): -want warnings, +got warnings\n%s\n", tc.reason, diff) t.Errorf("\n%s\nValidateDelete(...): -want warnings, +got warnings\n%s\n", tc.reason, diff)
} }
}) })