diff --git a/cmd/entrypoint/main.go b/cmd/entrypoint/main.go index 1b8bb62bb56..3312d91f9b8 100644 --- a/cmd/entrypoint/main.go +++ b/cmd/entrypoint/main.go @@ -47,8 +47,7 @@ var ( breakpointOnFailure = flag.Bool("breakpoint_on_failure", false, "If specified, expect steps to not skip on failure") onError = flag.String("on_error", "", "Set to \"continue\" to ignore an error and continue when a container terminates with a non-zero exit code."+ " Set to \"stopAndFail\" to declare a failure with a step error and stop executing the rest of the steps.") - stepMetadataDir = flag.String("step_metadata_dir", "", "If specified, create directory to store the step metadata e.g. /tekton/steps//") - stepMetadataDirLink = flag.String("step_metadata_dir_link", "", "creates a symbolic link to the specified step_metadata_dir e.g. /tekton/steps//") + stepMetadataDir = flag.String("step_metadata_dir", "", "If specified, create directory to store the step metadata e.g. /tekton/steps//") ) const ( @@ -133,7 +132,6 @@ func main() { BreakpointOnFailure: *breakpointOnFailure, OnError: *onError, StepMetadataDir: *stepMetadataDir, - StepMetadataDirLink: *stepMetadataDirLink, } // Copy any creds injected by the controller into the $HOME directory of the current diff --git a/cmd/entrypoint/post_writer.go b/cmd/entrypoint/post_writer.go index 43b2d47980d..3de0ee3f5b1 100644 --- a/cmd/entrypoint/post_writer.go +++ b/cmd/entrypoint/post_writer.go @@ -3,6 +3,7 @@ package main import ( "log" "os" + "path/filepath" "github.com/tektoncd/pipeline/pkg/entrypoint" ) @@ -13,11 +14,16 @@ type realPostWriter struct{} var _ entrypoint.PostWriter = (*realPostWriter)(nil) // Write creates a file and writes content to that file if content is specified -// assumption here is the underlying directory structure already exists func (*realPostWriter) Write(file string, content string) { if file == "" { return } + + // Create directory if it doesn't already exist + if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil { + log.Fatalf("Error creating parent directory of %q: %v", file, err) + } + f, err := os.Create(file) if err != nil { log.Fatalf("Creating %q: %v", file, err) @@ -29,26 +35,3 @@ func (*realPostWriter) Write(file string, content string) { } } } - -// CreateDirWithSymlink creates the specified directory and a symbolic link to that directory -func (*realPostWriter) CreateDirWithSymlink(source, link string) { - if source == "" { - return - } - if err := os.MkdirAll(source, 0770); err != nil { - log.Fatalf("Creating directory %q: %v", source, err) - } - - if link == "" { - return - } - // create a symlink if it does not exist - if _, err := os.Stat(link); os.IsNotExist(err) { - // check if a source exist before creating a symbolic link - if _, err := os.Stat(source); err == nil { - if err := os.Symlink(source, link); err != nil { - log.Fatalf("Creating a symlink %q: %v", link, err) - } - } - } -} diff --git a/cmd/entrypoint/post_writer_test.go b/cmd/entrypoint/post_writer_test.go index dba13f39219..5ec16fc372f 100644 --- a/cmd/entrypoint/post_writer_test.go +++ b/cmd/entrypoint/post_writer_test.go @@ -3,10 +3,16 @@ package main import ( "io/ioutil" "os" + "path/filepath" "testing" ) func TestRealPostWriter_WriteFileContent(t *testing.T) { + testdir, err := ioutil.TempDir("", "post-writer") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(testdir) tests := []struct { name, file, content string }{{ @@ -18,6 +24,9 @@ func TestRealPostWriter_WriteFileContent(t *testing.T) { }, { name: "create an empty file", file: "sample.txt", + }, { + name: "create an empty file in new subdirectory", + file: filepath.Join(testdir, "dir", "sample.txt"), }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -39,39 +48,3 @@ func TestRealPostWriter_WriteFileContent(t *testing.T) { }) } } - -func TestRealPostWriter_CreateStepPath(t *testing.T) { - tests := []struct { - name, source, link string - }{{ - name: "Create a path with a file", - source: "sample.txt", - link: "0", - }, { - name: "Create a path without specifying any path", - }, { - name: "Create a sym link without specifying any link path", - source: "sample.txt", - }, { - name: "Create a sym link without specifying any source", - link: "0.txt", - }} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - rw := realPostWriter{} - rw.CreateDirWithSymlink(tt.source, tt.link) - if tt.source != "" { - defer os.Remove(tt.source) - if _, err := os.Stat(tt.source); err != nil { - t.Fatalf("Failed to create a file %q", tt.source) - } - } - if tt.source != "" && tt.link != "" { - defer os.Remove(tt.link) - if _, err := os.Stat(tt.link); err != nil { - t.Fatalf("Failed to create a sym link %q", tt.link) - } - } - }) - } -} diff --git a/cmd/entrypoint/subcommands/step_init.go b/cmd/entrypoint/subcommands/step_init.go new file mode 100644 index 00000000000..1daeb1de03e --- /dev/null +++ b/cmd/entrypoint/subcommands/step_init.go @@ -0,0 +1,46 @@ +package subcommands + +import ( + "log" + "os" + "path/filepath" + "strconv" +) + +// StepInitCommand is the name of the /tekton/steps initialization command. +const StepInitCommand = "step-init" + +var ( + // root is the location of the Tekton root directory. + // Included as a global variable to allow overriding for tests. + tektonRoot = "/tekton" +) + +// stepInit sets up the /tekton/steps directory for the pod. +// This expects the list of steps (in order matching the Task spec). +func stepInit(steps []string) error { + // Setup step directory symlinks - step data is written to a /tekton/run//status + // folder corresponding to each step - this is only mounted RW for the matching user step + // (and RO for all other steps). + // /tekton/steps provides a convenience symlink so that Tekton utilities to reference steps + // by name or index. + // NOTE: /tekton/steps may be removed in the future. Prefer using /tekton/run directly if + // possible. + + // Create directory if it doesn't already exist + stepDir := filepath.Join(tektonRoot, "steps") + if err := os.MkdirAll(stepDir, os.ModePerm); err != nil { + log.Fatalf("Error creating steps directory %q: %v", stepDir, err) + } + + for i, s := range steps { + run := filepath.Join(tektonRoot, "run", strconv.Itoa(i), "status") + if err := os.Symlink(run, filepath.Join(stepDir, s)); err != nil { + return err + } + if err := os.Symlink(run, filepath.Join(stepDir, strconv.Itoa(i))); err != nil { + return err + } + } + return nil +} diff --git a/cmd/entrypoint/subcommands/step_init_test.go b/cmd/entrypoint/subcommands/step_init_test.go new file mode 100644 index 00000000000..163bc8c8c46 --- /dev/null +++ b/cmd/entrypoint/subcommands/step_init_test.go @@ -0,0 +1,63 @@ +package subcommands + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestStepInit(t *testing.T) { + tmp, err := ioutil.TempDir("", "step-init-*") + if err != nil { + t.Fatalf("error creating temp directory: %v", err) + } + defer os.RemoveAll(tmp) + + // Override tektonRoot for testing. + tektonRoot = tmp + + // Create step directory so that symlinks can be successfully created. + // This is typically done by volume mounts, so it needs to be done manually + // in tests. + stepDir := filepath.Join(tmp, "steps") + if err := os.Mkdir(stepDir, os.ModePerm); err != nil { + t.Fatalf("error creating step directory: %v", err) + } + + steps := []string{"a", "b"} + if err := stepInit(steps); err != nil { + t.Fatalf("stepInit: %v", err) + } + + // Map of symlinks to expected /tekton/run folders. + // Expected format: + // Key: /tekton/steps/ + // Value: /tekton/run//status + wantLinks := map[string]string{ + "a": "0", + "0": "0", + "b": "1", + "1": "1", + } + + direntry, err := os.ReadDir(stepDir) + if err != nil { + t.Fatalf("os.ReadDir: %v", err) + } + for _, de := range direntry { + t.Run(de.Name(), func(t *testing.T) { + l, err := os.Readlink(filepath.Join(stepDir, de.Name())) + if err != nil { + t.Fatal(err) + } + want, ok := wantLinks[de.Name()] + if !ok { + t.Fatalf("unexpected symlink: %s", de.Name()) + } + if wantDir := filepath.Join(tmp, "run", want, "status"); l != wantDir { + t.Errorf("want %s, got %s", wantDir, l) + } + }) + } +} diff --git a/cmd/entrypoint/subcommands/subcommands.go b/cmd/entrypoint/subcommands/subcommands.go index 08f16f17257..2cae28b2011 100644 --- a/cmd/entrypoint/subcommands/subcommands.go +++ b/cmd/entrypoint/subcommands/subcommands.go @@ -72,6 +72,11 @@ func Process(args []string) error { } return SubcommandSuccessful{message: fmt.Sprintf("Decoded script %s", src)} } + case StepInitCommand: + if err := stepInit(args[1:]); err != nil { + return SubcommandError{subcommand: StepInitCommand, message: err.Error()} + } + return SubcommandSuccessful{message: "Setup /step directories"} default: } return nil diff --git a/cmd/entrypoint/subcommands/subcommands_test.go b/cmd/entrypoint/subcommands/subcommands_test.go index 666bcd8e495..2e3c8a17310 100644 --- a/cmd/entrypoint/subcommands/subcommands_test.go +++ b/cmd/entrypoint/subcommands/subcommands_test.go @@ -38,6 +38,21 @@ func TestProcessSuccessfulSubcommands(t *testing.T) { if _, ok := returnValue.(SubcommandSuccessful); !ok { t.Errorf("unexpected return value from decode-script command: %v", returnValue) } + + t.Run(StepInitCommand, func(t *testing.T) { + tektonRoot = tmp + + returnValue := Process([]string{StepInitCommand}) + if _, ok := returnValue.(SubcommandSuccessful); !ok { + t.Errorf("unexpected return value from step-init command: %v", returnValue) + } + + returnValue = Process([]string{StepInitCommand, "foo", "bar"}) + if _, ok := returnValue.(SubcommandSuccessful); !ok { + t.Errorf("unexpected return value from step-init command w/ params: %v", returnValue) + } + }) + } // TestProcessIgnoresNonSubcommands checks that any input to Process which diff --git a/docs/developers/README.md b/docs/developers/README.md index b16af63ac83..a90b3ea3597 100644 --- a/docs/developers/README.md +++ b/docs/developers/README.md @@ -172,15 +172,16 @@ Here is an example of a directory layout for a simple Task with 2 script steps: |-- run `-- 0 `-- out + `-- status + `-- exitCode |-- scripts | |-- script-0-t4jd8 | `-- script-1-4pjwp |-- steps -| |-- 0 -> /tekton/steps/step-unnamed-0 -| |-- 1 -> /tekton/steps/step-foo -| |-- step-foo -| `-- step-unnamed-0 -| `-- exitCode +| |-- 0 -> /tekton/run/0/status +| |-- 1 -> /tekton/run/1/status +| |-- step-foo -> /tekton/run/1/status +| `-- step-unnamed-0 -> /tekton/run/0/status `-- termination ``` @@ -541,14 +542,43 @@ integration tests run. When the flag in your cluster is `alpha` _all_ integration tests are executed, both `stable` and `alpha`. Setting the feature flag to `stable` will exclude `alpha` tests. -## What and Why of `/tekton/steps` +## What and Why of `/tekton/run` -`/tekton/steps/` is an implicit volume mounted on a pod and created for storing -the step specific information/metadata. There is one more subdirectory created -under `/tekton/steps/` for each step in a task. +`/tekton/run` is a collection of implicit volumes mounted on a pod and created +for storing the step specific information/metadata. Steps can only write +metadata to their own `/run` directory - all other step volumes are mounted as +`readonly`. The `/run` directories are considered internal implementation details +of Tekton and are not bound by the API compatibility policy - the contents and +structure can be safely changed so long as user behavior remains the same. -Let's take an example of a task with three steps, each exiting with non-zero -exit code: +### `/tekton/steps` + +`/tekton/steps` are special subdirectories are created for each step in a task - +each directory is actually a symlink to a directory in the Step's corresponding +`/tekton/run` volume. This is done to ensure that step directories can only be +modified by their own Step. To ensure that these symlinks are not modified, the +entire `/tekton/steps` volume is initially populated by an initContainer, and +mounted `readonly` on all user steps. + +These symlinks are created as a part of the `step-init` entrypoint subcommand +initContainer on each Task Pod. + +### Entrypoint configuration + +The entrypoint is modified to include an additional flag representing the step +specific directory where step metadata should be written: + +``` +step_metadata_dir - the dir specified in this flag is created to hold a step specific metadata +``` + +`step_metadata_dir` is set to `/tekton/run//status` for the entrypoint +of each step. + +### Example + +Let's take an example of a task with two steps, each exiting with non-zero exit +code: ```yaml kind: TaskRun @@ -562,121 +592,57 @@ spec: name: step0 onError: continue script: | - echo "This is step 0" - ls -1R /tekton/steps/ exit 1 - image: alpine onError: continue script: | - echo "This is step 1" - ls -1R /tekton/steps/ exit 2 - - image: alpine - name: step2 - onError: continue - script: | - echo "This is step 2" - ls -1R /tekton/steps/ - exit 3 ``` -The container `step-step0` for the first step `step0` shows three subdirectories -(one for each step) under `/tekton/steps/` and all three of them are empty. +During `step-step0`, the first container is actively running so none of the +output files are populated yet. The `/tekton/steps` directories are symlinked to +locations that do not yet exist, but will be populated during execution. ``` -kubectl logs pod/test-taskrun-2rb9k-pod-bphct -c step-step0 -+ echo 'This is step 0' -+ ls -1R /tekton/steps/ -This is step 0 -/tekton/steps/: -0 -1 -2 -step-step0 -step-step2 -step-unnamed-1 - -/tekton/steps/step-step0: -/tekton/steps/step-step2: -/tekton/steps/step-unnamed-1: -+ exit 1 -``` - -The container `step-unnamed-1` for the second step which has no name shows three -subdirectories (one for each step) under `/tekton/steps/` along with the -`exitCode` file under the first step directory which has finished executing: - -``` -kubectl logs pod/test-taskrun-2rb9k-pod-bphct -c step-unnamed-1 -This is step 1 -+ echo 'This is step 1' -+ ls -1R /tekton/steps/ -/tekton/steps/: -0 -1 -2 -step-step0 -step-step2 -step-unnamed-1 - -/tekton/steps/step-step0: -exitCode - -/tekton/steps/step-step2: - -/tekton/steps/step-unnamed-1: -+ exit 2 -``` - -The container `step-step2` for the third step `step2` shows three subdirectories -(one for each step) under `/tekton/steps/` along with the `exitCode` file under -the first and second step directory since both are done executing: - -``` -kubectl logs pod/test-taskrun-2rb9k-pod-bphct -c step-step2 -This is step 2 -+ echo 'This is step 2' -+ ls -1R /tekton/steps/ -/tekton/steps/: -0 -1 -2 -step-step0 -step-step2 -step-unnamed-1 - -/tekton/steps/step-step0: -exitCode - -/tekton/steps/step-step2: - -/tekton/steps/step-unnamed-1: -exitCode -+ exit 3 +/tekton +|-- run +| |-- 0 +| `-- 1 +|-- steps + |-- 0 -> /tekton/run/0/status + |-- 1 -> /tekton/run/1/status + |-- step-step0 -> /tekton/run/0/status + `-- step-unnamed1 -> /tekton/run/1/status ``` -The entrypoint is modified to include an additional two flags representing the -step specific directory and a symbolic link: +During `step-unnamed1`, the first container has now finished. The output files +for the first step are now populated, and the folder pointed to by +`/tekton/steps/0` now exists, and is populated with a file named `exitCode` +which contains the exit code of the first step. ``` -step_metadata_dir - the dir specified in this flag is created to hold a step specific metadata -step_metadata_dir_link - the dir specified in this flag is created as a symbolic link to step_metadata_dir +/tekton +|-- run +| |-- 0 +| | |-- out +| | `-- status +| | `-- exitCode +| `-- 1 +|-- steps + |-- 0 -> /tekton/run/0/status + |-- 1 -> /tekton/run/1/status + |-- step-step0 -> /tekton/run/0/status + `-- step-unnamed1 -> /tekton/run/1/status ``` -`step_metadata_dir` is set to `/tekton/steps/step-step0` and -`step_metadata_dir_link` is set to `/tekton/steps/0` for the entrypoint of the -first step in the above example task. - -Notice an additional entries `0`, `1`, and `2` showing under `/tekton/steps/`. -These are symbolic links created which are linked with their respective step -directories, `step-step0`, `step-unnamed-1`, and `step-step2`. These symbolic -links are created to provide simplified access to the step metadata directories -i.e., instead of referring to a directory with the step name, access it via the -step index. The step index becomes complex and hard to keep track of in a task -with a long list of steps, for example, a task with 20 steps. Creating the step -metadata directory using a step name and creating a symbolic link using the step -index gives the user flexibility, and an option to choose whatever works best -for them. +Notice that there are multiple symlinks showing under `/tekton/steps/` pointing +to the same `/tekton/run` location. These symbolic links are created to provide +simplified access to the step metadata directories i.e., instead of referring to +a directory with the step name, access it via the step index. The step index +becomes complex and hard to keep track of in a task with a long list of steps, +for example, a task with 20 steps. Creating the step metadata directory using a +step name and creating a symbolic link using the step index gives the user +flexibility, and an option to choose whatever works best for them. ## How to access the exit code of a step from any subsequent step in a task diff --git a/examples/v1beta1/taskruns/readonly-internal-dir.yaml b/examples/v1beta1/taskruns/readonly-internal-dir.yaml index 24bf1a75386..e4d83e2f4ca 100644 --- a/examples/v1beta1/taskruns/readonly-internal-dir.yaml +++ b/examples/v1beta1/taskruns/readonly-internal-dir.yaml @@ -19,3 +19,13 @@ spec: echo "able to write to run directory of non-current step" exit 1 fi + - image: ubuntu + script: | + set +e # dont fail the script on error + + # Steps should not be able to write to other step's step directories. + echo "hello world" > /tekton/steps/0/exitCode + if [ $? -eq 0 ] ; then + echo "able to write to run directory of non-current step" + exit 1 + fi \ No newline at end of file diff --git a/pkg/entrypoint/entrypointer.go b/pkg/entrypoint/entrypointer.go index 7d1dd1d97bc..d4c3877fe65 100644 --- a/pkg/entrypoint/entrypointer.go +++ b/pkg/entrypoint/entrypointer.go @@ -80,10 +80,6 @@ type Entrypointer struct { OnError string // StepMetadataDir is the directory for a step where the step related metadata can be stored StepMetadataDir string - // StepMetadataDirLink is the directory which needs to be linked to the StepMetadataDir - // the symlink is mainly created for providing easier access to the step metadata - // i.e. use `/tekton/steps/0/exitCode` instead of `/tekton/steps/my-awesome-step/exitCode` - StepMetadataDirLink string } // Waiter encapsulates waiting for files to exist. @@ -101,8 +97,6 @@ type Runner interface { type PostWriter interface { // Write writes to the path when complete. Write(file, content string) - // CreateDirWithSymlink creates directory and a symlink - CreateDirWithSymlink(source, link string) } // Go optionally waits for a file, runs the command, and writes a @@ -119,10 +113,6 @@ func (e Entrypointer) Go() error { _ = logger.Sync() }() - // Create the directory where we will store the exit codes (and eventually other metadata) of Steps. - // Create a symlink to the directory for easier access by the index instead of a step name. - e.PostWriter.CreateDirWithSymlink(e.StepMetadataDir, e.StepMetadataDirLink) - for _, f := range e.WaitFiles { if err := e.Waiter.Wait(f, e.WaitFileContent, e.BreakpointOnFailure); err != nil { // An error happened while waiting, so we bail @@ -185,7 +175,7 @@ func (e Entrypointer) Go() error { case err == nil: // if err is nil, write zero exit code and a post file e.WritePostFile(e.PostFile, nil) - e.WriteExitCodeFile(e.StepMetadataDirLink, "0") + e.WriteExitCodeFile(e.StepMetadataDir, "0") default: // for a step without continue on error and any error, write a post file with .err e.WritePostFile(e.PostFile, err) diff --git a/pkg/entrypoint/entrypointer_test.go b/pkg/entrypoint/entrypointer_test.go index 85966cd728c..ec872f56e85 100644 --- a/pkg/entrypoint/entrypointer_test.go +++ b/pkg/entrypoint/entrypointer_test.go @@ -24,6 +24,7 @@ import ( "io/ioutil" "os" "os/exec" + "path/filepath" "reflect" "testing" "time" @@ -146,22 +147,19 @@ func TestEntrypointer(t *testing.T) { }, { desc: "post file", postFile: "writeme", + stepDir: ".", }, { desc: "all together now", entrypoint: "echo", args: []string{"some", "args"}, waitFiles: []string{"waitforme"}, postFile: "writeme", + stepDir: ".", }, { desc: "multiple wait files", waitFiles: []string{"waitforme", "metoo", "methree"}, }, { desc: "breakpointOnFailure to wait or not to wait ", breakpointOnFailure: true, - }, { - desc: "create a step path", - entrypoint: "echo", - stepDir: "step-one", - stepDirLink: "0", }} { t.Run(c.desc, func(t *testing.T) { fw, fr, fpw := &fakeWaiter{}, &fakeRunner{}, &fakePostWriter{} @@ -184,7 +182,6 @@ func TestEntrypointer(t *testing.T) { Timeout: &timeout, BreakpointOnFailure: c.breakpointOnFailure, StepMetadataDir: c.stepDir, - StepMetadataDirLink: c.stepDirLink, }.Go() if err != nil { t.Fatalf("Entrypointer failed: %v", err) @@ -219,6 +216,10 @@ func TestEntrypointer(t *testing.T) { } else if *fpw.wrote != c.postFile { t.Errorf("Wrote post file %q, want %q", *fpw.wrote, c.postFile) } + + if d := filepath.Dir(*fpw.wrote); d != c.stepDir { + t.Errorf("Post file written to wrong directory %q, want %q", d, c.stepDir) + } } if c.postFile == "" && fpw.wrote != nil { t.Errorf("Wrote post file when not required") @@ -244,18 +245,6 @@ func TestEntrypointer(t *testing.T) { if err := os.Remove(terminationPath); err != nil { t.Errorf("Could not remove termination path: %s", err) } - - if c.stepDir != "" { - if c.stepDir != *fpw.source { - t.Error("Wanted step path created, got nil") - } - } - - if c.stepDirLink != "" { - if c.stepDirLink != *fpw.link { - t.Error("Wanted step path symbolic link created, got nil") - } - } }) } } @@ -378,8 +367,6 @@ type fakePostWriter struct { wrote *string exitCodeFile *string exitCode *string - source *string - link *string } func (f *fakePostWriter) Write(file, content string) { @@ -391,11 +378,6 @@ func (f *fakePostWriter) Write(file, content string) { } } -func (f *fakePostWriter) CreateDirWithSymlink(source, link string) { - f.source = &source - f.link = &link -} - type fakeErrorWaiter struct{ waited *string } func (f *fakeErrorWaiter) Wait(file string, expectContent bool, breakpointOnFailure bool) error { diff --git a/pkg/pod/entrypoint.go b/pkg/pod/entrypoint.go index b5bdc8a1299..2dc83c139ce 100644 --- a/pkg/pod/entrypoint.go +++ b/pkg/pod/entrypoint.go @@ -26,7 +26,6 @@ import ( "strconv" "strings" - "github.com/tektoncd/pipeline/pkg/apis/pipeline" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" "gomodules.xyz/jsonpatch/v2" corev1 "k8s.io/api/core/v1" @@ -111,7 +110,7 @@ func orderContainers(commonExtraEntrypointArgs []string, steps []corev1.Containe for i, s := range steps { var argsForEntrypoint []string - name := StepName(steps[i].Name, i) + idx := strconv.Itoa(i) switch i { case 0: argsForEntrypoint = []string{ @@ -119,19 +118,17 @@ func orderContainers(commonExtraEntrypointArgs []string, steps []corev1.Containe "-wait_file", filepath.Join(downwardMountPoint, downwardMountReadyFile), "-wait_file_content", // Wait for file contents, not just an empty file. // Start next step. - "-post_file", filepath.Join(runDir, strconv.Itoa(i), "out"), + "-post_file", filepath.Join(runDir, idx, "out"), "-termination_path", terminationPath, - "-step_metadata_dir", filepath.Join(pipeline.StepsDir, name), - "-step_metadata_dir_link", filepath.Join(pipeline.StepsDir, fmt.Sprintf("%d", i)), + "-step_metadata_dir", filepath.Join(runDir, idx, "status"), } default: // All other steps wait for previous file, write next file. argsForEntrypoint = []string{ "-wait_file", filepath.Join(runDir, strconv.Itoa(i-1), "out"), - "-post_file", filepath.Join(runDir, strconv.Itoa(i), "out"), + "-post_file", filepath.Join(runDir, idx, "out"), "-termination_path", terminationPath, - "-step_metadata_dir", filepath.Join(pipeline.StepsDir, name), - "-step_metadata_dir_link", filepath.Join(pipeline.StepsDir, fmt.Sprintf("%d", i)), + "-step_metadata_dir", filepath.Join(runDir, idx, "status"), } } argsForEntrypoint = append(argsForEntrypoint, commonExtraEntrypointArgs...) diff --git a/pkg/pod/entrypoint_test.go b/pkg/pod/entrypoint_test.go index f41544261ed..e895f58146f 100644 --- a/pkg/pod/entrypoint_test.go +++ b/pkg/pod/entrypoint_test.go @@ -58,8 +58,7 @@ func TestOrderContainers(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-entrypoint", "cmd", "--", "arg1", "arg2", }, @@ -72,8 +71,7 @@ func TestOrderContainers(t *testing.T) { "-wait_file", "/tekton/run/0/out", "-post_file", "/tekton/run/1/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-1", - "-step_metadata_dir_link", "/tekton/steps/1", + "-step_metadata_dir", "/tekton/run/1/status", "-entrypoint", "cmd1", "--", "cmd2", "cmd3", "arg1", "arg2", @@ -87,8 +85,7 @@ func TestOrderContainers(t *testing.T) { "-wait_file", "/tekton/run/1/out", "-post_file", "/tekton/run/2/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-2", - "-step_metadata_dir_link", "/tekton/steps/2", + "-step_metadata_dir", "/tekton/run/2/status", "-entrypoint", "cmd", "--", "arg1", "arg2", }, @@ -117,8 +114,7 @@ func TestOrderContainersWithDebugOnFailure(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-breakpoint_on_failure", "-entrypoint", "cmd", "--", "arg1", "arg2", @@ -171,8 +167,7 @@ func TestEntryPointResults(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-results", "sum,sub", "-entrypoint", "cmd", "--", "arg1", "arg2", @@ -186,8 +181,7 @@ func TestEntryPointResults(t *testing.T) { "-wait_file", "/tekton/run/0/out", "-post_file", "/tekton/run/1/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-1", - "-step_metadata_dir_link", "/tekton/steps/1", + "-step_metadata_dir", "/tekton/run/1/status", "-results", "sum,sub", "-entrypoint", "cmd1", "--", "cmd2", "cmd3", @@ -202,8 +196,7 @@ func TestEntryPointResults(t *testing.T) { "-wait_file", "/tekton/run/1/out", "-post_file", "/tekton/run/2/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-2", - "-step_metadata_dir_link", "/tekton/steps/2", + "-step_metadata_dir", "/tekton/run/2/status", "-results", "sum,sub", "-entrypoint", "cmd", "--", "arg1", "arg2", @@ -243,8 +236,7 @@ func TestEntryPointResultsSingleStep(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-results", "sum,sub", "-entrypoint", "cmd", "--", "arg1", "arg2", @@ -281,8 +273,7 @@ func TestEntryPointSingleResultsSingleStep(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-results", "sum", "-entrypoint", "cmd", "--", "arg1", "arg2", @@ -327,8 +318,7 @@ func TestEntryPointOnError(t *testing.T) { "-wait_file_content", "-post_file", "/tekton/run/0/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-failing-step", - "-step_metadata_dir_link", "/tekton/steps/0", + "-step_metadata_dir", "/tekton/run/0/status", "-on_error", "continue", "-entrypoint", "cmd", "--", }, @@ -342,8 +332,7 @@ func TestEntryPointOnError(t *testing.T) { "-wait_file", "/tekton/run/0/out", "-post_file", "/tekton/run/1/out", "-termination_path", "/tekton/termination", - "-step_metadata_dir", "/tekton/steps/step-passing-step", - "-step_metadata_dir_link", "/tekton/steps/1", + "-step_metadata_dir", "/tekton/run/1/status", "-on_error", "stopAndFail", "-entrypoint", "cmd", "--", }, diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index e7fb17fa5ed..402c9d0ae1f 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -73,6 +73,7 @@ var ( }, { Name: "tekton-internal-steps", MountPath: pipeline.StepsDir, + ReadOnly: true, }} implicitVolumes = []corev1.Volume{{ Name: "tekton-internal-workspace", @@ -187,7 +188,10 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1beta1.TaskRun, taskSpec } // place the entrypoint first in case other init containers rely on its // features (e.g. decode-script). - initContainers = append([]corev1.Container{entrypointInit}, initContainers...) + initContainers = append([]corev1.Container{ + entrypointInit, + tektonDirInit(b.Images.EntrypointImage, steps), + }, initContainers...) volumes = append(volumes, binVolume, downwardVolume) // Add implicit env vars. @@ -398,3 +402,22 @@ func runVolume(i int) corev1.Volume { VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, } } + +func tektonDirInit(image string, steps []v1beta1.Step) corev1.Container { + cmd := make([]string, 0, len(steps)+2) + cmd = append(cmd, "/ko-app/entrypoint", "step-init") + for i, s := range steps { + cmd = append(cmd, StepName(s.Name, i)) + } + + return corev1.Container{ + Name: "step-init", + Image: image, + WorkingDir: "/", + Command: cmd, + VolumeMounts: []corev1.VolumeMount{{ + Name: "tekton-internal-steps", + MountPath: pipeline.StepsDir, + }}, + } +} diff --git a/pkg/pod/pod_test.go b/pkg/pod/pod_test.go index 170ca1b303c..d3346562922 100644 --- a/pkg/pod/pod_test.go +++ b/pkg/pod/pod_test.go @@ -122,7 +122,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -136,9 +136,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -171,7 +169,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -185,9 +183,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -218,7 +214,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -232,9 +228,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -269,7 +263,7 @@ func TestPodBuild(t *testing.T) { want: &corev1.PodSpec{ ServiceAccountName: "service-account", RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -283,9 +277,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-basic-docker=multi-creds=https://docker.io", "-basic-docker=multi-creds=https://us.gcr.io", "-basic-git=multi-creds=github.com", @@ -338,7 +330,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -352,9 +344,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -397,7 +387,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "a-very-very-long-character-step-name-to-trigger-max-len----and-invalid-characters"}}})}, Containers: []corev1.Container{{ Name: "step-a-very-very-long-character-step-name-to-trigger-max-len", // step name trimmed. Image: "image", @@ -411,9 +401,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-a-very-very-long-character-step-name-to-trigger-max-len----and-invalid-characters", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -441,7 +429,7 @@ func TestPodBuild(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "ends-with-invalid-%%__$$"}}})}, Containers: []corev1.Container{{ Name: "step-ends-with-invalid", // invalid suffix removed. Image: "image", @@ -455,9 +443,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-ends-with-invalid-%%__$$", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -488,6 +474,7 @@ func TestPodBuild(t *testing.T) { RestartPolicy: corev1.RestartPolicyNever, InitContainers: []corev1.Container{ placeToolsInit, + tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}}), { Name: "working-dir-initializer", Image: images.ShellImage, @@ -510,9 +497,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -548,7 +533,7 @@ func TestPodBuild(t *testing.T) { wantAnnotations: map[string]string{}, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "primary-name"}}})}, Containers: []corev1.Container{{ Name: "step-primary-name", Image: "primary-image", @@ -562,9 +547,7 @@ func TestPodBuild(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-primary-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -608,6 +591,7 @@ func TestPodBuild(t *testing.T) { RestartPolicy: corev1.RestartPolicyNever, InitContainers: []corev1.Container{ placeToolsInit, + tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "primary-name"}}}), { Name: "place-scripts", Image: "busybox", @@ -635,9 +619,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-primary-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -680,7 +662,7 @@ _EOF_ wantAnnotations: map[string]string{}, // no ready annotations on pod create since sidecars are present want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "primary-name"}}})}, Containers: []corev1.Container{{ Name: "step-primary-name", Image: "primary-image", @@ -694,9 +676,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-primary-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -740,8 +720,11 @@ _EOF_ }}}, }, want: &corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + RestartPolicy: corev1.RestartPolicyNever, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{ + {Container: corev1.Container{Name: "unnamed-0"}}, + {Container: corev1.Container{Name: "unnamed-1"}}, + })}, Containers: []corev1.Container{{ Name: "step-unnamed-0", Image: "image", @@ -755,9 +738,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-unnamed-0", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -785,9 +766,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-unnamed-1", - "-step_metadata_dir_link", - "/tekton/steps/1", + "/tekton/run/1/status", "-entrypoint", "cmd", "--", @@ -846,6 +825,11 @@ print("Hello from Python")`, RestartPolicy: corev1.RestartPolicyNever, InitContainers: []corev1.Container{ placeToolsInit, + tektonDirInit(images.EntrypointImage, []v1beta1.Step{ + {Container: corev1.Container{Name: "one"}}, + {Container: corev1.Container{Name: "two"}}, + {Container: corev1.Container{Name: "regular-step"}}, + }), { Name: "place-scripts", Image: images.ShellImage, @@ -879,9 +863,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-one", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "/tekton/scripts/script-0-9l9zj", "--", @@ -906,9 +888,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-two", - "-step_metadata_dir_link", - "/tekton/steps/1", + "/tekton/run/1/status", "-entrypoint", "/tekton/scripts/script-1-mz4c7", "--", @@ -933,9 +913,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-regular-step", - "-step_metadata_dir_link", - "/tekton/steps/2", + "/tekton/run/2/status", "-entrypoint", "regular", "--", @@ -975,19 +953,22 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit, { - Name: "place-scripts", - Image: images.ShellImage, - Command: []string{"sh"}, - Args: []string{"-c", `scriptfile="/tekton/scripts/script-0-9l9zj" + InitContainers: []corev1.Container{placeToolsInit, + tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "one"}}}), + { + Name: "place-scripts", + Image: images.ShellImage, + Command: []string{"sh"}, + Args: []string{"-c", `scriptfile="/tekton/scripts/script-0-9l9zj" touch ${scriptfile} && chmod +x ${scriptfile} cat > ${scriptfile} << '_EOF_' IyEvYmluL3NoCiQk _EOF_ /tekton/bin/entrypoint decode-script "${scriptfile}" `}, - VolumeMounts: []corev1.VolumeMount{writeScriptsVolumeMount, binMount}, - }}, + VolumeMounts: []corev1.VolumeMount{writeScriptsVolumeMount, binMount}, + }, + }, Containers: []corev1.Container{{ Name: "step-one", Image: "image", @@ -1001,9 +982,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-one", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "/tekton/scripts/script-0-9l9zj", "--", @@ -1040,7 +1019,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "schedule-me"}}})}, SchedulerName: "there-scheduler", Volumes: append(implicitVolumes, binVolume, runVolume(0), downwardVolume, corev1.Volume{ Name: "tekton-creds-init-home-0", @@ -1059,9 +1038,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-schedule-me", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1095,7 +1072,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "image-pull"}}})}, Volumes: append(implicitVolumes, binVolume, runVolume(0), downwardVolume, corev1.Volume{ Name: "tekton-creds-init-home-0", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{Medium: corev1.StorageMediumMemory}}, @@ -1113,9 +1090,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-image-pull", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1150,7 +1125,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "host-aliases"}}})}, Volumes: append(implicitVolumes, binVolume, runVolume(0), downwardVolume, corev1.Volume{ Name: "tekton-creds-init-home-0", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{Medium: corev1.StorageMediumMemory}}, @@ -1168,9 +1143,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-host-aliases", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1203,7 +1176,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "use-my-hostNetwork"}}})}, HostNetwork: true, Volumes: append(implicitVolumes, binVolume, runVolume(0), downwardVolume, corev1.Volume{ Name: "tekton-creds-init-home-0", @@ -1222,9 +1195,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-use-my-hostNetwork", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1250,7 +1221,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1264,9 +1235,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-timeout", "1s", "-entrypoint", @@ -1299,7 +1268,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1313,9 +1282,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1341,7 +1308,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1355,9 +1322,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1393,7 +1358,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1407,9 +1372,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1461,7 +1424,7 @@ _EOF_ }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1475,9 +1438,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1508,7 +1469,7 @@ _EOF_ wantPodName: "task-run-0123456789-01234560d38957287bb0283c59440df14069f59-pod", want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1522,9 +1483,7 @@ _EOF_ "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-entrypoint", "cmd", "--", @@ -1664,7 +1623,7 @@ func TestPodBuildwithAlphaAPIEnabled(t *testing.T) { }, want: &corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, - InitContainers: []corev1.Container{placeToolsInit}, + InitContainers: []corev1.Container{placeToolsInit, tektonDirInit(images.EntrypointImage, []v1beta1.Step{{Container: corev1.Container{Name: "name"}}})}, Containers: []corev1.Container{{ Name: "step-name", Image: "image", @@ -1678,9 +1637,7 @@ func TestPodBuildwithAlphaAPIEnabled(t *testing.T) { "-termination_path", "/tekton/termination", "-step_metadata_dir", - "/tekton/steps/step-name", - "-step_metadata_dir_link", - "/tekton/steps/0", + "/tekton/run/0/status", "-breakpoint_on_failure", "-entrypoint", "cmd", diff --git a/pkg/reconciler/taskrun/taskrun_test.go b/pkg/reconciler/taskrun/taskrun_test.go index fee80512052..68708f75716 100644 --- a/pkg/reconciler/taskrun/taskrun_test.go +++ b/pkg/reconciler/taskrun/taskrun_test.go @@ -50,6 +50,7 @@ import ( eventstest "github.com/tektoncd/pipeline/test/events" "github.com/tektoncd/pipeline/test/names" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" k8sapierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -2308,7 +2309,7 @@ func TestExpandMountPath(t *testing.T) { t.Fatalf("failed to find expanded Workspace mountpath %v", expectedMountPath) } - if a := pod.Spec.Containers[0].Args[14]; a != expectedReplacedArgs { + if a := pod.Spec.Containers[0].Args; a[len(a)-1] != expectedReplacedArgs { t.Fatalf("failed to replace Workspace mountpath variable, expected %s, actual: %s", expectedReplacedArgs, a) } } @@ -4490,6 +4491,7 @@ func podVolumeMounts(idx, totalSteps int) []corev1.VolumeMount { mnts = append(mnts, corev1.VolumeMount{ Name: "tekton-internal-steps", MountPath: "/tekton/steps", + ReadOnly: true, }) return mnts @@ -4510,9 +4512,7 @@ func podArgs(stepName string, cmd string, additionalArgs []string, idx int) []st "-termination_path", "/tekton/termination", "-step_metadata_dir", - fmt.Sprintf("/tekton/steps/step-%s", stepName), - "-step_metadata_dir_link", - fmt.Sprintf("/tekton/steps/%d", idx), + fmt.Sprintf("/tekton/run/%d/status", idx), "-entrypoint", cmd, "--", @@ -4584,6 +4584,18 @@ func expectedPod(podName, taskName, taskRunName, ns, saName string, isClusterTas }, } + stepNames := make([]string, 0, len(steps)) + for _, s := range steps { + stepNames = append(stepNames, fmt.Sprintf("step-%s", s.name)) + } + p.Spec.InitContainers = []corev1.Container{placeToolsInitContainer, { + Name: "step-init", + Image: images.EntrypointImage, + Command: append([]string{"/ko-app/entrypoint", "step-init"}, stepNames...), + WorkingDir: "/", + VolumeMounts: []v1.VolumeMount{{Name: "tekton-internal-steps", MountPath: "/tekton/steps"}}, + }} + for idx, s := range steps { p.Spec.Volumes = append(p.Spec.Volumes, corev1.Volume{ Name: fmt.Sprintf("tekton-creds-init-home-%d", idx),