1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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)
}
|