Signed-off-by: David Calavera <david.calavera@gmail.com>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,20 @@ |
| 0 |
+package server |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net/http" |
|
| 4 |
+ "strconv" |
|
| 5 |
+ "strings" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func boolValue(r *http.Request, k string) bool {
|
|
| 9 |
+ s := strings.ToLower(strings.TrimSpace(r.FormValue(k))) |
|
| 10 |
+ return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none") |
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+func int64Value(r *http.Request, k string) int64 {
|
|
| 14 |
+ val, err := strconv.ParseInt(r.FormValue(k), 10, 64) |
|
| 15 |
+ if err != nil {
|
|
| 16 |
+ return 0 |
|
| 17 |
+ } |
|
| 18 |
+ return val |
|
| 19 |
+} |
| 0 | 20 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,55 @@ |
| 0 |
+package server |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "net/http" |
|
| 4 |
+ "net/url" |
|
| 5 |
+ "testing" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func TestBoolValue(t *testing.T) {
|
|
| 9 |
+ cases := map[string]bool{
|
|
| 10 |
+ "": false, |
|
| 11 |
+ "0": false, |
|
| 12 |
+ "no": false, |
|
| 13 |
+ "false": false, |
|
| 14 |
+ "none": false, |
|
| 15 |
+ "1": true, |
|
| 16 |
+ "yes": true, |
|
| 17 |
+ "true": true, |
|
| 18 |
+ "one": true, |
|
| 19 |
+ "100": true, |
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ for c, e := range cases {
|
|
| 23 |
+ v := url.Values{}
|
|
| 24 |
+ v.Set("test", c)
|
|
| 25 |
+ r, _ := http.NewRequest("POST", "", nil)
|
|
| 26 |
+ r.Form = v |
|
| 27 |
+ |
|
| 28 |
+ a := boolValue(r, "test") |
|
| 29 |
+ if a != e {
|
|
| 30 |
+ t.Fatalf("Value: %s, expected: %v, actual: %v", c, e, a)
|
|
| 31 |
+ } |
|
| 32 |
+ } |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func TestInt64Value(t *testing.T) {
|
|
| 36 |
+ cases := map[string]int64{
|
|
| 37 |
+ "": 0, |
|
| 38 |
+ "asdf": 0, |
|
| 39 |
+ "0": 0, |
|
| 40 |
+ "1": 1, |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ for c, e := range cases {
|
|
| 44 |
+ v := url.Values{}
|
|
| 45 |
+ v.Set("test", c)
|
|
| 46 |
+ r, _ := http.NewRequest("POST", "", nil)
|
|
| 47 |
+ r.Form = v |
|
| 48 |
+ |
|
| 49 |
+ a := int64Value(r, "test") |
|
| 50 |
+ if a != e {
|
|
| 51 |
+ t.Fatalf("Value: %s, expected: %v, actual: %v", c, e, a)
|
|
| 52 |
+ } |
|
| 53 |
+ } |
|
| 54 |
+} |
| ... | ... |
@@ -381,7 +381,7 @@ func (s *Server) getImagesJSON(eng *engine.Engine, version version.Version, w ht |
| 381 | 381 |
Filters: r.Form.Get("filters"),
|
| 382 | 382 |
// FIXME this parameter could just be a match filter |
| 383 | 383 |
Filter: r.Form.Get("filter"),
|
| 384 |
- All: toBool(r.Form.Get("all")),
|
|
| 384 |
+ All: boolValue(r, "all"), |
|
| 385 | 385 |
} |
| 386 | 386 |
|
| 387 | 387 |
images, err := s.daemon.Repositories().Images(&imagesConfig) |
| ... | ... |
@@ -597,8 +597,8 @@ func (s *Server) getContainersJSON(eng *engine.Engine, version version.Version, |
| 597 | 597 |
} |
| 598 | 598 |
|
| 599 | 599 |
config := &daemon.ContainersConfig{
|
| 600 |
- All: toBool(r.Form.Get("all")),
|
|
| 601 |
- Size: toBool(r.Form.Get("size")),
|
|
| 600 |
+ All: boolValue(r, "all"), |
|
| 601 |
+ Size: boolValue(r, "size"), |
|
| 602 | 602 |
Since: r.Form.Get("since"),
|
| 603 | 603 |
Before: r.Form.Get("before"),
|
| 604 | 604 |
Filters: r.Form.Get("filters"),
|
| ... | ... |
@@ -640,14 +640,14 @@ func (s *Server) getContainersLogs(eng *engine.Engine, version version.Version, |
| 640 | 640 |
} |
| 641 | 641 |
|
| 642 | 642 |
// Validate args here, because we can't return not StatusOK after job.Run() call |
| 643 |
- stdout, stderr := toBool(r.Form.Get("stdout")), toBool(r.Form.Get("stderr"))
|
|
| 643 |
+ stdout, stderr := boolValue(r, "stdout"), boolValue(r, "stderr") |
|
| 644 | 644 |
if !(stdout || stderr) {
|
| 645 | 645 |
return fmt.Errorf("Bad parameters: you must choose at least one stream")
|
| 646 | 646 |
} |
| 647 | 647 |
|
| 648 | 648 |
logsConfig := &daemon.ContainerLogsConfig{
|
| 649 |
- Follow: toBool(r.Form.Get("follow")),
|
|
| 650 |
- Timestamps: toBool(r.Form.Get("timestamps")),
|
|
| 649 |
+ Follow: boolValue(r, "follow"), |
|
| 650 |
+ Timestamps: boolValue(r, "timestamps"), |
|
| 651 | 651 |
Tail: r.Form.Get("tail"),
|
| 652 | 652 |
UseStdout: stdout, |
| 653 | 653 |
UseStderr: stderr, |
| ... | ... |
@@ -671,7 +671,7 @@ func (s *Server) postImagesTag(eng *engine.Engine, version version.Version, w ht |
| 671 | 671 |
|
| 672 | 672 |
repo := r.Form.Get("repo")
|
| 673 | 673 |
tag := r.Form.Get("tag")
|
| 674 |
- force := toBool(r.Form.Get("force"))
|
|
| 674 |
+ force := boolValue(r, "force") |
|
| 675 | 675 |
if err := s.daemon.Repositories().Tag(repo, tag, vars["name"], force); err != nil {
|
| 676 | 676 |
return err |
| 677 | 677 |
} |
| ... | ... |
@@ -690,11 +690,20 @@ func (s *Server) postCommit(eng *engine.Engine, version version.Version, w http. |
| 690 | 690 |
|
| 691 | 691 |
cont := r.Form.Get("container")
|
| 692 | 692 |
|
| 693 |
- pause := toBool(r.Form.Get("pause"))
|
|
| 693 |
+ pause := boolValue(r, "pause") |
|
| 694 | 694 |
if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
|
| 695 | 695 |
pause = true |
| 696 | 696 |
} |
| 697 | 697 |
|
| 698 |
+ c, _, err := runconfig.DecodeContainerConfig(r.Body) |
|
| 699 |
+ if err != nil && err != io.EOF { //Do not fail if body is empty.
|
|
| 700 |
+ return err |
|
| 701 |
+ } |
|
| 702 |
+ |
|
| 703 |
+ if c == nil {
|
|
| 704 |
+ c = &runconfig.Config{}
|
|
| 705 |
+ } |
|
| 706 |
+ |
|
| 698 | 707 |
containerCommitConfig := &daemon.ContainerCommitConfig{
|
| 699 | 708 |
Pause: pause, |
| 700 | 709 |
Repo: r.Form.Get("repo"),
|
| ... | ... |
@@ -702,10 +711,10 @@ func (s *Server) postCommit(eng *engine.Engine, version version.Version, w http. |
| 702 | 702 |
Author: r.Form.Get("author"),
|
| 703 | 703 |
Comment: r.Form.Get("comment"),
|
| 704 | 704 |
Changes: r.Form["changes"], |
| 705 |
- Config: r.Body, |
|
| 705 |
+ Config: c, |
|
| 706 | 706 |
} |
| 707 | 707 |
|
| 708 |
- imgID, err := s.daemon.ContainerCommit(cont, containerCommitConfig) |
|
| 708 |
+ imgID, err := builder.Commit(s.daemon, eng, cont, containerCommitConfig) |
|
| 709 | 709 |
if err != nil {
|
| 710 | 710 |
return err |
| 711 | 711 |
} |
| ... | ... |
@@ -782,10 +791,15 @@ func (s *Server) postImagesCreate(eng *engine.Engine, version version.Version, w |
| 782 | 782 |
imageImportConfig.Json = false |
| 783 | 783 |
} |
| 784 | 784 |
|
| 785 |
- if err := s.daemon.Repositories().Import(src, repo, tag, imageImportConfig, eng); err != nil {
|
|
| 785 |
+ newConfig, err := builder.BuildFromConfig(s.daemon, eng, &runconfig.Config{}, imageImportConfig.Changes)
|
|
| 786 |
+ if err != nil {
|
|
| 786 | 787 |
return err |
| 787 | 788 |
} |
| 789 |
+ imageImportConfig.ContainerConfig = newConfig |
|
| 788 | 790 |
|
| 791 |
+ if err := s.daemon.Repositories().Import(src, repo, tag, imageImportConfig); err != nil {
|
|
| 792 |
+ return err |
|
| 793 |
+ } |
|
| 789 | 794 |
} |
| 790 | 795 |
|
| 791 | 796 |
return nil |
| ... | ... |
@@ -977,9 +991,9 @@ func (s *Server) deleteContainers(eng *engine.Engine, version version.Version, w |
| 977 | 977 |
|
| 978 | 978 |
name := vars["name"] |
| 979 | 979 |
config := &daemon.ContainerRmConfig{
|
| 980 |
- ForceRemove: toBool(r.Form.Get("force")),
|
|
| 981 |
- RemoveVolume: toBool(r.Form.Get("v")),
|
|
| 982 |
- RemoveLink: toBool(r.Form.Get("link")),
|
|
| 980 |
+ ForceRemove: boolValue(r, "force"), |
|
| 981 |
+ RemoveVolume: boolValue(r, "v"), |
|
| 982 |
+ RemoveLink: boolValue(r, "link"), |
|
| 983 | 983 |
} |
| 984 | 984 |
|
| 985 | 985 |
if err := s.daemon.ContainerRm(name, config); err != nil {
|
| ... | ... |
@@ -1004,8 +1018,8 @@ func (s *Server) deleteImages(eng *engine.Engine, version version.Version, w htt |
| 1004 | 1004 |
} |
| 1005 | 1005 |
|
| 1006 | 1006 |
name := vars["name"] |
| 1007 |
- force := toBool(r.Form.Get("force"))
|
|
| 1008 |
- noprune := toBool(r.Form.Get("noprune"))
|
|
| 1007 |
+ force := boolValue(r, "force") |
|
| 1008 |
+ noprune := boolValue(r, "noprune") |
|
| 1009 | 1009 |
|
| 1010 | 1010 |
list, err := s.daemon.ImageDelete(name, force, noprune) |
| 1011 | 1011 |
if err != nil {
|
| ... | ... |
@@ -1152,19 +1166,19 @@ func (s *Server) postContainersAttach(eng *engine.Engine, version version.Versio |
| 1152 | 1152 |
} else {
|
| 1153 | 1153 |
errStream = outStream |
| 1154 | 1154 |
} |
| 1155 |
- logs := toBool(r.Form.Get("logs"))
|
|
| 1156 |
- stream := toBool(r.Form.Get("stream"))
|
|
| 1155 |
+ logs := boolValue(r, "logs") |
|
| 1156 |
+ stream := boolValue(r, "stream") |
|
| 1157 | 1157 |
|
| 1158 | 1158 |
var stdin io.ReadCloser |
| 1159 | 1159 |
var stdout, stderr io.Writer |
| 1160 | 1160 |
|
| 1161 |
- if toBool(r.Form.Get("stdin")) {
|
|
| 1161 |
+ if boolValue(r, "stdin") {
|
|
| 1162 | 1162 |
stdin = inStream |
| 1163 | 1163 |
} |
| 1164 |
- if toBool(r.Form.Get("stdout")) {
|
|
| 1164 |
+ if boolValue(r, "stdout") {
|
|
| 1165 | 1165 |
stdout = outStream |
| 1166 | 1166 |
} |
| 1167 |
- if toBool(r.Form.Get("stderr")) {
|
|
| 1167 |
+ if boolValue(r, "stderr") {
|
|
| 1168 | 1168 |
stderr = errStream |
| 1169 | 1169 |
} |
| 1170 | 1170 |
|
| ... | ... |
@@ -1246,11 +1260,9 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R |
| 1246 | 1246 |
authConfig = ®istry.AuthConfig{}
|
| 1247 | 1247 |
configFileEncoded = r.Header.Get("X-Registry-Config")
|
| 1248 | 1248 |
configFile = ®istry.ConfigFile{}
|
| 1249 |
- job = builder.NewBuildConfig(eng.Logging, eng.Stderr) |
|
| 1249 |
+ buildConfig = builder.NewBuildConfig() |
|
| 1250 | 1250 |
) |
| 1251 | 1251 |
|
| 1252 |
- b := &builder.BuilderJob{eng, getDaemon(eng)}
|
|
| 1253 |
- |
|
| 1254 | 1252 |
// This block can be removed when API versions prior to 1.9 are deprecated. |
| 1255 | 1253 |
// Both headers will be parsed and sent along to the daemon, but if a non-empty |
| 1256 | 1254 |
// ConfigFile is present, any value provided as an AuthConfig directly will |
| ... | ... |
@@ -1273,39 +1285,41 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R |
| 1273 | 1273 |
} |
| 1274 | 1274 |
} |
| 1275 | 1275 |
|
| 1276 |
+ stdout := engine.NewOutput() |
|
| 1277 |
+ stdout.Set(utils.NewWriteFlusher(w)) |
|
| 1278 |
+ |
|
| 1276 | 1279 |
if version.GreaterThanOrEqualTo("1.8") {
|
| 1277 |
- job.JSONFormat = true |
|
| 1278 |
- streamJSON(job.Stdout, w, true) |
|
| 1279 |
- } else {
|
|
| 1280 |
- job.Stdout.Add(utils.NewWriteFlusher(w)) |
|
| 1280 |
+ w.Header().Set("Content-Type", "application/json")
|
|
| 1281 |
+ buildConfig.JSONFormat = true |
|
| 1281 | 1282 |
} |
| 1282 | 1283 |
|
| 1283 |
- if toBool(r.FormValue("forcerm")) && version.GreaterThanOrEqualTo("1.12") {
|
|
| 1284 |
- job.Remove = true |
|
| 1284 |
+ if boolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
|
|
| 1285 |
+ buildConfig.Remove = true |
|
| 1285 | 1286 |
} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
|
| 1286 |
- job.Remove = true |
|
| 1287 |
+ buildConfig.Remove = true |
|
| 1287 | 1288 |
} else {
|
| 1288 |
- job.Remove = toBool(r.FormValue("rm"))
|
|
| 1289 |
+ buildConfig.Remove = boolValue(r, "rm") |
|
| 1289 | 1290 |
} |
| 1290 |
- if toBool(r.FormValue("pull")) && version.GreaterThanOrEqualTo("1.16") {
|
|
| 1291 |
- job.Pull = true |
|
| 1291 |
+ if boolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
|
|
| 1292 |
+ buildConfig.Pull = true |
|
| 1292 | 1293 |
} |
| 1293 |
- job.Stdin.Add(r.Body) |
|
| 1294 | 1294 |
|
| 1295 |
- // FIXME(calavera): !!!!! Remote might not be used. Solve the mistery before merging |
|
| 1296 |
- //job.Setenv("remote", r.FormValue("remote"))
|
|
| 1297 |
- job.DockerfileName = r.FormValue("dockerfile")
|
|
| 1298 |
- job.RepoName = r.FormValue("t")
|
|
| 1299 |
- job.SuppressOutput = toBool(r.FormValue("q"))
|
|
| 1300 |
- job.NoCache = toBool(r.FormValue("nocache"))
|
|
| 1301 |
- job.ForceRemove = toBool(r.FormValue("forcerm"))
|
|
| 1302 |
- job.AuthConfig = authConfig |
|
| 1303 |
- job.ConfigFile = configFile |
|
| 1304 |
- job.MemorySwap = toInt64(r.FormValue("memswap"))
|
|
| 1305 |
- job.Memory = toInt64(r.FormValue("memory"))
|
|
| 1306 |
- job.CpuShares = toInt64(r.FormValue("cpushares"))
|
|
| 1307 |
- job.CpuSetCpus = r.FormValue("cpusetcpus")
|
|
| 1308 |
- job.CpuSetMems = r.FormValue("cpusetmems")
|
|
| 1295 |
+ buildConfig.Stdout = stdout |
|
| 1296 |
+ buildConfig.Context = r.Body |
|
| 1297 |
+ |
|
| 1298 |
+ buildConfig.RemoteURL = r.FormValue("remote")
|
|
| 1299 |
+ buildConfig.DockerfileName = r.FormValue("dockerfile")
|
|
| 1300 |
+ buildConfig.RepoName = r.FormValue("t")
|
|
| 1301 |
+ buildConfig.SuppressOutput = boolValue(r, "q") |
|
| 1302 |
+ buildConfig.NoCache = boolValue(r, "nocache") |
|
| 1303 |
+ buildConfig.ForceRemove = boolValue(r, "forcerm") |
|
| 1304 |
+ buildConfig.AuthConfig = authConfig |
|
| 1305 |
+ buildConfig.ConfigFile = configFile |
|
| 1306 |
+ buildConfig.MemorySwap = int64Value(r, "memswap") |
|
| 1307 |
+ buildConfig.Memory = int64Value(r, "memory") |
|
| 1308 |
+ buildConfig.CpuShares = int64Value(r, "cpushares") |
|
| 1309 |
+ buildConfig.CpuSetCpus = r.FormValue("cpusetcpus")
|
|
| 1310 |
+ buildConfig.CpuSetMems = r.FormValue("cpusetmems")
|
|
| 1309 | 1311 |
|
| 1310 | 1312 |
// Job cancellation. Note: not all job types support this. |
| 1311 | 1313 |
if closeNotifier, ok := w.(http.CloseNotifier); ok {
|
| ... | ... |
@@ -1316,13 +1330,13 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R |
| 1316 | 1316 |
case <-finished: |
| 1317 | 1317 |
case <-closeNotifier.CloseNotify(): |
| 1318 | 1318 |
logrus.Infof("Client disconnected, cancelling job: build")
|
| 1319 |
- job.Cancel() |
|
| 1319 |
+ buildConfig.Cancel() |
|
| 1320 | 1320 |
} |
| 1321 | 1321 |
}() |
| 1322 | 1322 |
} |
| 1323 | 1323 |
|
| 1324 |
- if err := b.CmdBuild(job); err != nil {
|
|
| 1325 |
- if !job.Stdout.Used() {
|
|
| 1324 |
+ if err := builder.Build(s.daemon, eng, buildConfig); err != nil {
|
|
| 1325 |
+ if !stdout.Used() {
|
|
| 1326 | 1326 |
return err |
| 1327 | 1327 |
} |
| 1328 | 1328 |
sf := streamformatter.NewStreamFormatter(version.GreaterThanOrEqualTo("1.8"))
|
| ... | ... |
@@ -1676,17 +1690,3 @@ func allocateDaemonPort(addr string) error {
|
| 1676 | 1676 |
} |
| 1677 | 1677 |
return nil |
| 1678 | 1678 |
} |
| 1679 |
- |
|
| 1680 |
-func toBool(s string) bool {
|
|
| 1681 |
- s = strings.ToLower(strings.TrimSpace(s)) |
|
| 1682 |
- return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none") |
|
| 1683 |
-} |
|
| 1684 |
- |
|
| 1685 |
-// FIXME(calavera): This is a copy of the Env.GetInt64 |
|
| 1686 |
-func toInt64(s string) int64 {
|
|
| 1687 |
- val, err := strconv.ParseInt(s, 10, 64) |
|
| 1688 |
- if err != nil {
|
|
| 1689 |
- return 0 |
|
| 1690 |
- } |
|
| 1691 |
- return val |
|
| 1692 |
-} |
| ... | ... |
@@ -2,7 +2,6 @@ package builder |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"bytes" |
| 5 |
- "encoding/json" |
|
| 6 | 5 |
"fmt" |
| 7 | 6 |
"io" |
| 8 | 7 |
"io/ioutil" |
| ... | ... |
@@ -18,7 +17,6 @@ import ( |
| 18 | 18 |
"github.com/docker/docker/graph" |
| 19 | 19 |
"github.com/docker/docker/pkg/archive" |
| 20 | 20 |
"github.com/docker/docker/pkg/httputils" |
| 21 |
- "github.com/docker/docker/pkg/ioutils" |
|
| 22 | 21 |
"github.com/docker/docker/pkg/parsers" |
| 23 | 22 |
"github.com/docker/docker/pkg/streamformatter" |
| 24 | 23 |
"github.com/docker/docker/pkg/urlutil" |
| ... | ... |
@@ -38,11 +36,6 @@ var validCommitCommands = map[string]bool{
|
| 38 | 38 |
"onbuild": true, |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
-type BuilderJob struct {
|
|
| 42 |
- Engine *engine.Engine |
|
| 43 |
- Daemon *daemon.Daemon |
|
| 44 |
-} |
|
| 45 |
- |
|
| 46 | 41 |
type Config struct {
|
| 47 | 42 |
DockerfileName string |
| 48 | 43 |
RemoteURL string |
| ... | ... |
@@ -61,9 +54,8 @@ type Config struct {
|
| 61 | 61 |
AuthConfig *registry.AuthConfig |
| 62 | 62 |
ConfigFile *registry.ConfigFile |
| 63 | 63 |
|
| 64 |
- Stdout *engine.Output |
|
| 65 |
- Stderr *engine.Output |
|
| 66 |
- Stdin *engine.Input |
|
| 64 |
+ Stdout io.Writer |
|
| 65 |
+ Context io.ReadCloser |
|
| 67 | 66 |
// When closed, the job has been cancelled. |
| 68 | 67 |
// Note: not all jobs implement cancellation. |
| 69 | 68 |
// See Job.Cancel() and Job.WaitCancelled() |
| ... | ... |
@@ -83,24 +75,15 @@ func (b *Config) WaitCancelled() <-chan struct{} {
|
| 83 | 83 |
return b.cancelled |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
-func NewBuildConfig(logging bool, err io.Writer) *Config {
|
|
| 87 |
- c := &Config{
|
|
| 88 |
- Stdout: engine.NewOutput(), |
|
| 89 |
- Stderr: engine.NewOutput(), |
|
| 90 |
- Stdin: engine.NewInput(), |
|
| 91 |
- cancelled: make(chan struct{}),
|
|
| 86 |
+func NewBuildConfig() *Config {
|
|
| 87 |
+ return &Config{
|
|
| 88 |
+ AuthConfig: ®istry.AuthConfig{},
|
|
| 89 |
+ ConfigFile: ®istry.ConfigFile{},
|
|
| 90 |
+ cancelled: make(chan struct{}),
|
|
| 92 | 91 |
} |
| 93 |
- if logging {
|
|
| 94 |
- c.Stderr.Add(ioutils.NopWriteCloser(err)) |
|
| 95 |
- } |
|
| 96 |
- return c |
|
| 97 |
-} |
|
| 98 |
- |
|
| 99 |
-func (b *BuilderJob) Install() {
|
|
| 100 |
- b.Engine.Register("build_config", b.CmdBuildConfig)
|
|
| 101 | 92 |
} |
| 102 | 93 |
|
| 103 |
-func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
|
|
| 94 |
+func Build(d *daemon.Daemon, e *engine.Engine, buildConfig *Config) error {
|
|
| 104 | 95 |
var ( |
| 105 | 96 |
repoName string |
| 106 | 97 |
tag string |
| ... | ... |
@@ -109,7 +92,7 @@ func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
|
| 109 | 109 |
|
| 110 | 110 |
repoName, tag = parsers.ParseRepositoryTag(buildConfig.RepoName) |
| 111 | 111 |
if repoName != "" {
|
| 112 |
- if err := registry.ValidateRepositoryName(buildConfig.RepoName); err != nil {
|
|
| 112 |
+ if err := registry.ValidateRepositoryName(repoName); err != nil {
|
|
| 113 | 113 |
return err |
| 114 | 114 |
} |
| 115 | 115 |
if len(tag) > 0 {
|
| ... | ... |
@@ -120,7 +103,7 @@ func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
|
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
if buildConfig.RemoteURL == "" {
|
| 123 |
- context = ioutil.NopCloser(buildConfig.Stdin) |
|
| 123 |
+ context = ioutil.NopCloser(buildConfig.Context) |
|
| 124 | 124 |
} else if urlutil.IsGitURL(buildConfig.RemoteURL) {
|
| 125 | 125 |
if !urlutil.IsGitTransport(buildConfig.RemoteURL) {
|
| 126 | 126 |
buildConfig.RemoteURL = "https://" + buildConfig.RemoteURL |
| ... | ... |
@@ -166,8 +149,8 @@ func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
|
| 166 | 166 |
sf := streamformatter.NewStreamFormatter(buildConfig.JSONFormat) |
| 167 | 167 |
|
| 168 | 168 |
builder := &Builder{
|
| 169 |
- Daemon: b.Daemon, |
|
| 170 |
- Engine: b.Engine, |
|
| 169 |
+ Daemon: d, |
|
| 170 |
+ Engine: e, |
|
| 171 | 171 |
OutStream: &streamformatter.StdoutFormater{
|
| 172 | 172 |
Writer: buildConfig.Stdout, |
| 173 | 173 |
StreamFormatter: sf, |
| ... | ... |
@@ -200,41 +183,28 @@ func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
|
| 200 | 200 |
} |
| 201 | 201 |
|
| 202 | 202 |
if repoName != "" {
|
| 203 |
- b.Daemon.Repositories().Tag(repoName, tag, id, true) |
|
| 203 |
+ return d.Repositories().Tag(repoName, tag, id, true) |
|
| 204 | 204 |
} |
| 205 | 205 |
return nil |
| 206 | 206 |
} |
| 207 | 207 |
|
| 208 |
-func (b *BuilderJob) CmdBuildConfig(job *engine.Job) error {
|
|
| 209 |
- if len(job.Args) != 0 {
|
|
| 210 |
- return fmt.Errorf("Usage: %s\n", job.Name)
|
|
| 211 |
- } |
|
| 212 |
- |
|
| 213 |
- var ( |
|
| 214 |
- changes = job.GetenvList("changes")
|
|
| 215 |
- newConfig runconfig.Config |
|
| 216 |
- ) |
|
| 217 |
- |
|
| 218 |
- if err := job.GetenvJson("config", &newConfig); err != nil {
|
|
| 219 |
- return err |
|
| 220 |
- } |
|
| 221 |
- |
|
| 208 |
+func BuildFromConfig(d *daemon.Daemon, e *engine.Engine, c *runconfig.Config, changes []string) (*runconfig.Config, error) {
|
|
| 222 | 209 |
ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n"))) |
| 223 | 210 |
if err != nil {
|
| 224 |
- return err |
|
| 211 |
+ return nil, err |
|
| 225 | 212 |
} |
| 226 | 213 |
|
| 227 | 214 |
// ensure that the commands are valid |
| 228 | 215 |
for _, n := range ast.Children {
|
| 229 | 216 |
if !validCommitCommands[n.Value] {
|
| 230 |
- return fmt.Errorf("%s is not a valid change command", n.Value)
|
|
| 217 |
+ return nil, fmt.Errorf("%s is not a valid change command", n.Value)
|
|
| 231 | 218 |
} |
| 232 | 219 |
} |
| 233 | 220 |
|
| 234 | 221 |
builder := &Builder{
|
| 235 |
- Daemon: b.Daemon, |
|
| 236 |
- Engine: b.Engine, |
|
| 237 |
- Config: &newConfig, |
|
| 222 |
+ Daemon: d, |
|
| 223 |
+ Engine: e, |
|
| 224 |
+ Config: c, |
|
| 238 | 225 |
OutStream: ioutil.Discard, |
| 239 | 226 |
ErrStream: ioutil.Discard, |
| 240 | 227 |
disableCommit: true, |
| ... | ... |
@@ -242,12 +212,32 @@ func (b *BuilderJob) CmdBuildConfig(job *engine.Job) error {
|
| 242 | 242 |
|
| 243 | 243 |
for i, n := range ast.Children {
|
| 244 | 244 |
if err := builder.dispatch(i, n); err != nil {
|
| 245 |
- return err |
|
| 245 |
+ return nil, err |
|
| 246 | 246 |
} |
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 |
- if err := json.NewEncoder(job.Stdout).Encode(builder.Config); err != nil {
|
|
| 250 |
- return err |
|
| 249 |
+ return builder.Config, nil |
|
| 250 |
+} |
|
| 251 |
+ |
|
| 252 |
+func Commit(d *daemon.Daemon, eng *engine.Engine, name string, c *daemon.ContainerCommitConfig) (string, error) {
|
|
| 253 |
+ container, err := d.Get(name) |
|
| 254 |
+ if err != nil {
|
|
| 255 |
+ return "", err |
|
| 251 | 256 |
} |
| 252 |
- return nil |
|
| 257 |
+ |
|
| 258 |
+ newConfig, err := BuildFromConfig(d, eng, c.Config, c.Changes) |
|
| 259 |
+ if err != nil {
|
|
| 260 |
+ return "", err |
|
| 261 |
+ } |
|
| 262 |
+ |
|
| 263 |
+ if err := runconfig.Merge(newConfig, container.Config); err != nil {
|
|
| 264 |
+ return "", err |
|
| 265 |
+ } |
|
| 266 |
+ |
|
| 267 |
+ img, err := d.Commit(container, c.Repo, c.Tag, c.Comment, c.Author, c.Pause, newConfig) |
|
| 268 |
+ if err != nil {
|
|
| 269 |
+ return "", err |
|
| 270 |
+ } |
|
| 271 |
+ |
|
| 272 |
+ return img.ID, nil |
|
| 253 | 273 |
} |
| ... | ... |
@@ -1,12 +1,6 @@ |
| 1 | 1 |
package daemon |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "bytes" |
|
| 5 |
- "encoding/json" |
|
| 6 |
- "io" |
|
| 7 |
- |
|
| 8 |
- "github.com/Sirupsen/logrus" |
|
| 9 |
- "github.com/docker/docker/engine" |
|
| 10 | 4 |
"github.com/docker/docker/image" |
| 11 | 5 |
"github.com/docker/docker/runconfig" |
| 12 | 6 |
) |
| ... | ... |
@@ -18,49 +12,7 @@ type ContainerCommitConfig struct {
|
| 18 | 18 |
Author string |
| 19 | 19 |
Comment string |
| 20 | 20 |
Changes []string |
| 21 |
- Config io.ReadCloser |
|
| 22 |
-} |
|
| 23 |
- |
|
| 24 |
-func (daemon *Daemon) ContainerCommit(name string, c *ContainerCommitConfig) (string, error) {
|
|
| 25 |
- container, err := daemon.Get(name) |
|
| 26 |
- if err != nil {
|
|
| 27 |
- return "", err |
|
| 28 |
- } |
|
| 29 |
- |
|
| 30 |
- var ( |
|
| 31 |
- subenv engine.Env |
|
| 32 |
- config = container.Config |
|
| 33 |
- stdoutBuffer = bytes.NewBuffer(nil) |
|
| 34 |
- newConfig runconfig.Config |
|
| 35 |
- ) |
|
| 36 |
- |
|
| 37 |
- if err := subenv.Decode(c.Config); err != nil {
|
|
| 38 |
- logrus.Errorf("%s", err)
|
|
| 39 |
- } |
|
| 40 |
- |
|
| 41 |
- buildConfigJob := daemon.eng.Job("build_config")
|
|
| 42 |
- buildConfigJob.Stdout.Add(stdoutBuffer) |
|
| 43 |
- buildConfigJob.SetenvList("changes", c.Changes)
|
|
| 44 |
- // FIXME this should be remove when we remove deprecated config param |
|
| 45 |
- buildConfigJob.SetenvSubEnv("config", &subenv)
|
|
| 46 |
- |
|
| 47 |
- if err := buildConfigJob.Run(); err != nil {
|
|
| 48 |
- return "", err |
|
| 49 |
- } |
|
| 50 |
- if err := json.NewDecoder(stdoutBuffer).Decode(&newConfig); err != nil {
|
|
| 51 |
- return "", err |
|
| 52 |
- } |
|
| 53 |
- |
|
| 54 |
- if err := runconfig.Merge(&newConfig, config); err != nil {
|
|
| 55 |
- return "", err |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- img, err := daemon.Commit(container, c.Repo, c.Tag, c.Comment, c.Author, c.Pause, &newConfig) |
|
| 59 |
- if err != nil {
|
|
| 60 |
- return "", err |
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- return img.ID, nil |
|
| 21 |
+ Config *runconfig.Config |
|
| 64 | 22 |
} |
| 65 | 23 |
|
| 66 | 24 |
// Commit creates a new filesystem image from the current state of a container. |
| ... | ... |
@@ -11,7 +11,6 @@ import ( |
| 11 | 11 |
"github.com/Sirupsen/logrus" |
| 12 | 12 |
apiserver "github.com/docker/docker/api/server" |
| 13 | 13 |
"github.com/docker/docker/autogen/dockerversion" |
| 14 |
- "github.com/docker/docker/builder" |
|
| 15 | 14 |
"github.com/docker/docker/daemon" |
| 16 | 15 |
_ "github.com/docker/docker/daemon/execdriver/lxc" |
| 17 | 16 |
_ "github.com/docker/docker/daemon/execdriver/native" |
| ... | ... |
@@ -141,9 +140,6 @@ func mainDaemon() {
|
| 141 | 141 |
"graphdriver": d.GraphDriver().String(), |
| 142 | 142 |
}).Info("Docker daemon")
|
| 143 | 143 |
|
| 144 |
- b := &builder.BuilderJob{eng, d}
|
|
| 145 |
- b.Install() |
|
| 146 |
- |
|
| 147 | 144 |
// after the daemon is done setting up we can tell the api to start |
| 148 | 145 |
// accepting connections with specified daemon |
| 149 | 146 |
api.AcceptConnections(d) |
| ... | ... |
@@ -155,7 +151,6 @@ func mainDaemon() {
|
| 155 | 155 |
if errAPI != nil {
|
| 156 | 156 |
logrus.Fatalf("Shutting down due to ServeAPI error: %v", errAPI)
|
| 157 | 157 |
} |
| 158 |
- |
|
| 159 | 158 |
} |
| 160 | 159 |
|
| 161 | 160 |
// currentUserIsOwner checks whether the current user is the owner of the given |
| ... | ... |
@@ -1,13 +1,10 @@ |
| 1 | 1 |
package graph |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "bytes" |
|
| 5 |
- "encoding/json" |
|
| 6 | 4 |
"io" |
| 7 | 5 |
"net/http" |
| 8 | 6 |
"net/url" |
| 9 | 7 |
|
| 10 |
- "github.com/docker/docker/engine" |
|
| 11 | 8 |
"github.com/docker/docker/pkg/archive" |
| 12 | 9 |
"github.com/docker/docker/pkg/httputils" |
| 13 | 10 |
"github.com/docker/docker/pkg/progressreader" |
| ... | ... |
@@ -17,20 +14,18 @@ import ( |
| 17 | 17 |
) |
| 18 | 18 |
|
| 19 | 19 |
type ImageImportConfig struct {
|
| 20 |
- Changes []string |
|
| 21 |
- InConfig io.ReadCloser |
|
| 22 |
- Json bool |
|
| 23 |
- OutStream io.Writer |
|
| 24 |
- //OutStream WriteFlusher |
|
| 20 |
+ Changes []string |
|
| 21 |
+ InConfig io.ReadCloser |
|
| 22 |
+ Json bool |
|
| 23 |
+ OutStream io.Writer |
|
| 24 |
+ ContainerConfig *runconfig.Config |
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 |
-func (s *TagStore) Import(src string, repo string, tag string, imageImportConfig *ImageImportConfig, eng *engine.Engine) error {
|
|
| 27 |
+func (s *TagStore) Import(src string, repo string, tag string, imageImportConfig *ImageImportConfig) error {
|
|
| 28 | 28 |
var ( |
| 29 |
- sf = streamformatter.NewStreamFormatter(imageImportConfig.Json) |
|
| 30 |
- archive archive.ArchiveReader |
|
| 31 |
- resp *http.Response |
|
| 32 |
- stdoutBuffer = bytes.NewBuffer(nil) |
|
| 33 |
- newConfig runconfig.Config |
|
| 29 |
+ sf = streamformatter.NewStreamFormatter(imageImportConfig.Json) |
|
| 30 |
+ archive archive.ArchiveReader |
|
| 31 |
+ resp *http.Response |
|
| 34 | 32 |
) |
| 35 | 33 |
|
| 36 | 34 |
if src == "-" {
|
| ... | ... |
@@ -63,20 +58,7 @@ func (s *TagStore) Import(src string, repo string, tag string, imageImportConfig |
| 63 | 63 |
archive = progressReader |
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 |
- buildConfigJob := eng.Job("build_config")
|
|
| 67 |
- buildConfigJob.Stdout.Add(stdoutBuffer) |
|
| 68 |
- buildConfigJob.SetenvList("changes", imageImportConfig.Changes)
|
|
| 69 |
- // FIXME this should be remove when we remove deprecated config param |
|
| 70 |
- //buildConfigJob.Setenv("config", job.Getenv("config"))
|
|
| 71 |
- |
|
| 72 |
- if err := buildConfigJob.Run(); err != nil {
|
|
| 73 |
- return err |
|
| 74 |
- } |
|
| 75 |
- if err := json.NewDecoder(stdoutBuffer).Decode(&newConfig); err != nil {
|
|
| 76 |
- return err |
|
| 77 |
- } |
|
| 78 |
- |
|
| 79 |
- img, err := s.graph.Create(archive, "", "", "Imported from "+src, "", nil, &newConfig) |
|
| 66 |
+ img, err := s.graph.Create(archive, "", "", "Imported from "+src, "", nil, imageImportConfig.ContainerConfig) |
|
| 80 | 67 |
if err != nil {
|
| 81 | 68 |
return err |
| 82 | 69 |
} |