From 1479d62da4785109db1daace2e7bf9aa4d963a36 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Wed, 4 Dec 2019 17:33:47 +0530 Subject: [PATCH 1/4] chore(builder): add builder for SA name Signed-off-by: Akhil Mohan --- pkg/kubernetes/pod/v1alpha1/build.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/kubernetes/pod/v1alpha1/build.go b/pkg/kubernetes/pod/v1alpha1/build.go index 80a1142fa9..793c751131 100644 --- a/pkg/kubernetes/pod/v1alpha1/build.go +++ b/pkg/kubernetes/pod/v1alpha1/build.go @@ -175,6 +175,20 @@ func (b *Builder) WithVolume(volume corev1.Volume) *Builder { return b.WithVolumes([]corev1.Volume{volume}) } +// WithServiceAccountName sets the ServiceAccountName of Pod spec with +// the provided value +func (b *Builder) WithServiceAccountName(serviceAccountName string) *Builder { + if len(serviceAccountName) == 0 { + b.errs = append( + b.errs, + errors.New("failed to build Pod object: missing Pod service account name"), + ) + return b + } + b.pod.object.Spec.ServiceAccountName = serviceAccountName + return b +} + // Build returns the Pod API instance func (b *Builder) Build() (*corev1.Pod, error) { if len(b.errs) > 0 { From e408344f94166132193f105c43f710202ce2e237 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Wed, 4 Dec 2019 18:02:57 +0530 Subject: [PATCH 2/4] fix(env): add functions to get openebs service account Signed-off-by: Akhil Mohan --- cmd/provisioner-localpv/app/env.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/provisioner-localpv/app/env.go b/cmd/provisioner-localpv/app/env.go index aff437bc4d..e8c69d4f0d 100644 --- a/cmd/provisioner-localpv/app/env.go +++ b/cmd/provisioner-localpv/app/env.go @@ -25,6 +25,7 @@ import ( // provisioner also uses the following: // OPENEBS_NAMESPACE // NODE_NAME +// OPENEBS_SERVICE_ACCOUNT // OPENEBS_IO_K8S_MASTER // OPENEBS_IO_KUBE_CONFIG @@ -54,3 +55,7 @@ func getDefaultHelperImage() string { func getDefaultBasePath() string { return menv.GetOrDefault(ProvisionerBasePath, string(defaultBasePath)) } + +func getOpenEBSServiceAccountName() string { + return menv.Get(menv.OpenEBSServiceAccount) +} From ecac147fb31f44cba9f693b66dd1b7518557c702 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Wed, 4 Dec 2019 18:04:59 +0530 Subject: [PATCH 3/4] fix(provisioner, local): add SA to helper pod add service account name and privileged context to helper pods launched by localpv provisioner. Both the init and cleanup pods require to be in privileged context so that the operations can be done on openshift/coreos based clusters. Signed-off-by: Akhil Mohan --- .../app/helper_hostpath.go | 19 ++++++++++++++++--- .../app/provisioner_hostpath.go | 10 ++++++---- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cmd/provisioner-localpv/app/helper_hostpath.go b/cmd/provisioner-localpv/app/helper_hostpath.go index 2431e19bfb..f39e271590 100644 --- a/cmd/provisioner-localpv/app/helper_hostpath.go +++ b/cmd/provisioner-localpv/app/helper_hostpath.go @@ -63,6 +63,9 @@ type HelperPodOptions struct { //path is the volume hostpath directory path string + + // serviceAccountName is the service account with which the pod should be launched + serviceAccountName string } // validate checks that the required fields to launch @@ -70,8 +73,11 @@ type HelperPodOptions struct { // create or delete a directory (path) on a given node hostname (nodeHostname). // name refers to the volume being created or deleted. func (pOpts *HelperPodOptions) validate() error { - if pOpts.name == "" || pOpts.path == "" || pOpts.nodeHostname == "" { - return errors.Errorf("invalid empty name or hostpath or hostname") + if pOpts.name == "" || + pOpts.path == "" || + pOpts.nodeHostname == "" || + pOpts.serviceAccountName == "" { + return errors.Errorf("invalid empty name or hostpath or hostname or service account name") } return nil } @@ -146,10 +152,16 @@ func (p *Provisioner) createCleanupPod(pOpts *HelperPodOptions) error { } func (p *Provisioner) launchPod(config podConfig) (*corev1.Pod, error) { + // the helper pod need to be launched in privileged mode. This is because in CoreOS + // nodes, pods without privileged access cannot write to the host directory. + // Helper pods need to create and delete directories on the host. + privileged := true + helperPod, _ := pod.NewBuilder(). WithName(config.podName + "-" + config.pOpts.name). WithRestartPolicy(corev1.RestartPolicyNever). WithNodeSelectorHostnameNew(config.pOpts.nodeHostname). + WithServiceAccountName(config.pOpts.serviceAccountName). WithContainerBuilder( container.NewBuilder(). WithName("local-path-" + config.podName). @@ -161,7 +173,8 @@ func (p *Provisioner) launchPod(config podConfig) (*corev1.Pod, error) { ReadOnly: false, MountPath: "/data/", }, - }), + }). + WithPrivilegedSecurityContext(&privileged), ). WithVolumeBuilder( volume.NewBuilder(). diff --git a/cmd/provisioner-localpv/app/provisioner_hostpath.go b/cmd/provisioner-localpv/app/provisioner_hostpath.go index 0a2524dcc1..4385a5753f 100644 --- a/cmd/provisioner-localpv/app/provisioner_hostpath.go +++ b/cmd/provisioner-localpv/app/provisioner_hostpath.go @@ -35,6 +35,7 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.VolumeOptions, volumeC nodeHostname := GetNodeHostname(opts.SelectedNode) name := opts.PVName stgType := volumeConfig.GetStorageType() + saName := getOpenEBSServiceAccountName() path, err := volumeConfig.GetPath() if err != nil { @@ -53,10 +54,11 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.VolumeOptions, volumeC //Before using the path for local PV, make sure it is created. initCmdsForPath := []string{"mkdir", "-m", "0777", "-p"} podOpts := &HelperPodOptions{ - cmdsForPath: initCmdsForPath, - name: name, - path: path, - nodeHostname: nodeHostname, + cmdsForPath: initCmdsForPath, + name: name, + path: path, + nodeHostname: nodeHostname, + serviceAccountName: saName, } iErr := p.createInitPod(podOpts) From 9fa23531c464906ee8a038b7f445556caee30667 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Wed, 4 Dec 2019 18:14:14 +0530 Subject: [PATCH 4/4] chore(unit-test): add test cases for getOpenEBSServiceAccount Signed-off-by: Akhil Mohan --- cmd/provisioner-localpv/app/env_test.go | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/cmd/provisioner-localpv/app/env_test.go b/cmd/provisioner-localpv/app/env_test.go index 7e46b0b860..98ff521f3b 100644 --- a/cmd/provisioner-localpv/app/env_test.go +++ b/cmd/provisioner-localpv/app/env_test.go @@ -124,3 +124,36 @@ func TestGetDefaultBasePath(t *testing.T) { }) } } + +func TestGetOpenEBSServiceAccountName(t *testing.T) { + testCases := map[string]struct { + value string + expectedValue string + }{ + "Missing env variable": { + value: "", + expectedValue: "", + }, + "Present env variable with value": { + value: "value1", + expectedValue: "value1", + }, + "Present env variable with whitespaces": { + value: " ", + expectedValue: "", + }, + } + for k, v := range testCases { + v := v + t.Run(k, func(t *testing.T) { + if len(v.value) != 0 { + os.Setenv(string(menv.OpenEBSServiceAccount), v.value) + } + actualValue := getOpenEBSServiceAccountName() + if !reflect.DeepEqual(actualValue, v.expectedValue) { + t.Errorf("expected %s got %s", v.expectedValue, actualValue) + } + os.Unsetenv(string(menv.OpenEBSServiceAccount)) + }) + } +}