Browse code

Isolate run() from commit

Guillaume J. Charmes authored on 2013/05/21 07:02:32
Showing 1 changed files
... ...
@@ -77,7 +77,11 @@ func (b *BuilderClient) CmdRun(args string) error {
77 77
 	if err != nil {
78 78
 		return err
79 79
 	}
80
+
81
+	cmd, env := b.config.Cmd, b.config.Env
82
+	b.config.Cmd = nil
80 83
 	MergeConfig(b.config, config)
84
+
81 85
 	body, statusCode, err := b.cli.call("POST", "/images/getCache", &ApiImageConfig{Id: b.image, Config: b.config})
82 86
 	if err != nil {
83 87
 		if statusCode != 404 {
... ...
@@ -89,11 +93,16 @@ func (b *BuilderClient) CmdRun(args string) error {
89 89
 		if err := json.Unmarshal(body, apiId); err != nil {
90 90
 			return err
91 91
 		}
92
+		utils.Debugf("Use cached version")
92 93
 		b.image = apiId.Id
93 94
 		return nil
94 95
 	}
95
-	b.commit()
96
-	return nil
96
+	cid, err := b.run()
97
+	if err != nil {
98
+		return err
99
+	}
100
+	b.config.Cmd, b.config.Env = cmd, env
101
+	return b.commit(cid)
97 102
 }
98 103
 
99 104
 func (b *BuilderClient) CmdEnv(args string) error {
... ...
@@ -133,54 +142,80 @@ func (b *BuilderClient) CmdInsert(args string) error {
133 133
 	return fmt.Errorf("INSERT not implemented")
134 134
 }
135 135
 
136
-func (b *BuilderClient) commit() error {
137
-	if b.config.Cmd == nil || len(b.config.Cmd) < 1 {
138
-		b.config.Cmd = []string{"echo"}
136
+func (b *BuilderClient) run() (string, error) {
137
+	if b.image == "" {
138
+		return "", fmt.Errorf("Please provide a source image with `from` prior to run")
139 139
 	}
140
-
140
+	b.config.Image = b.image
141 141
 	body, _, err := b.cli.call("POST", "/containers/create", b.config)
142 142
 	if err != nil {
143
-		return err
143
+		return "", err
144 144
 	}
145 145
 
146
-	out := &ApiRun{}
147
-	err = json.Unmarshal(body, out)
148
-	if err != nil {
149
-		return err
146
+	apiRun := &ApiRun{}
147
+	if err := json.Unmarshal(body, apiRun); err != nil {
148
+		return "", err
150 149
 	}
151
-
152
-	for _, warning := range out.Warnings {
150
+	for _, warning := range apiRun.Warnings {
153 151
 		fmt.Fprintln(os.Stderr, "WARNING: ", warning)
154 152
 	}
155 153
 
156 154
 	//start the container
157
-	_, _, err = b.cli.call("POST", "/containers/"+out.Id+"/start", nil)
155
+	_, _, err = b.cli.call("POST", "/containers/"+apiRun.Id+"/start", nil)
158 156
 	if err != nil {
159
-		return err
157
+		return "", err
160 158
 	}
161
-	b.tmpContainers[out.Id] = struct{}{}
159
+	b.tmpContainers[apiRun.Id] = struct{}{}
162 160
 
163 161
 	// Wait for it to finish
164
-	_, _, err = b.cli.call("POST", "/containers/"+out.Id+"/wait", nil)
162
+	body, _, err = b.cli.call("POST", "/containers/"+apiRun.Id+"/wait", nil)
165 163
 	if err != nil {
166
-		return err
164
+		return "", err
165
+	}
166
+	apiWait := &ApiWait{}
167
+	if err := json.Unmarshal(body, apiWait); err != nil {
168
+		return "", err
169
+	}
170
+	if apiWait.StatusCode != 0 {
171
+		return "", fmt.Errorf("The command %v returned a non-zero code: %d", b.config.Cmd, apiWait.StatusCode)
172
+	}
173
+
174
+	return apiRun.Id, nil
175
+}
176
+
177
+func (b *BuilderClient) commit(id string) error {
178
+	if b.image == "" {
179
+		return fmt.Errorf("Please provide a source image with `from` prior to run")
180
+	}
181
+	b.config.Image = b.image
182
+
183
+	if id == "" {
184
+		cmd := b.config.Cmd
185
+		b.config.Cmd = []string{"true"}
186
+		if cid, err := b.run(); err != nil {
187
+			return err
188
+		} else {
189
+			id = cid
190
+		}
191
+		b.config.Cmd = cmd
167 192
 	}
168 193
 
169 194
 	// Commit the container
170 195
 	v := url.Values{}
171
-	v.Set("container", out.Id)
196
+	v.Set("container", id)
172 197
 	v.Set("author", b.maintainer)
173
-	body, _, err = b.cli.call("POST", "/commit?"+v.Encode(), b.config)
198
+
199
+	body, _, err := b.cli.call("POST", "/commit?"+v.Encode(), b.config)
174 200
 	if err != nil {
175 201
 		return err
176 202
 	}
177 203
 	apiId := &ApiId{}
178
-	err = json.Unmarshal(body, apiId)
179
-	if err != nil {
204
+	if err := json.Unmarshal(body, apiId); err != nil {
180 205
 		return err
181 206
 	}
182 207
 	b.tmpImages[apiId.Id] = struct{}{}
183 208
 	b.image = apiId.Id
209
+	b.needCommit = false
184 210
 	return nil
185 211
 }
186 212
 
... ...
@@ -221,7 +256,9 @@ func (b *BuilderClient) Build(dockerfile io.Reader) (string, error) {
221 221
 		fmt.Printf("===> %v\n", b.image)
222 222
 	}
223 223
 	if b.needCommit {
224
-		b.commit()
224
+		if err := b.commit(""); err != nil {
225
+			return "", err
226
+		}
225 227
 	}
226 228
 	if b.image != "" {
227 229
 		// The build is successful, keep the temporary containers and images