Merge pull request #1825 from dotcloud/merge-builder-runtime

Refactor to merge builder.go into runtime.go
This commit is contained in:
Solomon Hykes 2013-09-09 15:11:41 -07:00
Родитель 8ddfb4d6aa eca861a99d
Коммит e503f6a878
8 изменённых файлов: 203 добавлений и 237 удалений

Просмотреть файл

@ -321,7 +321,7 @@ func TestGetContainersJSON(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "test"},
})
@ -357,10 +357,8 @@ func TestGetContainersExport(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"touch", "/test"},
@ -409,10 +407,8 @@ func TestGetContainersChanges(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/rm", "/etc/passwd"},
@ -458,9 +454,7 @@ func TestGetContainersTop(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/sh", "-c", "cat"},
@ -541,10 +535,8 @@ func TestGetContainersByName(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "test"},
@ -574,10 +566,9 @@ func TestPostCommit(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"touch", "/test"},
@ -671,7 +662,7 @@ func TestPostContainersKill(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/cat"},
@ -713,7 +704,7 @@ func TestPostContainersRestart(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/cat"},
@ -767,7 +758,7 @@ func TestPostContainersStart(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/cat"},
@ -817,7 +808,7 @@ func TestPostContainersStop(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/cat"},
@ -864,7 +855,7 @@ func TestPostContainersWait(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/sleep", "1"},
@ -906,7 +897,7 @@ func TestPostContainersAttach(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/cat"},
@ -998,7 +989,7 @@ func TestDeleteContainers(t *testing.T) {
srv := &Server{runtime: runtime}
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"touch", "/test"},
})
@ -1185,10 +1176,8 @@ func TestPostContainersCopy(t *testing.T) {
srv := &Server{runtime: runtime}
builder := NewBuilder(runtime)
// Create a container and remove a file
container, err := builder.Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"touch", "/test.txt"},

Просмотреть файл

@ -1,154 +0,0 @@
package docker
import (
"fmt"
"github.com/dotcloud/docker/utils"
"os"
"path"
"time"
)
var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
type Builder struct {
runtime *Runtime
repositories *TagStore
graph *Graph
config *Config
image *Image
}
func NewBuilder(runtime *Runtime) *Builder {
return &Builder{
runtime: runtime,
graph: runtime.graph,
repositories: runtime.repositories,
}
}
func (builder *Builder) Create(config *Config) (*Container, error) {
// Lookup image
img, err := builder.repositories.LookupImage(config.Image)
if err != nil {
return nil, err
}
if img.Config != nil {
MergeConfig(config, img.Config)
}
if len(config.Entrypoint) != 0 && config.Cmd == nil {
config.Cmd = []string{}
} else if config.Cmd == nil || len(config.Cmd) == 0 {
return nil, fmt.Errorf("No command 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]
}
var args []string
var entrypoint string
if len(config.Entrypoint) != 0 {
entrypoint = config.Entrypoint[0]
args = append(config.Entrypoint[1:], config.Cmd...)
} else {
entrypoint = config.Cmd[0]
args = config.Cmd[1:]
}
container := &Container{
// FIXME: we should generate the ID here instead of receiving it as an argument
ID: id,
Created: time.Now(),
Path: entrypoint,
Args: args, //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
}
resolvConf, err := utils.GetResolvConf()
if err != nil {
return nil, err
}
if len(config.Dns) == 0 && len(builder.runtime.Dns) == 0 && utils.CheckLocalDns(resolvConf) {
//"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns
builder.runtime.Dns = defaultDns
}
// If custom dns exists, then create a resolv.conf for the container
if len(config.Dns) > 0 || len(builder.runtime.Dns) > 0 {
var dns []string
if len(config.Dns) > 0 {
dns = config.Dns
} else {
dns = builder.runtime.Dns
}
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 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
}
// Step 3: register the container
if err := builder.runtime.Register(container); err != nil {
return nil, err
}
return container, nil
}
// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (builder *Builder) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
// FIXME: freeze the container before copying it to avoid data corruption?
// FIXME: this shouldn't be in commands.
if err := container.EnsureMounted(); err != nil {
return nil, err
}
rwTar, err := container.ExportRw()
if err != nil {
return nil, err
}
// Create a new image from the container's base layers + a new layer from container changes
img, err := builder.graph.Create(rwTar, container, comment, author, config)
if err != nil {
return nil, err
}
// Register the image if needed
if repository != "" {
if err := builder.repositories.Set(repository, tag, img.ID, true); err != nil {
return img, err
}
}
return img, nil
}

Просмотреть файл

@ -23,7 +23,6 @@ type BuildFile interface {
type buildFile struct {
runtime *Runtime
builder *Builder
srv *Server
image string
@ -337,7 +336,7 @@ func (b *buildFile) CmdAdd(args string) error {
b.config.Image = b.image
// Create the container and start it
container, err := b.builder.Create(b.config)
container, err := b.runtime.Create(b.config)
if err != nil {
return err
}
@ -372,7 +371,7 @@ func (b *buildFile) run() (string, error) {
b.config.Image = b.image
// Create the container and start it
c, err := b.builder.Create(b.config)
c, err := b.runtime.Create(b.config)
if err != nil {
return "", err
}
@ -428,7 +427,7 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
}
}
container, err := b.builder.Create(b.config)
container, err := b.runtime.Create(b.config)
if err != nil {
return err
}
@ -450,7 +449,7 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
autoConfig := *b.config
autoConfig.Cmd = autoCmd
// Commit the container
image, err := b.builder.Commit(container, "", "", "", b.maintainer, &autoConfig)
image, err := b.runtime.Commit(container, "", "", "", b.maintainer, &autoConfig)
if err != nil {
return err
}
@ -524,7 +523,6 @@ func (b *buildFile) Build(context io.Reader) (string, error) {
func NewBuildFile(srv *Server, out io.Writer, verbose, utilizeCache bool) BuildFile {
return &buildFile{
builder: NewBuilder(srv.runtime),
runtime: srv.runtime,
srv: srv,
config: &Config{},

Просмотреть файл

@ -18,7 +18,7 @@ import (
func TestIDFormat(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container1, err := NewBuilder(runtime).Create(
container1, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/sh", "-c", "echo hello world"},
@ -388,7 +388,7 @@ func TestRun(t *testing.T) {
func TestOutput(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"},
@ -411,7 +411,7 @@ func TestKillDifferentUser(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"},
OpenStdin: true,
@ -471,7 +471,7 @@ func TestCreateVolume(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := NewBuilder(runtime).Create(config)
c, err := runtime.Create(config)
if err != nil {
t.Fatal(err)
}
@ -486,7 +486,7 @@ func TestCreateVolume(t *testing.T) {
func TestKill(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"},
},
@ -530,9 +530,7 @@ func TestExitCode(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
builder := NewBuilder(runtime)
trueContainer, err := builder.Create(&Config{
trueContainer, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true", ""},
})
@ -547,7 +545,7 @@ func TestExitCode(t *testing.T) {
t.Errorf("Unexpected exit code %d (expected 0)", trueContainer.State.ExitCode)
}
falseContainer, err := builder.Create(&Config{
falseContainer, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/false", ""},
})
@ -566,7 +564,7 @@ func TestExitCode(t *testing.T) {
func TestRestart(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"},
},
@ -596,7 +594,7 @@ func TestRestart(t *testing.T) {
func TestRestartStdin(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"},
@ -673,10 +671,8 @@ func TestUser(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
builder := NewBuilder(runtime)
// Default user must be root
container, err := builder.Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
},
@ -694,7 +690,7 @@ func TestUser(t *testing.T) {
}
// Set a username
container, err = builder.Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
@ -714,7 +710,7 @@ func TestUser(t *testing.T) {
}
// Set a UID
container, err = builder.Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
@ -734,7 +730,7 @@ func TestUser(t *testing.T) {
}
// Set a different user by uid
container, err = builder.Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
@ -756,7 +752,7 @@ func TestUser(t *testing.T) {
}
// Set a different user by username
container, err = builder.Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
@ -776,7 +772,7 @@ func TestUser(t *testing.T) {
}
// Test an wrong username
container, err = builder.Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"id"},
@ -797,9 +793,7 @@ func TestMultipleContainers(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
builder := NewBuilder(runtime)
container1, err := builder.Create(&Config{
container1, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"},
},
@ -809,7 +803,7 @@ func TestMultipleContainers(t *testing.T) {
}
defer runtime.Destroy(container1)
container2, err := builder.Create(&Config{
container2, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"sleep", "2"},
},
@ -853,7 +847,7 @@ func TestMultipleContainers(t *testing.T) {
func TestStdin(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"},
@ -898,7 +892,7 @@ func TestStdin(t *testing.T) {
func TestTty(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"cat"},
@ -943,7 +937,7 @@ func TestTty(t *testing.T) {
func TestEnv(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"env"},
},
@ -992,7 +986,7 @@ func TestEnv(t *testing.T) {
func TestEntrypoint(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Entrypoint: []string{"/bin/echo"},
@ -1015,7 +1009,7 @@ func TestEntrypoint(t *testing.T) {
func TestEntrypointNoCmd(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Entrypoint: []string{"/bin/echo", "foobar"},
@ -1066,7 +1060,7 @@ func TestLXCConfig(t *testing.T) {
cpuMin := 100
cpuMax := 10000
cpu := cpuMin + rand.Intn(cpuMax-cpuMin)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true"},
@ -1090,7 +1084,7 @@ func TestLXCConfig(t *testing.T) {
func TestCustomLxcConfig(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/true"},
@ -1121,7 +1115,7 @@ func BenchmarkRunSequencial(b *testing.B) {
runtime := mkRuntime(b)
defer nuke(runtime)
for i := 0; i < b.N; i++ {
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foo"},
},
@ -1153,7 +1147,7 @@ func BenchmarkRunParallel(b *testing.B) {
complete := make(chan error)
tasks = append(tasks, complete)
go func(i int, complete chan error) {
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foo"},
},
@ -1229,7 +1223,7 @@ func TestBindMounts(t *testing.T) {
func TestVolumesFromReadonlyMount(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(
container, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"},
@ -1248,7 +1242,7 @@ func TestVolumesFromReadonlyMount(t *testing.T) {
t.Fail()
}
container2, err := NewBuilder(runtime).Create(
container2, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"/bin/echo", "-n", "foobar"},
@ -1284,7 +1278,7 @@ func TestRestartWithVolumes(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"echo", "-n", "foobar"},
Volumes: map[string]struct{}{"/test": {}},
@ -1327,7 +1321,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", "echo -n bar > /test/foo"},
Volumes: map[string]struct{}{"/test": {}},
@ -1354,7 +1348,7 @@ func TestVolumesFromWithVolumes(t *testing.T) {
t.Fail()
}
container2, err := NewBuilder(runtime).Create(
container2, err := runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"cat", "/test/foo"},
@ -1395,7 +1389,7 @@ func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
if err != nil {
t.Fatal(err)
}
c, err := NewBuilder(runtime).Create(config)
c, err := runtime.Create(config)
if err != nil {
t.Fatal(err)
}

Просмотреть файл

@ -12,8 +12,11 @@ import (
"path"
"sort"
"strings"
"time"
)
var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
type Capabilities struct {
MemoryLimit bool
SwapLimit bool
@ -42,6 +45,7 @@ func init() {
sysInitPath = utils.SelfPath()
}
// List returns an array of all containers registered in the runtime.
func (runtime *Runtime) List() []*Container {
containers := new(History)
for e := runtime.containers.Front(); e != nil; e = e.Next() {
@ -60,6 +64,8 @@ func (runtime *Runtime) getContainerElement(id string) *list.Element {
return nil
}
// Get looks for a container by the specified ID or name, and returns it.
// If the container is not found, or if an error occurs, nil is returned.
func (runtime *Runtime) Get(name string) *Container {
id, err := runtime.idIndex.Get(name)
if err != nil {
@ -72,6 +78,8 @@ func (runtime *Runtime) Get(name string) *Container {
return e.Value.(*Container)
}
// Exists returns a true if a container of the specified ID or name exists,
// false otherwise.
func (runtime *Runtime) Exists(id string) bool {
return runtime.Get(id) != nil
}
@ -80,6 +88,9 @@ func (runtime *Runtime) containerRoot(id string) string {
return path.Join(runtime.repository, id)
}
// Load reads the contents of a container from disk and registers
// it with Register.
// This is typically done at startup.
func (runtime *Runtime) Load(id string) (*Container, error) {
container := &Container{root: runtime.containerRoot(id)}
if err := container.FromDisk(); err != nil {
@ -177,6 +188,7 @@ func (runtime *Runtime) LogToDisk(src *utils.WriteBroadcaster, dst, stream strin
return nil
}
// Destroy unregisters a container from the runtime and cleanly removes its contents from the filesystem.
func (runtime *Runtime) Destroy(container *Container) error {
if container == nil {
return fmt.Errorf("The given container is <nil>")
@ -233,6 +245,7 @@ func (runtime *Runtime) restore() error {
return nil
}
// FIXME: comment please!
func (runtime *Runtime) UpdateCapabilities(quiet bool) {
if cgroupMemoryMountpoint, err := utils.FindCgroupMountpoint("memory"); err != nil {
if !quiet {
@ -260,6 +273,133 @@ func (runtime *Runtime) UpdateCapabilities(quiet bool) {
}
}
// Create creates a new container from the given configuration.
func (runtime *Runtime) Create(config *Config) (*Container, error) {
// Lookup image
img, err := runtime.repositories.LookupImage(config.Image)
if err != nil {
return nil, err
}
if img.Config != nil {
MergeConfig(config, img.Config)
}
if len(config.Entrypoint) != 0 && config.Cmd == nil {
config.Cmd = []string{}
} else if config.Cmd == nil || len(config.Cmd) == 0 {
return nil, fmt.Errorf("No command 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]
}
var args []string
var entrypoint string
if len(config.Entrypoint) != 0 {
entrypoint = config.Entrypoint[0]
args = append(config.Entrypoint[1:], config.Cmd...)
} else {
entrypoint = config.Cmd[0]
args = config.Cmd[1:]
}
container := &Container{
// FIXME: we should generate the ID here instead of receiving it as an argument
ID: id,
Created: time.Now(),
Path: entrypoint,
Args: args, //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 = 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
}
resolvConf, err := utils.GetResolvConf()
if err != nil {
return nil, err
}
if len(config.Dns) == 0 && len(runtime.Dns) == 0 && utils.CheckLocalDns(resolvConf) {
//"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns
runtime.Dns = defaultDns
}
// If custom dns exists, then create a resolv.conf for the container
if len(config.Dns) > 0 || len(runtime.Dns) > 0 {
var dns []string
if len(config.Dns) > 0 {
dns = config.Dns
} else {
dns = runtime.Dns
}
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 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
}
// Step 3: register the container
if err := runtime.Register(container); err != nil {
return nil, err
}
return container, nil
}
// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (runtime *Runtime) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
// FIXME: freeze the container before copying it to avoid data corruption?
// FIXME: this shouldn't be in commands.
if err := container.EnsureMounted(); err != nil {
return nil, err
}
rwTar, err := container.ExportRw()
if err != nil {
return nil, err
}
// Create a new image from the container's base layers + a new layer from container changes
img, err := runtime.graph.Create(rwTar, container, comment, author, config)
if err != nil {
return nil, err
}
// Register the image if needed
if repository != "" {
if err := runtime.repositories.Set(repository, tag, img.ID, true); err != nil {
return img, err
}
}
return img, nil
}
// FIXME: harmonize with NewGraph()
func NewRuntime(flGraphPath string, autoRestart bool, dns []string) (*Runtime, error) {
runtime, err := NewRuntimeFromDirectory(flGraphPath, autoRestart)
@ -325,6 +465,8 @@ func NewRuntimeFromDirectory(root string, autoRestart bool) (*Runtime, error) {
return runtime, nil
}
// History is a convenience type for storing a list of containers,
// ordered by creation date.
type History []*Container
func (history *History) Len() int {
@ -347,3 +489,4 @@ func (history *History) Add(container *Container) {
*history = append(*history, container)
sort.Sort(history)
}

Просмотреть файл

@ -144,9 +144,7 @@ func TestRuntimeCreate(t *testing.T) {
t.Errorf("Expected 0 containers, %v found", len(runtime.List()))
}
builder := NewBuilder(runtime)
container, err := builder.Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"ls", "-al"},
},
@ -187,7 +185,7 @@ func TestRuntimeCreate(t *testing.T) {
}
// Make sure crete with bad parameters returns an error
_, err = builder.Create(
_, err = runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
},
@ -196,7 +194,7 @@ func TestRuntimeCreate(t *testing.T) {
t.Fatal("Builder.Create should throw an error when Cmd is missing")
}
_, err = builder.Create(
_, err = runtime.Create(
&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{},
@ -210,7 +208,7 @@ func TestRuntimeCreate(t *testing.T) {
func TestDestroy(t *testing.T) {
runtime := mkRuntime(t)
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(&Config{
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"ls", "-al"},
},
@ -296,7 +294,7 @@ func startEchoServerContainer(t *testing.T, proto string) (*Runtime, *Container,
t.Fatal(fmt.Errorf("Unknown protocol %v", proto))
}
t.Log("Trying port", strPort)
container, err = NewBuilder(runtime).Create(&Config{
container, err = runtime.Create(&Config{
Image: GetTestImage(runtime).ID,
Cmd: []string{"sh", "-c", cmd},
PortSpecs: []string{fmt.Sprintf("%s/%s", strPort, proto)},

Просмотреть файл

@ -139,8 +139,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.
return "", err
}
b := NewBuilder(srv.runtime)
c, err := b.Create(config)
c, err := srv.runtime.Create(config)
if err != nil {
return "", err
}
@ -149,7 +148,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.
return "", err
}
// FIXME: Handle custom repo, tag comment, author
img, err = b.Commit(c, "", "", img.Comment, img.Author, nil)
img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil)
if err != nil {
return "", err
}
@ -400,7 +399,7 @@ func (srv *Server) ContainerCommit(name, repo, tag, author, comment string, conf
if container == nil {
return "", fmt.Errorf("No such container: %s", name)
}
img, err := NewBuilder(srv.runtime).Commit(container, repo, tag, comment, author, config)
img, err := srv.runtime.Commit(container, repo, tag, comment, author, config)
if err != nil {
return "", err
}
@ -915,8 +914,7 @@ func (srv *Server) ContainerCreate(config *Config) (string, error) {
if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit {
config.MemorySwap = -1
}
b := NewBuilder(srv.runtime)
container, err := b.Create(config)
container, err := srv.runtime.Create(config)
if err != nil {
if srv.runtime.graph.IsNotExist(err) {

Просмотреть файл

@ -101,7 +101,7 @@ func mkContainer(r *Runtime, args []string, t *testing.T) (*Container, *HostConf
if config.Image == "_" {
config.Image = GetTestImage(r).ID
}
c, err := NewBuilder(r).Create(config)
c, err := r.Create(config)
if err != nil {
return nil, nil, err
}