Procházet zdrojové kódy

Moving runtime.Create to builder.Create

Guillaume J. Charmes před 12 roky
rodič
revize
6f2125386a
3 změnil soubory, kde provedl 90 přidání a 23 odebrání
  1. 79 17
      builder.go
  2. 10 3
      commands.go
  3. 1 3
      runtime.go

+ 79 - 17
builder.go

@@ -4,38 +4,80 @@ import (
 	"bufio"
 	"fmt"
 	"io"
+	"os"
+	"path"
 	"strings"
+	"time"
 )
 
 type Builder struct {
-	runtime *Runtime
+	runtime      *Runtime
+	repositories *TagStore
 }
 
 func NewBuilder(runtime *Runtime) *Builder {
 	return &Builder{
-		runtime: runtime,
+		runtime:      runtime,
+		repositories: runtime.repositories,
 	}
 }
 
-func (builder *Builder) Run(image *Image, cmd ...string) (*Container, error) {
-	// FIXME: pass a NopWriter instead of nil
-	config, err := ParseRun(append([]string{"-d", image.Id}, cmd...), nil, builder.runtime.capabilities)
-	if config.Image == "" {
-		return nil, fmt.Errorf("Image not specified")
+func (builder *Builder) Create(config *Config) (*Container, error) {
+	// Lookup image
+	img, err := builder.repositories.LookupImage(config.Image)
+	if err != nil {
+		return nil, err
 	}
-	if len(config.Cmd) == 0 {
-		return nil, fmt.Errorf("Command not specified")
+	// Generate id
+	id := GenerateId()
+	// Generate default hostname
+	// FIXME: the lxc template no longer needs to set a default hostname
+	if config.Hostname == "" {
+		config.Hostname = id[:12]
 	}
-	if config.Tty {
-		return nil, fmt.Errorf("The tty mode is not supported within the builder")
+
+	container := &Container{
+		// FIXME: we should generate the ID here instead of receiving it as an argument
+		Id:              id,
+		Created:         time.Now(),
+		Path:            config.Cmd[0],
+		Args:            config.Cmd[1:], //FIXME: de-duplicate from config
+		Config:          config,
+		Image:           img.Id, // Always use the resolved image id
+		NetworkSettings: &NetworkSettings{},
+		// FIXME: do we need to store this in the container?
+		SysInitPath: sysInitPath,
+	}
+	container.root = builder.runtime.containerRoot(container.Id)
+	// Step 1: create the container directory.
+	// This doubles as a barrier to avoid race conditions.
+	if err := os.Mkdir(container.root, 0700); err != nil {
+		return nil, err
 	}
 
-	// Create new container
-	container, err := builder.runtime.Create(config)
-	if err != nil {
+	// If custom dns exists, then create a resolv.conf for the container
+	if len(config.Dns) > 0 {
+		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
+		f, err := os.Create(container.ResolvConfPath)
+		if err != nil {
+			return nil, err
+		}
+		defer f.Close()
+		for _, dns := range config.Dns {
+			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
+				return nil, err
+			}
+		}
+	} else {
+		container.ResolvConfPath = "/etc/resolv.conf"
+	}
+
+	// Step 2: save the container json
+	if err := container.ToDisk(); err != nil {
 		return nil, err
 	}
-	if err := container.Start(); err != nil {
+	// Step 3: register the container
+	if err := builder.runtime.Register(container); err != nil {
 		return nil, err
 	}
 	return container, nil
@@ -96,12 +138,19 @@ func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) error {
 			if image == nil {
 				return fmt.Errorf("Please provide a source image with `from` prior to run")
 			}
+			config, err := ParseRun([]string{image.Id, "/bin/sh", "-c", tmp[1]}, nil, builder.runtime.capabilities)
+			if err != nil {
+				return err
+			}
 
 			// Create the container and start it
-			c, err := builder.Run(image, "/bin/sh", "-c", tmp[1])
+			c, err := builder.Create(config)
 			if err != nil {
 				return err
 			}
+			if err := c.Start(); err != nil {
+				return err
+			}
 			tmpContainers[c.Id] = struct{}{}
 
 			// Wait for it to finish
@@ -134,11 +183,24 @@ func (builder *Builder) Build(dockerfile io.Reader, stdout io.Writer) error {
 			}
 			defer file.Body.Close()
 
-			c, err := builder.Run(base, "echo", "insert", tmp2[0], tmp2[1])
+			config, err := ParseRun([]string{base.Id, "echo", "insert", tmp2[0], tmp2[1]}, nil, builder.runtime.capabilities)
+			if err != nil {
+				return err
+			}
+			c, err := builder.Create(config)
 			if err != nil {
 				return err
 			}
 
+			if err := c.Start(); err != nil {
+				return err
+			}
+
+			// Wait for echo to finish
+			if result := c.Wait(); result != 0 {
+				return fmt.Errorf("!!! '%s' return non-zero exit code '%d'. Aborting.", tmp[1], result)
+			}
+
 			if err := c.Inject(file.Body, tmp2[1]); err != nil {
 				return err
 			}

+ 10 - 3
commands.go

@@ -91,8 +91,13 @@ func (srv *Server) CmdInsert(stdin io.ReadCloser, stdout rcli.DockerConn, args .
 	}
 	defer file.Body.Close()
 
+	config, err := ParseRun([]string{img.Id, "echo", "insert", url, path}, nil, srv.runtime.capabilities)
+	if err != nil {
+		return err
+	}
+
 	b := NewBuilder(srv.runtime)
-	c, err := b.Run(img, "echo", "insert", url, path)
+	c, err := b.Create(config)
 	if err != nil {
 		return err
 	}
@@ -1065,8 +1070,10 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
 	// or tell the client there is no options
 	stdout.Flush()
 
+	b := NewBuilder(srv.runtime)
+
 	// Create new container
-	container, err := srv.runtime.Create(config)
+	container, err := b.Create(config)
 	if err != nil {
 		// If container not found, try to pull it
 		if srv.runtime.graph.IsNotExist(err) {
@@ -1074,7 +1081,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
 			if err = srv.CmdPull(stdin, stdout, config.Image); err != nil {
 				return err
 			}
-			if container, err = srv.runtime.Create(config); err != nil {
+			if container, err = b.Create(config); err != nil {
 				return err
 			}
 		} else {

+ 1 - 3
runtime.go

@@ -12,7 +12,6 @@ import (
 	"path"
 	"sort"
 	"strings"
-	"time"
 )
 
 type Capabilities struct {
@@ -116,7 +115,6 @@ func (runtime *Runtime) mergeConfig(userConf, imageConf *Config) {
 }
 
 func (runtime *Runtime) Create(config *Config) (*Container, error) {
-
 	// Lookup image
 	img, err := runtime.repositories.LookupImage(config.Image)
 	if err != nil {
@@ -151,7 +149,6 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
 		// FIXME: do we need to store this in the container?
 		SysInitPath: sysInitPath,
 	}
-
 	container.root = runtime.containerRoot(container.Id)
 	// Step 1: create the container directory.
 	// This doubles as a barrier to avoid race conditions.
@@ -187,6 +184,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
 	return container, nil
 }
 
+======= end
 func (runtime *Runtime) Load(id string) (*Container, error) {
 	container := &Container{root: runtime.containerRoot(id)}
 	if err := container.FromDisk(); err != nil {