From 5b7f2b3310428403ae7b1a8529248ba52b7de623 Mon Sep 17 00:00:00 2001 From: Di Xu Date: Wed, 16 Aug 2017 14:52:29 +0800 Subject: [PATCH] support imagePullSecrets and imagePullPolicy in kubefed init --- federation/pkg/kubefed/init/init.go | 36 +++++++++++++------ federation/pkg/kubefed/init/init_test.go | 44 +++++++++++++++++++----- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/federation/pkg/kubefed/init/init.go b/federation/pkg/kubefed/init/init.go index 60803e75ec..4193c598b4 100644 --- a/federation/pkg/kubefed/init/init.go +++ b/federation/pkg/kubefed/init/init.go @@ -136,6 +136,8 @@ type initFederation struct { type initFederationOptions struct { dnsZoneName string serverImage string + imagePullPolicy string + imagePullSecrets string dnsProvider string dnsProviderConfig string etcdImage string @@ -161,6 +163,8 @@ type initFederationOptions struct { func (o *initFederationOptions) Bind(flags *pflag.FlagSet, defaultServerImage, defaultEtcdImage string) { flags.StringVar(&o.dnsZoneName, "dns-zone-name", "", "DNS suffix for this federation. Federated Service DNS names are published with this suffix.") flags.StringVar(&o.serverImage, "image", defaultServerImage, "Image to use for federation API server and controller manager binaries.") + flags.StringVar(&o.imagePullPolicy, "image-pull-policy", string(api.PullIfNotPresent), "PullPolicy describes a policy for if/when to pull a container image. The default pull policy is IfNotPresent which will not pull an image if it already exists.") + flags.StringVar(&o.imagePullSecrets, "image-pull-secrets", "", "Provide secrets that can access the private registry.") flags.StringVar(&o.dnsProvider, "dns-provider", "", "Dns provider to be used for this deployment.") flags.StringVar(&o.dnsProviderConfig, "dns-provider-config", "", "Config file path on local file system for configuring DNS provider.") flags.StringVar(&o.etcdImage, "etcd-image", defaultEtcdImage, "Image to use for etcd server.") @@ -368,7 +372,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error { fmt.Fprint(cmdOut, "Creating federation component deployments...") glog.V(4).Info("Creating federation control plane components") - _, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.serverImage, i.options.etcdImage, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun, i.options.nodeSelector) + _, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.commonOptions.Name, i.options.serverImage, i.options.etcdImage, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun, i.options.nodeSelector, i.options.imagePullPolicy, i.options.imagePullSecrets) if err != nil { return err } @@ -403,7 +407,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error { glog.V(4).Info("Creating federation controller manager deployment") - _, err = createControllerManager(hostClientset, i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, cmName, i.options.serverImage, cmKubeconfigName, i.options.dnsZoneName, i.options.dnsProvider, i.options.dnsProviderConfig, sa.Name, dnsProviderSecret, i.options.controllerManagerOverrides, i.options.dryRun, i.options.nodeSelector) + _, err = createControllerManager(hostClientset, i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, cmName, i.options.serverImage, cmKubeconfigName, i.options.dnsZoneName, i.options.dnsProvider, i.options.dnsProviderConfig, sa.Name, dnsProviderSecret, i.options.controllerManagerOverrides, i.options.dryRun, i.options.nodeSelector, i.options.imagePullPolicy, i.options.imagePullSecrets) if err != nil { return err } @@ -709,7 +713,7 @@ func createPVC(clientset client.Interface, namespace, svcName, federationName, e return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc) } -func createAPIServer(clientset client.Interface, namespace, name, federationName, serverImage, etcdImage, advertiseAddress, credentialsName string, hasHTTPBasicAuthFile, hasTokenAuthFile bool, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool, nodeSelector map[string]string) (*extensions.Deployment, error) { +func createAPIServer(clientset client.Interface, namespace, name, federationName, serverImage, etcdImage, advertiseAddress, credentialsName string, hasHTTPBasicAuthFile, hasTokenAuthFile bool, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool, nodeSelector map[string]string, imagePullPolicy, imagePullSecrets string) (*extensions.Deployment, error) { command := []string{ "/hyperkube", "federation-apiserver", @@ -755,9 +759,10 @@ func createAPIServer(clientset client.Interface, namespace, name, federationName Spec: api.PodSpec{ Containers: []api.Container{ { - Name: "apiserver", - Image: serverImage, - Command: command, + Name: "apiserver", + Image: serverImage, + ImagePullPolicy: api.PullPolicy(imagePullPolicy), + Command: command, Ports: []api.ContainerPort{ { Name: apiServerSecurePortName, @@ -787,6 +792,11 @@ func createAPIServer(clientset client.Interface, namespace, name, federationName }, }, NodeSelector: nodeSelector, + ImagePullSecrets: []api.LocalObjectReference{ + { + Name: imagePullSecrets, + }, + }, Volumes: []api.Volume{ { Name: credentialsName, @@ -884,7 +894,7 @@ func createRoleBindings(clientset client.Interface, namespace, saName, federatio return newRole, newRolebinding, err } -func createControllerManager(clientset client.Interface, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider, dnsProviderConfig, saName string, dnsProviderSecret *api.Secret, argOverrides map[string]string, dryRun bool, nodeSelector map[string]string) (*extensions.Deployment, error) { +func createControllerManager(clientset client.Interface, namespace, name, svcName, cmName, image, kubeconfigName, dnsZoneName, dnsProvider, dnsProviderConfig, saName string, dnsProviderSecret *api.Secret, argOverrides map[string]string, dryRun bool, nodeSelector map[string]string, imagePullPolicy, imagePullSecrets string) (*extensions.Deployment, error) { command := []string{ "/hyperkube", "federation-controller-manager", @@ -931,9 +941,10 @@ func createControllerManager(clientset client.Interface, namespace, name, svcNam Spec: api.PodSpec{ Containers: []api.Container{ { - Name: "controller-manager", - Image: image, - Command: command, + Name: "controller-manager", + Image: image, + ImagePullPolicy: api.PullPolicy(imagePullPolicy), + Command: command, VolumeMounts: []api.VolumeMount{ { Name: kubeconfigName, @@ -954,6 +965,11 @@ func createControllerManager(clientset client.Interface, namespace, name, svcNam }, }, NodeSelector: nodeSelector, + ImagePullSecrets: []api.LocalObjectReference{ + { + Name: imagePullSecrets, + }, + }, Volumes: []api.Volume{ { Name: kubeconfigName, diff --git a/federation/pkg/kubefed/init/init_test.go b/federation/pkg/kubefed/init/init_test.go index f0e74a1e0c..ea24ad9287 100644 --- a/federation/pkg/kubefed/init/init_test.go +++ b/federation/pkg/kubefed/init/init_test.go @@ -96,6 +96,8 @@ func TestInitFederation(t *testing.T) { apiserverServiceType v1.ServiceType advertiseAddress string serverImage string + imagePullPolicy string + imagePullSecrets string etcdImage string etcdPVCapacity string etcdPVStorageClass string @@ -119,6 +121,7 @@ func TestInitFederation(t *testing.T) { lbIP: lbIP, apiserverServiceType: v1.ServiceTypeLoadBalancer, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "5Gi", etcdPersistence: "true", expectedErr: "", @@ -137,6 +140,7 @@ func TestInitFederation(t *testing.T) { lbIP: lbIP, apiserverServiceType: v1.ServiceTypeLoadBalancer, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "", //test for default value of pvc-size etcdPersistence: "true", expectedErr: "", @@ -150,6 +154,7 @@ func TestInitFederation(t *testing.T) { lbIP: lbIP, apiserverServiceType: v1.ServiceTypeLoadBalancer, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "", etcdPersistence: "true", expectedErr: "", @@ -163,6 +168,7 @@ func TestInitFederation(t *testing.T) { lbIP: lbIP, apiserverServiceType: v1.ServiceTypeLoadBalancer, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "5Gi", etcdPersistence: "false", expectedErr: "", @@ -175,6 +181,7 @@ func TestInitFederation(t *testing.T) { dnsZoneName: "example.test.", apiserverServiceType: v1.ServiceTypeNodePort, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "5Gi", etcdPersistence: "true", expectedErr: "", @@ -188,6 +195,7 @@ func TestInitFederation(t *testing.T) { apiserverServiceType: v1.ServiceTypeNodePort, advertiseAddress: nodeIP, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdPVCapacity: "5Gi", etcdPersistence: "true", expectedErr: "", @@ -201,6 +209,7 @@ func TestInitFederation(t *testing.T) { apiserverServiceType: v1.ServiceTypeNodePort, advertiseAddress: nodeIP, serverImage: "example.test/foo:bar", + imagePullPolicy: "IfNotPresent", etcdImage: "gcr.io/google_containers/etcd:latest", etcdPVCapacity: "5Gi", etcdPVStorageClass: "fast", @@ -247,8 +256,11 @@ func TestInitFederation(t *testing.T) { if tc.etcdImage == "" { tc.etcdImage = defaultEtcdImage } + if tc.imagePullPolicy == "" { + tc.imagePullPolicy = "IfNotPresent" + } - hostFactory, err := fakeInitHostFactory(tc.apiserverServiceType, tc.federation, util.DefaultFederationSystemNamespace, tc.advertiseAddress, tc.lbIP, tc.dnsZoneName, tc.serverImage, tc.etcdImage, tc.dnsProvider, tc.dnsProviderConfig, tc.etcdPersistence, tc.etcdPVCapacity, tc.etcdPVStorageClass, tc.apiserverArgOverrides, tc.cmArgOverrides, tmpDirPath, tc.apiserverEnableHTTPBasicAuth, tc.apiserverEnableTokenAuth, tc.isRBACAPIAvailable, tc.nodeSelector) + hostFactory, err := fakeInitHostFactory(tc.apiserverServiceType, tc.federation, util.DefaultFederationSystemNamespace, tc.advertiseAddress, tc.lbIP, tc.dnsZoneName, tc.serverImage, tc.etcdImage, tc.dnsProvider, tc.dnsProviderConfig, tc.etcdPersistence, tc.etcdPVCapacity, tc.etcdPVStorageClass, tc.apiserverArgOverrides, tc.cmArgOverrides, tmpDirPath, tc.apiserverEnableHTTPBasicAuth, tc.apiserverEnableTokenAuth, tc.isRBACAPIAvailable, tc.nodeSelector, tc.imagePullPolicy, tc.imagePullSecrets) if err != nil { t.Fatalf("[%d] unexpected error: %v", i, err) } @@ -265,6 +277,7 @@ func TestInitFederation(t *testing.T) { cmd.Flags().Set("dns-zone-name", tc.dnsZoneName) cmd.Flags().Set("image", tc.serverImage) cmd.Flags().Set("etcd-image", tc.etcdImage) + cmd.Flags().Set("image-pull-policy", tc.imagePullPolicy) cmd.Flags().Set("dns-provider", tc.dnsProvider) cmd.Flags().Set("apiserver-arg-overrides", tc.apiserverArgOverrides) cmd.Flags().Set("controllermanager-arg-overrides", tc.cmArgOverrides) @@ -281,6 +294,9 @@ func TestInitFederation(t *testing.T) { if tc.etcdPersistence != "true" { cmd.Flags().Set("etcd-persistent-storage", tc.etcdPersistence) } + if tc.imagePullSecrets != "" { + cmd.Flags().Set("image-pull-secrets", tc.imagePullSecrets) + } if tc.apiserverServiceType != v1.ServiceTypeLoadBalancer { cmd.Flags().Set(apiserverServiceTypeFlag, string(tc.apiserverServiceType)) cmd.Flags().Set(apiserverAdvertiseAddressFlag, tc.advertiseAddress) @@ -626,7 +642,7 @@ func TestCertsHTTPS(t *testing.T) { } } -func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, namespaceName, advertiseAddress, lbIp, dnsZoneName, serverImage, etcdImage, dnsProvider, dnsProviderConfig, etcdPersistence, etcdPVCapacity, etcdPVStorageClass, apiserverOverrideArg, cmOverrideArg, tmpDirPath string, apiserverEnableHTTPBasicAuth, apiserverEnableTokenAuth, isRBACAPIAvailable bool, nodeSelectorString string) (cmdutil.Factory, error) { +func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, namespaceName, advertiseAddress, lbIp, dnsZoneName, serverImage, etcdImage, dnsProvider, dnsProviderConfig, etcdPersistence, etcdPVCapacity, etcdPVStorageClass, apiserverOverrideArg, cmOverrideArg, tmpDirPath string, apiserverEnableHTTPBasicAuth, apiserverEnableTokenAuth, isRBACAPIAvailable bool, nodeSelectorString string, imagePullPolicy, imagePullSecrets string) (cmdutil.Factory, error) { svcName := federationName + "-apiserver" svcUrlPrefix := "/api/v1/namespaces/federation-system/services" credSecretName := svcName + "-credentials" @@ -922,9 +938,10 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na Spec: v1.PodSpec{ Containers: []v1.Container{ { - Name: "apiserver", - Image: serverImage, - Command: apiserverCommand, + Name: "apiserver", + Image: serverImage, + ImagePullPolicy: v1.PullPolicy(imagePullPolicy), + Command: apiserverCommand, Ports: []v1.ContainerPort{ { Name: apiServerSecurePortName, @@ -954,6 +971,11 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na }, }, NodeSelector: nodeSelector, + ImagePullSecrets: []v1.LocalObjectReference{ + { + Name: imagePullSecrets, + }, + }, Volumes: []v1.Volume{ { Name: credSecretName, @@ -1040,9 +1062,10 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na Spec: v1.PodSpec{ Containers: []v1.Container{ { - Name: "controller-manager", - Image: serverImage, - Command: cmCommand, + Name: "controller-manager", + Image: serverImage, + ImagePullPolicy: v1.PullPolicy(imagePullPolicy), + Command: cmCommand, VolumeMounts: []v1.VolumeMount{ { Name: cmKubeconfigSecretName, @@ -1063,6 +1086,11 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na }, }, NodeSelector: nodeSelector, + ImagePullSecrets: []v1.LocalObjectReference{ + { + Name: imagePullSecrets, + }, + }, Volumes: []v1.Volume{ { Name: cmKubeconfigSecretName,