Skip to content

Commit

Permalink
Add unit tests for SSA
Browse files Browse the repository at this point in the history
Signed-off-by: Hasan Turken <[email protected]>
  • Loading branch information
turkenh committed Aug 23, 2023
1 parent 890b254 commit bad5f77
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 13 deletions.
22 changes: 22 additions & 0 deletions internal/controller/object/fake/mocks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fake

import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

// An UnstructuredExtractor mocks an UnstructuredExtractor.
// https://pkg.go.dev/k8s.io/client-go/applyconfigurations/meta/v1#UnstructuredExtractor
type UnstructuredExtractor struct {
ExtractFn func(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error)
ExtractStatusFn func(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error)
}

// Extract mocks the Extract method of an UnstructuredExtractor
func (u *UnstructuredExtractor) Extract(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error) {
return u.ExtractFn(object, fieldManager)
}

// ExtractStatus mocks the ExtractStatus method of an UnstructuredExtractor
func (u *UnstructuredExtractor) ExtractStatus(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error) {
return u.ExtractStatusFn(object, fieldManager)
}
161 changes: 148 additions & 13 deletions internal/controller/object/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -44,6 +45,7 @@ import (

"github.com/crossplane-contrib/provider-kubernetes/apis/object/v1alpha1"
kubernetesv1alpha1 "github.com/crossplane-contrib/provider-kubernetes/apis/v1alpha1"
"github.com/crossplane-contrib/provider-kubernetes/internal/controller/object/fake"
)

const (
Expand Down Expand Up @@ -505,8 +507,9 @@ func TestConnectorConnect(t *testing.T) {

func TestExternalObserve(t *testing.T) {
type args struct {
client resource.ClientApplicator
mg resource.Managed
client resource.ClientApplicator
mg resource.Managed
extractor v1.UnstructuredExtractor
}
type want struct {
out managed.ExternalObservation
Expand Down Expand Up @@ -647,6 +650,69 @@ func TestExternalObserve(t *testing.T) {
err: nil,
},
},
"SSAUpToDate": {
args: args{
mg: kubernetesObject(),
client: resource.ClientApplicator{
Client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
*obj.(*unstructured.Unstructured) = *externalResource(func(res *unstructured.Unstructured) {
// We should only care about the extracted fields, not the entire object.
// So, the below labels should not affect the observation since we
// don't care about them (no labels in the manifest).
res.SetLabels(map[string]string{"some-label": "some-value"})
})
return nil
}),
},
},
extractor: &fake.UnstructuredExtractor{
ExtractFn: func(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error) {
return externalResource(), nil
},
},
},
want: want{
out: managed.ExternalObservation{
ResourceExists: true,
ResourceUpToDate: true,
ConnectionDetails: managed.ConnectionDetails{},
},
err: nil,
},
},
"SSANotUpToDate": {
args: args{
mg: kubernetesObject(func(obj *v1alpha1.Object) {
obj.SetLabels(map[string]string{"some-label": "other-value"})
}),
client: resource.ClientApplicator{
Client: &test.MockClient{
MockGet: test.NewMockGetFn(nil, func(obj client.Object) error {
*obj.(*unstructured.Unstructured) = *externalResource(func(res *unstructured.Unstructured) {
res.SetLabels(map[string]string{"some-label": "some-value"})
})
return nil
}),
},
},
extractor: &fake.UnstructuredExtractor{
ExtractFn: func(object *unstructured.Unstructured, fieldManager string) (*unstructured.Unstructured, error) {
return externalResource(func(res *unstructured.Unstructured) {
res.SetLabels(map[string]string{"some-label": "some-value"})
}), nil
},
},
},
want: want{
out: managed.ExternalObservation{
ResourceExists: true,
ResourceUpToDate: false,
ConnectionDetails: nil,
},
err: nil,
},
},
"UpToDateIfManagementPolicyDefined": {
args: args{
mg: kubernetesObject(func(obj *v1alpha1.Object) {
Expand Down Expand Up @@ -893,9 +959,10 @@ func TestExternalObserve(t *testing.T) {
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
e := &external{
logger: logging.NewNopLogger(),
client: tc.args.client,
localClient: tc.args.client,
logger: logging.NewNopLogger(),
client: tc.args.client,
localClient: tc.args.client,
applyExtractor: tc.args.extractor,
}
got, gotErr := e.Observe(context.Background(), tc.args.mg)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
Expand All @@ -911,8 +978,9 @@ func TestExternalObserve(t *testing.T) {

func TestExternalCreate(t *testing.T) {
type args struct {
client resource.ClientApplicator
mg resource.Managed
client resource.ClientApplicator
mg resource.Managed
extractor v1.UnstructuredExtractor
}
type want struct {
out managed.ExternalCreation
Expand Down Expand Up @@ -1009,12 +1077,45 @@ func TestExternalCreate(t *testing.T) {
err: nil,
},
},
"SSAApplyFailed": {
args: args{
mg: kubernetesObject(),
client: resource.ClientApplicator{
Applicator: resource.ApplyFn(func(ctx context.Context, obj client.Object, op ...resource.ApplyOption) error {
return errBoom
}),
},
extractor: &fake.UnstructuredExtractor{},
},
want: want{
err: errors.Wrap(errBoom, errApplyObject),
},
},
"SSASuccess": {
args: args{
mg: kubernetesObject(),
client: resource.ClientApplicator{
Applicator: resource.ApplyFn(func(ctx context.Context, obj client.Object, op ...resource.ApplyOption) error {
_, ok := obj.GetAnnotations()[corev1.LastAppliedConfigAnnotation]
if ok {
t.Errorf("Last applied annotation should not be set with SSA apply")
}
return nil
}),
},
extractor: &fake.UnstructuredExtractor{},
},
want: want{
err: nil,
},
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
e := &external{
logger: logging.NewNopLogger(),
client: tc.args.client,
logger: logging.NewNopLogger(),
client: tc.args.client,
applyExtractor: tc.args.extractor,
}
got, gotErr := e.Create(context.Background(), tc.args.mg)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
Expand All @@ -1030,8 +1131,9 @@ func TestExternalCreate(t *testing.T) {

func TestExternalUpdate(t *testing.T) {
type args struct {
client resource.ClientApplicator
mg resource.Managed
client resource.ClientApplicator
mg resource.Managed
extractor v1.UnstructuredExtractor
}
type want struct {
out managed.ExternalUpdate
Expand Down Expand Up @@ -1116,12 +1218,45 @@ func TestExternalUpdate(t *testing.T) {
err: nil,
},
},
"SSAApplyFailed": {
args: args{
mg: kubernetesObject(),
client: resource.ClientApplicator{
Applicator: resource.ApplyFn(func(ctx context.Context, obj client.Object, op ...resource.ApplyOption) error {
return errBoom
}),
},
extractor: &fake.UnstructuredExtractor{},
},
want: want{
err: errors.Wrap(errBoom, errApplyObject),
},
},
"SSASuccess": {
args: args{
mg: kubernetesObject(),
client: resource.ClientApplicator{
Applicator: resource.ApplyFn(func(ctx context.Context, obj client.Object, op ...resource.ApplyOption) error {
_, ok := obj.GetAnnotations()[corev1.LastAppliedConfigAnnotation]
if ok {
t.Errorf("Last applied annotation should not be set with SSA apply")
}
return nil
}),
},
extractor: &fake.UnstructuredExtractor{},
},
want: want{
err: nil,
},
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
e := &external{
logger: logging.NewNopLogger(),
client: tc.args.client,
logger: logging.NewNopLogger(),
client: tc.args.client,
applyExtractor: tc.args.extractor,
}
got, gotErr := e.Update(context.Background(), tc.args.mg)
if diff := cmp.Diff(tc.want.err, gotErr, test.EquateErrors()); diff != "" {
Expand Down

0 comments on commit bad5f77

Please sign in to comment.