4
4
"archive/tar"
5
5
"bytes"
6
6
"compress/gzip"
7
+ "flag"
7
8
"fmt"
8
9
"io/ioutil"
9
10
"os"
@@ -18,9 +19,13 @@ import (
18
19
19
20
var Debug bool
20
21
21
- func die (s string , i ... interface {}) {
22
+ func warn (s string , i ... interface {}) {
22
23
s = fmt .Sprintf (s , i ... )
23
24
fmt .Fprintln (os .Stderr , strings .TrimSuffix (s , "\n " ))
25
+ }
26
+
27
+ func die (s string , i ... interface {}) {
28
+ warn (s , i ... )
24
29
os .Exit (1 )
25
30
}
26
31
@@ -31,41 +36,71 @@ func debug(i ...interface{}) {
31
36
}
32
37
}
33
38
39
+ type StringVector []string
40
+
41
+ func (v * StringVector ) String () string {
42
+ return `"` + strings .Join (* v , `" "` ) + `"`
43
+ }
44
+
45
+ func (v * StringVector ) Set (str string ) error {
46
+ * v = append (* v , str )
47
+ return nil
48
+ }
49
+
34
50
func main () {
51
+ var (
52
+ execOpts StringVector
53
+ goDefaultBinaryDesc string
54
+ goBinaryOpt string
55
+ goPathOpt string
56
+ )
57
+
58
+ // Find the go binary
59
+ gocmd , err := exec .LookPath ("go" )
60
+
61
+ flag .Var (& execOpts , "exec" , "Parameters passed to app, can be used multiple times" )
62
+ if err != nil {
63
+ goDefaultBinaryDesc = "Go binary to use (default: none found in $PATH, so it must be provided)"
64
+ } else {
65
+ goDefaultBinaryDesc = "Go binary to use (default: whatever go in $PATH)"
66
+ }
67
+ flag .StringVar (& goBinaryOpt , "go-binary" , gocmd , goDefaultBinaryDesc )
68
+ flag .StringVar (& goPathOpt , "go-path" , "" , "Custom GOPATH (default: a temporary directory)" )
69
+ flag .Parse ()
35
70
if os .Getenv ("GOPATH" ) != "" {
36
- die ( "to avoid confusion GOPATH must not be set " )
71
+ warn ( "GOPATH env var is ignored, use --go-path= \" $GOPATH \" option instead " )
37
72
}
38
- goroot := os .Getenv ("GOROOT" )
39
- if goroot = = "" {
40
- die ( " GOROOT must be set" )
73
+ goRoot := os .Getenv ("GOROOT" )
74
+ if goRoot ! = "" {
75
+ warn ( "Overriding GOROOT env var to %s" , goRoot )
41
76
}
42
77
if os .Getenv ("GOACI_DEBUG" ) != "" {
43
78
Debug = true
44
79
}
45
80
81
+ if goBinaryOpt == "" {
82
+ die ("go binary not found" )
83
+ }
84
+
46
85
// Set up a temporary directory for everything (gopath and builds)
47
86
tmpdir , err := ioutil .TempDir ("" , "goaci" )
48
87
if err != nil {
49
88
die ("error setting up temporary directory: %v" , err )
50
89
}
51
90
defer os .RemoveAll (tmpdir )
91
+ if goPathOpt == "" {
92
+ goPathOpt = tmpdir
93
+ }
52
94
53
95
// Scratch build dir for aci
54
96
acidir := filepath .Join (tmpdir , "aci" )
55
97
56
- // Be explicit with gobin
98
+ // Let's put final binary in tmpdir
57
99
gobin := filepath .Join (tmpdir , "bin" )
58
100
59
- // Find the go binary
60
- gocmd , err := exec .LookPath ("go" )
61
- if err != nil {
62
- die ("could not find `go` in path" )
63
- }
64
-
65
101
// Construct args for a go get that does a static build
66
- // TODO(jonboulle): go version 1.4
67
102
args := []string {
68
- gocmd ,
103
+ goBinaryOpt ,
69
104
"get" ,
70
105
"-a" ,
71
106
"-tags" , "netgo" ,
@@ -87,6 +122,7 @@ func main() {
87
122
if err != nil {
88
123
die ("bad app name: %v" , err )
89
124
}
125
+ args = append (args , ns )
90
126
91
127
// Use the last component, e.g. example.com/my/app --> app
92
128
ofn := filepath .Base (ns ) + ".aci"
@@ -96,15 +132,18 @@ func main() {
96
132
die ("error opening output file: %v" , err )
97
133
}
98
134
135
+ env := []string {
136
+ "GOPATH=" + goPathOpt ,
137
+ "GOBIN=" + gobin ,
138
+ "CGO_ENABLED=0" ,
139
+ "PATH=" + os .Getenv ("PATH" ),
140
+ }
141
+ if goRoot != "" {
142
+ env = append (env , "GOROOT=" + goRoot )
143
+ }
99
144
cmd := exec.Cmd {
100
- Env : []string {
101
- "GOPATH=" + tmpdir ,
102
- "GOBIN=" + gobin ,
103
- "GOROOT=" + goroot ,
104
- "CGO_ENABLED=0" ,
105
- "PATH=" + os .Getenv ("PATH" ),
106
- },
107
- Path : gocmd ,
145
+ Env : env ,
146
+ Path : goBinaryOpt ,
108
147
Args : args ,
109
148
Stderr : os .Stderr ,
110
149
Stdout : os .Stdout ,
@@ -145,15 +184,15 @@ func main() {
145
184
}
146
185
debug ("moved binary to:" , ep )
147
186
187
+ exec := []string {filepath .Join ("/" , fn )}
188
+ exec = append (exec , execOpts ... )
148
189
// Build the ACI
149
190
im := schema.ImageManifest {
150
191
ACKind : types .ACKind ("ImageManifest" ),
151
192
ACVersion : schema .AppContainerVersion ,
152
193
Name : * name ,
153
194
App : & types.App {
154
- Exec : types.Exec {
155
- filepath .Join ("/" , fn ),
156
- },
195
+ Exec : exec ,
157
196
User : "0" ,
158
197
Group : "0" ,
159
198
},
0 commit comments