diff options
Diffstat (limited to 'actions/run_action.go')
-rw-r--r-- | actions/run_action.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/actions/run_action.go b/actions/run_action.go new file mode 100644 index 0000000..ad374d8 --- /dev/null +++ b/actions/run_action.go @@ -0,0 +1,132 @@ +/* +Run Action + +Allows to run any available command or script in the filesystem or +in host environment. + +Yaml syntax: + - action: run + chroot: bool + postprocess: bool + script: script name + command: command line + +Properties 'command' and 'script' are mutually exclusive. + +- command -- command with arguments; the command expected to be accessible in +host's or chrooted environment -- depending on 'chroot' property. + +- script -- script with arguments; script must be located in recipe directory. + +Optional properties: + +- chroot -- run script or command in target filesystem if set to true. +In other case the command or script is executed within the build process, with +access to the filesystem and the image. In both cases it is run with root privileges. + +- postprocess -- if set script or command is executed after all other commands and +has access to the image file. + + +Properties 'chroot' and 'postprocess' are mutually exclusive. +*/ +package actions + +import ( + "errors" + "github.com/go-debos/fakemachine" + "path" + "strings" + + "github.com/go-debos/debos" +) + +type RunAction struct { + debos.BaseAction `yaml:",inline"` + Chroot bool + PostProcess bool + Script string + Command string +} + +func (run *RunAction) Verify(context *debos.DebosContext) error { + if run.PostProcess && run.Chroot { + return errors.New("Cannot run postprocessing in the chroot") + } + return nil +} + +func (run *RunAction) PreMachine(context *debos.DebosContext, m *fakemachine.Machine, + args *[]string) error { + + if run.Script == "" { + 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])) + } + + return nil +} + +func (run *RunAction) doRun(context debos.DebosContext) error { + run.LogStart() + var cmdline []string + var label string + var cmd debos.Command + + if run.Chroot { + cmd = debos.NewChrootCommandForContext(context) + } else { + cmd = debos.Command{} + } + + 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, "/script") + script[0] = strings.Replace(script[0], scriptpath, "/script", 1) + } + cmdline = []string{strings.Join(script, " ")} + label = path.Base(run.Script) + } else { + cmdline = []string{run.Command} + label = run.Command + } + + // Command/script with options passed as single string + cmdline = append([]string{"sh", "-c"}, cmdline...) + + if !run.PostProcess { + if !run.Chroot { + cmd.AddEnvKey("ROOTDIR", context.Rootdir) + } + if context.Image != "" { + cmd.AddEnvKey("IMAGE", context.Image) + } + } + + return cmd.Run(label, cmdline...) +} + +func (run *RunAction) Run(context *debos.DebosContext) error { + if run.PostProcess { + /* This runs in postprocessing instead */ + return nil + } + return run.doRun(*context) +} + +func (run *RunAction) PostMachine(context debos.DebosContext) error { + if !run.PostProcess { + return nil + } + return run.doRun(context) +} |