Skip to content

Commit

Permalink
Add support for volume mounts (#4673)
Browse files Browse the repository at this point in the history
* Add support for volume mounts

* Adatpt unit test to include VolumeMounts

Co-authored-by: Ralf Pannemans <[email protected]>

* Only accept volumeMounts with the name volume

---------

Co-authored-by: Johannes Dillmann <[email protected]>
Co-authored-by: Philipp Stehle <[email protected]>
Co-authored-by: Anil Keshav <[email protected]>
  • Loading branch information
4 people authored Dec 1, 2023
1 parent aab4de4 commit 6efb21b
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 35 deletions.
53 changes: 29 additions & 24 deletions pkg/config/stepmeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/pkg/errors"
)

const SupportedVolumeName = "volume"

// StepData defines the metadata for a step, like step descriptions, parameters, ...
type StepData struct {
Metadata StepMetadata `json:"metadata"`
Expand Down Expand Up @@ -105,25 +107,25 @@ type StepOutputs struct {
// Container defines an execution container
type Container struct {
//ToDo: check dockerOptions, dockerVolumeBind, containerPortMappings, sidecarOptions, sidecarVolumeBind
Command []string `json:"command"`
EnvVars []EnvVar `json:"env"`
Image string `json:"image"`
ImagePullPolicy string `json:"imagePullPolicy"`
Name string `json:"name"`
ReadyCommand string `json:"readyCommand"`
Shell string `json:"shell"`
WorkingDir string `json:"workingDir"`
Conditions []Condition `json:"conditions,omitempty"`
Options []Option `json:"options,omitempty"`
//VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"`
Command []string `json:"command"`
EnvVars []EnvVar `json:"env"`
Image string `json:"image"`
ImagePullPolicy string `json:"imagePullPolicy"`
Name string `json:"name"`
ReadyCommand string `json:"readyCommand"`
Shell string `json:"shell"`
WorkingDir string `json:"workingDir"`
Conditions []Condition `json:"conditions,omitempty"`
Options []Option `json:"options,omitempty"`
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"`
}

// ToDo: Add the missing Volumes part to enable the volume mount completely
// VolumeMount defines a mount path
// type VolumeMount struct {
// MountPath string `json:"mountPath"`
// Name string `json:"name"`
//}
type VolumeMount struct {
Name string `json:"name"`
MountPath string `json:"mountPath"`
}

// Option defines an docker option
type Option struct {
Expand Down Expand Up @@ -385,7 +387,7 @@ func (container *Container) commonConfiguration(keyPrefix string, config *map[st
}
putStringIfNotEmpty(*config, keyPrefix+"Workspace", container.WorkingDir)
putSliceIfNotEmpty(*config, keyPrefix+"Options", OptionsAsStringSlice(container.Options))
//putSliceIfNotEmpty(*config, keyPrefix+"VolumeBind", volumeMountsAsStringSlice(container.VolumeMounts))
putSliceIfNotEmpty(*config, keyPrefix+"VolumeBind", volumeMountsAsStringSlice(container.VolumeMounts))

}

Expand Down Expand Up @@ -518,11 +520,14 @@ func ResolveMetadata(gitHubTokens map[string]string, metaDataResolver func() map
return metadata, nil
}

//ToDo: Enable this when the Volumes part is also implemented
//func volumeMountsAsStringSlice(volumeMounts []VolumeMount) []string {
// e := []string{}
// for _, v := range volumeMounts {
// e = append(e, fmt.Sprintf("%v:%v", v.Name, v.MountPath))
// }
// return e
//}
func volumeMountsAsStringSlice(volumeMounts []VolumeMount) []string {
e := []string{}
for _, v := range volumeMounts {
if v.Name != SupportedVolumeName {
log.Entry().Warningf("Unsupported volume name: %q, only %q is supported", v.Name, SupportedVolumeName)
continue
}
e = append(e, fmt.Sprintf("%v:%v", v.Name, v.MountPath))
}
return e
}
20 changes: 10 additions & 10 deletions pkg/config/stepmeta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,10 @@ func TestGetContextDefaults(t *testing.T) {
{Name: "opt1", Value: "optValue1"},
{Name: "opt2", Value: "optValue2"},
},
//VolumeMounts: []VolumeMount{
// {MountPath: "mp1", Name: "mn1"},
// {MountPath: "mp2", Name: "mn2"},
//},
VolumeMounts: []VolumeMount{
{MountPath: "mp1", Name: "volume"},
{MountPath: "mp2", Name: "mn2"},
},
},
},
Sidecars: []Container{
Expand All @@ -419,10 +419,10 @@ func TestGetContextDefaults(t *testing.T) {
{Name: "opt3", Value: "optValue3"},
{Name: "opt4", Value: "optValue4"},
},
//VolumeMounts: []VolumeMount{
// {MountPath: "mp3", Name: "mn3"},
// {MountPath: "mp4", Name: "mn4"},
//},
VolumeMounts: []VolumeMount{
{MountPath: "mp3", Name: "mn3"},
{MountPath: "mp4", Name: "volume"},
},
},
},
},
Expand Down Expand Up @@ -451,7 +451,7 @@ func TestGetContextDefaults(t *testing.T) {
assert.Equal(t, true, d.Defaults[0].Steps["testStep"]["dockerPullImage"], "dockerPullImage default not available")
assert.Equal(t, "/test/dir", d.Defaults[0].Steps["testStep"]["dockerWorkspace"], "dockerWorkspace default not available")
assert.Equal(t, []interface{}{"opt1 optValue1", "opt2 optValue2"}, d.Defaults[0].Steps["testStep"]["dockerOptions"], "dockerOptions default not available")
//assert.Equal(t, []interface{}{"mn1:mp1", "mn2:mp2"}, d.Defaults[0].Steps["testStep"]["dockerVolumeBind"], "dockerVolumeBind default not available")
assert.Equal(t, []interface{}{"volume:mp1"}, d.Defaults[0].Steps["testStep"]["dockerVolumeBind"], "dockerVolumeBind default not available")

assert.Equal(t, "/sidecar/command", d.Defaults[0].Steps["testStep"]["sidecarCommand"], "sidecarCommand default not available")
assert.Equal(t, map[string]interface{}{"env3": "val3", "env4": "val4"}, d.Defaults[0].Steps["testStep"]["sidecarEnvVars"], "sidecarEnvVars default not available")
Expand All @@ -461,7 +461,7 @@ func TestGetContextDefaults(t *testing.T) {
assert.Equal(t, "/sidecar/command", d.Defaults[0].Steps["testStep"]["sidecarReadyCommand"], "sidecarReadyCommand default not available")
assert.Equal(t, "/sidecar/dir", d.Defaults[0].Steps["testStep"]["sidecarWorkspace"], "sidecarWorkspace default not available")
assert.Equal(t, []interface{}{"opt3 optValue3", "opt4 optValue4"}, d.Defaults[0].Steps["testStep"]["sidecarOptions"], "sidecarOptions default not available")
//assert.Equal(t, []interface{}{"mn3:mp3", "mn4:mp4"}, d.Defaults[0].Steps["testStep"]["sidecarVolumeBind"], "sidecarVolumeBind default not available")
assert.Equal(t, []interface{}{"volume:mp4"}, d.Defaults[0].Steps["testStep"]["sidecarVolumeBind"], "sidecarVolumeBind default not available")
})

t.Run("Container conditions", func(t *testing.T) {
Expand Down
13 changes: 13 additions & 0 deletions vars/dockerExecute.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ void call(Map parameters = [:], body) {
}

def securityContext = securityContextFromOptions(config.dockerOptions)
def containerMountPath = containerMountPathFromVolumeBind(config.dockerVolumeBind)
if (env.POD_NAME && isContainerDefined(config)) {
container(getContainerDefined(config)) {
withEnv(dockerEnvVars) {
Expand All @@ -208,6 +209,7 @@ void call(Map parameters = [:], body) {
stashContent: config.stashContent,
stashNoDefaultExcludes: config.stashNoDefaultExcludes,
securityContext: securityContext,
containerMountPath: containerMountPath,
]

if (config.sidecarImage) {
Expand Down Expand Up @@ -379,6 +381,17 @@ def securityContextFromOptions(dockerOptions) {
return securityContext
}

/*
* Picks the first volumeBind option and translates it into containerMountPath, currently only one fix volume is supported
*/
@NonCPS
def containerMountPathFromVolumeBind(dockerVolumeBind) {
if (dockerVolumeBind) {
return dockerVolumeBind[0].split(":")[1]
}
return ""
}

boolean isContainerDefined(config) {
Map containerMap = ContainerMap.instance.getMap()

Expand Down
5 changes: 4 additions & 1 deletion vars/dockerExecuteOnKubernetes.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -582,9 +582,12 @@ private List getContainerList(config) {
command : []
]
def resources = getResources(sideCarContainerName, config)
if(resources) {
if (resources) {
containerSpec.resources = resources
}
if (config.containerMountPath) {
containerSpec.volumeMounts = [[name: "volume", mountPath: config.containerMountPath]]
}
result.push(containerSpec)
}
return result
Expand Down

0 comments on commit 6efb21b

Please sign in to comment.