Skip to content

Commit

Permalink
feat(dynamic-localpv-provisioner):support pass image pull secrets whe…
Browse files Browse the repository at this point in the history
…n creating init-pvc-pod by localpv-provisioner (#22)

Add image pull secret to init PVC pod with the environment variable

Signed-off-by: mahao <[email protected]>
  • Loading branch information
allenhaozi committed Jan 7, 2021
1 parent 76b21e4 commit ff95934
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 2 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
nohup.out
coverage.txt
.DS_Store
cmd/provisioner-localpv/start.sh
.idea
20 changes: 20 additions & 0 deletions cmd/provisioner-localpv/app/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

//"github.com/pkg/errors"
errors "github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
//storagev1 "k8s.io/api/storage/v1"
Expand Down Expand Up @@ -327,3 +328,22 @@ func GetNodeLabelValue(n *v1.Node, labelKey string) string {
func GetTaints(n *v1.Node) []v1.Taint {
return n.Spec.Taints
}

// GetImagePullSecrets parse image pull secrets from env
// transform string to corev1.LocalObjectReference
// multiple secrets are separated by commas
func GetImagePullSecrets(s string) []corev1.LocalObjectReference {
s = strings.TrimSpace(s)
list := make([]corev1.LocalObjectReference, 0)
if len(s) == 0 {
return list
}
arr := strings.Split(s, ",")
for _, item := range arr {
if len(item) > 0 {
l := corev1.LocalObjectReference{Name: strings.TrimSpace(item)}
list = append(list, l)
}
}
return list
}
66 changes: 66 additions & 0 deletions cmd/provisioner-localpv/app/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright 2019 The OpenEBS Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package app

import (
"reflect"
"testing"

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

func TestGetImagePullSecrets(t *testing.T) {
testCases := map[string]struct {
value string
expectedValue []corev1.LocalObjectReference
}{
"empty variable": {
value: "",
expectedValue: []corev1.LocalObjectReference{},
},
"single value": {
value: "image-pull-secret",
expectedValue: []corev1.LocalObjectReference{{Name: "image-pull-secret"}},
},
"multiple value": {
value: "image-pull-secret,secret-1",
expectedValue: []corev1.LocalObjectReference{{Name: "image-pull-secret"}, {Name: "secret-1"}},
},
"whitespaces": {
value: " ",
expectedValue: []corev1.LocalObjectReference{},
},
"single value with whitespaces": {
value: " docker-secret ",
expectedValue: []corev1.LocalObjectReference{{Name: "docker-secret"}},
},
"multiple value with whitespaces": {
value: " docker-secret, image-pull-secret ",
expectedValue: []corev1.LocalObjectReference{{Name: "docker-secret"}, {Name: "image-pull-secret"}},
},
}
for k, v := range testCases {
v := v
t.Run(k, func(t *testing.T) {
actualValue := GetImagePullSecrets(v.value)
if !reflect.DeepEqual(actualValue, v.expectedValue) {
t.Errorf("expected %s got %s", v.expectedValue, actualValue)
}
})
}
}
7 changes: 7 additions & 0 deletions cmd/provisioner-localpv/app/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ const (
// ProvisionerBasePath is the environment variable that provides the
// default base path on the node where host-path PVs will be provisioned.
ProvisionerBasePath menv.ENVKey = "OPENEBS_IO_BASE_PATH"

// ProvisionerImagePullSecrets is the environment variable that provides the
// init pod to use as authentication when pulling helper image, it is used in the scene where authentication is required
ProvisionerImagePullSecrets menv.ENVKey = "OPENEBS_IO_IMAGE_PULL_SECRETS"
)

var (
Expand All @@ -59,3 +63,6 @@ func getDefaultBasePath() string {
func getOpenEBSServiceAccountName() string {
return menv.Get(menv.OpenEBSServiceAccount)
}
func getOpenEBSImagePullSecrets() string {
return menv.Get(ProvisionerImagePullSecrets)
}
40 changes: 39 additions & 1 deletion cmd/provisioner-localpv/app/env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ limitations under the License.
package app

import (
menv "github.com/openebs/maya/pkg/env/v1alpha1"
"os"
"reflect"
"testing"

menv "github.com/openebs/maya/pkg/env/v1alpha1"
)

func TestGetOpenEBSNamespace(t *testing.T) {
Expand Down Expand Up @@ -157,3 +158,40 @@ func TestGetOpenEBSServiceAccountName(t *testing.T) {
})
}
}

func TestGetOpenEBSImagePullSecrets(t *testing.T) {
testCases := map[string]struct {
value string
expectedValue string
}{
"Missing env variable": {
value: "",
expectedValue: "",
},
"Present env variable with value": {
value: "image-pull-secret",
expectedValue: "image-pull-secret",
},
"Present env variable with multiple value": {
value: "image-pull-secret,secret-1",
expectedValue: "image-pull-secret,secret-1",
},
"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(ProvisionerImagePullSecrets), v.value)
}
actualValue := getOpenEBSImagePullSecrets()
if !reflect.DeepEqual(actualValue, v.expectedValue) {
t.Errorf("expected %s got %s", v.expectedValue, actualValue)
}
os.Unsetenv(string(ProvisionerImagePullSecrets))
})
}
}
3 changes: 3 additions & 0 deletions cmd/provisioner-localpv/app/helper_hostpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ type HelperPodOptions struct {
serviceAccountName string

selectedNodeTaints []corev1.Taint

imagePullSecrets []corev1.LocalObjectReference
}

// validate checks that the required fields to launch
Expand Down Expand Up @@ -189,6 +191,7 @@ func (p *Provisioner) launchPod(config podConfig) (*corev1.Pod, error) {
}).
WithPrivilegedSecurityContext(&privileged),
).
WithImagePullSecrets(config.pOpts.imagePullSecrets).
WithVolumeBuilder(
volume.NewBuilder().
WithName("data").
Expand Down
5 changes: 4 additions & 1 deletion cmd/provisioner-localpv/app/provisioner_hostpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.ProvisionOptions, volu
return nil, err
}

klog.Infof("Creating volume %v at node with label %v=%v, path:%v", name, nodeAffinityKey, nodeAffinityValue, path)
imagePullSecrets := GetImagePullSecrets(getOpenEBSImagePullSecrets())

klog.Infof("Creating volume %v at node with label %v=%v, path:%v,ImagePullSecrets:%v", name, nodeAffinityKey, nodeAffinityValue, path, imagePullSecrets)

//Before using the path for local PV, make sure it is created.
initCmdsForPath := []string{"mkdir", "-m", "0777", "-p"}
Expand All @@ -69,6 +71,7 @@ func (p *Provisioner) ProvisionHostPath(opts pvController.ProvisionOptions, volu
nodeAffinityLabelValue: nodeAffinityValue,
serviceAccountName: saName,
selectedNodeTaints: taints,
imagePullSecrets: imagePullSecrets,
}
iErr := p.createInitPod(podOpts)
if iErr != nil {
Expand Down
11 changes: 11 additions & 0 deletions pkg/kubernetes/api/core/v1/pod/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,17 @@ func (b *Builder) WithContainer(container corev1.Container) *Builder {
return b.WithContainers([]corev1.Container{container})
}

// WithImagePullSecrets sets the pod image pull secrets
// + optional
// if the length is zero that no secret is needed to pull the image
func (b *Builder) WithImagePullSecrets(secrets []corev1.LocalObjectReference) *Builder {
if len(secrets) == 0 {
return b
}
b.pod.object.Spec.ImagePullSecrets = secrets
return b
}

// WithVolumes sets the Volumes field in Pod with provided arguments
func (b *Builder) WithVolumes(volumes []corev1.Volume) *Builder {
if len(volumes) == 0 {
Expand Down

0 comments on commit ff95934

Please sign in to comment.