Skip to content

Commit

Permalink
allow reference to existing secret as imagePullSecret
Browse files Browse the repository at this point in the history
allows reference to existing secrets for imagePullSecrets without
passing the secret itself. this enables management of secrets by an external
system like sealedsecrets and prevents the secret data from being stored in helm.

it works by allowing use of the installation's imagePullSecret field
directly instead of the toplevel imagePullSecrets field
  • Loading branch information
ozdanborne committed May 16, 2023
1 parent 4bbda7d commit 9ca05e4
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 18 deletions.
29 changes: 29 additions & 0 deletions charts/test/helm_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package charttest

import (
"os/exec"
"testing"

"github.com/onsi/ginkgo/reporters"
"github.com/projectcalico/calico/libcalico-go/lib/testutils"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func init() {
testutils.HookLogrusForGinkgo()
}

func TestHelm(t *testing.T) {
// testutils.HookLogrusForGinkgo()
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("../../report/helm_suite.xml")

_, err := exec.LookPath("helm")
if err != nil {
t.Skip("skipping exec tests since 'helm' is not installed")
}

RunSpecsWithDefaultAndCustomReporters(t, "Helm Suite", []Reporter{junitReporter})
}
112 changes: 112 additions & 0 deletions charts/test/tigera_operator_chart_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Package charttest uses 'helm template' to render the helm package with various input values,
// unmarshals the resulting yaml into kubernetes resource types, and then tests that the correct fields
// are set accordingly.
package charttest

import (
"path/filepath"

corev1 "k8s.io/api/core/v1"

"github.com/gruntwork-io/terratest/modules/helm"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Tigera Operator Helm Chart", func() {
Describe("image pull secrets", func() {
Context("using toplevel config field", func() {
opts := &helm.Options{
SetValues: map[string]string{
"imagePullSecrets.my-secret": "secret1",
},
}

It("sets imagePullSecrets on serviceaccount", func() {
var serviceAccount corev1.ServiceAccount
err := renderChartResource(opts, "templates/tigera-operator/02-serviceaccount-tigera-operator.yaml", &serviceAccount)
Expect(err).ToNot(HaveOccurred())
Expect(serviceAccount.ImagePullSecrets).To(ConsistOf(
corev1.LocalObjectReference{Name: "my-secret"},
))
})

It("creates a secret", func() {
var secret corev1.Secret
err := renderChartResource(opts, "templates/tigera-operator/01-imagepullsecret.yaml", &secret)
Expect(err).ToNot(HaveOccurred())
Expect(secret.Name).To(Equal("my-secret"))
Expect(secret.Data).To(Equal(map[string][]byte{
".dockerconfigjson": []byte("secret1"),
}))
})
})

Context("using installation's config field", func() {
opts := &helm.Options{
SetValues: map[string]string{
"installation.imagePullSecrets[0].name": "my-secret",
},
}

It("sets imagePullSecrets on serviceaccount", func() {
var serviceAccount corev1.ServiceAccount
err := renderChartResource(opts, "templates/tigera-operator/02-serviceaccount-tigera-operator.yaml", &serviceAccount)
Expect(err).ToNot(HaveOccurred())
Expect(serviceAccount.ImagePullSecrets).To(ConsistOf(
corev1.LocalObjectReference{Name: "my-secret"},
))
})

It("does not create a secret", func() {
// assert an error occured. no other way to assert "file was not rendered"
err := renderChartResource(opts, "templates/tigera-operator/01-imagepullsecret.yaml", &corev1.Secret{})
Expect(err).To(HaveOccurred())
})
})

Describe("using both toplevel and installation fields", func() {
opts := &helm.Options{
SetValues: map[string]string{
"imagePullSecrets.secret-1": "secret1",
"installation.imagePullSecrets[0].name": "secret-2",
},
}

It("sets both imagePullSecrets on serviceaccount", func() {
var serviceAccount corev1.ServiceAccount
err := renderChartResource(opts, "templates/tigera-operator/02-serviceaccount-tigera-operator.yaml", &serviceAccount)
Expect(err).ToNot(HaveOccurred())
Expect(serviceAccount.ImagePullSecrets).To(ConsistOf(
corev1.LocalObjectReference{Name: "secret-1"},
corev1.LocalObjectReference{Name: "secret-2"},
))
})

It("only creates a secret for the toplevel secret", func() {
var secret corev1.Secret
err := renderChartResource(opts, "templates/tigera-operator/01-imagepullsecret.yaml", &secret)
Expect(err).ToNot(HaveOccurred())
Expect(secret.Name).To(Equal("secret-1"))
Expect(secret.Data).To(Equal(map[string][]byte{
".dockerconfigjson": []byte("secret1"),
}))
})
})
})
})

func renderChartResource(options *helm.Options, templatePath string, into any) error {
helmChartPath, err := filepath.Abs("../tigera-operator")
if err != nil {
return err
}

output, err := helm.RenderTemplateE(GinkgoT(), options, helmChartPath, "tigera-operator", []string{templatePath})
if err != nil {
return err
}
helm.UnmarshalK8SYaml(GinkgoT(), output, &into)
return nil
}
13 changes: 13 additions & 0 deletions charts/tigera-operator/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,16 @@
{{- end -}}
{{- .image -}}:{{- .version -}}
{{- end -}}

{{/*
generate imagePullSecrets for installation and deployments
by combining installation.imagePullSecrets with toplevel imagePullSecrets.
*/}}

{{- define "tigera-operator.imagePullSecrets" -}}
{{- $secrets := default list .Values.installation.imagePullSecrets -}}
{{- range $key, $val := .Values.imagePullSecrets -}}
{{- $secrets = append $secrets (dict "name" $key) -}}
{{- end -}}
{{ $secrets | toYaml }}
{{- end -}}
7 changes: 1 addition & 6 deletions charts/tigera-operator/templates/crs/custom-resources.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
{{ if .Values.installation.enabled }}
{{ $installSpec := omit .Values.installation "enabled" }}
{{ $secrets := list }}
{{ range $name := keys .Values.imagePullSecrets -}}
{{ $item := dict "name" $name }}
{{ $secrets = append $secrets $item }}
{{ end }}
{{ $_ := set $installSpec "imagePullSecrets" $secrets }}
{{ $_ := set $installSpec "imagePullSecrets" (include "tigera-operator.imagePullSecrets" . | fromYamlArray) }}
{{ $_ := set $installSpec "kubeletVolumePluginPath" .Values.kubeletVolumePluginPath }}

apiVersion: operator.tigera.io/v1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
{{ $secrets := list }}
{{ range $name := keys .Values.imagePullSecrets -}}
{{ $item := dict "name" $name }}
{{ $secrets = append $secrets $item }}
{{ end }}

apiVersion: v1
kind: ServiceAccount
metadata:
name: tigera-operator
namespace: {{.Release.Namespace}}
imagePullSecrets: {{- $secrets | toYaml | nindent 2 }}
imagePullSecrets: {{- include "tigera-operator.imagePullSecrets" . | nindent 2 }}
12 changes: 12 additions & 0 deletions charts/tigera-operator/values.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
# imagePullSecrets are a special helm field which, when specified, creates a secret
# containing the pull secret and configures operator's serviceaccount to use it to pull the operator image
# as well as configuring the installation resource so that images launched by the operator will use it as well.
# this field is a map where the key is the desired secret name and the value is the contents of the imagePullSecret.
#
# Example: --set-file imagePullSecrets.gcr=./pull-secret.json
imagePullSecrets: {}

installation:
enabled: true
kubernetesProvider: ""
# imagePullSecrets are configured on all images deployed by the tigera-operator.
# secrets specified here must exist in the tigera-operator namespace; they won't be created by the operator or helm.
# imagePullSecrets are a slice of LocalObjectReferences, which is the same format they appear as on deployments.
#
# Example: --set installation.imagePullSecrets[0].name=my-existing-secret
imagePullSecrets: []

apiServer:
enabled: true
Expand Down
21 changes: 16 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ require (
k8s.io/component-base v0.26.3
k8s.io/klog/v2 v2.80.1
k8s.io/kube-openapi v0.0.0-20230303024457-afdc3dddf62d
k8s.io/kubernetes v1.26.3
k8s.io/utils v0.0.0-20230313181309-38a27ef9d749
modernc.org/memory v1.5.0
sigs.k8s.io/kind v0.11.1
Expand All @@ -109,7 +108,7 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/mocks v0.4.2 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.1.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/GoogleCloudPlatform/k8s-cloud-provider v1.18.1-0.20220218231025-f11817397a1b // indirect
Expand All @@ -121,7 +120,7 @@ require (
github.com/alexflint/go-filemutex v1.1.0 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e // indirect
github.com/aws/aws-sdk-go v1.44.116 // indirect
github.com/aws/aws-sdk-go v1.44.122 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.6.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.0 // indirect
Expand All @@ -131,6 +130,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.9.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect
Expand All @@ -141,6 +141,7 @@ require (
github.com/containerd/ttrpc v1.1.0 // indirect
github.com/coreos/go-iptables v0.6.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
Expand All @@ -150,6 +151,7 @@ require (
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.2.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.4 // indirect
Expand All @@ -158,6 +160,7 @@ require (
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.0.0-20170327191703-71201497bace // indirect
github.com/go-sql-driver/mysql v1.4.1 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
Expand All @@ -172,8 +175,12 @@ require (
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/gruntwork-io/go-commons v0.8.0 // indirect
github.com/gruntwork-io/terratest v0.41.24 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.8 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
Expand All @@ -186,6 +193,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2 // indirect
github.com/mdlayher/genetlink v1.0.0 // indirect
github.com/mdlayher/netlink v1.1.0 // indirect
Expand All @@ -209,8 +217,10 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/otp v1.2.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1 // indirect
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646 // indirect
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
Expand All @@ -222,6 +232,7 @@ require (
github.com/stretchr/testify v1.8.1 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/urfave/cli v1.22.2 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/vmware/govmomi v0.20.3 // indirect
go.opencensus.io v0.24.0 // indirect
Expand All @@ -241,7 +252,7 @@ require (
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/oauth2 v0.1.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/time v0.1.0 // indirect
golang.org/x/tools v0.6.0 // indirect
Expand Down
Loading

0 comments on commit 9ca05e4

Please sign in to comment.