Skip to content

Commit

Permalink
Enable testing SubReconcilers with duck typed resources (#454)
Browse files Browse the repository at this point in the history
The Resource is now converted to an unstructured before being set as a
given on the fake client. Previously it would panic because the duck was
not registered on the scheme (which it should not be).

Signed-off-by: Scott Andrews <andrewssc@vmware.com>
  • Loading branch information
scothis committed Nov 6, 2023
1 parent 1dfaa1c commit d4d2708
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 2 deletions.
61 changes: 61 additions & 0 deletions reconcilers/sync_test.go
Expand Up @@ -271,3 +271,64 @@ func TestSyncReconciler(t *testing.T) {
return rtc.Metadata["SubReconciler"].(func(*testing.T, reconcilers.Config) reconcilers.SubReconciler[*resources.TestResource])(t, c)
})
}

func TestSyncReconcilerDuck(t *testing.T) {
testNamespace := "test-namespace"
testName := "test-resource"

scheme := runtime.NewScheme()
// _ = resources.AddToScheme(scheme)

resource := dies.TestDuckBlank.
APIVersion(resources.GroupVersion.String()).
Kind("TestResource").
MetadataDie(func(d *diemetav1.ObjectMetaDie) {
d.Namespace(testNamespace)
d.Name(testName)
}).
SpecDie(func(d *dies.TestDuckSpecDie) {
d.AddField("mutation", "false")
}).
StatusDie(func(d *dies.TestResourceStatusDie) {
d.ConditionsDie(
diemetav1.ConditionBlank.Type(apis.ConditionReady).Status(metav1.ConditionUnknown).Reason("Initializing"),
)
})

rts := rtesting.SubReconcilerTests[*resources.TestDuck]{
"sync no mutation": {
Resource: resource.DieReleasePtr(),
Metadata: map[string]interface{}{
"SubReconciler": func(t *testing.T, c reconcilers.Config) reconcilers.SubReconciler[*resources.TestDuck] {
return &reconcilers.SyncReconciler[*resources.TestDuck]{
Sync: func(ctx context.Context, resource *resources.TestDuck) error {
return nil
},
}
},
},
},
"sync with mutation": {
Resource: resource.DieReleasePtr(),
ExpectResource: resource.
SpecDie(func(d *dies.TestDuckSpecDie) {
d.AddField("mutation", "true")
}).
DieReleasePtr(),
Metadata: map[string]interface{}{
"SubReconciler": func(t *testing.T, c reconcilers.Config) reconcilers.SubReconciler[*resources.TestDuck] {
return &reconcilers.SyncReconciler[*resources.TestDuck]{
Sync: func(ctx context.Context, resource *resources.TestDuck) error {
resource.Spec.Fields["mutation"] = "true"
return nil
},
}
},
},
},
}

rts.Run(t, scheme, func(t *testing.T, rtc *rtesting.SubReconcilerTestCase[*resources.TestDuck], c reconcilers.Config) reconcilers.SubReconciler[*resources.TestDuck] {
return rtc.Metadata["SubReconciler"].(func(*testing.T, reconcilers.Config) reconcilers.SubReconciler[*resources.TestDuck])(t, c)
})
}
16 changes: 14 additions & 2 deletions testing/subreconciler.go
Expand Up @@ -14,9 +14,11 @@ import (
"github.com/go-logr/logr/testr"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/vmware-labs/reconciler-runtime/duck"
"github.com/vmware-labs/reconciler-runtime/internal"
"github.com/vmware-labs/reconciler-runtime/reconcilers"
rtime "github.com/vmware-labs/reconciler-runtime/time"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -182,12 +184,22 @@ func (tc *SubReconcilerTestCase[T]) Run(t *testing.T, scheme *runtime.Scheme, fa
}()
}

var givenResource client.Object = tc.Resource
if duck.IsDuck(givenResource, scheme) {
// convert the given resource duck to Unstructured so that it can be created on the fake client
uobj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tc.Resource)
if err != nil {
t.Fatalf("unable to convert Resource to Unstructured: %s", err)
}
givenResource = &unstructured.Unstructured{Object: uobj}
}

expectConfig := &ExpectConfig{
Name: "default",
Scheme: scheme,
StatusSubResourceTypes: tc.StatusSubResourceTypes,
GivenObjects: append(tc.GivenObjects, tc.Resource),
APIGivenObjects: append(tc.APIGivenObjects, tc.Resource),
GivenObjects: append(tc.GivenObjects, givenResource),
APIGivenObjects: append(tc.APIGivenObjects, givenResource),
WithClientBuilder: tc.WithClientBuilder,
WithReactors: tc.WithReactors,
GivenTracks: tc.GivenTracks,
Expand Down

0 comments on commit d4d2708

Please sign in to comment.