diff --git a/Makefile b/Makefile index 59ba04e..ca8070a 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ CRD_OPTIONS ?= "crd:crdVersions=v1" ENVTEST_K8S_VERSION = 1.25 # Namespace to deploy resources into -NAMESPACE ?= open-cluster-management +NAMESPACE ?= multicluster-engine # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -88,7 +88,7 @@ secret: ## Generate secret for OCM access config: ## Create custom resources cd config/samples && $(KUSTOMIZE) edit set namespace $(NAMESPACE) $(KUSTOMIZE) build config/samples | kubectl apply -f - - cd config/samples && $(KUSTOMIZE) edit set namespace open-cluster-management + cd config/samples && $(KUSTOMIZE) edit set namespace multicluster-engine logs: ## Print operator logs @kubectl logs -f $(shell kubectl get pod -l app=discovery-operator -o jsonpath="{.items[0].metadata.name}") diff --git a/README.md b/README.md index 88fee76..2654937 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,11 @@ The discovery operator generates `DiscoveredClusters` based on a `DiscoveryConfi make secret OCM_API_TOKEN= ``` -The OpenShift Cluster Manager API Token can be retrieved from [here](https://cloud.redhat.com/openshift/token). This will create a secret named `ocm-api-token` in the current namespace. With the secret created you can then create the `DiscoveryConfig` resource using the following command: +The OpenShift Cluster Manager API Token can be retrieved from [here](https://cloud.redhat.com/openshift/token). This will create a secret named `ocm-api-token` in the current namespace. With the secret created you can then create the `DiscoveryConfig` resource using the following commands: ```shell -make samples +make secret +make connfig ``` This will create a `DiscoveryConfig` like the example below: diff --git a/controllers/discoveryconfig_controller.go b/controllers/discoveryconfig_controller.go index 0a5e44d..9788cf0 100644 --- a/controllers/discoveryconfig_controller.go +++ b/controllers/discoveryconfig_controller.go @@ -31,6 +31,7 @@ import ( ref "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/log" discovery "github.com/stolostron/discovery/api/v1" @@ -107,10 +108,10 @@ func (r *DiscoveryConfigReconciler) Reconcile(ctx context.Context, req ctrl.Requ } // SetupWithManager ... -func (r *DiscoveryConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { +func (r *DiscoveryConfigReconciler) SetupWithManager(mgr ctrl.Manager) (controller.Controller, error) { return ctrl.NewControllerManagedBy(mgr). For(&discovery.DiscoveryConfig{}). - Complete(r) + Build(r) } func (r *DiscoveryConfigReconciler) updateDiscoveredClusters(ctx context.Context, config *discovery.DiscoveryConfig) error { diff --git a/controllers/managedcluster_controller.go b/controllers/managedcluster_controller.go index 87c1183..8d67202 100644 --- a/controllers/managedcluster_controller.go +++ b/controllers/managedcluster_controller.go @@ -133,10 +133,7 @@ func (r *ManagedClusterReconciler) SetupWithManager(mgr ctrl.Manager) error { return errors.Wrapf(err, "error creating controller") } - if err := c.Watch( - &source.Channel{Source: r.Trigger}, - &handler.EnqueueRequestForObject{}, - ); err != nil { + if err := c.Watch(source.Channel(r.Trigger, &handler.EnqueueRequestForObject{})); err != nil { return errors.Wrapf(err, "failed adding a watch channel") } diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 7674674..1e127ad 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -86,7 +86,7 @@ var _ = BeforeSuite(func() { }) Expect(err).ToNot(HaveOccurred()) - err = (&DiscoveryConfigReconciler{ + _, err = (&DiscoveryConfigReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), }).SetupWithManager(k8sManager) diff --git a/go.mod b/go.mod index a006ca8..32041b7 100644 --- a/go.mod +++ b/go.mod @@ -14,13 +14,13 @@ require ( github.com/stolostron/klusterlet-addon-controller v0.0.0-20240229083605-8bd4a2ae81c0 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 - k8s.io/api v0.29.3 - k8s.io/apiextensions-apiserver v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/client-go v0.29.3 + k8s.io/api v0.30.1 + k8s.io/apiextensions-apiserver v0.30.1 + k8s.io/apimachinery v0.30.1 + k8s.io/client-go v0.30.1 k8s.io/metrics v0.29.3 open-cluster-management.io/api v0.13.0 - sigs.k8s.io/controller-runtime v0.17.2 + sigs.k8s.io/controller-runtime v0.18.5 sigs.k8s.io/yaml v1.4.0 ) @@ -89,7 +89,7 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/component-base v0.29.3 // indirect + k8s.io/component-base v0.30.1 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240403164606-bc84c2ddaf99 // indirect k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect diff --git a/go.sum b/go.sum index 4408ae2..9e020b3 100644 --- a/go.sum +++ b/go.sum @@ -243,14 +243,24 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/api v0.30.1 h1:kCm/6mADMdbAxmIh0LBjS54nQBE+U4KmbCfIkF5CpJY= +k8s.io/api v0.30.1/go.mod h1:ddbN2C0+0DIiPntan/bye3SW3PdwLa11/0yqwvuRrJM= k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= +k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= +k8s.io/apiextensions-apiserver v0.30.1/go.mod h1:R4GuSrlhgq43oRY9sF2IToFh7PVlF1JjfWdoG3pixk4= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= +k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= +k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= +k8s.io/component-base v0.30.1 h1:bvAtlPh1UrdaZL20D9+sWxsJljMi0QZ3Lmw+kmZAaxQ= +k8s.io/component-base v0.30.1/go.mod h1:e/X9kDiOebwlI41AvBHuWdqFriSRrX50CdwA9TFaHLI= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240403164606-bc84c2ddaf99 h1:w6nThEmGo9zcL+xH1Tu6pjxJ3K1jXFW+V0u4peqN8ks= @@ -265,6 +275,8 @@ open-cluster-management.io/api v0.13.0/go.mod h1:CuCPEzXDvOyxBB0H1d1eSeajbHqaeGE rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= +sigs.k8s.io/controller-runtime v0.18.5 h1:nTHio/W+Q4aBlQMgbnC5hZb4IjIidyrizMai9P6n4Rk= +sigs.k8s.io/controller-runtime v0.18.5/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/main.go b/main.go index 48f169f..b2f44ff 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,11 @@ import ( goruntime "runtime" + "k8s.io/client-go/util/workqueue" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/source" + "go.uber.org/zap/zapcore" admissionregistration "k8s.io/api/admissionregistration/v1" apixv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -47,10 +52,11 @@ import ( clusterapiv1beta2 "open-cluster-management.io/api/cluster/v1beta2" 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/controller" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/webhook" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -69,8 +75,9 @@ const ( ) var ( - scheme = runtime.NewScheme() - setupLog = ctrl.Log.WithName("setup") + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") + discoveryConfigController controller.Controller ControllerError = "unable to create controller" ) @@ -159,10 +166,12 @@ func main() { events := make(chan event.GenericEvent) - if err = (&controllers.DiscoveryConfigReconciler{ + discoveryConfigReconciler := &controllers.DiscoveryConfigReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { + } + discoveryConfigController, err = discoveryConfigReconciler.SetupWithManager(mgr) + if err != nil { setupLog.Error(err, ControllerError, "controller", "DiscoveryConfig") os.Exit(1) } @@ -208,6 +217,8 @@ func main() { os.Exit(1) } + go addDiscoverySecretWatch(context.Background(), mgr, uncachedClient) + setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { setupLog.Error(err, "problem running manager") @@ -233,7 +244,7 @@ func ensureWebhooks(k8sClient client.Client) error { // This way if the CRD is deleted the webhook will be removed with it crdKey := types.NamespacedName{Name: crdName} owner := &apixv1.CustomResourceDefinition{} - if err := k8sClient.Get(context.TODO(), crdKey, owner); err != nil { + if err := k8sClient.Get(context.Background(), crdKey, owner); err != nil { setupLog.Error(err, "Failed to get DiscoveredCluster CRD") time.Sleep(5 * time.Second) continue @@ -284,3 +295,37 @@ func ensureWebhooks(k8sClient client.Client) error { } return fmt.Errorf("unable to ensure validatingwebhook exists in allotted time") } + +func addDiscoverySecretWatch(ctx context.Context, mgr ctrl.Manager, uncachedClient client.Client) { + for { + config := &discoveryv1.DiscoveryConfig{} + configName := "discovery" + err := uncachedClient.Get(ctx, types.NamespacedName{Name: configName}, config) + // Create the event handler + if err == nil { + err := discoveryConfigController.Watch(source.Kind(mgr.GetCache(), &corev1.Secret{}, + handler.TypedFuncs[*corev1.Secret]{ + UpdateFunc: func(ctx context.Context, e event.TypedUpdateEvent[*corev1.Secret], q workqueue.RateLimitingInterface) { + updatedSecret := e.ObjectNew + if updatedSecret.Name == config.Spec.Credential && updatedSecret.Namespace == config.Namespace { + q.Add( + reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: config.Name, + Namespace: config.Namespace, + }, + }, + ) + } + }, + })) + if err == nil { + setupLog.Info("secret watch added") + return + } + } + + // If we encounter an error, wait and retry + time.Sleep(30 * time.Second) + } +}