From 0783f07ff371290dea401c13025fcc4774149e3b Mon Sep 17 00:00:00 2001 From: Weston Haught Date: Wed, 29 Apr 2020 10:40:32 -0700 Subject: [PATCH 1/2] Set observed gen in gen-reconciler --- .../generators/reconciler_reconciler.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/codegen/cmd/injection-gen/generators/reconciler_reconciler.go b/codegen/cmd/injection-gen/generators/reconciler_reconciler.go index e24cc321f9..048bde86e9 100644 --- a/codegen/cmd/injection-gen/generators/reconciler_reconciler.go +++ b/codegen/cmd/injection-gen/generators/reconciler_reconciler.go @@ -106,6 +106,7 @@ func (g *reconcilerReconcilerGenerator) GenerateType(c *generator.Context, t *ty // Deps "clientsetInterface": c.Universe.Type(types.Name{Name: "Interface", Package: g.clientsetPkg}), "resourceLister": c.Universe.Type(types.Name{Name: g.listerName, Package: g.listerPkg}), + "conditionSet": c.Universe.Type(types.Name{Name: "ConditionSet", Package: "knative.dev/pkg/apis"}), // K8s types "recordEventRecorder": c.Universe.Type(types.Name{Name: "EventRecorder", Package: "k8s.io/client-go/tools/record"}), // methods @@ -211,6 +212,9 @@ type reconcilerImpl struct { // Check that our Reconciler implements controller.Reconciler var _ controller.Reconciler = (*reconcilerImpl)(nil) +// Creates a {{.conditionSet|raw}} to manipulate resource status conditions +var condSet = apis.NewLivingConditionSet() + ` var reconcilerNewReconciler = ` @@ -320,6 +324,22 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro } } + // Bump observed generation to denote that we have processed this + // generation regardless of success or failure. + resource.Status.ObservedGeneration = resource.Generation + + if resource.Status.ObservedGeneration != original.Status.ObservedGeneration && reconcileEvent != nil { + originalRc := original.Status.GetCondition(apis.ConditionReady) + rc := resource.Status.GetCondition(apis.ConditionReady) + // if a new generation is observed and reconciliation reported an error event + // the reconciler should change the ready state. By default we will set unknown. + if equality.Semantic.DeepEqual(originalRc, rc) { + logger.Warnw("A reconconiler observed a new generation without updating the resource status") + condSet.Manage(&resource.Status).MarkUnknown( + apis.ConditionReady, "", "unsucessfully observed a new generation") + } + } + // Synchronize the status. if equality.Semantic.DeepEqual(original.Status, resource.Status) { // If we didn't change anything then don't call updateStatus. From e4e185e5235ff50ffd246cc0873c955d3ffae313 Mon Sep 17 00:00:00 2001 From: Weston Haught Date: Wed, 29 Apr 2020 13:18:09 -0700 Subject: [PATCH 2/2] Create a new comment tag for duck logic --- apis/test/example/v1alpha1/foo_types.go | 1 + codegen/cmd/injection-gen/generators/packages.go | 8 ++++++++ .../cmd/injection-gen/generators/reconciler_reconciler.go | 8 +++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apis/test/example/v1alpha1/foo_types.go b/apis/test/example/v1alpha1/foo_types.go index 22ac876ffd..6adc0dd19f 100644 --- a/apis/test/example/v1alpha1/foo_types.go +++ b/apis/test/example/v1alpha1/foo_types.go @@ -28,6 +28,7 @@ import ( // +genclient // +genreconciler +// +genducklogic // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Foo is for testing. diff --git a/codegen/cmd/injection-gen/generators/packages.go b/codegen/cmd/injection-gen/generators/packages.go index ce8b6dbc68..841b57ac9e 100644 --- a/codegen/cmd/injection-gen/generators/packages.go +++ b/codegen/cmd/injection-gen/generators/packages.go @@ -206,6 +206,12 @@ func isNonNamespaced(t *types.Type) bool { return nonNamespaced } +func genDuckLogic(t *types.Type) bool { + comments := append(append([]string{}, t.SecondClosestCommentLines...), t.CommentLines...) + _, duckLogic := types.ExtractCommentTags("+", comments)["genducklogic"] + return duckLogic +} + func vendorless(p string) string { if pos := strings.LastIndex(p, "/vendor/"); pos != -1 { return p[pos+len("/vendor/"):] @@ -418,6 +424,7 @@ func reconcilerPackages(basePackage string, groupPkgName string, gv clientgentyp reconcilerClass, hasReconcilerClass := extractReconcilerClassTag(t) nonNamespaced := isNonNamespaced(t) + genDuck := genDuckLogic(t) packagePath := filepath.Join(packagePath, strings.ToLower(t.Name.Name)) @@ -506,6 +513,7 @@ func reconcilerPackages(basePackage string, groupPkgName string, gv clientgentyp reconcilerClass: reconcilerClass, hasReconcilerClass: hasReconcilerClass, nonNamespaced: nonNamespaced, + genDuckLogic: genDuck, }) return generators diff --git a/codegen/cmd/injection-gen/generators/reconciler_reconciler.go b/codegen/cmd/injection-gen/generators/reconciler_reconciler.go index 048bde86e9..eb555add3e 100644 --- a/codegen/cmd/injection-gen/generators/reconciler_reconciler.go +++ b/codegen/cmd/injection-gen/generators/reconciler_reconciler.go @@ -40,6 +40,7 @@ type reconcilerReconcilerGenerator struct { reconcilerClass string hasReconcilerClass bool nonNamespaced bool + genDuckLogic bool groupGoName string groupVersion clientgentypes.GroupVersion @@ -75,6 +76,7 @@ func (g *reconcilerReconcilerGenerator) GenerateType(c *generator.Context, t *ty "class": g.reconcilerClass, "hasClass": g.hasReconcilerClass, "nonNamespaced": g.nonNamespaced, + "genDuckLogic": g.genDuckLogic, "controllerImpl": c.Universe.Type(types.Name{ Package: "knative.dev/pkg/controller", Name: "Impl", @@ -212,8 +214,10 @@ type reconcilerImpl struct { // Check that our Reconciler implements controller.Reconciler var _ controller.Reconciler = (*reconcilerImpl)(nil) -// Creates a {{.conditionSet|raw}} to manipulate resource status conditions +{{if .genDuckLogic}} +// Creates the {{.conditionSet|raw}} to manipulate resource status conditions var condSet = apis.NewLivingConditionSet() +{{end}} ` @@ -324,6 +328,7 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro } } + {{if .genDuckLogic}} // Bump observed generation to denote that we have processed this // generation regardless of success or failure. resource.Status.ObservedGeneration = resource.Generation @@ -339,6 +344,7 @@ func (r *reconcilerImpl) Reconcile(ctx {{.contextContext|raw}}, key string) erro apis.ConditionReady, "", "unsucessfully observed a new generation") } } + {{end}} // Synchronize the status. if equality.Semantic.DeepEqual(original.Status, resource.Status) {