Browse Source

move controller into pkg

Kellin McAvoy 5 years ago
parent
commit
3fd7586033
34 changed files with 729 additions and 79 deletions
  1. 5 0
      .github/ci/ct.yaml
  2. 4 0
      .github/workflows/all.yml
  3. 55 0
      .github/workflows/helm.yml
  4. 4 0
      .github/workflows/main.yml
  5. 2 0
      .gitignore
  6. 2 2
      Dockerfile
  7. 25 1
      Makefile
  8. 2 2
      apis/externalsecrets/v1alpha1/externalsecret_types.go
  9. 3 3
      apis/externalsecrets/v1alpha1/secretstore_types.go
  10. 1 1
      apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go
  11. 1 8
      apis/meta/v1/types.go
  12. 0 16
      apis/meta/v1/zz_generated.deepcopy.go
  13. 4 6
      config/crd/bases/external-secrets.io_clustersecretstores.yaml
  14. 1 3
      config/crd/bases/external-secrets.io_externalsecrets.yaml
  15. 4 6
      config/crd/bases/external-secrets.io_secretstores.yaml
  16. 26 0
      deploy/charts/external-secrets/.helmignore
  17. 14 0
      deploy/charts/external-secrets/Chart.yaml
  18. 63 0
      deploy/charts/external-secrets/README.md
  19. 38 0
      deploy/charts/external-secrets/README.md.gotmpl
  20. 2 0
      deploy/charts/external-secrets/ci/main-values.yaml
  21. 7 0
      deploy/charts/external-secrets/templates/NOTES.txt
  22. 62 0
      deploy/charts/external-secrets/templates/_helpers.tpl
  23. 4 0
      deploy/charts/external-secrets/templates/crds/README.md
  24. 74 0
      deploy/charts/external-secrets/templates/deployment.yaml
  25. 101 0
      deploy/charts/external-secrets/templates/rbac.yaml
  26. 20 0
      deploy/charts/external-secrets/templates/service.yaml
  27. 12 0
      deploy/charts/external-secrets/templates/serviceaccount.yaml
  28. 68 0
      deploy/charts/external-secrets/values.yaml
  29. 7 6
      main.go
  30. 7 7
      controllers/externalsecret_controller.go
  31. 4 4
      controllers/suite_test.go
  32. 7 7
      controllers/secretstore_controller.go
  33. 81 0
      pkg/controllers/secretstore/suite_test.go
  34. 19 7
      pkg/provider/schema/schema_test.go

+ 5 - 0
.github/ci/ct.yaml

@@ -0,0 +1,5 @@
+chart-dirs:
+  - deploy/charts
+helm-extra-args: "--timeout=5m"
+check-version-increment: false
+target-branch: main

+ 4 - 0
.github/workflows/all.yml

@@ -7,8 +7,12 @@ on:
       - '*/*'       # matches every branch containing a single '/'
       - '**'        # matches every branch
       - '!main'     # excludes main
+    paths-ignore:
+      - 'deploy/**'
   pull_request:
     branches: [ '!main' ]
+    paths-ignore:
+      - 'deploy/**'
 
 env:
   KUBEBUILDER_VERSION: 2.3.1

+ 55 - 0
.github/workflows/helm.yml

@@ -0,0 +1,55 @@
+name: Helm
+
+on:
+  push:
+    tags:
+      - '*'
+    paths:
+      - 'deploy/charts/**'
+  pull_request:
+    branches: main
+    paths:
+      - 'deploy/charts/**'
+
+jobs:
+  lint-and-test:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+
+      - name: Generate chart
+        run: |
+          make crds-to-chart
+
+      - name: Set up Helm
+        uses: azure/setup-helm@v1
+        with:
+          version: v3.4.2
+
+      - uses: actions/setup-python@v2
+        with:
+          python-version: 3.7
+
+      - name: Set up chart-testing
+        uses: helm/chart-testing-action@v2.0.1
+
+      - name: Run chart-testing (list-changed)
+        id: list-changed
+        run: |
+          changed=$(ct list-changed --config=.github/ci/ct.yaml)
+          if [[ -n "$changed" ]]; then
+            echo "::set-output name=changed::true"
+          fi
+
+      - name: Run chart-testing (lint)
+        run: ct lint --config=.github/ci/ct.yaml
+
+      - name: Create kind cluster
+        uses: helm/kind-action@v1.1.0
+        if: steps.list-changed.outputs.changed == 'true'
+
+      - name: Run chart-testing (install)
+        run: ct install --config=.github/ci/ct.yaml

+ 4 - 0
.github/workflows/main.yml

@@ -5,8 +5,12 @@ on:
     branches: [ main ]
     tags:
       - '*'
+    paths-ignore:
+      - 'deploy/**'
   pull_request:
     branches: [ main ]
+    paths-ignore:
+      - 'deploy/**'
 
 env:
   KUBEBUILDER_VERSION: 2.3.1

+ 2 - 0
.gitignore

@@ -24,3 +24,5 @@ bin
 
 # Code test output
 cover.out
+
+deploy/charts/external-secrets/templates/crds/*.yaml

+ 2 - 2
Dockerfile

@@ -11,8 +11,8 @@ RUN go mod download
 
 # Copy the go source
 COPY main.go main.go
-COPY api/ api/
-COPY controllers/ controllers/
+COPY apis/ apis/
+COPY pkg/ pkg/
 
 # Build
 RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go

+ 25 - 1
Makefile

@@ -7,6 +7,8 @@ SHELL         := /bin/bash
 IMG ?= controller:latest
 # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
 CRD_OPTIONS ?= "crd:trivialVersions=true"
+HELM_DIR    ?= deploy/charts/external-secrets
+CRD_DIR     ?= config/crd/bases
 
 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
 ifeq (,$(shell go env GOBIN))
@@ -43,7 +45,13 @@ deploy: manifests ## Deploy controller in the Kubernetes cluster of current cont
 	kustomize build config/default | kubectl apply -f -
 
 manifests: controller-gen ## Generate manifests e.g. CRD, RBAC etc.
-	$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
+	$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=$(CRD_DIR)
+# Remove extra header lines in generated CRDs
+	@for i in $(CRD_DIR)/*.yaml; do \
+  		tail -n +3 <"$$i" >"$$i.bkp" && \
+  		cp "$$i.bkp" "$$i" && \
+  		rm "$$i.bkp"; \
+  	done
 
 lint/check: # Check install of golanci-lint
 	@if ! golangci-lint --version > /dev/null 2>&1; then \
@@ -77,6 +85,22 @@ docker-build: test ## Build the docker image
 docker-push: ## Push the docker image
 	docker push ${IMG}
 
+helm-docs: ## Generate helm docs
+	cd $(HELM_DIR); \
+	docker run --rm -v $(shell pwd)/$(HELM_DIR):/helm-docs -u $(shell id -u) jnorwood/helm-docs:latest
+
+crds-to-chart: # Copy crds to helm chart directory
+	cp $(CRD_DIR)/*.yaml $(HELM_DIR)/templates/crds/
+# Add helm chart if statement for installing CRDs
+	@for i in $(HELM_DIR)/templates/crds/*.yaml; do \
+		cp "$$i" "$$i.bkp" && \
+		echo "{{- if .Values.installCRDs }}" > "$$i" && \
+		cat "$$i.bkp" >> "$$i" && \
+		echo "{{- end }}" >> "$$i" && \
+		rm "$$i.bkp"; \
+	done
+
+
 # find or download controller-gen
 # download controller-gen if necessary
 controller-gen:

+ 2 - 2
apis/externalsecrets/v1alpha1/externalsecret_types.go

@@ -174,7 +174,7 @@ type ExternalSecretStatus struct {
 
 // +kubebuilder:object:root=true
 
-// ExternalSecret is the Schema for the externalsecrets API.
+// ExternalSecret is the Schema for the external-secrets API.
 type ExternalSecret struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -185,7 +185,7 @@ type ExternalSecret struct {
 
 // +kubebuilder:object:root=true
 
-// ExternalSecretList contains a list of ExternalSecret.
+// ExternalSecretList contains a list of ExternalSecret resources.
 type ExternalSecretList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`

+ 3 - 3
apis/externalsecrets/v1alpha1/secretstore_types.go

@@ -102,7 +102,7 @@ type SecretStore struct {
 
 // +kubebuilder:object:root=true
 
-// SecretStoreList contains a list of SecretStore.
+// SecretStoreList contains a list of SecretStore resources.
 type SecretStoreList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
@@ -124,9 +124,9 @@ type ClusterSecretStore struct {
 
 // +kubebuilder:object:root=true
 
-// ClusterSecretStoreList contains a list of ClusterSecretStore.
+// ClusterSecretStoreList contains a list of ClusterSecretStore resources.
 type ClusterSecretStoreList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata,omitempty"`
-	Items           []ExternalSecret `json:"items"`
+	Items           []ClusterSecretStore `json:"items"`
 }

+ 1 - 1
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -104,7 +104,7 @@ func (in *ClusterSecretStoreList) DeepCopyInto(out *ClusterSecretStoreList) {
 	in.ListMeta.DeepCopyInto(&out.ListMeta)
 	if in.Items != nil {
 		in, out := &in.Items, &out.Items
-		*out = make([]ExternalSecret, len(*in))
+		*out = make([]ClusterSecretStore, len(*in))
 		for i := range *in {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}

+ 1 - 8
apis/meta/v1/types.go

@@ -14,18 +14,11 @@ limitations under the License.
 
 package v1
 
-// A reference to an object in the same namespace as the referent.
-type LocalObjectReference struct {
-	// Name of the resource being referred to.
-	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
-	Name string `json:"name"`
-}
-
 // A reference to a specific 'key' within a Secret resource,
 // In some instances, `key` is a required field.
 type SecretKeySelector struct {
 	// The name of the Secret resource being referred to.
-	LocalObjectReference `json:",inline"`
+	Name string `json:"name"`
 	// Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults
 	// to the namespace of the referent.
 	// +optional

+ 0 - 16
apis/meta/v1/zz_generated.deepcopy.go

@@ -21,24 +21,8 @@ package v1
 import ()
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *LocalObjectReference) DeepCopyInto(out *LocalObjectReference) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalObjectReference.
-func (in *LocalObjectReference) DeepCopy() *LocalObjectReference {
-	if in == nil {
-		return nil
-	}
-	out := new(LocalObjectReference)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) {
 	*out = *in
-	out.LocalObjectReference = in.LocalObjectReference
 	if in.Namespace != nil {
 		in, out := &in.Namespace, &out.Namespace
 		*out = new(string)

+ 4 - 6
config/crd/bases/external-secrets.io_clustersecretstores.yaml

@@ -1,5 +1,3 @@
-
----
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
@@ -76,8 +74,8 @@ spec:
                                       may be required.
                                     type: string
                                   name:
-                                    description: 'Name of the resource being referred
-                                      to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                    description: The name of the Secret resource being
+                                      referred to.
                                     type: string
                                   namespace:
                                     description: Namespace of the resource being referred
@@ -98,8 +96,8 @@ spec:
                                       may be required.
                                     type: string
                                   name:
-                                    description: 'Name of the resource being referred
-                                      to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                    description: The name of the Secret resource being
+                                      referred to.
                                     type: string
                                   namespace:
                                     description: Namespace of the resource being referred

+ 1 - 3
config/crd/bases/external-secrets.io_externalsecrets.yaml

@@ -1,5 +1,3 @@
-
----
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
@@ -19,7 +17,7 @@ spec:
   - name: v1alpha1
     schema:
       openAPIV3Schema:
-        description: ExternalSecret is the Schema for the externalsecrets API.
+        description: ExternalSecret is the Schema for the external-secrets API.
         properties:
           apiVersion:
             description: 'APIVersion defines the versioned schema of this representation

+ 4 - 6
config/crd/bases/external-secrets.io_secretstores.yaml

@@ -1,5 +1,3 @@
-
----
 apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
@@ -76,8 +74,8 @@ spec:
                                       may be required.
                                     type: string
                                   name:
-                                    description: 'Name of the resource being referred
-                                      to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                    description: The name of the Secret resource being
+                                      referred to.
                                     type: string
                                   namespace:
                                     description: Namespace of the resource being referred
@@ -98,8 +96,8 @@ spec:
                                       may be required.
                                     type: string
                                   name:
-                                    description: 'Name of the resource being referred
-                                      to. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                    description: The name of the Secret resource being
+                                      referred to.
                                     type: string
                                   namespace:
                                     description: Namespace of the resource being referred

+ 26 - 0
deploy/charts/external-secrets/.helmignore

@@ -0,0 +1,26 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
+
+# CRD README.md
+templates/crds/README.md

+ 14 - 0
deploy/charts/external-secrets/Chart.yaml

@@ -0,0 +1,14 @@
+apiVersion: v2
+name: external-secrets
+description: External secret management for Kubernetes
+type: application
+version: "0.1.0"
+appVersion: "0.1.0"
+kubeVersion: ">= 1.11.0"
+keywords:
+  - kubernetes-external-secrets
+  - secrets
+home: https://github.com/external-secrets/external-secrets
+maintainers:
+  - name: mcavoyk
+    email: kellinmcavoy@gmail.com

+ 63 - 0
deploy/charts/external-secrets/README.md

@@ -0,0 +1,63 @@
+# external-secrets
+
+[//]: # (README.md generated by gotmpl. DO NOT EDIT.)
+
+![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square)
+
+External secret management for Kubernetes
+
+## TL;DR
+```bash
+helm repo add external-secrets https://external-secrets.github.io/external-secrets
+helm install external-secrets/external-secrets
+```
+
+## Installing the Chart
+To install the chart with the release name `external-secrets`:
+```bash
+helm install external-secrets external-secrets/external-secrets
+```
+
+### Custom Resources
+By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value.
+
+## Uninstalling the Chart
+To uninstall the `external-secrets` deployment:
+```bash
+helm uninstall external-secrets
+```
+The command removes all the Kubernetes components associated with the chart and deletes the release.
+
+## Configuration
+Read through the external-secrets [values.yaml](https://github.com/external-secrets/external-secrets/blob/master/deploy/charts/external-secrets/values.yaml)
+file. It has several commented out suggested values.
+
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| affinity | object | `{}` |  |
+| extraArgs | object | `{}` |  |
+| extraEnv | list | `[]` |  |
+| fullnameOverride | string | `""` |  |
+| image.pullPolicy | string | `"IfNotPresent"` |  |
+| image.repository | string | `"ghcr.io/external-secrets/external-secrets"` |  |
+| image.tag | string | `""` | The image tag to use. The default is the chart appVersion. |
+| imagePullSecrets | list | `[]` |  |
+| installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. |
+| leaderElect | bool | `true` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. |
+| nameOverride | string | `""` |  |
+| nodeSelector | object | `{}` |  |
+| podAnnotations | object | `{}` |  |
+| podLabels | object | `{}` |  |
+| podSecurityContext | object | `{}` |  |
+| prometheus.enabled | bool | `false` | Specifies whether to expose Service resource for collecting Prometheus metrics |
+| prometheus.service.port | int | `8080` |  |
+| rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. |
+| replicaCount | int | `1` |  |
+| resources | object | `{}` |  |
+| securityContext | object | `{}` |  |
+| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. |
+| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. |
+| 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 | `[]` |  |

+ 38 - 0
deploy/charts/external-secrets/README.md.gotmpl

@@ -0,0 +1,38 @@
+{{- $valuesYAML := "https://github.com/external-secrets/external-secrets/blob/master/deploy/charts/external-secrets/values.yaml" -}}
+{{- $chartRepo := "https://external-secrets.github.io/external-secrets" -}}
+{{- $org := "external-secrets" -}}
+{{ template "chart.header" . }}
+
+[//]: # (README.md generated by gotmpl. DO NOT EDIT.)
+
+{{ template "chart.typeBadge" . }}{{ template "chart.versionBadge" . }}{{ template "chart.appVersionBadge" . }}
+
+{{ template "chart.description" . }}
+
+## TL;DR
+```bash
+helm repo add {{ $org }} {{ $chartRepo }}
+helm install {{ $org }}/{{ template "chart.name" . }}
+```
+
+## Installing the Chart
+To install the chart with the release name `{{ template "chart.name" . }}`:
+```bash
+helm install {{ template "chart.name" . }} {{ $org }}/{{ template "chart.name" . }}
+```
+
+### Custom Resources
+By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value.
+
+## Uninstalling the Chart
+To uninstall the `{{ template "chart.name" . }}` deployment:
+```bash
+helm uninstall {{ template "chart.name" . }}
+```
+The command removes all the Kubernetes components associated with the chart and deletes the release.
+
+## Configuration
+Read through the {{ template "chart.name" . }} [values.yaml]({{ $valuesYAML }})
+file. It has several commented out suggested values.
+
+{{ template "chart.valuesSection" . }}

+ 2 - 0
deploy/charts/external-secrets/ci/main-values.yaml

@@ -0,0 +1,2 @@
+image:
+  tag: main

+ 7 - 0
deploy/charts/external-secrets/templates/NOTES.txt

@@ -0,0 +1,7 @@
+external-secrets has been deployed successfully!
+
+In order to begin using ExternalSecrets, you will need to set up a SecretStore
+or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).
+
+More information on the different types of SecretStores and how to configure them
+can be found in our Github: {{ .Chart.Home }}

+ 62 - 0
deploy/charts/external-secrets/templates/_helpers.tpl

@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "external-secrets.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "external-secrets.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "external-secrets.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "external-secrets.labels" -}}
+helm.sh/chart: {{ include "external-secrets.chart" . }}
+{{ include "external-secrets.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "external-secrets.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "external-secrets.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "external-secrets.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "external-secrets.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}

+ 4 - 0
deploy/charts/external-secrets/templates/crds/README.md

@@ -0,0 +1,4 @@
+# CRD Template Directory
+the CRDs are generated in pipeline during helm package. To install the CRDs please set `installCRDS: true`.
+
+The latest CRDs in the repository are located [here](../../../../../config/crd/bases)

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

@@ -0,0 +1,74 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "external-secrets.fullname" . }}
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels:
+      {{- include "external-secrets.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      {{- with .Values.podAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      labels:
+        {{- include "external-secrets.selectorLabels" . | nindent 8 }}
+        {{- with .Values.podLabels }}
+          {{- toYaml . | nindent 8 }}
+        {{- end }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      serviceAccountName: {{ include "external-secrets.serviceAccountName" . }}
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      containers:
+        - name: {{ .Chart.Name }}
+          {{- with .Values.securityContext }}
+          securityContext:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          args:
+          {{- if .Values.leaderElect }}
+          - --enable-leader-election=true
+          {{- end }}
+          {{- range $key, $value := .Values.extraArgs }}
+            {{- if $value }}
+          - --{{ $key }}={{ $value }}
+            {{- else }}
+          - --{{ $key }}
+            {{- end }}
+          {{- end }}
+          ports:
+            - containerPort: {{ .Values.prometheus.service.port }}
+              protocol: TCP
+          {{- with .Values.extraEnv }}
+          env:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          {{- with .Values.resources }}
+          resources:
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}

+ 101 - 0
deploy/charts/external-secrets/templates/rbac.yaml

@@ -0,0 +1,101 @@
+{{- if .Values.rbac.create -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ include "external-secrets.fullname" . }}-controller
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+rules:
+  - apiGroups:
+    - "external-secrets.io"
+    resources:
+    - "secretstores"
+    - "clustersecretstores"
+    - "externalsecrets"
+    verbs:
+    - "get"
+    - "list"
+    - "watch"
+  - apiGroups:
+    - "external-secrets.io"
+    resources:
+    - "externalsecrets"
+    - "externalsecrets/status"
+    verbs:
+    - "update"
+    - "patch"
+  - apiGroups:
+    - ""
+    resources:
+    - "secrets"
+    verbs:
+    - "get"
+    - "list"
+    - "watch"
+    - "create"
+    - "update"
+    - "delete"
+  - apiGroups:
+    - ""
+    resources:
+    - "events"
+    verbs:
+    - "create"
+    - "patch"
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ include "external-secrets.fullname" . }}-controller
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: {{ include "external-secrets.fullname" . }}-controller
+subjects:
+  - name: {{ include "external-secrets.serviceAccountName" . }}
+    namespace: {{ .Release.Namespace | quote }}
+    kind: ServiceAccount
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: {{ include "external-secrets.fullname" . }}-leaderelection
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+rules:
+  - apiGroups:
+    - ""
+    resources:
+    - "configmaps"
+    resourceNames:
+    - "external-secrets-controller"
+    verbs:
+    - "get"
+    - "update"
+    - "patch"
+  - apiGroups:
+    - ""
+    resources:
+    - "configmaps"
+    verbs:
+    - "create"
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: {{ include "external-secrets.fullname" . }}-leaderelection
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: {{ include "external-secrets.fullname" . }}-leaderelection
+subjects:
+  - kind: ServiceAccount
+    name: {{ include "external-secrets.serviceAccountName" . }}
+    namespace: {{ .Release.Namespace | quote }}
+{{- end }}

+ 20 - 0
deploy/charts/external-secrets/templates/service.yaml

@@ -0,0 +1,20 @@
+{{- if .Values.prometheus.enabled }}
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "external-secrets.fullname" . }}-metrics
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+  annotations:
+    prometheus.io/path: "/metrics"
+    prometheus.io/scrape: "true"
+    prometheus.io/port: {{ .Values.prometheus.service.port | quote }}
+spec:
+  type: ClusterIP
+  ports:
+    - port: {{ .Values.prometheus.service.port }}
+      targetPort: {{ .Values.prometheus.service.port }}
+      protocol: TCP
+  selector:
+    {{- include "external-secrets.selectorLabels" . | nindent 4 }}
+{{- end }}

+ 12 - 0
deploy/charts/external-secrets/templates/serviceaccount.yaml

@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "external-secrets.serviceAccountName" . }}
+  labels:
+    {{- include "external-secrets.labels" . | nindent 4 }}
+  {{- with .Values.serviceAccount.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- end }}

+ 68 - 0
deploy/charts/external-secrets/values.yaml

@@ -0,0 +1,68 @@
+replicaCount: 1
+
+image:
+  repository: ghcr.io/external-secrets/external-secrets
+  pullPolicy: IfNotPresent
+  # -- The image tag to use. The default is the chart appVersion.
+  tag: ""
+
+# -- If set, install and upgrade CRDs through helm chart.
+installCRDs: true
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+# -- If true, external-secrets will perform leader election between instances to ensure no more
+# than one instance of external-secrets operates at a time.
+leaderElect: false
+
+serviceAccount:
+  # -- Specifies whether a service account should be created.
+  create: true
+  # -- Annotations to add to the service account.
+  annotations: {}
+  # -- The name of the service account to use.
+  # If not set and create is true, a name is generated using the fullname template.
+  name: ""
+
+rbac:
+  # -- Specifies whether role and rolebinding resources should be created.
+  create: true
+
+## -- Extra environment variables to add to container.
+extraEnv: []
+
+## -- Map of extra arguments to pass to container.
+extraArgs: {}
+
+podAnnotations: {}
+podLabels: {}
+
+podSecurityContext: {}
+  # fsGroup: 2000
+
+securityContext: {}
+  # capabilities:
+  #   drop:
+  #   - ALL
+  # readOnlyRootFilesystem: true
+  # runAsNonRoot: true
+  # runAsUser: 1000
+
+resources: {}
+  # requests:
+  #   cpu: 10m
+  #   memory: 32Mi
+
+prometheus:
+  # -- Specifies whether to expose Service resource for collecting Prometheus metrics
+  enabled: false
+  service:
+    port: 8080
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}

+ 7 - 6
main.go

@@ -25,8 +25,9 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 
 	// +kubebuilder:scaffold:imports
-	externalsecretsv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
-	"github.com/external-secrets/external-secrets/controllers"
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	"github.com/external-secrets/external-secrets/pkg/controllers/externalsecret"
+	"github.com/external-secrets/external-secrets/pkg/controllers/secretstore"
 )
 
 var (
@@ -37,7 +38,7 @@ var (
 func init() {
 	_ = clientgoscheme.AddToScheme(scheme)
 
-	_ = externalsecretsv1alpha1.AddToScheme(scheme)
+	_ = esv1alpha1.AddToScheme(scheme)
 	// +kubebuilder:scaffold:scheme
 }
 
@@ -57,14 +58,14 @@ func main() {
 		MetricsBindAddress: metricsAddr,
 		Port:               9443,
 		LeaderElection:     enableLeaderElection,
-		LeaderElectionID:   "1fc40399.io",
+		LeaderElectionID:   "external-secrets-controller",
 	})
 	if err != nil {
 		setupLog.Error(err, "unable to start manager")
 		os.Exit(1)
 	}
 
-	if err = (&controllers.SecretStoreReconciler{
+	if err = (&secretstore.Reconciler{
 		Client: mgr.GetClient(),
 		Log:    ctrl.Log.WithName("controllers").WithName("SecretStore"),
 		Scheme: mgr.GetScheme(),
@@ -72,7 +73,7 @@ func main() {
 		setupLog.Error(err, "unable to create controller", "controller", "SecretStore")
 		os.Exit(1)
 	}
-	if err = (&controllers.ExternalSecretReconciler{
+	if err = (&externalsecret.Reconciler{
 		Client: mgr.GetClient(),
 		Log:    ctrl.Log.WithName("controllers").WithName("ExternalSecret"),
 		Scheme: mgr.GetScheme(),

+ 7 - 7
controllers/externalsecret_controller.go

@@ -12,7 +12,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package controllers
+package externalsecret
 
 import (
 	"context"
@@ -22,11 +22,11 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	externalsecretsv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 )
 
-// ExternalSecretReconciler reconciles a ExternalSecret object.
-type ExternalSecretReconciler struct {
+// Reconciler reconciles a ExternalSecret object.
+type Reconciler struct {
 	client.Client
 	Log    logr.Logger
 	Scheme *runtime.Scheme
@@ -35,7 +35,7 @@ type ExternalSecretReconciler struct {
 // +kubebuilder:rbac:groups=external-secrets.io,resources=externalsecrets,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=external-secrets.io,resources=externalsecrets/status,verbs=get;update;patch
 
-func (r *ExternalSecretReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
+func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
 	_ = context.Background()
 	_ = r.Log.WithValues("externalsecret", req.NamespacedName)
 
@@ -44,8 +44,8 @@ func (r *ExternalSecretReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err
 	return ctrl.Result{}, nil
 }
 
-func (r *ExternalSecretReconciler) SetupWithManager(mgr ctrl.Manager) error {
+func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
-		For(&externalsecretsv1alpha1.ExternalSecret{}).
+		For(&esv1alpha1.ExternalSecret{}).
 		Complete(r)
 }

+ 4 - 4
controllers/suite_test.go

@@ -12,7 +12,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package controllers
+package externalsecret
 
 import (
 	"path/filepath"
@@ -28,7 +28,7 @@ import (
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 
-	externalsecretsv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 )
 
 // These tests use Ginkgo (BDD-style Go testing framework). Refer to
@@ -59,10 +59,10 @@ var _ = BeforeSuite(func(done Done) {
 	Expect(err).ToNot(HaveOccurred())
 	Expect(cfg).ToNot(BeNil())
 
-	err = externalsecretsv1alpha1.AddToScheme(scheme.Scheme)
+	err = esv1alpha1.AddToScheme(scheme.Scheme)
 	Expect(err).NotTo(HaveOccurred())
 
-	err = externalsecretsv1alpha1.AddToScheme(scheme.Scheme)
+	err = esv1alpha1.AddToScheme(scheme.Scheme)
 	Expect(err).NotTo(HaveOccurred())
 
 	// +kubebuilder:scaffold:scheme

+ 7 - 7
controllers/secretstore_controller.go

@@ -12,7 +12,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package controllers
+package secretstore
 
 import (
 	"context"
@@ -22,11 +22,11 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
-	externalsecretsv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 )
 
-// SecretStoreReconciler reconciles a SecretStore object.
-type SecretStoreReconciler struct {
+// Reconciler reconciles a SecretStore object.
+type Reconciler struct {
 	client.Client
 	Log    logr.Logger
 	Scheme *runtime.Scheme
@@ -35,7 +35,7 @@ type SecretStoreReconciler struct {
 // +kubebuilder:rbac:groups=external-secrets.io,resources=secretstores,verbs=get;list;watch;create;update;patch;delete
 // +kubebuilder:rbac:groups=external-secrets.io,resources=secretstores/status,verbs=get;update;patch
 
-func (r *SecretStoreReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
+func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
 	_ = context.Background()
 	_ = r.Log.WithValues("secretstore", req.NamespacedName)
 
@@ -44,8 +44,8 @@ func (r *SecretStoreReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error)
 	return ctrl.Result{}, nil
 }
 
-func (r *SecretStoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
+func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewControllerManagedBy(mgr).
-		For(&externalsecretsv1alpha1.SecretStore{}).
+		For(&esv1alpha1.SecretStore{}).
 		Complete(r)
 }

+ 81 - 0
pkg/controllers/secretstore/suite_test.go

@@ -0,0 +1,81 @@
+/*
+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 secretstore
+
+import (
+	"path/filepath"
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"k8s.io/client-go/kubernetes/scheme"
+	"k8s.io/client-go/rest"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/envtest"
+	"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+)
+
+// These tests use Ginkgo (BDD-style Go testing framework). Refer to
+// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
+
+var cfg *rest.Config
+var k8sClient client.Client
+var testEnv *envtest.Environment
+
+func TestAPIs(t *testing.T) {
+	RegisterFailHandler(Fail)
+
+	RunSpecsWithDefaultAndCustomReporters(t,
+		"Controller Suite",
+		[]Reporter{printer.NewlineReporter{}})
+}
+
+var _ = BeforeSuite(func(done Done) {
+	logf.SetLogger(zap.LoggerTo(GinkgoWriter, true))
+
+	By("bootstrapping test environment")
+	testEnv = &envtest.Environment{
+		CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
+	}
+
+	var err error
+	cfg, err = testEnv.Start()
+	Expect(err).ToNot(HaveOccurred())
+	Expect(cfg).ToNot(BeNil())
+
+	err = esv1alpha1.AddToScheme(scheme.Scheme)
+	Expect(err).NotTo(HaveOccurred())
+
+	err = esv1alpha1.AddToScheme(scheme.Scheme)
+	Expect(err).NotTo(HaveOccurred())
+
+	// +kubebuilder:scaffold:scheme
+
+	k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
+	Expect(err).ToNot(HaveOccurred())
+	Expect(k8sClient).ToNot(BeNil())
+
+	close(done)
+}, 60)
+
+var _ = AfterSuite(func() {
+	By("tearing down the test environment")
+	err := testEnv.Stop()
+	Expect(err).ToNot(HaveOccurred())
+})

+ 19 - 7
pkg/provider/schema/schema_test.go

@@ -44,11 +44,23 @@ func (p *PP) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretData
 func TestRegister(t *testing.T) {
 	p, ok := GetProviderByName("awssm")
 	assert.Nil(t, p)
-	assert.False(t, ok)
-	ForceRegister(&PP{}, &esv1alpha1.SecretStoreProvider{
-		AWSSM: &esv1alpha1.AWSSMProvider{},
-	})
-	p, ok = GetProviderByName("awssm")
-	assert.NotNil(t, p)
-	assert.True(t, ok)
+	assert.False(t, ok, "provider should not be registered")
+
+	testProvider := &PP{}
+	secretStore := &esv1alpha1.SecretStore{
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				AWSSM: &esv1alpha1.AWSSMProvider{},
+			},
+		},
+	}
+
+	ForceRegister(testProvider, secretStore.Spec.Provider)
+	p1, ok := GetProviderByName("awssm")
+	assert.True(t, ok, "provider should be registered")
+	assert.Equal(t, testProvider, p1)
+
+	p2, err := GetProvider(secretStore)
+	assert.Nil(t, err)
+	assert.Equal(t, testProvider, p2)
 }