Skip to content

Commit

Permalink
Add support for persistent volume claims in kube files
Browse files Browse the repository at this point in the history
In k8s a persistent volume claim (PVC) allow pods to define a volume
by referencing the name of a PVC. The PVC basically contains criterias
that k8s then use to select which storage source it will use for the
volume.

Podman only provide one abtracted storage, the named volumes, and
create them if they don't exists yet. So this patch simply use a
volume with the name of the PVC.

Signed-off-by: Alban Bedel <[email protected]>
  • Loading branch information
AlbanBedel committed Nov 27, 2020
1 parent b84304d commit 66944ba
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
9 changes: 9 additions & 0 deletions pkg/specgen/generate/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ func ToSpecGen(ctx context.Context, containerYAML v1.Container, iid string, newI
mount.Options = []string{"ro"}
}
s.Mounts = append(s.Mounts, mount)
case KubeVolumeTypeNamed:
namedVolume := specgen.NamedVolume{
Dest: volume.MountPath,
Name: volumeSource.Source,
}
if volume.ReadOnly {
namedVolume.Options = []string{"ro"}
}
s.Volumes = append(s.Volumes, &namedVolume)
default:
return nil, errors.Errorf("Unsupported volume source type")
}
Expand Down
15 changes: 13 additions & 2 deletions pkg/specgen/generate/kube/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ type KubeVolumeType int

const (
KubeVolumeTypeBindMount KubeVolumeType = iota
KubeVolumeTypeNamed KubeVolumeType = iota
)

type KubeVolume struct {
// Type of volume to create
Type KubeVolumeType
// Path for bind mount
// Path for bind mount or volume name for named volume
Source string
}

Expand Down Expand Up @@ -87,12 +88,22 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}, nil
}

// Create a KubeVolume from a PersistentVolumeClaimVolumeSource
func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource) (*KubeVolume, error) {
return &KubeVolume{
Type: KubeVolumeTypeNamed,
Source: claim.ClaimName,
}, nil
}

// Create a KubeVolume from one of the supported VolumeSource
func VolumeFromSource(volumeSource v1.VolumeSource) (*KubeVolume, error) {
if volumeSource.HostPath != nil {
return VolumeFromHostPath(volumeSource.HostPath)
} else if volumeSource.PersistentVolumeClaim != nil {
return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim)
} else {
return nil, errors.Errorf("HostPath is currently the only supported VolumeSource")
return nil, errors.Errorf("HostPath and PersistentVolumeClaim are currently the conly supported VolumeSource")
}
}

Expand Down
41 changes: 41 additions & 0 deletions test/e2e/play_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ spec:
path: {{ .HostPath.Path }}
type: {{ .HostPath.Type }}
{{- end }}
{{- if (eq .VolumeType "PersistentVolumeClaim") }}
persistentVolumeClaim:
claimName: {{ .PersistentVolumeClaim.ClaimName }}
{{- end }}
{{ end }}
{{ end }}
status: {}
Expand Down Expand Up @@ -699,10 +703,15 @@ type HostPath struct {
Type string
}

type PersistentVolumeClaim struct {
ClaimName string
}

type Volume struct {
VolumeType string
Name string
HostPath
PersistentVolumeClaim
}

// getHostPathVolume takes a type and a location for a HostPath
Expand All @@ -718,6 +727,18 @@ func getHostPathVolume(vType, vPath string) *Volume {
}
}

// getHostPathVolume takes a name for a Persistentvolumeclaim
// volume giving it a default name of volName
func getPersistentVolumeClaimVolume(vName string) *Volume {
return &Volume{
VolumeType: "PersistentVolumeClaim",
Name: defaultVolName,
PersistentVolumeClaim: PersistentVolumeClaim{
ClaimName: vName,
},
}
}

type Env struct {
Name string
Value string
Expand Down Expand Up @@ -1389,6 +1410,26 @@ spec:
Expect(inspect.OutputToString()).To(ContainSubstring(correct))
})

It("podman play kube test with PersistentVolumeClaim volume", func() {
volumeName := "namedVolume"

ctr := getCtr(withVolumeMount("/test", false), withImage(BB))
pod := getPod(withVolume(getPersistentVolumeClaimVolume(volumeName)), withCtr(ctr))
err = generateKubeYaml("pod", pod, kubeYaml)
Expect(err).To(BeNil())

kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))

inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))

correct := fmt.Sprintf("volume:%s", volumeName)
Expect(inspect.OutputToString()).To(Equal(correct))
})

It("podman play kube applies labels to pods", func() {
var numReplicas int32 = 5
expectedLabelKey := "key1"
Expand Down

0 comments on commit 66944ba

Please sign in to comment.