From dba121e5c7e542382969b1050ee590d45e357326 Mon Sep 17 00:00:00 2001 From: zoetrope Date: Tue, 15 Jun 2021 10:31:36 +0900 Subject: [PATCH 1/2] [WIP] using typed-ssa with k8s 1.21 --- go.mod | 25 +++++----- internal/reconcilers/anchor.go | 89 +++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index 2e1516612..f2fafb91d 100644 --- a/go.mod +++ b/go.mod @@ -6,21 +6,20 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.2.0 contrib.go.opencensus.io/exporter/stackdriver v0.13.0 github.com/emicklei/go-restful v2.10.0+incompatible // indirect - github.com/go-logr/logr v0.3.0 - github.com/go-logr/zapr v0.2.0 - github.com/go-openapi/spec v0.19.5 // indirect + github.com/go-logr/logr v0.4.0 + github.com/go-logr/zapr v0.4.0 github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/onsi/ginkgo v1.14.1 - github.com/onsi/gomega v1.10.2 + github.com/onsi/ginkgo v1.16.4 + github.com/onsi/gomega v1.13.0 github.com/open-policy-agent/cert-controller v0.2.0 - github.com/spf13/cobra v1.1.1 + github.com/spf13/cobra v1.1.3 go.opencensus.io v0.22.3 - go.uber.org/zap v1.15.0 - k8s.io/api v0.20.4 - k8s.io/apiextensions-apiserver v0.20.4 - k8s.io/apimachinery v0.20.4 + go.uber.org/zap v1.17.0 + k8s.io/api v0.21.1 + k8s.io/apiextensions-apiserver v0.21.1 + k8s.io/apimachinery v0.21.1 k8s.io/cli-runtime v0.20.4 - k8s.io/client-go v0.20.4 - sigs.k8s.io/controller-runtime v0.8.3 - sigs.k8s.io/controller-tools v0.5.0 + k8s.io/client-go v0.21.1 + sigs.k8s.io/controller-runtime v0.9.0 + sigs.k8s.io/controller-tools v0.6.0 ) diff --git a/internal/reconcilers/anchor.go b/internal/reconcilers/anchor.go index 4bc23e60d..947bc52e3 100644 --- a/internal/reconcilers/anchor.go +++ b/internal/reconcilers/anchor.go @@ -19,22 +19,24 @@ import ( "context" "errors" "fmt" + "strings" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + corev1apply "k8s.io/client-go/applyconfigurations/core/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2" "sigs.k8s.io/hierarchical-namespaces/internal/config" "sigs.k8s.io/hierarchical-namespaces/internal/forest" - "sigs.k8s.io/hierarchical-namespaces/internal/metadata" ) // AnchorReconciler reconciles SubnamespaceAnchor CRs to make sure all the subnamespaces are @@ -106,17 +108,11 @@ func (r *AnchorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr return ctrl.Result{}, err } - // If the subnamespace doesn't exist, create it. - if inst.Status.State == api.Missing { - if err := r.writeNamespace(ctx, log, nm, pnm); err != nil { - // Write the "Missing" state to the anchor status if the subnamespace - // cannot be created for some reason. Without it, the anchor status will - // remain empty by default. - if anchorErr := r.writeInstance(ctx, log, inst); anchorErr != nil { - log.Error(anchorErr, "while setting anchor state", "state", api.Missing, "reason", err) - } - return ctrl.Result{}, err + if err := r.updateNamespace(ctx, log, nm, pnm); err != nil { + if anchorErr := r.writeInstance(ctx, log, inst); anchorErr != nil { + log.Error(anchorErr, "while setting anchor state", "state", api.Missing, "reason", err) } + return ctrl.Result{}, err } // Add finalizers on all non-forbidden anchors to ensure it's not deleted until @@ -369,18 +365,37 @@ func (r *AnchorReconciler) getNamespace(ctx context.Context, nm string) (*corev1 return ns, nil } -func (r *AnchorReconciler) writeNamespace(ctx context.Context, log logr.Logger, nm, pnm string) error { - inst := &corev1.Namespace{} - inst.ObjectMeta.Name = nm - metadata.SetAnnotation(inst, api.SubnamespaceOf, pnm) - - // It's safe to use create here since if the namespace is created by someone - // else while this reconciler is running, returning an error will trigger a - // retry. The reconciler will set the 'Conflict' state instead of recreating - // this namespace. All other transient problems should trigger a retry too. - log.Info("Creating subnamespace") - if err := r.Create(ctx, inst); err != nil { - log.Error(err, "While creating subnamespace") +func (r *AnchorReconciler) updateNamespace(ctx context.Context, log logr.Logger, nm, pnm string) error { + pnmInst := &corev1.Namespace{} + pnnm := types.NamespacedName{Name: pnm} + if err := r.Get(ctx, pnnm, pnmInst); err != nil { + return err + } + + labels := map[string]string{} + for k, v := range pnmInst.Labels { + if strings.Contains(k, api.MetaGroup) { + continue + } + labels[k] = v + } + inst := corev1apply.Namespace(nm).WithAnnotations(map[string]string{ + api.SubnamespaceOf: pnmInst.Name, + }).WithLabels(labels) + + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(inst) + if err != nil { + return err + } + patch := &unstructured.Unstructured{ + Object: obj, + } + + log.Info("Updating subnamespace") + if err := r.Patch(ctx, patch, client.Apply, &client.PatchOptions{ + FieldManager: api.MetaGroup, + }); err != nil { + log.Error(err, "While updating subnamespace") return err } return nil @@ -397,15 +412,31 @@ func (r *AnchorReconciler) deleteNamespace(ctx context.Context, log logr.Logger, func (r *AnchorReconciler) SetupWithManager(mgr ctrl.Manager) error { // Maps an subnamespace to its anchor in the parent namespace. nsMapFn := func(obj client.Object) []reconcile.Request { - if obj.GetAnnotations()[api.SubnamespaceOf] == "" { - return nil + result := make([]reconcile.Request, 0) + nss := &corev1.NamespaceList{} + err := r.List(context.Background(), nss) + if err != nil { + return result + } + // Fetch subnamespaces + for _, ns := range nss.Items { + if obj.GetName() == ns.Name { + continue + } + if _, ok := ns.Labels[obj.GetName()+api.LabelTreeDepthSuffix]; ok { + result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{ + Name: ns.Name, + Namespace: ns.GetAnnotations()[api.SubnamespaceOf], + }}) + } } - return []reconcile.Request{ - {NamespacedName: types.NamespacedName{ + if obj.GetAnnotations()[api.SubnamespaceOf] != "" { + result = append(result, reconcile.Request{NamespacedName: types.NamespacedName{ Name: obj.GetName(), Namespace: obj.GetAnnotations()[api.SubnamespaceOf], - }}, + }}) } + return result } return ctrl.NewControllerManagedBy(mgr). For(&api.SubnamespaceAnchor{}). From 1f7d58d225253ca5d02a74f69210e02b9a4f451d Mon Sep 17 00:00:00 2001 From: zoetrope Date: Tue, 15 Jun 2021 10:49:53 +0900 Subject: [PATCH 2/2] [WIP] fix --- go.mod | 25 +++++++++++++------------ internal/reconcilers/anchor.go | 29 ++++++++++++----------------- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/go.mod b/go.mod index f2fafb91d..2e1516612 100644 --- a/go.mod +++ b/go.mod @@ -6,20 +6,21 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.2.0 contrib.go.opencensus.io/exporter/stackdriver v0.13.0 github.com/emicklei/go-restful v2.10.0+incompatible // indirect - github.com/go-logr/logr v0.4.0 - github.com/go-logr/zapr v0.4.0 + github.com/go-logr/logr v0.3.0 + github.com/go-logr/zapr v0.2.0 + github.com/go-openapi/spec v0.19.5 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect - github.com/onsi/ginkgo v1.16.4 - github.com/onsi/gomega v1.13.0 + github.com/onsi/ginkgo v1.14.1 + github.com/onsi/gomega v1.10.2 github.com/open-policy-agent/cert-controller v0.2.0 - github.com/spf13/cobra v1.1.3 + github.com/spf13/cobra v1.1.1 go.opencensus.io v0.22.3 - go.uber.org/zap v1.17.0 - k8s.io/api v0.21.1 - k8s.io/apiextensions-apiserver v0.21.1 - k8s.io/apimachinery v0.21.1 + go.uber.org/zap v1.15.0 + k8s.io/api v0.20.4 + k8s.io/apiextensions-apiserver v0.20.4 + k8s.io/apimachinery v0.20.4 k8s.io/cli-runtime v0.20.4 - k8s.io/client-go v0.21.1 - sigs.k8s.io/controller-runtime v0.9.0 - sigs.k8s.io/controller-tools v0.6.0 + k8s.io/client-go v0.20.4 + sigs.k8s.io/controller-runtime v0.8.3 + sigs.k8s.io/controller-tools v0.5.0 ) diff --git a/internal/reconcilers/anchor.go b/internal/reconcilers/anchor.go index 947bc52e3..cdb74e664 100644 --- a/internal/reconcilers/anchor.go +++ b/internal/reconcilers/anchor.go @@ -24,10 +24,8 @@ import ( "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - corev1apply "k8s.io/client-go/applyconfigurations/core/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" @@ -37,6 +35,7 @@ import ( api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2" "sigs.k8s.io/hierarchical-namespaces/internal/config" "sigs.k8s.io/hierarchical-namespaces/internal/forest" + "sigs.k8s.io/hierarchical-namespaces/internal/metadata" ) // AnchorReconciler reconciles SubnamespaceAnchor CRs to make sure all the subnamespaces are @@ -372,27 +371,23 @@ func (r *AnchorReconciler) updateNamespace(ctx context.Context, log logr.Logger, return err } - labels := map[string]string{} + inst := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + } + inst.ObjectMeta.Name = nm + metadata.SetAnnotation(inst, api.SubnamespaceOf, pnm) for k, v := range pnmInst.Labels { if strings.Contains(k, api.MetaGroup) { continue } - labels[k] = v - } - inst := corev1apply.Namespace(nm).WithAnnotations(map[string]string{ - api.SubnamespaceOf: pnmInst.Name, - }).WithLabels(labels) - - obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(inst) - if err != nil { - return err - } - patch := &unstructured.Unstructured{ - Object: obj, + metadata.SetLabel(inst, k, v) } log.Info("Updating subnamespace") - if err := r.Patch(ctx, patch, client.Apply, &client.PatchOptions{ + if err := r.Patch(ctx, inst, client.Apply, &client.PatchOptions{ FieldManager: api.MetaGroup, }); err != nil { log.Error(err, "While updating subnamespace")