Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow reference to existing secret as imagePullSecret #7657

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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})
}
116 changes: 116 additions & 0 deletions charts/test/tigera_operator_chart_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// 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"
"testing"

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

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

. "github.com/onsi/gomega"
)

func TestTigeraOperatorHelmChart(t *testing.T) {
t.Run("image pull secrets", func(t *testing.T) {
t.Run("using toplevel config field", func(t *testing.T) {
opts := &helm.Options{
SetValues: map[string]string{
"imagePullSecrets.my-secret": "secret1",
},
}

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

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

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

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

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

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

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

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

func renderChartResource(t *testing.T, options *helm.Options, templatePath string, into any) error {
helmChartPath, err := filepath.Abs("../tigera-operator")
Expect(err).ToNot(HaveOccurred())

output, err := helm.RenderTemplateE(t, options, helmChartPath, "tigera-operator", []string{templatePath})
if err != nil {
return err
}
helm.UnmarshalK8SYaml(t, output, &into)
return nil
}
15 changes: 12 additions & 3 deletions charts/tigera-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ ownership of the helm resources to the new chart location.
The default values.yaml should be suitable for most basic deployments.

```
# Image pull secrets to provision for pulling images from private registries.
# This field is a map of desired Secret name to .dockerconfigjson formatted data to use for the secret.
# Populates the `imagePullSecrets` property for all Pods controlled by the `Installation` resource.
# imagePullSecrets is a special helm field which, when specified, creates a secret
# containing the pull secret which is used to pull all images deployed by this helm chart and the resulting operator.
# 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: {}

# Configures general installation parameters for Calico. Schema is based
Expand All @@ -99,6 +101,13 @@ 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: []

# Configures general installation parameters for Calico. Schema is based
# on the operator.tigera.io/Installation API documented
# here: https://projectcalico.docs.tigera.io/reference/installation/api#operator.tigera.io/v1.APIServerSpec
Expand Down
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 -}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose if a secret is defined in both places we'll get an error back from k8s?

This is probably OK, although I can definitely imagine users trying to put a secret in both places.

{{- range $key, $val := .Values.imagePullSecrets -}}
{{- $secrets = append $secrets (dict "name" $key) -}}
{{- end -}}
{{ $secrets | toYaml }}
{{- end -}}
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 }}
11 changes: 11 additions & 0 deletions charts/tigera-operator/values.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
# imagePullSecrets is a special helm field which, when specified, creates a secret
# containing the pull secret which is used to pull all images deployed by this helm chart and the resulting operator.
# 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
caseydavenport marked this conversation as resolved.
Show resolved Hide resolved
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
20 changes: 16 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
github.com/google/netstack v0.0.0-20191123085552-55fcc16cd0eb
github.com/google/safetext v0.0.0-20230106111101-7156a760e523
github.com/google/uuid v1.3.0
github.com/gruntwork-io/terratest v0.41.24
github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07
github.com/joho/godotenv v1.4.0
github.com/json-iterator/go v1.1.12
Expand Down Expand Up @@ -110,7 +111,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 @@ -122,7 +123,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 @@ -132,6 +133,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 @@ -142,6 +144,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 @@ -151,6 +154,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 @@ -159,6 +163,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 @@ -173,8 +178,11 @@ 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/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 @@ -187,6 +195,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 @@ -210,8 +219,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 @@ -223,6 +234,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 @@ -242,7 +254,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