-
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 mode support to windows tasks #4128
Conversation
Hi @DrWadsy. Thanks for your PR. I'm waiting for a tektoncd member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/assign @dibyom |
/ok-to-test |
The following is the coverage report on the affected files.
|
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.
First of all, this is great. 🤩
I'd love to have an e2e test covering this, which probably means engaging with the plumbing repo to ensure the test cluster has some Windows nodes. That'd be great to have even without this script support, to ensure we can run even non-script Windows tasks.
I don't think we necessarily need to block this PR on e2e tests, but I want to make sure we have those in place before we promise much more support.
pkg/pod/script.go
Outdated
for _, step := range steps { | ||
cleaned := strings.TrimSpace(step.Script) | ||
if strings.HasPrefix(cleaned, "#!win") { | ||
requiresWindows = true |
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.
Could this just be return true
?
Same below with the requiresWindows = true; break
which just does return requiresWIndows
.
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.
Yes, this should just be return true. The variable is an artifact from before I refactored this into a helper method, I'll change that :)
@@ -365,7 +365,7 @@ func TestConvertScripts_WithSidecar(t *testing.T) { | |||
MountPath: "/another/one", | |||
}} | |||
|
|||
gotInit, gotSteps, gotSidecars := convertScripts(images.ShellImage, []v1beta1.Step{{ | |||
gotInit, gotSteps, gotSidecars := convertScripts(images.ShellImage, images.ShellImageWin, []v1beta1.Step{{ | |||
Script: `#!/bin/sh | |||
script-1`, | |||
Container: corev1.Container{Image: "step-1"}, |
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.
Can we also add unit test coverage for this new behavior in this file?
@@ -133,9 +133,9 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1beta1.TaskRun, taskSpec | |||
// Convert any steps with Script to command+args. | |||
// If any are found, append an init container to initialize scripts. | |||
if alphaAPIEnabled { | |||
scriptsInit, stepContainers, sidecarContainers = convertScripts(b.Images.ShellImage, steps, taskSpec.Sidecars, taskRun.Spec.Debug) | |||
scriptsInit, stepContainers, sidecarContainers = convertScripts(b.Images.ShellImage, b.Images.ShellImageWin, steps, taskSpec.Sidecars, taskRun.Spec.Debug) |
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.
Should windows support go into the alpha feature gate, alongside debug support? 🤔
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.
Good point.
I changed this call because I changed the signature of the convertScripts method, but we could pass nil and check for that before we do any windows checks?
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.
Passing nil or an empty string for the windows shell image when alphaAPIEnabled
is false
would work ok I think. An alternative would be to write an entirely windows-focused convertScripts
implementation and only invoke it if alphaAPIEnabled
is true
and requiresWindows
would be true. Might involve a bit more duplication or end up being more lines but it might reduce the number of windows-specific branches? Could also push a change like that back to a refactor pr in future as well though.
The following is the coverage report on the affected files.
|
Is there anything else I need to do here to get this moving forward? |
After #4139 is merged it would be great to have some e2e tests defined for this as well. We're still working on adding automation to those tests, though. |
/retest |
1 similar comment
/retest |
/lgtm |
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 left a bunch of comments but it looks like it's almost ready to go to me. Biggest question to my mind is whether we branch in our existing funcs (like convertScripts
) or write windows-specific versions of those.
docs/tasks.md
Outdated
@@ -265,6 +265,51 @@ steps: | |||
#!/usr/bin/env bash | |||
/bin/my-binary | |||
``` | |||
|
|||
**Windows scripts** |
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.
Suggest making this a heading and adding it to the Table of Contents at the top. Maybe a sub-heading of "Running scripts within Steps" so:
##### Windows Scripts
|
||
`#!win <interpreter command> <args>` | ||
|
||
Unlike linux, we need to specify how to interpret the script file which is generated by Tekton. The example below shows how to execute a powershell script: |
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 didn't totally understand this bit on first read, since linux also uses shebang lines to specify how to interpret script files. Is it referring to the use of arguments (-File
)? Or just that we have to be completely explicit otherwise tekton will assume it's for linux?
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.
We have to be explicit that this script will run under windows, and we also have to tell tekton how this script is to be run (which is what a linux shebang does for us). Windows needs to know which executable (e.g. powershell.exe, or pwsh.exe) it needs to use in order to run the script, and also specify any args (e.g. both of those .exe's require the -File argument in order to interpret commands in a file).
pkg/entrypoint/termination
Outdated
@@ -0,0 +1 @@ | |||
[{"key":"StartedAt","value":"2021-08-19T11:40:06.469+10:00","type":"InternalTektonResult"},{"key":"ExitCode","value":"2","type":"InternalTektonResult"},{"key":"StartedAt","value":"2021-08-19T11:40:06.504+10:00","type":"InternalTektonResult"},{"key":"StartedAt","value":"2021-08-19T11:40:06.519+10:00","type":"InternalTektonResult"},{"key":"StartedAt","value":"2021-08-19T11:40:06.531+10:00","type":"InternalTektonResult"}] |
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.
This is an artifact of a unit test in pkg/entrypoint
and should be removed I think. If you rebase on main
and re-run go test ./...
it shouldn't appear again.
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.
Good catch :) I'm pretty sure I've rebased on main recently, so I'll remove that file...
@@ -133,9 +133,9 @@ func (b *Builder) Build(ctx context.Context, taskRun *v1beta1.TaskRun, taskSpec | |||
// Convert any steps with Script to command+args. | |||
// If any are found, append an init container to initialize scripts. | |||
if alphaAPIEnabled { | |||
scriptsInit, stepContainers, sidecarContainers = convertScripts(b.Images.ShellImage, steps, taskSpec.Sidecars, taskRun.Spec.Debug) | |||
scriptsInit, stepContainers, sidecarContainers = convertScripts(b.Images.ShellImage, b.Images.ShellImageWin, steps, taskSpec.Sidecars, taskRun.Spec.Debug) |
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.
Passing nil or an empty string for the windows shell image when alphaAPIEnabled
is false
would work ok I think. An alternative would be to write an entirely windows-focused convertScripts
implementation and only invoke it if alphaAPIEnabled
is true
and requiresWindows
would be true. Might involve a bit more duplication or end up being more lines but it might reduce the number of windows-specific branches? Could also push a change like that back to a refactor pr in future as well though.
@@ -74,16 +74,28 @@ var ( | |||
// 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 []v1beta1.Step, sidecars []v1beta1.Sidecar, debugConfig *v1beta1.TaskRunDebug) (*corev1.Container, []corev1.Container, []corev1.Container) { | |||
func convertScripts(shellImageLinux string, shellImageWin string, steps []v1beta1.Step, sidecars []v1beta1.Sidecar, debugConfig *v1beta1.TaskRunDebug) (*corev1.Container, []corev1.Container, []corev1.Container) { | |||
placeScripts := false | |||
// Place scripts is an init container used for creating scripts in the |
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.
This comment goes with the corev1.Container
struct declared on line 94 I think. Suggest moving it down or removing it.
pkg/pod/script.go
Outdated
} | ||
} | ||
// If no step needs windows, then check sidecars to be sure | ||
if !requiresWindows { |
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.
Given requiresWindows
is never changed I don't think it's needed. Simply running the loop over steps and then sidecars should be equivalent I think?
/retest |
Thanks a lot for tackling those changes @DrWadsy . One more suggestion here - to maintain parity with other alpha features I think we should probably reject submitted TaskRuns / Tasks that use a windows script if the Adding validation is super easy - we can do this in I think the additional validation would look something like: if s.Script != "" {
cleaned := strings.TrimSpace(s.Script)
if strings.HasPrefix(cleaned, "#!win") {
errs = errs.Also(ValidateEnabledAPIFields(ctx, "windows script support", config.AlphaAPIFields).ViaField("script"))
}
} Adding a unit test to confirm this behaviour should then be as simple as adding an entry to the table in https://github.com/tektoncd/pipeline/blob/main/pkg/apis/pipeline/v1beta1/task_validation_test.go#L1200-L1202 |
The following is the coverage report on the affected files.
|
Nice one, cheers! /approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: sbwsg The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Also just noticed - could you squash the commits down too? We typically squash down into 1 before merge to help keep the history a little more easily scannable. I normally do that with |
Steps and sidecars can contain a script field. In linux tasks these scripts are copied into files which are made executable and then steps are added to the task to execute those files. This commit adds comparable functionality if scripts are used in a task which will run on a windows node. On a windows node the mechanics are different, due to how windows handles executable files. The key difference is that Tekton needs to know that a script will run on windows, and how to run the file (which interpreter to use). This is done through a ‘windows shebang’ line at the start of the script. The line must begin with ‘#!win’. After that the user needs to provide the interpreter to use, as well as any necessary arguments. The line must be written such that the name of the file containing the script to execute can be appended to the end. For example, to run the script in the file ‘test.ps1’ with powershell, the command would usually be ‘powershell -File test.ps1’ and so the shebang line must be ‘#!win powershell -File’. If no interpreter is provided (i.e. the shebang line is only ‘#!win’) then the script contents will be stored in a .cmd file and executed. Finally, since a pod cannot contain a mix of windows and linux containers a windows shell image has been added to the Images structure, which will be used in the place-scripts step when needed on a windows node. To maintain parity with other alpha features, task validation for tasks containing windows scripts will now require the 'enable-api-fields' flag to be 'alpha'. TaskRuns/Tasks that contain windows scripts will be rejected if this flag is not set, giving the user immediate feedback. The integration tests for windows scripts have been updated to reflect this alpha flag requirement.
acfa9e9
to
32d8f2a
Compare
The following is the coverage report on the affected files.
|
/retest |
@imjasonh I made some code changes and squashed this all down into a single commit, and so the PR lost the lgtm you added. Could you please check this over one more time? :) |
@imjasonh is out for another week I think, so I took a look. /lgtm |
Changes
Steps and sidecars can contain a script field. In Linux tasks these
scripts are copied into files which are made executable and then
steps are added to the task to execute those files. This commit adds
comparable functionality if scripts are used in a task which will run
on a Windows node.
On a Windows node the mechanics are different, due to how Windows
handles executable files. The key difference is that Tekton needs to
know that a script will run on Windows, and how to run the file
(which interpreter to use). This is done through a ‘windows shebang’
line at the start of the script.
The line must begin with
#!win
. After that the user needs to providethe interpreter to use, as well as any necessary arguments. The line
must be written such that the name of the file containing the script to
execute can be appended to the end.
For example, to run the script in the file
test.ps1
with powershell,the command would usually be
powershell -File test.ps1
and so theshebang line must be
#!win powershell -File
.If no interpreter is provided (i.e. the shebang line is only ‘#!win’) then
the script contents will be stored in a .cmd file and executed.
Finally, since a pod cannot contain a mix of Windows and Linux
containers a windows shell image has been added to the Images
structure, which will be used in the place-scripts step when needed
on a windows node.
Related:
Issue #1826
TEP-0057
/kind feature
Submitter Checklist
As the author of this PR, please check off the items in this checklist:
functionality, content, code)
Release Notes