Browse Source

Using cobra commands instead of several binaries

Signed-off-by: Gustavo Carvalho <gustavo.carvalho@container-solutions.com>
Gustavo Carvalho 4 years ago
parent
commit
2e6017dd4b

+ 0 - 8
Makefile

@@ -102,10 +102,6 @@ build-%: generate ## Build binary for the specified arch
 	@$(INFO) go build $*
 	@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
 		go build -o '$(OUTPUT_DIR)/external-secrets-linux-$*' main.go
-	@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
-		go build -o 'webhook/$(OUTPUT_DIR)/external-secrets-webhook-linux-$*' webhook/main.go
-	@CGO_ENABLED=0 GOOS=linux GOARCH=$* \
-		go build -o 'webhook/certcontroller/$(OUTPUT_DIR)/external-secrets-cert-controller-linux-$*' webhook/certcontroller/main.go
 	@$(OK) go build $*
 
 lint.check: ## Check install of golanci-lint
@@ -212,15 +208,11 @@ build.all: docker.build helm.build ## Build all artifacts (docker image, helm ch
 docker.build: $(addprefix build-,$(ARCH)) ## Build the docker image
 	@$(INFO) docker build
 	@docker build . $(BUILD_ARGS) -t $(IMAGE_REGISTRY):$(VERSION)
-	@docker build webhook/ $(BUILD_ARGS) -t $(IMAGE_REGISTRY)-webhook:$(VERSION)
-	@docker build webhook/certcontroller $(BUILD_ARGS) -t $(IMAGE_REGISTRY)-cert-controller:$(VERSION)
 	@$(OK) docker build
 
 docker.push: ## Push the docker image to the registry
 	@$(INFO) docker push
 	@docker push $(IMAGE_REGISTRY):$(VERSION)
-	@docker push $(IMAGE_REGISTRY)-webhook:$(VERSION)
-	@docker push $(IMAGE_REGISTRY)-cert-controller:$(VERSION)
 	@$(OK) docker push
 
 # RELEASE_TAG is tag to promote. Default is promoting to main branch, but can be overriden

+ 98 - 0
cmd/certcontroller.go

@@ -0,0 +1,98 @@
+/*
+Copyright © 2022 ESO Maintainer team
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cmd
+
+import (
+	"os"
+	"time"
+
+	"github.com/spf13/cobra"
+	"go.uber.org/zap/zapcore"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/controller"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	"github.com/external-secrets/external-secrets/pkg/controllers/crds"
+)
+
+var certcontrollerCmd = &cobra.Command{
+	Use:   "certcontroller",
+	Short: "Controller to manage certificates for external secrets CRDs",
+	Long: `Controller to manage certificates for external secrets CRDs.
+	For more information visit https://external-secrets.io`,
+	Run: func(cmd *cobra.Command, args []string) {
+		var lvl zapcore.Level
+		err := lvl.UnmarshalText([]byte(loglevel))
+		if err != nil {
+			setupLog.Error(err, "error unmarshalling loglevel")
+			os.Exit(1)
+		}
+		logger := zap.New(zap.Level(lvl))
+		ctrl.SetLogger(logger)
+
+		mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
+			Scheme:             scheme,
+			MetricsBindAddress: metricsAddr,
+			Port:               9443,
+			LeaderElection:     enableLeaderElection,
+			LeaderElectionID:   "crd-certs-controller",
+		})
+		if err != nil {
+			setupLog.Error(err, "unable to start manager")
+			os.Exit(1)
+		}
+		crds := &crds.Reconciler{
+			Client:                 mgr.GetClient(),
+			Log:                    ctrl.Log.WithName("controllers").WithName("webhook-certs-updater"),
+			Scheme:                 mgr.GetScheme(),
+			SvcName:                serviceName,
+			SvcNamespace:           serviceNamespace,
+			SecretName:             secretName,
+			SecretNamespace:        secretNamespace,
+			RequeueInterval:        crdRequeueInterval,
+			CrdResources:           []string{"externalsecrets.external-secrets.io", "clustersecretstores.external-secrets.io", "secretstores.external-secrets.io"},
+			CAName:                 "external-secrets",
+			CAOrganization:         "external-secrets",
+			RestartOnSecretRefresh: false,
+		}
+		if err := crds.SetupWithManager(mgr, controller.Options{
+			MaxConcurrentReconciles: concurrent,
+		}); err != nil {
+			setupLog.Error(err, errCreateController, "controller", "CustomResourceDefinition")
+			os.Exit(1)
+		}
+		setupLog.Info("starting manager")
+		if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
+			setupLog.Error(err, "problem running manager")
+			os.Exit(1)
+		}
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(certcontrollerCmd)
+
+	certcontrollerCmd.Flags().StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
+	certcontrollerCmd.Flags().StringVar(&serviceName, "service-name", "external-secrets-webhook", "Webhook service name")
+	certcontrollerCmd.Flags().StringVar(&serviceNamespace, "service-namespace", "default", "Webhook service namespace")
+	certcontrollerCmd.Flags().StringVar(&secretName, "secret-name", "external-secrets-webhook", "Secret to store certs for webhook")
+	certcontrollerCmd.Flags().StringVar(&secretNamespace, "secret-namespace", "default", "namespace of the secret to store certs")
+	certcontrollerCmd.Flags().BoolVar(&enableLeaderElection, "enable-leader-election", false,
+		"Enable leader election for controller manager. "+
+			"Enabling this will ensure there is only one active controller manager.")
+	certcontrollerCmd.Flags().StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
+	certcontrollerCmd.Flags().DurationVar(&crdRequeueInterval, "crd-requeue-interval", time.Minute*5, "Time duration between reconciling CRDs for new certs")
+}

+ 148 - 0
cmd/root.go

@@ -0,0 +1,148 @@
+/*
+Copyright © 2022 ESO Maintainer Team
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cmd
+
+import (
+	"os"
+	"time"
+
+	"github.com/spf13/cobra"
+	"go.uber.org/zap/zapcore"
+	"k8s.io/apimachinery/pkg/runtime"
+	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
+
+	// To allow using gcp auth.
+	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/controller"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+	"github.com/external-secrets/external-secrets/pkg/controllers/externalsecret"
+	"github.com/external-secrets/external-secrets/pkg/controllers/secretstore"
+)
+
+var (
+	scheme                        = runtime.NewScheme()
+	setupLog                      = ctrl.Log.WithName("setup")
+	dnsName                       string
+	certDir                       string
+	metricsAddr                   string
+	controllerClass               string
+	enableLeaderElection          bool
+	concurrent                    int
+	loglevel                      string
+	namespace                     string
+	storeRequeueInterval          time.Duration
+	serviceName, serviceNamespace string
+	secretName, secretNamespace   string
+	crdRequeueInterval            time.Duration
+	certCheckInterval             time.Duration
+)
+
+const (
+	errCreateController = "unable to create controller"
+)
+
+func init() {
+	_ = clientgoscheme.AddToScheme(scheme)
+	_ = esv1beta1.AddToScheme(scheme)
+	_ = esv1alpha1.AddToScheme(scheme)
+}
+
+var rootCmd = &cobra.Command{
+	Use:   "external-secrets",
+	Short: "operator that reconciles ExternalSecrets and SecretStores",
+	Long:  `For more information visit https://external-secrets.io`,
+	Run: func(cmd *cobra.Command, args []string) {
+		var lvl zapcore.Level
+		err := lvl.UnmarshalText([]byte(loglevel))
+		if err != nil {
+			setupLog.Error(err, "error unmarshalling loglevel")
+			os.Exit(1)
+		}
+		logger := zap.New(zap.Level(lvl))
+		ctrl.SetLogger(logger)
+
+		mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
+			Scheme:             scheme,
+			MetricsBindAddress: metricsAddr,
+			Port:               9443,
+			LeaderElection:     enableLeaderElection,
+			LeaderElectionID:   "external-secrets-controller",
+			Namespace:          namespace,
+		})
+		if err != nil {
+			setupLog.Error(err, "unable to start manager")
+			os.Exit(1)
+		}
+		if err = (&secretstore.StoreReconciler{
+			Client:          mgr.GetClient(),
+			Log:             ctrl.Log.WithName("controllers").WithName("SecretStore"),
+			Scheme:          mgr.GetScheme(),
+			ControllerClass: controllerClass,
+			RequeueInterval: storeRequeueInterval,
+		}).SetupWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateController, "controller", "SecretStore")
+			os.Exit(1)
+		}
+		if err = (&secretstore.ClusterStoreReconciler{
+			Client:          mgr.GetClient(),
+			Log:             ctrl.Log.WithName("controllers").WithName("ClusterSecretStore"),
+			Scheme:          mgr.GetScheme(),
+			ControllerClass: controllerClass,
+			RequeueInterval: storeRequeueInterval,
+		}).SetupWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateController, "controller", "ClusterSecretStore")
+			os.Exit(1)
+		}
+		if err = (&externalsecret.Reconciler{
+			Client:          mgr.GetClient(),
+			Log:             ctrl.Log.WithName("controllers").WithName("ExternalSecret"),
+			Scheme:          mgr.GetScheme(),
+			ControllerClass: controllerClass,
+			RequeueInterval: time.Hour,
+		}).SetupWithManager(mgr, controller.Options{
+			MaxConcurrentReconciles: concurrent,
+		}); err != nil {
+			setupLog.Error(err, errCreateController, "controller", "ExternalSecret")
+			os.Exit(1)
+		}
+		setupLog.Info("starting manager")
+		if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
+			setupLog.Error(err, "problem running manager")
+			os.Exit(1)
+		}
+
+	},
+}
+
+func Execute() {
+	cobra.CheckErr(rootCmd.Execute())
+}
+
+func init() {
+	rootCmd.Flags().StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
+	rootCmd.Flags().StringVar(&controllerClass, "controller-class", "default", "the controller is instantiated with a specific controller name and filters ES based on this property")
+	rootCmd.Flags().BoolVar(&enableLeaderElection, "enable-leader-election", false,
+		"Enable leader election for controller manager. "+
+			"Enabling this will ensure there is only one active controller manager.")
+	rootCmd.Flags().IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
+	rootCmd.Flags().StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
+	rootCmd.Flags().StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
+	rootCmd.Flags().DurationVar(&storeRequeueInterval, "store-requeue-interval", time.Minute*5, "Time duration between reconciling (Cluster)SecretStores")
+}

+ 143 - 0
cmd/webhook.go

@@ -0,0 +1,143 @@
+/*
+Copyright © 2022 NAME HERE <EMAIL ADDRESS>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package cmd
+
+import (
+	"context"
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+
+	"github.com/spf13/cobra"
+	"go.uber.org/zap/zapcore"
+	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+	"github.com/external-secrets/external-secrets/pkg/controllers/crds"
+)
+
+const (
+	errCreateWebhook = "unable to create webhook"
+)
+
+func init() {
+	_ = clientgoscheme.AddToScheme(scheme)
+	_ = esv1beta1.AddToScheme(scheme)
+	_ = esv1alpha1.AddToScheme(scheme)
+}
+
+var webhookCmd = &cobra.Command{
+	Use:   "webhook",
+	Short: "Webhook implementation for ExternalSecrets and SecretStores.",
+	Long: `Webhook implementation for ExternalSecrets and SecretStores.
+	For more information visit https://external-secrets.io`,
+	Run: func(cmd *cobra.Command, args []string) {
+		var lvl zapcore.Level
+		err := lvl.UnmarshalText([]byte(loglevel))
+		if err != nil {
+			setupLog.Error(err, "error unmarshalling loglevel")
+			os.Exit(1)
+		}
+		c := crds.CertInfo{
+			CertDir:  certDir,
+			CertName: "tls.crt",
+			KeyName:  "tls.key",
+			CAName:   "ca.crt",
+		}
+
+		logger := zap.New(zap.Level(lvl))
+		ctrl.SetLogger(logger)
+
+		setupLog.Info("validating certs")
+		err = crds.CheckCerts(c, dnsName, time.Now().Add(time.Hour))
+		if err != nil {
+			setupLog.Error(err, "error checking certs")
+			os.Exit(1)
+		}
+		ctx, cancel := context.WithCancel(context.Background())
+		go func(c crds.CertInfo, dnsName string, every time.Duration) {
+			sigs := make(chan os.Signal, 1)
+			signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
+			ticker := time.NewTicker(every)
+			for {
+				select {
+				case <-sigs:
+					cancel()
+				case <-ticker.C:
+					setupLog.Info("validating certs")
+					err = crds.CheckCerts(c, dnsName, time.Now().Add(crds.LookaheadInterval+time.Minute))
+					if err != nil {
+						cancel()
+					}
+					setupLog.Info("certs are valid")
+				}
+			}
+		}(c, dnsName, certCheckInterval)
+
+		mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
+			Scheme:             scheme,
+			MetricsBindAddress: metricsAddr,
+			Port:               9443,
+			CertDir:            certDir,
+		})
+		if err != nil {
+			setupLog.Error(err, "unable to start manager")
+			os.Exit(1)
+		}
+		if err = (&esv1beta1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1beta1")
+			os.Exit(1)
+		}
+		if err = (&esv1beta1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1beta1")
+			os.Exit(1)
+		}
+		if err = (&esv1beta1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1beta1")
+			os.Exit(1)
+		}
+		if err = (&esv1alpha1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1alpha1")
+			os.Exit(1)
+		}
+		if err = (&esv1alpha1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1alpha1")
+			os.Exit(1)
+		}
+		if err = (&esv1alpha1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
+			setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1alpha1")
+			os.Exit(1)
+		}
+		setupLog.Info("starting manager")
+		if err := mgr.Start(ctx); err != nil {
+			setupLog.Error(err, "problem running manager")
+			os.Exit(1)
+		}
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(webhookCmd)
+	webhookCmd.Flags().StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
+	webhookCmd.Flags().StringVar(&dnsName, "dns-name", "localhost", "DNS name to validate certificates with")
+	webhookCmd.Flags().StringVar(&certDir, "cert-dir", "/tmp/k8s-webhook-server/serving-certs", "path to check for certs")
+	webhookCmd.Flags().StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
+	webhookCmd.Flags().DurationVar(&certCheckInterval, "check-interval", 5*time.Minute, "certificate check interval")
+}

+ 3 - 2
deploy/charts/external-secrets/README.md

@@ -41,7 +41,7 @@ The command removes all the Kubernetes components associated with the chart and
 | certController.extraEnv | list | `[]` |  |
 | certController.fullnameOverride | string | `""` |  |
 | certController.image.pullPolicy | string | `"IfNotPresent"` |  |
-| certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets-cert-controller"` |  |
+| certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` |  |
 | certController.image.tag | string | `""` |  |
 | certController.imagePullSecrets | list | `[]` |  |
 | certController.nameOverride | string | `""` |  |
@@ -90,13 +90,14 @@ The command removes all the Kubernetes components associated with the chart and
 | serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. |
 | tolerations | list | `[]` |  |
 | webhook.affinity | object | `{}` |  |
+| webhook.certCheckInterval | string | `"5m"` |  |
 | webhook.certDir | string | `"/tmp/certs"` |  |
 | webhook.deploymentAnnotations | object | `{}` | Annotations to add to Deployment |
 | webhook.extraArgs | object | `{}` |  |
 | webhook.extraEnv | list | `[]` |  |
 | webhook.fullnameOverride | string | `""` |  |
 | webhook.image.pullPolicy | string | `"IfNotPresent"` |  |
-| webhook.image.repository | string | `"ghcr.io/external-secrets/external-secrets-webhook"` |  |
+| webhook.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` |  |
 | webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. |
 | webhook.imagePullSecrets | list | `[]` |  |
 | webhook.nameOverride | string | `""` |  |

+ 1 - 0
deploy/charts/external-secrets/templates/cert-controller-deployment.yaml

@@ -44,6 +44,7 @@ spec:
           image: "{{ .Values.certController.image.repository }}:{{ .Values.certController.image.tag | default .Chart.AppVersion }}"
           imagePullPolicy: {{ .Values.certController.image.pullPolicy }}
           args:
+          - certcontroller
           - --crd-requeue-interval={{ .Values.certController.requeueInterval }}
           - --service-name={{ include "external-secrets.fullname" . }}-webhook
           - --service-namespace={{ .Release.Namespace }}

+ 2 - 0
deploy/charts/external-secrets/templates/webhook-deployment.yaml

@@ -44,8 +44,10 @@ spec:
           image: "{{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Chart.AppVersion }}"
           imagePullPolicy: {{ .Values.webhook.image.pullPolicy }}
           args:
+          - webhook
           - --dns-name={{ include "external-secrets.fullname" . }}-webhook.{{ .Release.Namespace }}.svc
           - --cert-dir={{ .Values.webhook.certDir }}
+          - --check-interval={{ .Values.webhook.certCheckInterval }}
           {{- range $key, $value := .Values.webhook.extraArgs }}
             {{- if $value }}
           - --{{ $key }}={{ $value }}

+ 3 - 2
deploy/charts/external-secrets/values.yaml

@@ -88,10 +88,11 @@ affinity: {}
 priorityClassName: ""
 
 webhook:
+  certCheckInterval: "5m"
   replicaCount: 1
   certDir: /tmp/certs
   image:
-    repository: ghcr.io/external-secrets/external-secrets-webhook
+    repository: ghcr.io/external-secrets/external-secrets
     pullPolicy: IfNotPresent
   # -- The image tag to use. The default is the chart appVersion.
     tag: ""
@@ -155,7 +156,7 @@ webhook:
 certController:
   requeueInterval: "5m"
   image:
-    repository: ghcr.io/external-secrets/external-secrets-cert-controller
+    repository: ghcr.io/external-secrets/external-secrets
     pullPolicy: IfNotPresent
     tag: ""
   imagePullSecrets: []

+ 0 - 2
e2e/Makefile

@@ -23,8 +23,6 @@ test: e2e-image ## Run e2e tests against current kube context
 		BUILD_ARGS="${BUILD_ARGS} --build-arg TARGETARCH=amd64 --build-arg TARGETOS=linux"
 	kind load docker-image --name="external-secrets" $(IMAGE_REGISTRY):$(VERSION)
 	kind load docker-image --name="external-secrets" $(E2E_IMAGE_REGISTRY):$(VERSION)
-	kind load docker-image --name="external-secrets" $(IMAGE_REGISTRY)-webhook:$(VERSION)
-	kind load docker-image --name="external-secrets" $(IMAGE_REGISTRY)-cert-controller:$(VERSION)
 	./run.sh
 
 test.managed: e2e-image ## Run e2e tests against current kube context

+ 2 - 2
e2e/framework/addon/eso.go

@@ -37,11 +37,11 @@ func NewESO(mutators ...MutationFunc) *ESO {
 				},
 				{
 					Key:   "webhook.image.repository",
-					Value: os.Getenv("IMAGE_REGISTRY") + "-webhook",
+					Value: os.Getenv("IMAGE_REGISTRY"),
 				},
 				{
 					Key:   "certController.image.repository",
-					Value: os.Getenv("IMAGE_REGISTRY") + "-cert-controller",
+					Value: os.Getenv("IMAGE_REGISTRY"),
 				},
 				{
 					Key:   "webhook.image.tag",

+ 1 - 1
go.mod

@@ -87,6 +87,7 @@ require (
 
 require (
 	cloud.google.com/go/iam v0.1.1
+	github.com/spf13/cobra v1.3.0
 	k8s.io/apiextensions-apiserver v0.23.0
 )
 
@@ -184,7 +185,6 @@ require (
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 	github.com/ryanuber/go-glob v1.0.0 // indirect
 	github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b // indirect
-	github.com/spf13/cobra v1.3.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/stretchr/objx v0.2.0 // indirect
 	github.com/tidwall/match v1.1.1 // indirect

+ 4 - 110
main.go

@@ -1,4 +1,6 @@
 /*
+Copyright © 2022 ESO Maintainer Team
+
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
@@ -11,118 +13,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-
 package main
 
-import (
-	"flag"
-	"os"
-	"time"
-
-	"go.uber.org/zap/zapcore"
-	"k8s.io/apimachinery/pkg/runtime"
-	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/controller"
-	"sigs.k8s.io/controller-runtime/pkg/log/zap"
-
-	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
-	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
-	"github.com/external-secrets/external-secrets/pkg/controllers/externalsecret"
-	"github.com/external-secrets/external-secrets/pkg/controllers/secretstore"
-)
-
-var (
-	scheme   = runtime.NewScheme()
-	setupLog = ctrl.Log.WithName("setup")
-)
-
-const (
-	errCreateController = "unable to create controller"
-)
-
-func init() {
-	_ = clientgoscheme.AddToScheme(scheme)
-	_ = esv1beta1.AddToScheme(scheme)
-	_ = esv1alpha1.AddToScheme(scheme)
-}
+import "github.com/external-secrets/external-secrets/cmd"
 
 func main() {
-	var metricsAddr string
-	var controllerClass string
-	var enableLeaderElection bool
-	var concurrent int
-	var loglevel string
-	var namespace string
-	var storeRequeueInterval time.Duration
-	flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
-	flag.StringVar(&controllerClass, "controller-class", "default", "the controller is instantiated with a specific controller name and filters ES based on this property")
-	flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
-		"Enable leader election for controller manager. "+
-			"Enabling this will ensure there is only one active controller manager.")
-	flag.IntVar(&concurrent, "concurrent", 1, "The number of concurrent ExternalSecret reconciles.")
-	flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
-	flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
-	flag.DurationVar(&storeRequeueInterval, "store-requeue-interval", time.Minute*5, "Time duration between reconciling (Cluster)SecretStores")
-	flag.Parse()
-
-	var lvl zapcore.Level
-	err := lvl.UnmarshalText([]byte(loglevel))
-	if err != nil {
-		setupLog.Error(err, "error unmarshalling loglevel")
-		os.Exit(1)
-	}
-	logger := zap.New(zap.Level(lvl))
-	ctrl.SetLogger(logger)
-
-	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
-		Scheme:             scheme,
-		MetricsBindAddress: metricsAddr,
-		Port:               9443,
-		LeaderElection:     enableLeaderElection,
-		LeaderElectionID:   "external-secrets-controller",
-		Namespace:          namespace,
-	})
-	if err != nil {
-		setupLog.Error(err, "unable to start manager")
-		os.Exit(1)
-	}
-	if err = (&secretstore.StoreReconciler{
-		Client:          mgr.GetClient(),
-		Log:             ctrl.Log.WithName("controllers").WithName("SecretStore"),
-		Scheme:          mgr.GetScheme(),
-		ControllerClass: controllerClass,
-		RequeueInterval: storeRequeueInterval,
-	}).SetupWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateController, "controller", "SecretStore")
-		os.Exit(1)
-	}
-	if err = (&secretstore.ClusterStoreReconciler{
-		Client:          mgr.GetClient(),
-		Log:             ctrl.Log.WithName("controllers").WithName("ClusterSecretStore"),
-		Scheme:          mgr.GetScheme(),
-		ControllerClass: controllerClass,
-		RequeueInterval: storeRequeueInterval,
-	}).SetupWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateController, "controller", "ClusterSecretStore")
-		os.Exit(1)
-	}
-	if err = (&externalsecret.Reconciler{
-		Client:          mgr.GetClient(),
-		Log:             ctrl.Log.WithName("controllers").WithName("ExternalSecret"),
-		Scheme:          mgr.GetScheme(),
-		ControllerClass: controllerClass,
-		RequeueInterval: time.Hour,
-	}).SetupWithManager(mgr, controller.Options{
-		MaxConcurrentReconciles: concurrent,
-	}); err != nil {
-		setupLog.Error(err, errCreateController, "controller", "ExternalSecret")
-		os.Exit(1)
-	}
-	setupLog.Info("starting manager")
-	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
-		setupLog.Error(err, "problem running manager")
-		os.Exit(1)
-	}
+	cmd.Execute()
 }

+ 0 - 9
webhook/Dockerfile

@@ -1,9 +0,0 @@
-FROM gcr.io/distroless/static
-ARG TARGETOS
-ARG TARGETARCH
-COPY bin/external-secrets-webhook-${TARGETOS}-${TARGETARCH} /bin/external-secrets-webhook
-
-# Run as UID for nobody
-USER 65534
-
-ENTRYPOINT ["/bin/external-secrets-webhook"]

+ 0 - 9
webhook/certcontroller/Dockerfile

@@ -1,9 +0,0 @@
-FROM gcr.io/distroless/static
-ARG TARGETOS
-ARG TARGETARCH
-COPY bin/external-secrets-cert-controller-${TARGETOS}-${TARGETARCH} /bin/external-secrets-cert-controller
-
-# Run as UID for nobody
-USER 65534
-
-ENTRYPOINT ["/bin/external-secrets-cert-controller"]

+ 0 - 117
webhook/certcontroller/main.go

@@ -1,117 +0,0 @@
-/*
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"flag"
-	"os"
-	"time"
-
-	"go.uber.org/zap/zapcore"
-	"k8s.io/apimachinery/pkg/runtime"
-	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/controller"
-	"sigs.k8s.io/controller-runtime/pkg/log/zap"
-
-	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
-	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
-	"github.com/external-secrets/external-secrets/pkg/controllers/crds"
-)
-
-var (
-	scheme   = runtime.NewScheme()
-	setupLog = ctrl.Log.WithName("setup")
-)
-
-const (
-	errCreateController = "unable to create controller"
-)
-
-func init() {
-	_ = clientgoscheme.AddToScheme(scheme)
-	_ = esv1beta1.AddToScheme(scheme)
-	_ = esv1alpha1.AddToScheme(scheme)
-}
-
-func main() {
-	var metricsAddr string
-	var enableLeaderElection bool
-	var concurrent int
-	var loglevel string
-	var namespace string
-	var serviceName, serviceNamespace string
-	var secretName, secretNamespace string
-	var crdRequeueInterval time.Duration
-	flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
-	flag.StringVar(&serviceName, "service-name", "external-secrets-webhook", "Webhook service name")
-	flag.StringVar(&serviceNamespace, "service-namespace", "default", "Webhook service namespace")
-	flag.StringVar(&secretName, "secret-name", "external-secrets-webhook", "Secret to store certs for webhook")
-	flag.StringVar(&secretNamespace, "secret-namespace", "default", "namespace of the secret to store certs")
-	flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
-		"Enable leader election for controller manager. "+
-			"Enabling this will ensure there is only one active controller manager.")
-	flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
-	flag.DurationVar(&crdRequeueInterval, "crd-requeue-interval", time.Minute*5, "Time duration between reconciling CRDs for new certs")
-	flag.Parse()
-
-	var lvl zapcore.Level
-	err := lvl.UnmarshalText([]byte(loglevel))
-	if err != nil {
-		setupLog.Error(err, "error unmarshalling loglevel")
-		os.Exit(1)
-	}
-	logger := zap.New(zap.Level(lvl))
-	ctrl.SetLogger(logger)
-
-	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
-		Scheme:             scheme,
-		MetricsBindAddress: metricsAddr,
-		Port:               9443,
-		LeaderElection:     enableLeaderElection,
-		LeaderElectionID:   "crd-certs-controller",
-		Namespace:          namespace,
-	})
-	if err != nil {
-		setupLog.Error(err, "unable to start manager")
-		os.Exit(1)
-	}
-	crds := &crds.Reconciler{
-		Client:                 mgr.GetClient(),
-		Log:                    ctrl.Log.WithName("controllers").WithName("webhook-certs-updater"),
-		Scheme:                 mgr.GetScheme(),
-		SvcName:                serviceName,
-		SvcNamespace:           serviceNamespace,
-		SecretName:             secretName,
-		SecretNamespace:        secretNamespace,
-		RequeueInterval:        crdRequeueInterval,
-		CrdResources:           []string{"externalsecrets.external-secrets.io", "clustersecretstores.external-secrets.io", "secretstores.external-secrets.io"},
-		CAName:                 "external-secrets",
-		CAOrganization:         "external-secrets",
-		RestartOnSecretRefresh: false,
-	}
-	if err := crds.SetupWithManager(mgr, controller.Options{
-		MaxConcurrentReconciles: concurrent,
-	}); err != nil {
-		setupLog.Error(err, errCreateController, "controller", "CustomResourceDefinition")
-		os.Exit(1)
-	}
-	setupLog.Info("starting manager")
-	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
-		setupLog.Error(err, "problem running manager")
-		os.Exit(1)
-	}
-}

+ 0 - 154
webhook/main.go

@@ -1,154 +0,0 @@
-/*
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package main
-
-import (
-	"context"
-	"flag"
-	"os"
-	"os/signal"
-	"syscall"
-	"time"
-
-	"go.uber.org/zap/zapcore"
-	"k8s.io/apimachinery/pkg/runtime"
-	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/log/zap"
-
-	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
-	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
-	"github.com/external-secrets/external-secrets/pkg/controllers/crds"
-)
-
-var (
-	scheme   = runtime.NewScheme()
-	setupLog = ctrl.Log.WithName("setup")
-)
-
-const (
-	errCreateWebhook = "unable to create webhook"
-)
-
-func init() {
-	_ = clientgoscheme.AddToScheme(scheme)
-	_ = esv1beta1.AddToScheme(scheme)
-	_ = esv1alpha1.AddToScheme(scheme)
-}
-
-func main() {
-	var metricsAddr string
-	var enableLeaderElection bool
-	var loglevel string
-	var namespace string
-	var dnsName string
-	var certDir string
-	flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
-	flag.StringVar(&dnsName, "dns-name", "localhost", "DNS name to validate certificates with")
-	flag.StringVar(&certDir, "cert-dir", "/tmp/k8s-webhook-server/serving-certs", "path to check for certs")
-	flag.StringVar(&loglevel, "loglevel", "info", "loglevel to use, one of: debug, info, warn, error, dpanic, panic, fatal")
-	flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
-		"Enable leader election for controller manager. "+
-			"Enabling this will ensure there is only one active controller manager.")
-	flag.StringVar(&namespace, "namespace", "", "watch external secrets scoped in the provided namespace only. ClusterSecretStore can be used but only work if it doesn't reference resources from other namespaces")
-	flag.Parse()
-
-	var lvl zapcore.Level
-	err := lvl.UnmarshalText([]byte(loglevel))
-	if err != nil {
-		setupLog.Error(err, "error unmarshalling loglevel")
-		os.Exit(1)
-	}
-	c := crds.CertInfo{
-		CertDir:  certDir,
-		CertName: "tls.crt",
-		KeyName:  "tls.key",
-		CAName:   "ca.crt",
-	}
-
-	logger := zap.New(zap.Level(lvl))
-	ctrl.SetLogger(logger)
-
-	setupLog.Info("validating certs")
-	err = crds.CheckCerts(c, dnsName, time.Now().Add(time.Hour))
-	if err != nil {
-		setupLog.Error(err, "error checking certs")
-		os.Exit(1)
-	}
-	ctx, cancel := context.WithCancel(context.Background())
-	go func(c crds.CertInfo, dnsName string) {
-		// notify on sigterm and hour
-		sigs := make(chan os.Signal, 1)
-		signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
-		ticker := time.NewTicker(time.Hour)
-		for {
-			select {
-			case <-sigs:
-				cancel()
-			case <-ticker.C:
-				setupLog.Info("validating certs")
-				err = crds.CheckCerts(c, dnsName, time.Now().Add(crds.LookaheadInterval+time.Minute))
-				if err != nil {
-					cancel()
-				}
-				setupLog.Info("certs are valid")
-			}
-		}
-	}(c, dnsName)
-
-	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
-		Scheme:             scheme,
-		MetricsBindAddress: metricsAddr,
-		Port:               9443,
-		CertDir:            certDir,
-		LeaderElection:     enableLeaderElection,
-		LeaderElectionID:   "webhook-controller",
-		Namespace:          namespace,
-	})
-	if err != nil {
-		setupLog.Error(err, "unable to start manager")
-		os.Exit(1)
-	}
-	if err = (&esv1beta1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1beta1")
-		os.Exit(1)
-	}
-	if err = (&esv1beta1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1beta1")
-		os.Exit(1)
-	}
-	if err = (&esv1beta1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1beta1")
-		os.Exit(1)
-	}
-	if err = (&esv1alpha1.ExternalSecret{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "ExternalSecret-v1alpha1")
-		os.Exit(1)
-	}
-	if err = (&esv1alpha1.SecretStore{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "SecretStore-v1alpha1")
-		os.Exit(1)
-	}
-	if err = (&esv1alpha1.ClusterSecretStore{}).SetupWebhookWithManager(mgr); err != nil {
-		setupLog.Error(err, errCreateWebhook, "webhook", "ClusterSecretStore-v1alpha1")
-		os.Exit(1)
-	}
-	setupLog.Info("starting manager")
-	if err := mgr.Start(ctx); err != nil {
-		setupLog.Error(err, "problem running manager")
-		os.Exit(1)
-	}
-}