From 8f4aad453743bd2c0032277879f6c8570088d032 Mon Sep 17 00:00:00 2001 From: Scott Andrews Date: Tue, 3 May 2022 12:55:34 -0400 Subject: [PATCH] Allow OurChild to make decisions with the parent and child objects This is a breaking change, but OurChild was fairly useless without knowing the parent resource that that child resource is owned by. Signed-off-by: Scott Andrews --- reconcilers/reconcilers.go | 11 +++++---- reconcilers/reconcilers_validate_test.go | 30 +++++++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/reconcilers/reconcilers.go b/reconcilers/reconcilers.go index 1acdeb5..31d9436 100644 --- a/reconcilers/reconcilers.go +++ b/reconcilers/reconcilers.go @@ -538,7 +538,7 @@ type ChildReconciler struct { // children match. // // Expected function signature: - // func(child client.Object) bool + // func(parent, child client.Object) bool // // +optional OurChild interface{} @@ -666,13 +666,14 @@ func (r *ChildReconciler) validate(ctx context.Context) error { // validate OurChild function signature: // nil - // func(child client.Object) interface{} + // func(parent, child client.Object) bool if r.OurChild != nil { fn := reflect.TypeOf(r.OurChild) - if fn.NumIn() != 1 || fn.NumOut() != 1 || - !reflect.TypeOf(r.ChildType).AssignableTo(fn.In(0)) || + if fn.NumIn() != 2 || fn.NumOut() != 1 || + !reflect.TypeOf(castParentType).AssignableTo(fn.In(0)) || + !reflect.TypeOf(r.ChildType).AssignableTo(fn.In(1)) || fn.Out(0).Kind() != reflect.Bool { - return fmt.Errorf("ChildReconciler must implement OurChild: nil | func(%s) bool, found: %s", reflect.TypeOf(r.ChildType), fn) + return fmt.Errorf("ChildReconciler must implement OurChild: nil | func(%s, %s) bool, found: %s", reflect.TypeOf(castParentType), reflect.TypeOf(r.ChildType), fn) } } diff --git a/reconcilers/reconcilers_validate_test.go b/reconcilers/reconcilers_validate_test.go index b4a802d..5ae3678 100644 --- a/reconcilers/reconcilers_validate_test.go +++ b/reconcilers/reconcilers_validate_test.go @@ -550,7 +550,7 @@ func TestChildReconciler_validate(t *testing.T) { ReflectChildStatusOnParent: func(parent *corev1.ConfigMap, child *corev1.Pod, err error) {}, MergeBeforeUpdate: func(current, desired *corev1.Pod) {}, SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, - OurChild: func(child *corev1.Pod) bool { return false }, + OurChild: func(parent *corev1.ConfigMap, child *corev1.Pod) bool { return false }, }, }, { @@ -565,7 +565,7 @@ func TestChildReconciler_validate(t *testing.T) { SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, OurChild: func() bool { return false }, }, - shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.Pod) bool, found: func() bool", + shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.ConfigMap, *v1.Pod) bool, found: func() bool", }, { name: "OurChild in 1", @@ -577,9 +577,23 @@ func TestChildReconciler_validate(t *testing.T) { ReflectChildStatusOnParent: func(parent *corev1.ConfigMap, child *corev1.Pod, err error) {}, MergeBeforeUpdate: func(current, desired *corev1.Pod) {}, SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, - OurChild: func(child *corev1.Secret) bool { return false }, + OurChild: func(parent *corev1.ConfigMap, child *corev1.Secret) bool { return false }, }, - shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.Pod) bool, found: func(*v1.Secret) bool", + shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.ConfigMap, *v1.Pod) bool, found: func(*v1.ConfigMap, *v1.Secret) bool", + }, + { + name: "OurChild in 2", + parent: &corev1.ConfigMap{}, + reconciler: &ChildReconciler{ + ChildType: &corev1.Pod{}, + ChildListType: &corev1.PodList{}, + DesiredChild: func(ctx context.Context, parent *corev1.ConfigMap) (*corev1.Pod, error) { return nil, nil }, + ReflectChildStatusOnParent: func(parent *corev1.ConfigMap, child *corev1.Pod, err error) {}, + MergeBeforeUpdate: func(current, desired *corev1.Pod) {}, + SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, + OurChild: func(parent *corev1.Secret, child *corev1.Pod) bool { return false }, + }, + shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.ConfigMap, *v1.Pod) bool, found: func(*v1.Secret, *v1.Pod) bool", }, { name: "OurChild num out", @@ -591,9 +605,9 @@ func TestChildReconciler_validate(t *testing.T) { ReflectChildStatusOnParent: func(parent *corev1.ConfigMap, child *corev1.Pod, err error) {}, MergeBeforeUpdate: func(current, desired *corev1.Pod) {}, SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, - OurChild: func(child *corev1.Pod) {}, + OurChild: func(parent *corev1.ConfigMap, child *corev1.Pod) {}, }, - shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.Pod) bool, found: func(*v1.Pod)", + shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.ConfigMap, *v1.Pod) bool, found: func(*v1.ConfigMap, *v1.Pod)", }, { name: "OurChild out 1", @@ -605,9 +619,9 @@ func TestChildReconciler_validate(t *testing.T) { ReflectChildStatusOnParent: func(parent *corev1.ConfigMap, child *corev1.Pod, err error) {}, MergeBeforeUpdate: func(current, desired *corev1.Pod) {}, SemanticEquals: func(a1, a2 *corev1.Pod) bool { return false }, - OurChild: func(child *corev1.Pod) *corev1.Pod { return child }, + OurChild: func(parent *corev1.ConfigMap, child *corev1.Pod) *corev1.Pod { return child }, }, - shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.Pod) bool, found: func(*v1.Pod) *v1.Pod", + shouldErr: "ChildReconciler must implement OurChild: nil | func(*v1.ConfigMap, *v1.Pod) bool, found: func(*v1.ConfigMap, *v1.Pod) *v1.Pod", }, { name: "Sanitize",