From b266e18fd45e936e6149d40c202deff0f39cb8e9 Mon Sep 17 00:00:00 2001 From: Sirajudeen Date: Wed, 14 Oct 2020 02:39:46 +0000 Subject: [PATCH] Image override for cert-manager components * Images added to clusterctl object like Providers So that repository and tag for one or all of the cert-manager components can be overriden using patch/replacement clusterctl Documentation for Image Override: https://cluster-api.sigs.k8s.io/clusterctl/configuration.html#image-overrides Change-Id: Id9de8d1967e49aeb3293f6802e51d66d598333ae Closes: #350 --- .../versions-airshipctl.yaml | 3 ++ manifests/function/clusterctl/clusterctl.yaml | 7 +++ .../clusterctl/replacements/versions.yaml | 10 ++++ pkg/api/v1alpha1/clusterctl_types.go | 10 +++- pkg/clusterctl/client/client_test.go | 41 +++++++++++++++- .../valid/ephemeral/initinfra/clusterctl.yaml | 2 +- pkg/clusterctl/implementations/reader.go | 25 ++++++++-- pkg/clusterctl/implementations/reader_test.go | 48 +++++++++++++++++++ 8 files changed, 139 insertions(+), 7 deletions(-) diff --git a/manifests/function/airshipctl-base-catalogues/versions-airshipctl.yaml b/manifests/function/airshipctl-base-catalogues/versions-airshipctl.yaml index ed3cd6cde..cd5c68c28 100644 --- a/manifests/function/airshipctl-base-catalogues/versions-airshipctl.yaml +++ b/manifests/function/airshipctl-base-catalogues/versions-airshipctl.yaml @@ -68,4 +68,7 @@ images: manager: ghcr.io/fluxcd/helm-controller:v0.2.0 source_controller: # source-controller Deployment manager: ghcr.io/fluxcd/source-controller:v0.2.1 + cert-manager: + repository: "quay.io/jetstack" + kubernetes: v1.18.6 diff --git a/manifests/function/clusterctl/clusterctl.yaml b/manifests/function/clusterctl/clusterctl.yaml index fde2f6602..ce2e69436 100644 --- a/manifests/function/clusterctl/clusterctl.yaml +++ b/manifests/function/clusterctl/clusterctl.yaml @@ -33,6 +33,13 @@ providers: variable-substitution: true versions: v0.3.7: airshipctl/manifests/function/cacpk/v0.3.7 + +# The default image repository and tag for a specific component +# can be overriden here +images: + cert-manager: + repository: "quay.io/jetstack" + # These default images can be overridden via the `replacements/` entrypoint additional-vars: CONTAINER_CAPM3_MANAGER: quay.io/metal3-io/cluster-api-provider-metal3:v0.3.2 diff --git a/manifests/function/clusterctl/replacements/versions.yaml b/manifests/function/clusterctl/replacements/versions.yaml index 8ee57f1b0..778b5e408 100644 --- a/manifests/function/clusterctl/replacements/versions.yaml +++ b/manifests/function/clusterctl/replacements/versions.yaml @@ -114,3 +114,13 @@ replacements: name: clusterctl_init fieldrefs: ["{.additional-vars.CONTAINER_CAPI_AUTH_PROXY}"] +# Replace the cert-manager image repository in the Clusterctl +- source: + objref: + name: versions-airshipctl + fieldref: "{.images.cert-manager.repository}" + target: + objref: + kind: Clusterctl + name: clusterctl_init + fieldrefs: ["{.images.cert-manager.repository}"] diff --git a/pkg/api/v1alpha1/clusterctl_types.go b/pkg/api/v1alpha1/clusterctl_types.go index 1f90df457..ab6dba356 100644 --- a/pkg/api/v1alpha1/clusterctl_types.go +++ b/pkg/api/v1alpha1/clusterctl_types.go @@ -36,7 +36,14 @@ type Clusterctl struct { AdditionalComponentVariables map[string]string `json:"additional-vars,omitempty"` // EnvVars if set to true, allows to source variables for cluster-api components // for environment variables. - EnvVars bool `json:"env-vars,omitempty"` + EnvVars bool `json:"env-vars,omitempty"` + ImageMetas map[string]ImageMeta `json:"images,omitempty"` +} + +// ImageMeta is part of clusterctl config +type ImageMeta struct { + Repository string `json:"repository,omitempty"` + Tag string `json:"tag,omitempty"` } // Provider is part of clusterctl config @@ -112,5 +119,6 @@ func DefaultClusterctl() *Clusterctl { InitOptions: &InitOptions{}, MoveOptions: &MoveOptions{}, Providers: make([]*Provider, 0), + ImageMetas: make(map[string]ImageMeta, 0), } } diff --git a/pkg/clusterctl/client/client_test.go b/pkg/clusterctl/client/client_test.go index adaf4789e..c6ddd1936 100644 --- a/pkg/clusterctl/client/client_test.go +++ b/pkg/clusterctl/client/client_test.go @@ -46,7 +46,11 @@ providers: type: "InfrastructureProvider" versions: v0.3.1: functions/capi/infrastructure/v0.3.1 - v0.3.2: functions/capi/infrastructure/v0.3.2` + v0.3.2: functions/capi/infrastructure/v0.3.2 +images: + cert-manager/cert-manager-cainjector: + repository: "myorg.io/local-repo" + tag: "v0.1"` ) func TestNewConfig(t *testing.T) { @@ -117,6 +121,41 @@ func TestNewConfig(t *testing.T) { } } +func TestImageMeta(t *testing.T) { + tests := []struct { + name string + conf *airshipv1.Clusterctl + component string + image string + want string + }{ + { + name: "clusterctl image override ", + component: "cert-manager", + image: "myorg.io/local-repo/cert-manager-cainjector:v0.1", + conf: &airshipv1.Clusterctl{ + ImageMetas: map[string]airshipv1.ImageMeta{ + "cert-manager/cert-manager-cainjector": { + Repository: "myorg.io/local-repo", + Tag: "v0.1", + }, + }, + }, + want: "myorg.io/local-repo/cert-manager-cainjector:v0.1", + }, + } + for _, tt := range tests { + conf := tt.conf + t.Run(tt.name, func(t *testing.T) { + got, err := newConfig(conf, testDataDir) + require.NoError(t, err) + image, err := got.ImageMeta().AlterImage(tt.component, tt.image) + require.NoError(t, err) + assert.Equal(t, image, tt.want) + }) + } +} + func TestNewClientEmptyOptions(t *testing.T) { c := &airshipv1.Clusterctl{} client, err := NewClient("", true, c) diff --git a/pkg/clusterctl/cmd/testdata/valid/ephemeral/initinfra/clusterctl.yaml b/pkg/clusterctl/cmd/testdata/valid/ephemeral/initinfra/clusterctl.yaml index 79da28b89..ba8b3d781 100644 --- a/pkg/clusterctl/cmd/testdata/valid/ephemeral/initinfra/clusterctl.yaml +++ b/pkg/clusterctl/cmd/testdata/valid/ephemeral/initinfra/clusterctl.yaml @@ -19,4 +19,4 @@ providers: type: "InfrastructureProvider" versions: v0.3.1: functions/capi/infrastructure/v0.3.1 - v0.3.2: functions/capi/infrastructure/v0.3.2 \ No newline at end of file + v0.3.2: functions/capi/infrastructure/v0.3.2 diff --git a/pkg/clusterctl/implementations/reader.go b/pkg/clusterctl/implementations/reader.go index 23a17ad5e..324587da8 100644 --- a/pkg/clusterctl/implementations/reader.go +++ b/pkg/clusterctl/implementations/reader.go @@ -48,6 +48,11 @@ type configProvider struct { Type clusterctlv1.ProviderType `json:"type,omitempty"` } +type imageMeta struct { + Repository string `json:"repository,omitempty"` + Tag string `json:"tag,omitempty"` +} + // Init implementation of clusterctl reader interface // This is dummy method that is must be present to implement Reader interface func (f *AirshipReader) Init(config string) error { @@ -109,6 +114,7 @@ func allowAppend(key, _ string) bool { func NewAirshipReader(options *airshipv1.Clusterctl) (*AirshipReader, error) { variables := map[string]string{} providers := []configProvider{} + images := map[string]imageMeta{} for _, prov := range options.Providers { appendProvider := configProvider{ Name: prov.Name, @@ -117,7 +123,7 @@ func NewAirshipReader(options *airshipv1.Clusterctl) (*AirshipReader, error) { } providers = append(providers, appendProvider) } - b, err := yaml.Marshal(providers) + providersYaml, err := yaml.Marshal(providers) if err != nil { return nil, err } @@ -127,10 +133,21 @@ func NewAirshipReader(options *airshipv1.Clusterctl) (*AirshipReader, error) { variables[key] = val } } + + for key, val := range options.ImageMetas { + imageVal := imageMeta{ + Repository: val.Repository, + Tag: val.Tag, + } + images[key] = imageVal + } + imagesYaml, err := yaml.Marshal(images) + if err != nil { + return nil, err + } // Add providers to config - variables[config.ProvidersConfigKey] = string(b) - // Add empty image configuration to config - variables[imagesConfigKey] = "" + variables[config.ProvidersConfigKey] = string(providersYaml) + variables[imagesConfigKey] = string(imagesYaml) return &AirshipReader{ variables: variables, varsFromEnv: options.EnvVars, diff --git a/pkg/clusterctl/implementations/reader_test.go b/pkg/clusterctl/implementations/reader_test.go index f38b39871..df3064dcc 100644 --- a/pkg/clusterctl/implementations/reader_test.go +++ b/pkg/clusterctl/implementations/reader_test.go @@ -57,6 +57,11 @@ func makeValidOptions() *airshipv1.Clusterctl { }, }, }, + ImageMetas: map[string]airshipv1.ImageMeta{ + "all": { + Repository: "myorg.io/all-repo", + }, + }, } } @@ -113,6 +118,49 @@ func TestGet(t *testing.T) { type: InfrastructureProvider - name: kubeadm type: ControlPlaneProvider +`, + }, + { + name: "image repo override for all clusterctl components", + options: makeValidOptions(), + key: "images", + expectedErr: nil, + expectedResult: `all: + repository: myorg.io/all-repo +`, + }, + { + name: "image override for cert-manager components", + options: &airshipv1.Clusterctl{ + ImageMetas: map[string]airshipv1.ImageMeta{ + "cert-manager": { + Repository: "myorg.io/certmanager-repo", + Tag: "v0.1", + }, + }, + }, + key: "images", + expectedErr: nil, + expectedResult: `cert-manager: + repository: myorg.io/certmanager-repo + tag: v0.1 +`, + }, + { + name: "image override for cainjector of cert-manager", + options: &airshipv1.Clusterctl{ + ImageMetas: map[string]airshipv1.ImageMeta{ + "cert-manager/cert-manager-cainjector": { + Repository: "myorg.io/certmanagercainjector-repo", + Tag: "v0.1", + }, + }, + }, + key: "images", + expectedErr: nil, + expectedResult: `cert-manager/cert-manager-cainjector: + repository: myorg.io/certmanagercainjector-repo + tag: v0.1 `, }, }