-
Notifications
You must be signed in to change notification settings - Fork 146
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
actions: run: Check script exists during recipe verification #302
base: main
Are you sure you want to change the base?
Changes from all commits
aba2686
4bc7393
858f94b
f805d84
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 |
---|---|---|
|
@@ -45,6 +45,8 @@ package actions | |
import ( | ||
"errors" | ||
"github.com/go-debos/fakemachine" | ||
"fmt" | ||
"os" | ||
"path" | ||
"strings" | ||
|
||
|
@@ -62,6 +64,9 @@ type RunAction struct { | |
Script string | ||
Command string | ||
Label string | ||
|
||
scriptPath string | ||
scriptArgs []string | ||
} | ||
|
||
func (run *RunAction) Verify(context *debos.DebosContext) error { | ||
|
@@ -72,6 +77,29 @@ func (run *RunAction) Verify(context *debos.DebosContext) error { | |
if run.Script == "" && run.Command == "" { | ||
return errors.New("Script and Command both cannot be empty") | ||
} | ||
|
||
if run.Script != "" { | ||
/* Extract the full script path from the arguments */ | ||
args := strings.Split(run.Script, " ") | ||
run.scriptPath = debos.CleanPathAt(args[0], context.RecipeDir) | ||
run.scriptArgs = args[1:] | ||
|
||
/* Check the script exists on the filesystem (following symlinks) */ | ||
stat, err := os.Stat(run.scriptPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if stat.IsDir() { | ||
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 then checking if it's a Dir this should proably check if it's a regular file |
||
return fmt.Errorf("script %s is a directory", run.Script) | ||
} | ||
|
||
/* Check the script is executable */ | ||
if stat.Mode()&0111 == 0 { | ||
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. executable and readable ideally; though i don't think golang gives you nice helpers for that unfortunately :/ |
||
return fmt.Errorf("script %s is not executable", run.Script) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
|
@@ -82,12 +110,8 @@ func (run *RunAction) PreMachine(context *debos.DebosContext, m *fakemachine.Mac | |
return nil | ||
} | ||
|
||
run.Script = debos.CleanPathAt(run.Script, context.RecipeDir) | ||
// Expect we have no blank spaces in path | ||
scriptpath := strings.Split(run.Script, " ") | ||
|
||
if !run.PostProcess { | ||
m.AddVolume(path.Dir(scriptpath[0])) | ||
m.AddVolume(path.Dir(run.scriptPath)) | ||
} | ||
|
||
return nil | ||
|
@@ -105,15 +129,14 @@ func (run *RunAction) doRun(context debos.DebosContext) error { | |
} | ||
|
||
if run.Script != "" { | ||
script := strings.SplitN(run.Script, " ", 2) | ||
script[0] = debos.CleanPathAt(script[0], context.RecipeDir) | ||
if run.Chroot { | ||
scriptpath := path.Dir(script[0]) | ||
cmd.AddBindMount(scriptpath, "/tmp/script") | ||
script[0] = strings.Replace(script[0], scriptpath, "/tmp/script", 1) | ||
scriptDir := path.Dir(run.scriptPath) | ||
cmd.AddBindMount(scriptDir, "/tmp/script") | ||
run.scriptPath = strings.Replace(run.scriptPath, scriptDir, "/tmp/script", 1) | ||
} | ||
cmdline = []string{strings.Join(script, " ")} | ||
label = path.Base(run.Script) | ||
cmdline = []string{run.scriptPath} | ||
cmdline = append(cmdline, run.scriptArgs...) | ||
label = path.Base(run.scriptPath) | ||
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. but then you don't see the arguments to the script anymore, which is a loss.. Probably this doesn't belong in this PR (it doesn't help with your stated target i think) but preventing "pollution" we could do either by:
|
||
} else { | ||
cmdline = []string{run.Command} | ||
|
||
|
@@ -140,7 +163,7 @@ func (run *RunAction) doRun(context debos.DebosContext) error { | |
} | ||
|
||
// Command/script with options passed as single string | ||
cmdline = append([]string{"sh", "-c"}, cmdline...) | ||
cmdline = append([]string{"sh", "-c"}, strings.Join(cmdline, " ")) | ||
|
||
if !run.Chroot { | ||
cmd.AddEnvKey("RECIPEDIR", context.RecipeDir) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
broken.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
test.sh |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
|
||
echo "test from script; arguments: $@" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
--- | ||
architecture: amd64 | ||
|
||
actions: | ||
- action: debootstrap | ||
suite: bullseye | ||
variant: minbase | ||
merged-usr: true | ||
|
||
- action: run | ||
description: Run a script which is a symlink | ||
script: scripts/test-symlink.sh argument1 argument2 | ||
|
||
- action: run | ||
description: Run a script with arguments | ||
script: scripts/test.sh argument1 argument2 | ||
|
||
- action: run | ||
description: Run a script without arguments | ||
script: scripts/test.sh | ||
|
||
- action: run | ||
description: Run a script with arguments in a chroot | ||
chroot: true | ||
script: scripts/test.sh argument1 argument2 | ||
|
||
- action: run | ||
description: Run a script without arguments in chroot | ||
chroot: true | ||
script: scripts/test.sh | ||
|
||
- action: run | ||
description: Test running a command | ||
command: echo test | ||
|
||
# TODO: This should fail in the Verify stage, we cannot yet check that in CI | ||
#- action: run | ||
# description: Run a script which has a broken symlink | ||
# chroot: true | ||
# script: scripts/test-broken-symlink.sh | ||
|
||
# TODO: This should fail in the Verify stage, we cannot yet check that in CI | ||
#- action: run | ||
# description: Run a script which has no exec bit set | ||
# chroot: true | ||
# script: scripts/test-broken-symlink.sh |
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.
kvm actually has the highest latency atm because of the runner setup; and really this should probably run on all types.. That said could you merge it with an existing tests so we don't need a new CI job for it ?
e.g. maybe merge it with the recipes test and the overlay test :)