diff --git a/README.md b/README.md index 8e43cf1f3..55c78a2c3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Local Path Provisioner provides a way for the Kubernetes users to utilize the lo ## Compare to built-in Local Persistent Volume feature in Kubernetes ### Pros -Dynamic provisioning the volume using [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) or [local volume](https://kubernetes.io/docs/concepts/storage/volumes/#local). +Dynamic provisioning the volume using [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) or [local](https://kubernetes.io/docs/concepts/storage/volumes/#local). * Currently the Kubernetes [Local Volume provisioner](/~https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner) cannot do dynamic provisioning for the local volumes. ### Cons diff --git a/examples/pod-with-local-volume/kustomization.yaml b/examples/pod-with-local-volume/kustomization.yaml new file mode 100644 index 000000000..b69f0d997 --- /dev/null +++ b/examples/pod-with-local-volume/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../pvc-with-local-volume +- pod.yaml diff --git a/examples/pod-with-local-volume/pod.yaml b/examples/pod-with-local-volume/pod.yaml new file mode 100644 index 000000000..9195997af --- /dev/null +++ b/examples/pod-with-local-volume/pod.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: volume-test +spec: + containers: + - name: volume-test + image: nginx:stable-alpine + imagePullPolicy: IfNotPresent + volumeMounts: + - name: volv + mountPath: /data + ports: + - containerPort: 80 + volumes: + - name: volv + persistentVolumeClaim: + claimName: local-volume-pvc diff --git a/examples/pvc-with-local-volume/kustomization.yaml b/examples/pvc-with-local-volume/kustomization.yaml new file mode 100644 index 000000000..7bfd4518a --- /dev/null +++ b/examples/pvc-with-local-volume/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- pvc.yaml diff --git a/examples/pvc-with-local-volume/pvc.yaml b/examples/pvc-with-local-volume/pvc.yaml new file mode 100644 index 000000000..59c241ce1 --- /dev/null +++ b/examples/pvc-with-local-volume/pvc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: local-volume-pvc + annotations: + volumeType: local +spec: + accessModes: + - ReadWriteOnce + storageClassName: local-path + resources: + requests: + storage: 128Mi diff --git a/provisioner.go b/provisioner.go index 2fa569914..82c802add 100644 --- a/provisioner.go +++ b/provisioner.go @@ -72,9 +72,8 @@ type NodePathMapData struct { } type ConfigData struct { - NodePathMap []*NodePathMapData `json:"nodePathMap,omitempty"` - CmdTimeoutSeconds int `json:"cmdTimeoutSeconds,omitempty"` - VolumeType string `json:"volumeType,omitempty"` + NodePathMap []*NodePathMapData `json:"nodePathMap,omitempty"` + CmdTimeoutSeconds int `json:"cmdTimeoutSeconds,omitempty"` } type NodePathMap struct { @@ -84,23 +83,6 @@ type NodePathMap struct { type Config struct { NodePathMap map[string]*NodePathMap CmdTimeoutSeconds int - VolumeType string -} - -func (c *Config) getPathBasedByVolumeType(pv *v1.PersistentVolume) (string, error) { - if c.VolumeType == "host" { - source := pv.Spec.PersistentVolumeSource.HostPath - if source == nil { - return "", fmt.Errorf("no HostPath set") - } - return source.Path, nil - } else { - source := pv.Spec.PersistentVolumeSource.Local - if source == nil { - return "", fmt.Errorf("no Local set") - } - return source.Path, nil - } } func NewProvisioner(stopCh chan struct{}, kubeClient *clientset.Clientset, @@ -248,7 +230,7 @@ func (p *LocalPathProvisioner) Provision(opts pvController.ProvisionOptions) (*v fs := v1.PersistentVolumeFilesystem var pvs v1.PersistentVolumeSource - if p.config.VolumeType == "local" { + if val, ok := opts.PVC.GetAnnotations()["volumeType"]; ok && strings.ToLower(val) == "local" { pvs = v1.PersistentVolumeSource{ Local: &v1.LocalVolumeSource{ Path: path, @@ -335,9 +317,13 @@ func (p *LocalPathProvisioner) getPathAndNodeForPV(pv *v1.PersistentVolume) (pat err = errors.Wrapf(err, "failed to delete volume %v", pv.Name) }() - path, pathErr := p.config.getPathBasedByVolumeType(pv) - if pathErr != nil { - return "", "", pathErr + volumeSource := pv.Spec.PersistentVolumeSource + if volumeSource.HostPath != nil && volumeSource.Local == nil { + path = volumeSource.HostPath.Path + } else if volumeSource.Local != nil && volumeSource.HostPath == nil { + path = volumeSource.Local.Path + } else { + return "", "", fmt.Errorf("no path set") } nodeAffinity := pv.Spec.NodeAffinity @@ -577,15 +563,5 @@ func canonicalizeConfig(data *ConfigData) (cfg *Config, err error) { } else { cfg.CmdTimeoutSeconds = defaultCmdTimeoutSeconds } - if data.VolumeType != "" { - vt := strings.ToLower(data.VolumeType) - if vt == "host" || vt == "local" { - cfg.VolumeType = vt - } else { - return nil, fmt.Errorf("invalid volume type %s", vt) - } - } else { - cfg.VolumeType = "host" - } return cfg, nil } diff --git a/test/pod_test.go b/test/pod_test.go index 8ec170b6b..fccecf081 100644 --- a/test/pod_test.go +++ b/test/pod_test.go @@ -8,6 +8,12 @@ import ( "github.com/stretchr/testify/suite" "testing" "time" + "strings" +) + +const ( + hostPathVolumeType = "hostPath" + localVolumeType = "local" ) type PodTestSuite struct { @@ -71,23 +77,29 @@ func TestPVCTestSuite(t *testing.T) { suite.Run(t, new(PodTestSuite)) } -func (p *PodTestSuite) TestPod() { +func (p *PodTestSuite) TestPodWithHostPathVolume() { p.kustomizeDir = "pod" - runTest(p, []string{p.config.IMAGE}, "ready") + runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) +} + +func (p *PodTestSuite) TestPodWithLocalVolume() { + p.kustomizeDir = "pod-with-local-volume" + + runTest(p, []string{p.config.IMAGE}, "ready", localVolumeType) } func (p *PodTestSuite) TestPodWithNodeAffinity() { p.kustomizeDir = "pod-with-node-affinity" - runTest(p, []string{p.config.IMAGE}, "ready") + runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } func (p *PodTestSuite) TestPodWithSecurityContext() { p.kustomizeDir = "pod-with-security-context" kustomizeDir := testdataFile(p.kustomizeDir) - runTest(p, []string{p.config.IMAGE}, "podscheduled") + runTest(p, []string{p.config.IMAGE}, "podscheduled", hostPathVolumeType) cmd := fmt.Sprintf(`kubectl get pod -l %s=%s -o=jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].reason}'`, LabelKey, LabelValue) @@ -116,10 +128,10 @@ loop: func (p *PodTestSuite) TestPodWithSubpath() { p.kustomizeDir = "pod-with-subpath" - runTest(p, []string{p.config.IMAGE}, "ready") + runTest(p, []string{p.config.IMAGE}, "ready", hostPathVolumeType) } -func runTest(p *PodTestSuite, images []string, waitCondition string) { +func runTest(p *PodTestSuite, images []string, waitCondition, volumeType string) { kustomizeDir := testdataFile(p.kustomizeDir) var cmds []string @@ -149,4 +161,12 @@ func runTest(p *PodTestSuite, images []string, waitCondition string) { break } } + + typeCheckCmd := fmt.Sprintf("kubectl get pv $(%s) -o jsonpath='{.spec.%s}'", "kubectl get pv -o jsonpath='{.items[0].metadata.name}'", volumeType) + c := createCmd(p.T(), typeCheckCmd, kustomizeDir, p.config.envs(), nil) + typeCheckOutput, _ := c.CombinedOutput() + fmt.Println(string(typeCheckOutput)) + if len(typeCheckOutput) == 0 || !strings.Contains(string(typeCheckOutput), "path") { + p.FailNow("volume Type not correct") + } } diff --git a/test/testdata/pod-with-local-volume/kustomization.yaml b/test/testdata/pod-with-local-volume/kustomization.yaml new file mode 100644 index 000000000..486f32d25 --- /dev/null +++ b/test/testdata/pod-with-local-volume/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../../../deploy +- ../../../examples/pod-with-local-volume +commonLabels: + app: local-path-provisioner +images: +- name: rancher/local-path-provisioner + newTag: dev diff --git a/test/testdata/pod-with-subpath/kustomization.yaml b/test/testdata/pod-with-subpath/kustomization.yaml index 4fbda0fb7..50c587a38 100644 --- a/test/testdata/pod-with-subpath/kustomization.yaml +++ b/test/testdata/pod-with-subpath/kustomization.yaml @@ -7,4 +7,4 @@ commonLabels: app: local-path-provisioner images: - name: rancher/local-path-provisioner - newTag: v0.0.18 + newTag: dev