Skip to content

Commit

Permalink
Initialize working dirs inside workspace dir
Browse files Browse the repository at this point in the history
In order to allow steps to define workingDirs that are subdirectories of the workspace directory we need to make sure they have been created first since they will not exist on startup.

Fixes #725
  • Loading branch information
dicarlo2 committed Apr 23, 2019
1 parent 0b42a42 commit 34db1a7
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
51 changes: 51 additions & 0 deletions pkg/reconciler/v1alpha1/taskrun/resources/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"io"
"io/ioutil"
"path/filepath"
"strings"

"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -91,9 +92,14 @@ const (
unnamedInitContainerPrefix = "build-step-unnamed-"
// Name of the credential initialization container.
credsInit = "credential-initializer"
// Name of the working dir initialization container.
workingDirInit = "working-dir-initializer"
)

var (
// The container used to initialize working directories before the build runs.
bashWorkingDirImage = flag.String("bash-working-dir-image", "override-with-bash-working-dir:latest",
"The container image for preparing our Build's working directories.")
// The container used to initialize credentials before the build runs.
credsImage = flag.String("creds-image", "override-with-creds:latest",
"The container image for preparing our Build's credentials.")
Expand Down Expand Up @@ -160,6 +166,47 @@ func makeCredentialInitializer(serviceAccountName, namespace string, kubeclient
}, volumes, nil
}

func makeWorkingDirScript(workingDirs []string) string {
seen := map[string]bool{}
script := ""
for _, wd := range workingDirs {
if wd != "" {
p := filepath.Clean(wd)
if rel, err := filepath.Rel(workspaceDir, p); err == nil && !strings.HasPrefix(rel, ".") && !seen[p] {
seen[p] = true
if script == "" {
script = fmt.Sprintf("mkdir -p %s", p)
} else {
script = fmt.Sprintf("%s %s", script, p)
}
}
}
}

return script
}

func makeWorkingDirInitializer(steps []corev1.Container) *corev1.Container {
workingDirs := make([]string, len(steps))
for _, step := range steps {
workingDirs = append(workingDirs, step.WorkingDir)
}

if script := makeWorkingDirScript(workingDirs); script != "" {
return &corev1.Container{
Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(containerPrefix + workingDirInit),
Image: *bashWorkingDirImage,
Command: []string{"/ko-app/bash"},
Args: []string{"-args", script},
VolumeMounts: implicitVolumeMounts,
Env: implicitEnvVars,
WorkingDir: workspaceDir,
}
}

return nil
}

// MakePod converts TaskRun and TaskSpec objects to a Pod which implements the taskrun specified
// by the supplied CRD.
func MakePod(taskRun *v1alpha1.TaskRun, taskSpec v1alpha1.TaskSpec, kubeclient kubernetes.Interface, cache *entrypoint.Cache, logger *zap.SugaredLogger) (*corev1.Pod, error) {
Expand All @@ -178,6 +225,10 @@ func MakePod(taskRun *v1alpha1.TaskRun, taskSpec v1alpha1.TaskSpec, kubeclient k
initContainers := []corev1.Container{*cred}
podContainers := []corev1.Container{}

if workingDir := makeWorkingDirInitializer(taskSpec.Steps); workingDir != nil {
initContainers = append(initContainers, *workingDir)
}

maxIndicesByResource := findMaxResourceRequest(taskSpec.Steps, corev1.ResourceCPU, corev1.ResourceMemory, corev1.ResourceEphemeralStorage)

for i := range taskSpec.Steps {
Expand Down
74 changes: 74 additions & 0 deletions pkg/reconciler/v1alpha1/taskrun/resources/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package resources

import (
"crypto/rand"
"fmt"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -249,6 +251,52 @@ func TestMakePod(t *testing.T) {
},
Volumes: implicitVolumes,
},
}, {
desc: "working-dir-in-workspace-dir",
ts: v1alpha1.TaskSpec{
Steps: []corev1.Container{{
Name: "name",
Image: "image",
WorkingDir: filepath.Join(workspaceDir, "test"),
}},
},
want: &corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
InitContainers: []corev1.Container{{
Name: containerPrefix + credsInit + "-9l9zj",
Image: *credsImage,
Command: []string{"/ko-app/creds-init"},
Args: []string{},
Env: implicitEnvVars,
VolumeMounts: implicitVolumeMounts,
WorkingDir: workspaceDir,
}, {
Name: containerPrefix + workingDirInit + "-mz4c7",
Image: *bashWorkingDirImage,
Command: []string{"/ko-app/bash"},
Args: []string{"-args", fmt.Sprintf("mkdir -p %s", filepath.Join(workspaceDir, "test"))},
Env: implicitEnvVars,
VolumeMounts: implicitVolumeMounts,
WorkingDir: workspaceDir,
}},
Containers: []corev1.Container{{
Name: "build-step-name",
Image: "image",
Env: implicitEnvVars,
VolumeMounts: implicitVolumeMounts,
WorkingDir: filepath.Join(workspaceDir, "test"),
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("0"),
corev1.ResourceMemory: resource.MustParse("0"),
corev1.ResourceEphemeralStorage: resource.MustParse("0"),
},
},
},
nopContainer,
},
Volumes: implicitVolumes,
},
}} {
t.Run(c.desc, func(t *testing.T) {
names.TestingSeed()
Expand Down Expand Up @@ -309,3 +357,29 @@ func TestMakePod(t *testing.T) {
})
}
}

func TestMakeWorkingDirScript(t *testing.T) {
for _, c := range []struct {
desc string
workingDirs []string
want string
}{{
desc: "default",
workingDirs: []string{"/workspace"},
want: "",
}, {
desc: "simple",
workingDirs: []string{"/workspace/foo", "/workspace/bar", "/baz"},
want: "mkdir -p /workspace/foo /workspace/bar",
}, {
desc: "empty",
workingDirs: []string{"/workspace", "", "/baz", "/workspacedir"},
want: "",
}} {
t.Run(c.desc, func(t *testing.T) {
if script := makeWorkingDirScript(c.workingDirs); script != c.want {
t.Errorf("Expected `%v`, got `%v`", c.want, script)
}
})
}
}

0 comments on commit 34db1a7

Please sign in to comment.