Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions pkg/compare/secret_reference.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package compare

import (
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
)

// SecretKeyReferenceEqual returns true if the supplied secret key references
// are equal.
func SecretKeyReferenceEqual(a, b *ackv1alpha1.SecretKeyReference) bool {
if HasNilDifference(a, b) {
return false
}
return a.Name == b.Name &&
a.Namespace == b.Namespace &&
a.Key == b.Key
}

// SliceSecretKeyReferenceEqual returns true if the supplied slices of secret
// key reference pointers contain the exact same elements.
func SliceSecretKeyReferenceEqual(
a, b []*ackv1alpha1.SecretKeyReference,
) bool {
equal, _, _ := CompareSecretKeyReferences(a, b)
return equal
}

// CompareSecretKeyReference returns true if the supplied slices of secret
// key reference pointers contain the exact same elements. It will also return 2
// slices containing elements contained in a that aren't in b, and elements
// contained in b that aren't in a, respectively. The comparison doesn't
// take into consideration the order of elements.
// Duplicated elements will not impact the behaviour of this function, meaning
// that the function will always return only unique instances of the added/removed
// elements.
func CompareSecretKeyReferences(
a, b []*ackv1alpha1.SecretKeyReference,
) (equal bool, added, removed []*ackv1alpha1.SecretKeyReference) {
// finding the removed elements
for _, aVal := range a {
found := false
for _, bVal := range b {
if SecretKeyReferenceEqual(aVal, bVal) {
found = true
break
}
}
if !found {
removed = append(removed, aVal)
continue
}
}
// finding the added elements
for _, bVal := range b {
found := false
for _, aVal := range a {
if SecretKeyReferenceEqual(aVal, bVal) {
found = true
break
}
}
if !found {
added = append(added, bVal)
}
}
if len(added) == 0 && len(removed) == 0 {
equal = true
}
return equal, cleanUpDuplicateSecretReferences(added), cleanUpDuplicateSecretReferences(removed)
}

// cleanUpDuplicateSecretReferences removes duplicate elements from a given slice
// of secret key references.
func cleanUpDuplicateSecretReferences(
a []*ackv1alpha1.SecretKeyReference,
) (uniqueSecretReferences []*ackv1alpha1.SecretKeyReference) {
for i := range a {
foundDuplicate := false
// just walk the array from index i and do not append anything if a
// duplicate is found.
for j := i + 1; j < len(a); j++ {
if SecretKeyReferenceEqual(a[i], a[j]) {
foundDuplicate = true
break
}
}
if !foundDuplicate {
uniqueSecretReferences = append(uniqueSecretReferences, a[i])
}
}
return uniqueSecretReferences
}
180 changes: 180 additions & 0 deletions pkg/compare/secret_reference_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package compare_test

import (
"reflect"
"testing"

k8scorev1 "k8s.io/api/core/v1"

ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
)

// newSecretReference is used a instantiate a secret reference used for testing purposes.
func newSecretReference(name string) *ackv1alpha1.SecretKeyReference {
return &ackv1alpha1.SecretKeyReference{
SecretReference: k8scorev1.SecretReference{
Namespace: "default",
Name: name,
},
Key: "password",
}
}

func TestSliceSecretKeyReferenceEqual(t *testing.T) {
type args struct {
a []*ackv1alpha1.SecretKeyReference
b []*ackv1alpha1.SecretKeyReference
}
tests := []struct {
name string
args args
wantEqual bool
wantAdded []*ackv1alpha1.SecretKeyReference
wantRemoved []*ackv1alpha1.SecretKeyReference
}{
{
name: "empty slices",
args: args{
a: nil,
b: nil,
},
wantEqual: true,
},
{
name: "empty slices - only one non nil slice",
args: args{
a: nil,
b: []*ackv1alpha1.SecretKeyReference{},
},
wantEqual: true,
},
{
name: "empty slices - two non nil slices",
args: args{
a: []*ackv1alpha1.SecretKeyReference{},
b: []*ackv1alpha1.SecretKeyReference{},
},
wantEqual: true,
},
{
name: "added secrets",
args: args{
a: []*ackv1alpha1.SecretKeyReference{},
b: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
},
},
wantEqual: false,
wantAdded: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
},
},
{
name: "removed secrets",
args: args{
a: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
},
b: []*ackv1alpha1.SecretKeyReference{},
},
wantEqual: false,
wantRemoved: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
},
},
{
name: "added and removed secrets",
args: args{
a: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
},
b: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret2"),
},
},
wantEqual: false,
wantAdded: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret2"),
},
wantRemoved: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
},
},
{
name: "equal slices with duplicate elements",
args: args{
a: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret1"),
newSecretReference("secret1"),
newSecretReference("secret2"),
},
b: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret2"),
newSecretReference("secret2"),
newSecretReference("secret2"),
newSecretReference("secret1"),
},
},
wantEqual: true,
wantAdded: nil,
wantRemoved: nil,
},
{
name: "added and removed secrets with duplicate elements",
args: args{
a: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
newSecretReference("secret2"),
newSecretReference("secret3"),
},
b: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret3"),
newSecretReference("secret4"),
newSecretReference("secret4"),
},
},
wantEqual: false,
wantAdded: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret4"),
},
wantRemoved: []*ackv1alpha1.SecretKeyReference{
newSecretReference("secret1"),
newSecretReference("secret2"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotEqual, gotAdded, gotRemoved := ackcompare.CompareSecretKeyReferences(tt.args.a, tt.args.b)
if gotEqual != tt.wantEqual {
t.Errorf("SliceSecretKeyReferenceEqual() gotEqual = %v, want %v", gotEqual, tt.wantEqual)
}
if !reflect.DeepEqual(gotAdded, tt.wantAdded) {
t.Errorf("SliceSecretKeyReferenceEqual() gotAdded = %v, want %v", gotAdded, tt.wantAdded)
}
if !reflect.DeepEqual(gotRemoved, tt.wantRemoved) {
t.Errorf("SliceSecretKeyReferenceEqual() gotRemoved = %v, want %v", gotRemoved, tt.wantRemoved)
}
})
}
}