Skip to content

Commit

Permalink
add support for subpath in play kube for named volumes
Browse files Browse the repository at this point in the history
subpath allows for only a subdirecty of a volumes data to be mounted in the container
add support for the named volume type sub path with others to follow.

resolves containers#12929

Signed-off-by: Charlie Doern <[email protected]>
  • Loading branch information
cdoern committed Dec 12, 2022
1 parent 6f1bc98 commit 95cc7e0
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 0 deletions.
3 changes: 3 additions & 0 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ type ContainerNamedVolume struct {
// IsAnonymous sets the named volume as anonymous even if it has a name
// This is used for emptyDir volumes from a kube yaml
IsAnonymous bool `json:"setAnonymous,omitempty"`
// SubPath determines which part of the Source will be mounted in the container
SubPath string
}

// ContainerOverlayVolume is an overlay volume that will be mounted into the
Expand Down Expand Up @@ -440,6 +442,7 @@ func (c *Container) NamedVolumes() []*ContainerNamedVolume {
newVol.Name = vol.Name
newVol.Dest = vol.Dest
newVol.Options = vol.Options
newVol.SubPath = vol.SubPath
volumes = append(volumes, newVol)
}

Expand Down
4 changes: 4 additions & 0 deletions libpod/container_internal_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return nil, err
}

if len(namedVol.SubPath) > 0 {
mountPoint = filepath.Join(mountPoint, namedVol.SubPath)
}

overlayFlag := false
upperDir := ""
workDir := ""
Expand Down
1 change: 1 addition & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,7 @@ func WithNamedVolumes(volumes []*ContainerNamedVolume) CtrCreateOption {
Dest: vol.Dest,
Options: mountOpts,
IsAnonymous: vol.IsAnonymous,
SubPath: vol.SubPath,
})
}

Expand Down
1 change: 1 addition & 0 deletions pkg/specgen/generate/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
Dest: v.Dest,
Options: v.Options,
IsAnonymous: v.IsAnonymous,
SubPath: v.SubPath,
})
}
options = append(options, libpod.WithNamedVolumes(vols))
Expand Down
1 change: 1 addition & 0 deletions pkg/specgen/generate/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Dest: volume.MountPath,
Name: volumeSource.Source,
Options: options,
SubPath: volume.SubPath,
}
s.Volumes = append(s.Volumes, &namedVolume)
case KubeVolumeTypeConfigMap:
Expand Down
2 changes: 2 additions & 0 deletions pkg/specgen/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type NamedVolume struct {
// IsAnonymous sets the named volume as anonymous even if it has a name
// This is used for emptyDir volumes from a kube yaml
IsAnonymous bool
// SubPath stores the sub directory of the named volume to be mounted in the container
SubPath string
}

// OverlayVolume holds information about an overlay volume that will be mounted into
Expand Down
57 changes: 57 additions & 0 deletions test/e2e/play_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,28 @@ spec:
- containerPort: 80
`

var subpathTest = `
apiVersion: v1
kind: Pod
metadata:
name: testpod
spec:
containers:
- name: testctr
image: quay.io/libpod/alpine_nginx:latest
command:
- sleep
- inf
volumeMounts:
- mountPath: /var
name: testing
subPath: testing/onlythis
volumes:
- name: testing
persistentVolumeClaim:
claimName: testvol
`

var checkInfraImagePodYaml = `
apiVersion: v1
kind: Pod
Expand Down Expand Up @@ -4460,4 +4482,39 @@ spec:
Expect(ps.OutputToStringArray()).To(HaveLen(0))
})

It("podman play kube with named volume subpaths", func() {
SkipIfRemote("volume export does not exist on remote")
volumeCreate := podmanTest.Podman([]string{"volume", "create", "testvol1"})
volumeCreate.WaitWithDefaultTimeout()
Expect(volumeCreate).Should(Exit(0))

session := podmanTest.Podman([]string{"run", "--volume", "testvol1:/data", ALPINE, "sh", "-c", "mkdir -p /data/testing/onlythis && touch /data/testing/onlythis/123.txt && echo hi >> /data/testing/onlythis/123.txt"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

tar := filepath.Join(podmanTest.TempDir, "out.tar")
session = podmanTest.Podman([]string{"volume", "export", "--output", tar, "testvol1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))

volumeCreate = podmanTest.Podman([]string{"volume", "create", "testvol"})
volumeCreate.WaitWithDefaultTimeout()
Expect(volumeCreate).Should(Exit(0))

volumeImp := podmanTest.Podman([]string{"volume", "import", "testvol", filepath.Join(podmanTest.TempDir, "out.tar")})
volumeImp.WaitWithDefaultTimeout()
Expect(volumeImp).Should(Exit(0))

err = writeYaml(subpathTest, kubeYaml)
Expect(err).ToNot(HaveOccurred())

playKube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
playKube.WaitWithDefaultTimeout()
Expect(playKube).Should(Exit(0))

exec := podmanTest.Podman([]string{"exec", "-it", "testpod-testctr", "cat", "/var/123.txt"})
exec.WaitWithDefaultTimeout()
Expect(exec).Should(Exit(0))
Expect(exec.OutputToString()).Should(Equal("hi"))
})
})

0 comments on commit 95cc7e0

Please sign in to comment.