Skip to content

Commit 6dd4a27

Browse files
authored
Add SecretKeyReference comparison functions to pkg/compare (#84)
Issue aws-controllers-k8s/community#1239 Currently, the code generator doesn't correctly generate delta comparison functions for secret fields, because the runtime doesn't contain any helper functions that can help in computing the delta of `SecretKeyReference` and `SecretKeyReference` slices. This patch adds two functions to help compare two instances or slices of `SecretKeyReference`. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent a548683 commit 6dd4a27

File tree

2 files changed

+284
-0
lines changed

2 files changed

+284
-0
lines changed

pkg/compare/secret_reference.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package compare
15+
16+
import (
17+
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
18+
)
19+
20+
// SecretKeyReferenceEqual returns true if the supplied secret key references
21+
// are equal.
22+
func SecretKeyReferenceEqual(a, b *ackv1alpha1.SecretKeyReference) bool {
23+
if HasNilDifference(a, b) {
24+
return false
25+
}
26+
return a.Name == b.Name &&
27+
a.Namespace == b.Namespace &&
28+
a.Key == b.Key
29+
}
30+
31+
// SliceSecretKeyReferenceEqual returns true if the supplied slices of secret
32+
// key reference pointers contain the exact same elements.
33+
func SliceSecretKeyReferenceEqual(
34+
a, b []*ackv1alpha1.SecretKeyReference,
35+
) bool {
36+
equal, _, _ := CompareSecretKeyReferences(a, b)
37+
return equal
38+
}
39+
40+
// CompareSecretKeyReference returns true if the supplied slices of secret
41+
// key reference pointers contain the exact same elements. It will also return 2
42+
// slices containing elements contained in a that aren't in b, and elements
43+
// contained in b that aren't in a, respectively. The comparison doesn't
44+
// take into consideration the order of elements.
45+
// Duplicated elements will not impact the behaviour of this function, meaning
46+
// that the function will always return only unique instances of the added/removed
47+
// elements.
48+
func CompareSecretKeyReferences(
49+
a, b []*ackv1alpha1.SecretKeyReference,
50+
) (equal bool, added, removed []*ackv1alpha1.SecretKeyReference) {
51+
// finding the removed elements
52+
for _, aVal := range a {
53+
found := false
54+
for _, bVal := range b {
55+
if SecretKeyReferenceEqual(aVal, bVal) {
56+
found = true
57+
break
58+
}
59+
}
60+
if !found {
61+
removed = append(removed, aVal)
62+
continue
63+
}
64+
}
65+
// finding the added elements
66+
for _, bVal := range b {
67+
found := false
68+
for _, aVal := range a {
69+
if SecretKeyReferenceEqual(aVal, bVal) {
70+
found = true
71+
break
72+
}
73+
}
74+
if !found {
75+
added = append(added, bVal)
76+
}
77+
}
78+
if len(added) == 0 && len(removed) == 0 {
79+
equal = true
80+
}
81+
return equal, cleanUpDuplicateSecretReferences(added), cleanUpDuplicateSecretReferences(removed)
82+
}
83+
84+
// cleanUpDuplicateSecretReferences removes duplicate elements from a given slice
85+
// of secret key references.
86+
func cleanUpDuplicateSecretReferences(
87+
a []*ackv1alpha1.SecretKeyReference,
88+
) (uniqueSecretReferences []*ackv1alpha1.SecretKeyReference) {
89+
for i := range a {
90+
foundDuplicate := false
91+
// just walk the array from index i and do not append anything if a
92+
// duplicate is found.
93+
for j := i + 1; j < len(a); j++ {
94+
if SecretKeyReferenceEqual(a[i], a[j]) {
95+
foundDuplicate = true
96+
break
97+
}
98+
}
99+
if !foundDuplicate {
100+
uniqueSecretReferences = append(uniqueSecretReferences, a[i])
101+
}
102+
}
103+
return uniqueSecretReferences
104+
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package compare_test
15+
16+
import (
17+
"reflect"
18+
"testing"
19+
20+
k8scorev1 "k8s.io/api/core/v1"
21+
22+
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
23+
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
24+
)
25+
26+
// newSecretReference is used a instantiate a secret reference used for testing purposes.
27+
func newSecretReference(name string) *ackv1alpha1.SecretKeyReference {
28+
return &ackv1alpha1.SecretKeyReference{
29+
SecretReference: k8scorev1.SecretReference{
30+
Namespace: "default",
31+
Name: name,
32+
},
33+
Key: "password",
34+
}
35+
}
36+
37+
func TestSliceSecretKeyReferenceEqual(t *testing.T) {
38+
type args struct {
39+
a []*ackv1alpha1.SecretKeyReference
40+
b []*ackv1alpha1.SecretKeyReference
41+
}
42+
tests := []struct {
43+
name string
44+
args args
45+
wantEqual bool
46+
wantAdded []*ackv1alpha1.SecretKeyReference
47+
wantRemoved []*ackv1alpha1.SecretKeyReference
48+
}{
49+
{
50+
name: "empty slices",
51+
args: args{
52+
a: nil,
53+
b: nil,
54+
},
55+
wantEqual: true,
56+
},
57+
{
58+
name: "empty slices - only one non nil slice",
59+
args: args{
60+
a: nil,
61+
b: []*ackv1alpha1.SecretKeyReference{},
62+
},
63+
wantEqual: true,
64+
},
65+
{
66+
name: "empty slices - two non nil slices",
67+
args: args{
68+
a: []*ackv1alpha1.SecretKeyReference{},
69+
b: []*ackv1alpha1.SecretKeyReference{},
70+
},
71+
wantEqual: true,
72+
},
73+
{
74+
name: "added secrets",
75+
args: args{
76+
a: []*ackv1alpha1.SecretKeyReference{},
77+
b: []*ackv1alpha1.SecretKeyReference{
78+
newSecretReference("secret1"),
79+
newSecretReference("secret2"),
80+
},
81+
},
82+
wantEqual: false,
83+
wantAdded: []*ackv1alpha1.SecretKeyReference{
84+
newSecretReference("secret1"),
85+
newSecretReference("secret2"),
86+
},
87+
},
88+
{
89+
name: "removed secrets",
90+
args: args{
91+
a: []*ackv1alpha1.SecretKeyReference{
92+
newSecretReference("secret1"),
93+
newSecretReference("secret2"),
94+
},
95+
b: []*ackv1alpha1.SecretKeyReference{},
96+
},
97+
wantEqual: false,
98+
wantRemoved: []*ackv1alpha1.SecretKeyReference{
99+
newSecretReference("secret1"),
100+
newSecretReference("secret2"),
101+
},
102+
},
103+
{
104+
name: "added and removed secrets",
105+
args: args{
106+
a: []*ackv1alpha1.SecretKeyReference{
107+
newSecretReference("secret1"),
108+
},
109+
b: []*ackv1alpha1.SecretKeyReference{
110+
newSecretReference("secret2"),
111+
},
112+
},
113+
wantEqual: false,
114+
wantAdded: []*ackv1alpha1.SecretKeyReference{
115+
newSecretReference("secret2"),
116+
},
117+
wantRemoved: []*ackv1alpha1.SecretKeyReference{
118+
newSecretReference("secret1"),
119+
},
120+
},
121+
{
122+
name: "equal slices with duplicate elements",
123+
args: args{
124+
a: []*ackv1alpha1.SecretKeyReference{
125+
newSecretReference("secret1"),
126+
newSecretReference("secret1"),
127+
newSecretReference("secret1"),
128+
newSecretReference("secret2"),
129+
},
130+
b: []*ackv1alpha1.SecretKeyReference{
131+
newSecretReference("secret2"),
132+
newSecretReference("secret2"),
133+
newSecretReference("secret2"),
134+
newSecretReference("secret1"),
135+
},
136+
},
137+
wantEqual: true,
138+
wantAdded: nil,
139+
wantRemoved: nil,
140+
},
141+
{
142+
name: "added and removed secrets with duplicate elements",
143+
args: args{
144+
a: []*ackv1alpha1.SecretKeyReference{
145+
newSecretReference("secret1"),
146+
newSecretReference("secret2"),
147+
newSecretReference("secret2"),
148+
newSecretReference("secret3"),
149+
},
150+
b: []*ackv1alpha1.SecretKeyReference{
151+
newSecretReference("secret3"),
152+
newSecretReference("secret4"),
153+
newSecretReference("secret4"),
154+
},
155+
},
156+
wantEqual: false,
157+
wantAdded: []*ackv1alpha1.SecretKeyReference{
158+
newSecretReference("secret4"),
159+
},
160+
wantRemoved: []*ackv1alpha1.SecretKeyReference{
161+
newSecretReference("secret1"),
162+
newSecretReference("secret2"),
163+
},
164+
},
165+
}
166+
for _, tt := range tests {
167+
t.Run(tt.name, func(t *testing.T) {
168+
gotEqual, gotAdded, gotRemoved := ackcompare.CompareSecretKeyReferences(tt.args.a, tt.args.b)
169+
if gotEqual != tt.wantEqual {
170+
t.Errorf("SliceSecretKeyReferenceEqual() gotEqual = %v, want %v", gotEqual, tt.wantEqual)
171+
}
172+
if !reflect.DeepEqual(gotAdded, tt.wantAdded) {
173+
t.Errorf("SliceSecretKeyReferenceEqual() gotAdded = %v, want %v", gotAdded, tt.wantAdded)
174+
}
175+
if !reflect.DeepEqual(gotRemoved, tt.wantRemoved) {
176+
t.Errorf("SliceSecretKeyReferenceEqual() gotRemoved = %v, want %v", gotRemoved, tt.wantRemoved)
177+
}
178+
})
179+
}
180+
}

0 commit comments

Comments
 (0)