Skip to content

Commit

Permalink
Implement GetExternalTags to return Crossplane tags for managed resou…
Browse files Browse the repository at this point in the history
…rce controllers to tag their external resources

Signed-off-by: Muvaffak Onus <onus.muvaffak@gmail.com>
  • Loading branch information
muvaf committed Mar 3, 2020
1 parent e8a71bf commit 0232d94
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 10 deletions.
16 changes: 6 additions & 10 deletions pkg/meta/meta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,15 +810,13 @@ func TestWasCreated(t *testing.T) {
}

func TestGetExternalName(t *testing.T) {
testName := "my-external-name"

cases := map[string]struct {
o metav1.Object
want string
}{
"ExternalNameExists": {
o: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ExternalNameAnnotationKey: testName}}},
want: testName,
o: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ExternalNameAnnotationKey: name}}},
want: name,
},
"NoExternalName": {
o: &corev1.Pod{},
Expand All @@ -830,32 +828,30 @@ func TestGetExternalName(t *testing.T) {
t.Run(name, func(t *testing.T) {
got := GetExternalName(tc.o)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("WasCreated(...): -want, +got:\n%s", diff)
t.Errorf("GetExternalName(...): -want, +got:\n%s", diff)
}
})
}
}

func TestSetExternalName(t *testing.T) {
testName := "my-external-name"

cases := map[string]struct {
o metav1.Object
name string
want metav1.Object
}{
"SetsTheCorrectKey": {
o: &corev1.Pod{},
name: testName,
want: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ExternalNameAnnotationKey: testName}}},
name: name,
want: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{ExternalNameAnnotationKey: name}}},
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
SetExternalName(tc.o, tc.name)
if diff := cmp.Diff(tc.want, tc.o); diff != "" {
t.Errorf("WasCreated(...): -want, +got:\n%s", diff)
t.Errorf("SetExternalName(...): -want, +got:\n%s", diff)
}
})
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/resource/fake/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ func (m *ManagedResourceReferencer) SetResourceReference(r *corev1.ObjectReferen
// GetResourceReference gets the ResourceReference.
func (m *ManagedResourceReferencer) GetResourceReference() *corev1.ObjectReference { return m.Ref }

// ProviderReferencer is a mock that implements ProviderReferencer interface.
type ProviderReferencer struct{ Ref *corev1.ObjectReference }

// SetProviderReference sets the ProviderReference.
func (m *ProviderReferencer) SetProviderReference(p *corev1.ObjectReference) { m.Ref = p }

// GetProviderReference gets the ProviderReference.
func (m *ProviderReferencer) GetProviderReference() *corev1.ObjectReference { return m.Ref }

// LocalConnectionSecretWriterTo is a mock that implements LocalConnectionSecretWriterTo interface.
type LocalConnectionSecretWriterTo struct {
Ref *v1alpha1.LocalSecretReference
Expand Down Expand Up @@ -200,6 +209,7 @@ type Managed struct {
metav1.ObjectMeta
ClassReferencer
ClaimReferencer
ProviderReferencer
ConnectionSecretWriterTo
Reclaimer
v1alpha1.ConditionedStatus
Expand Down
7 changes: 7 additions & 0 deletions pkg/resource/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ type CredentialsSecretReferencer interface {
SetCredentialsSecretReference(r v1alpha1.SecretKeySelector)
}

// A ProviderReferencer may reference a provider resource.
type ProviderReferencer interface {
GetProviderReference() *corev1.ObjectReference
SetProviderReference(p *corev1.ObjectReference)
}

// A Claim is a Kubernetes object representing an abstract resource claim (e.g.
// an SQL database) that may be bound to a concrete managed resource (e.g. a
// CloudSQL instance).
Expand Down Expand Up @@ -122,6 +128,7 @@ type Managed interface {

ClassReferencer
ClaimReferencer
ProviderReferencer
ConnectionSecretWriterTo
Reclaimer

Expand Down
25 changes: 25 additions & 0 deletions pkg/resource/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ const (
AnnotationDelimiter = "/"
)

// External resources are tagged/labelled with the following keys in the cloud
// provider API if the type supports.
const (
ExternalResourceTagKeyKind = "crossplane.io/kind"
ExternalResourceTagKeyName = "crossplane.io/name"
ExternalResourceTagKeyClass = "crossplane.io/class"
ExternalResourceTagKeyProvider = "crossplane.io/provider"
)

// A ClaimKind contains the type metadata for a kind of resource claim.
type ClaimKind schema.GroupVersionKind

Expand Down Expand Up @@ -227,3 +236,19 @@ func IsBound(b Bindable) bool {
func IsConditionTrue(c v1alpha1.Condition) bool {
return c.Status == corev1.ConditionTrue
}

// GetExternalTags returns the identifying tags to be used to tag the external
// resource in provider API.
func GetExternalTags(mg Managed) map[string]string {
tags := map[string]string{
ExternalResourceTagKeyKind: mg.GetObjectKind().GroupVersionKind().GroupKind().String(),
ExternalResourceTagKeyName: mg.GetName(),
}
if mg.GetClassReference() != nil {
tags[ExternalResourceTagKeyClass] = mg.GetClassReference().Name
}
if mg.GetProviderReference() != nil {
tags[ExternalResourceTagKeyProvider] = mg.GetProviderReference().Name
}
return tags
}
33 changes: 33 additions & 0 deletions pkg/resource/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,36 @@ func TestIsConditionTrue(t *testing.T) {
})
}
}

func TestGetExternalTags(t *testing.T) {
provName := "prov"
className := "classy"
cases := map[string]struct {
o Managed
want map[string]string
}{
"Successful": {
o: &fake.Managed{ObjectMeta: metav1.ObjectMeta{
Name: name,
},
ProviderReferencer: fake.ProviderReferencer{Ref: &corev1.ObjectReference{Name: provName}},
ClassReferencer: fake.ClassReferencer{Ref: &corev1.ObjectReference{Name: className}},
},
want: map[string]string{
ExternalResourceTagKeyKind: (&fake.Managed{}).GetObjectKind().GroupVersionKind().GroupKind().String(),
ExternalResourceTagKeyName: name,
ExternalResourceTagKeyProvider: provName,
ExternalResourceTagKeyClass: className,
},
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
got := GetExternalTags(tc.o)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Errorf("GetExternalTags(...): -want, +got:\n%s", diff)
}
})
}
}

0 comments on commit 0232d94

Please sign in to comment.