-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Script Support to Sidecars #1987
Changes from 2 commits
96c2cf7
2e0ef6f
ede66f7
753e286
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
apiVersion: tekton.dev/v1alpha1 | ||
kind: TaskRun | ||
metadata: | ||
generateName: sidecar-ready- | ||
spec: | ||
taskSpec: | ||
sidecars: | ||
- name: slow-sidecar | ||
image: ubuntu | ||
script: | | ||
echo "hello from sidecar" > /shared/message | ||
volumeMounts: | ||
- name: shared | ||
mountPath: /shared | ||
|
||
steps: | ||
- name: check-ready | ||
image: ubuntu | ||
# The step will only succeed if the sidecar has written this file, which | ||
# it does 5s after it starts, before it reports Ready. | ||
script: cat /shared/message | ||
volumeMounts: | ||
- name: shared | ||
mountPath: /shared | ||
|
||
# Sidecars don't have /workspace mounted by default, so we have to define | ||
# our own shared volume. | ||
volumes: | ||
- name: shared | ||
emptyDir: {} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -355,10 +355,14 @@ func TestMakePod(t *testing.T) { | |
Image: "primary-image", | ||
Command: []string{"cmd"}, // avoid entrypoint lookup. | ||
}}}, | ||
Sidecars: []corev1.Container{{ | ||
Name: "sc-name", | ||
Image: "sidecar-image", | ||
}}, | ||
Sidecars: []v1alpha1.Sidecar{ | ||
{ | ||
Container: corev1.Container{ | ||
Name: "sc-name", | ||
Image: "sidecar-image", | ||
}, | ||
}, | ||
}, | ||
}, | ||
wantAnnotations: map[string]string{}, | ||
want: &corev1.PodSpec{ | ||
|
@@ -394,6 +398,76 @@ func TestMakePod(t *testing.T) { | |
}}, | ||
Volumes: append(implicitVolumes, toolsVolume, downwardVolume), | ||
}, | ||
}, { | ||
desc: "sidecar container with script", | ||
ts: v1alpha1.TaskSpec{ | ||
Steps: []v1alpha1.Step{{Container: corev1.Container{ | ||
Name: "primary-name", | ||
Image: "primary-image", | ||
Command: []string{"cmd"}, // avoid entrypoint lookup. | ||
}}}, | ||
Sidecars: []v1alpha1.Sidecar{ | ||
{ | ||
Container: corev1.Container{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest collapsing these brackets to match format with the Step on line 404. Similarly for the init container on line 422. |
||
Name: "sc-name", | ||
Image: "sidecar-image", | ||
}, | ||
Script: "#!/bin/sh\necho hello from sidecar", | ||
}, | ||
}, | ||
}, | ||
wantAnnotations: map[string]string{}, | ||
want: &corev1.PodSpec{ | ||
RestartPolicy: corev1.RestartPolicyNever, | ||
InitContainers: []corev1.Container{ | ||
{ | ||
Name: "place-scripts", | ||
Image: "busybox", | ||
Command: []string{"sh"}, | ||
TTY: true, | ||
VolumeMounts: []corev1.VolumeMount{scriptsVolumeMount}, | ||
Args: []string{"-c", `tmpfile="/tekton/scripts/sidecar-script-0-9l9zj" | ||
touch ${tmpfile} && chmod +x ${tmpfile} | ||
cat > ${tmpfile} << 'sidecar-script-heredoc-randomly-generated-mz4c7' | ||
#!/bin/sh | ||
echo hello from sidecar | ||
sidecar-script-heredoc-randomly-generated-mz4c7 | ||
`}, | ||
}, | ||
placeToolsInit, | ||
}, | ||
Containers: []corev1.Container{{ | ||
Name: "step-primary-name", | ||
Image: "primary-image", | ||
Command: []string{"/tekton/tools/entrypoint"}, | ||
Args: []string{ | ||
"-wait_file", | ||
"/tekton/downward/ready", | ||
"-wait_file_content", | ||
"-post_file", | ||
"/tekton/tools/0", | ||
"-termination_path", | ||
"/tekton/termination", | ||
"-entrypoint", | ||
"cmd", | ||
"--", | ||
}, | ||
Env: implicitEnvVars, | ||
VolumeMounts: append([]corev1.VolumeMount{toolsMount, downwardMount}, implicitVolumeMounts...), | ||
WorkingDir: pipeline.WorkspaceDir, | ||
Resources: corev1.ResourceRequirements{Requests: allZeroQty()}, | ||
TerminationMessagePath: "/tekton/termination", | ||
}, { | ||
Name: "sidecar-sc-name", | ||
Image: "sidecar-image", | ||
Resources: corev1.ResourceRequirements{ | ||
Requests: nil, | ||
}, | ||
Command: []string{"/tekton/scripts/sidecar-script-0-9l9zj"}, | ||
VolumeMounts: []corev1.VolumeMount{scriptsVolumeMount}, | ||
}}, | ||
Volumes: append(implicitVolumes, scriptsVolume, toolsVolume, downwardVolume), | ||
}, | ||
}, { | ||
desc: "resource request", | ||
ts: v1alpha1.TaskSpec{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,12 +45,12 @@ var ( | |
} | ||
) | ||
|
||
// convertScripts converts any steps that specify a Script field into a normal Container. | ||
// convertScripts converts any steps and sidecars that specify a Script field into a normal Container. | ||
// | ||
// It does this by prepending a container that writes specified Script bodies | ||
// to executable files in a shared volumeMount, then produces Containers that | ||
// simply run those executable files. | ||
func convertScripts(shellImage string, steps []v1alpha1.Step) (*corev1.Container, []corev1.Container) { | ||
func convertScripts(shellImage string, steps []v1alpha1.Step, sidecars []v1alpha1.Sidecar) (*corev1.Container, []corev1.Container, []corev1.Container) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than amending the signature and adding the extra func to account for Sidecars, couldn't the caller (MakePod) simply execute this function twice? Once for Steps and once for Sidecars? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you can definitely do the same thing that way. I think in order to do that you need to change the signature of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be excellent, thank you @tomgeorge ! |
||
placeScripts := false | ||
placeScriptsInit := corev1.Container{ | ||
Name: "place-scripts", | ||
|
@@ -61,7 +61,21 @@ func convertScripts(shellImage string, steps []v1alpha1.Step) (*corev1.Container | |
VolumeMounts: []corev1.VolumeMount{scriptsVolumeMount}, | ||
} | ||
|
||
var containers []corev1.Container | ||
convertedStepContainers := convertListOfSteps(steps, &placeScriptsInit, &placeScripts, "script") | ||
sidecarContainers := convertListOfSteps(sidecars, &placeScriptsInit, &placeScripts, "sidecar-script") | ||
|
||
if placeScripts { | ||
return &placeScriptsInit, convertedStepContainers, sidecarContainers | ||
} | ||
return nil, convertedStepContainers, sidecarContainers | ||
} | ||
|
||
// convertListOfSteps does the heavy lifting for convertScripts. | ||
// | ||
// It iterates through the list of steps (or sidecars), generates the script file name and heredoc termination string, | ||
// adds an entry to the init container args, sets up the step container to run the script, and sets the volume mounts. | ||
func convertListOfSteps(steps []v1alpha1.Step, initContainer *corev1.Container, placeScripts *bool, format string) []corev1.Container { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggest "namePrefix" instead of "format" here, since the value isn't expected to be a format string. |
||
containers := []corev1.Container{} | ||
for i, s := range steps { | ||
if s.Script == "" { | ||
// Nothing to convert. | ||
|
@@ -81,20 +95,20 @@ func convertScripts(shellImage string, steps []v1alpha1.Step) (*corev1.Container | |
|
||
// At least one step uses a script, so we should return a | ||
// non-nil init container. | ||
placeScripts = true | ||
*placeScripts = true | ||
|
||
// Append to the place-scripts script to place the | ||
// script file in a known location in the scripts volume. | ||
tmpFile := filepath.Join(scriptsDir, names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("script-%d", i))) | ||
tmpFile := filepath.Join(scriptsDir, names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("%s-%d", format, i))) | ||
// heredoc is the "here document" placeholder string | ||
// used to cat script contents into the file. Typically | ||
// this is the string "EOF" but if this value were | ||
// "EOF" it would prevent users from including the | ||
// string "EOF" in their own scripts. Instead we | ||
// randomly generate a string to (hopefully) prevent | ||
// collisions. | ||
heredoc := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("script-heredoc-randomly-generated") | ||
placeScriptsInit.Args[1] += fmt.Sprintf(`tmpfile="%s" | ||
heredoc := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("%s-heredoc-randomly-generated", format)) | ||
initContainer.Args[1] += fmt.Sprintf(`tmpfile="%s" | ||
touch ${tmpfile} && chmod +x ${tmpfile} | ||
cat > ${tmpfile} << '%s' | ||
%s | ||
|
@@ -110,9 +124,5 @@ cat > ${tmpfile} << '%s' | |
steps[i].VolumeMounts = append(steps[i].VolumeMounts, scriptsVolumeMount) | ||
containers = append(containers, steps[i].Container) | ||
} | ||
|
||
if placeScripts { | ||
return &placeScriptsInit, containers | ||
} | ||
return nil, containers | ||
return containers | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm missing something here - where is the 5s delay happening? And what is meant here by the sidecar reporting Ready?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was me copy/pasting another example without deleting the comments. It isn't really waiting for anything to be ready.