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 4, 2019
1 parent 9428c43 commit f1dfc43
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
1 change: 1 addition & 0 deletions config/controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ spec:
"-git-image", "github.com/tektoncd/pipeline/cmd/git-init",
"-nop-image", "github.com/tektoncd/pipeline/cmd/nop",
"-bash-noop-image", "github.com/tektoncd/pipeline/cmd/bash",
"-bash-working-dir-image", "github.com/tektoncd/pipeline/cmd/bash",
"-gsutil-image","github.com/tektoncd/pipeline/cmd/gsutil",
"-entrypoint-image", "github.com/tektoncd/pipeline/cmd/entrypoint",
]
Expand Down
43 changes: 43 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"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -86,9 +87,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 @@ -155,6 +161,39 @@ func makeCredentialInitializer(serviceAccountName, namespace string, kubeclient
}, volumes, nil
}

func makeWorkingDirInitializer(taskSpec v1alpha1.TaskSpec) *corev1.Container {
seen := map[string]bool{}
script := ""
for _, step := range taskSpec.Steps {
if step.WorkingDir != "" {
p := filepath.Clean(step.WorkingDir)
if strings.HasPrefix(p, workspaceDir) && p != workspaceDir && !seen[p] {
seen[p] = true
command := fmt.Sprintf("mkdir -p %s", p)
if script == "" {
script = command
} else {
script = fmt.Sprintf("%s && %s", script, command)
}
}
}
}

if script == "" {
return nil
}

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,
}
}

// 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) (*corev1.Pod, error) {
Expand All @@ -174,6 +213,10 @@ func MakePod(taskRun *v1alpha1.TaskRun, taskSpec v1alpha1.TaskSpec, kubeclient k
initContainers := []corev1.Container{*cred}
podContainers := []corev1.Container{}

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

for i, step := range taskSpec.Steps {
step.Env = append(implicitEnvVars, step.Env...)
// TODO(mattmoor): Check that volumeMounts match volumes.
Expand Down
72 changes: 72 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 @@ -214,6 +216,76 @@ 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"),
},
nopContainer,
},
Volumes: implicitVolumes,
},
}, {
desc: "working-dir-outside-workspace-dir",
ts: v1alpha1.TaskSpec{
Steps: []corev1.Container{{
Name: "name",
Image: "image",
WorkingDir: "/some/other/dir",
}},
},
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,
}},
Containers: []corev1.Container{{
Name: "build-step-name",
Image: "image",
Env: implicitEnvVars,
VolumeMounts: implicitVolumeMounts,
WorkingDir: "/some/other/dir",
},
nopContainer,
},
Volumes: implicitVolumes,
},
}} {
t.Run(c.desc, func(t *testing.T) {
names.TestingSeed()
Expand Down

0 comments on commit f1dfc43

Please sign in to comment.