Skip to content

Commit f7aaa06

Browse files
author
Solomon Hykes
committed
+ Commit default runtime options with a layer
2 parents a3ce90b + 7ff65d4 commit f7aaa06

6 files changed

Lines changed: 149 additions & 17 deletions

File tree

commands.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout rcli.DockerConn, args .
477477
}
478478
archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout, "Importing %v/%v (%v)")
479479
}
480-
img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "")
480+
img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
481481
if err != nil {
482482
return err
483483
}
@@ -726,6 +726,7 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
726726
"Create a new image from a container's changes")
727727
flComment := cmd.String("m", "", "Commit message")
728728
flAuthor := cmd.String("author", "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\"")
729+
flConfig := cmd.String("config", "", "Config automatically applied when the image is run. "+`(ex: -config '{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')`)
729730
if err := cmd.Parse(args); err != nil {
730731
return nil
731732
}
@@ -734,7 +735,15 @@ func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...stri
734735
cmd.Usage()
735736
return nil
736737
}
737-
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor)
738+
739+
config := &Config{}
740+
if *flConfig != "" {
741+
if err := json.Unmarshal([]byte(*flConfig), config); err != nil {
742+
return err
743+
}
744+
}
745+
746+
img, err := srv.runtime.Commit(containerName, repository, tag, *flComment, *flAuthor, config)
738747
if err != nil {
739748
return err
740749
}
@@ -925,10 +934,6 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
925934
fmt.Fprintln(stdout, "Error: Image not specified")
926935
return fmt.Errorf("Image not specified")
927936
}
928-
if len(config.Cmd) == 0 {
929-
fmt.Fprintln(stdout, "Error: Command not specified")
930-
return fmt.Errorf("Command not specified")
931-
}
932937

933938
if config.Tty {
934939
stdout.SetOptionRawTerminal()

container_test.go

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ func TestDiff(t *testing.T) {
184184
if err != nil {
185185
t.Error(err)
186186
}
187-
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "")
187+
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image - diff", "", nil)
188188
if err != nil {
189189
t.Error(err)
190190
}
@@ -217,6 +217,84 @@ func TestDiff(t *testing.T) {
217217
}
218218
}
219219

220+
func TestCommitAutoRun(t *testing.T) {
221+
runtime, err := newTestRuntime()
222+
if err != nil {
223+
t.Fatal(err)
224+
}
225+
defer nuke(runtime)
226+
container1, err := runtime.Create(
227+
&Config{
228+
Image: GetTestImage(runtime).Id,
229+
Cmd: []string{"/bin/sh", "-c", "echo hello > /world"},
230+
},
231+
)
232+
if err != nil {
233+
t.Fatal(err)
234+
}
235+
defer runtime.Destroy(container1)
236+
237+
if container1.State.Running {
238+
t.Errorf("Container shouldn't be running")
239+
}
240+
if err := container1.Run(); err != nil {
241+
t.Fatal(err)
242+
}
243+
if container1.State.Running {
244+
t.Errorf("Container shouldn't be running")
245+
}
246+
247+
rwTar, err := container1.ExportRw()
248+
if err != nil {
249+
t.Error(err)
250+
}
251+
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", &Config{Cmd: []string{"cat", "/world"}})
252+
if err != nil {
253+
t.Error(err)
254+
}
255+
256+
// FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world
257+
258+
container2, err := runtime.Create(
259+
&Config{
260+
Image: img.Id,
261+
},
262+
)
263+
if err != nil {
264+
t.Fatal(err)
265+
}
266+
defer runtime.Destroy(container2)
267+
stdout, err := container2.StdoutPipe()
268+
if err != nil {
269+
t.Fatal(err)
270+
}
271+
stderr, err := container2.StderrPipe()
272+
if err != nil {
273+
t.Fatal(err)
274+
}
275+
if err := container2.Start(); err != nil {
276+
t.Fatal(err)
277+
}
278+
container2.Wait()
279+
output, err := ioutil.ReadAll(stdout)
280+
if err != nil {
281+
t.Fatal(err)
282+
}
283+
output2, err := ioutil.ReadAll(stderr)
284+
if err != nil {
285+
t.Fatal(err)
286+
}
287+
if err := stdout.Close(); err != nil {
288+
t.Fatal(err)
289+
}
290+
if err := stderr.Close(); err != nil {
291+
t.Fatal(err)
292+
}
293+
if string(output) != "hello\n" {
294+
t.Fatalf("Unexpected output. Expected %s, received: %s (err: %s)", "hello\n", output, output2)
295+
}
296+
}
297+
220298
func TestCommitRun(t *testing.T) {
221299
runtime, err := newTestRuntime()
222300
if err != nil {
@@ -248,7 +326,7 @@ func TestCommitRun(t *testing.T) {
248326
if err != nil {
249327
t.Error(err)
250328
}
251-
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "")
329+
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image", "", nil)
252330
if err != nil {
253331
t.Error(err)
254332
}

graph.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,14 @@ func (graph *Graph) Get(name string) (*Image, error) {
8484
}
8585

8686
// Create creates a new image and registers it in the graph.
87-
func (graph *Graph) Create(layerData Archive, container *Container, comment, author string) (*Image, error) {
87+
func (graph *Graph) Create(layerData Archive, container *Container, comment, author string, config *Config) (*Image, error) {
8888
img := &Image{
8989
Id: GenerateId(),
9090
Comment: comment,
9191
Created: time.Now(),
9292
DockerVersion: VERSION,
9393
Author: author,
94+
Config: config,
9495
}
9596
if container != nil {
9697
img.Parent = container.Image

graph_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestGraphCreate(t *testing.T) {
6262
if err != nil {
6363
t.Fatal(err)
6464
}
65-
image, err := graph.Create(archive, nil, "Testing", "")
65+
image, err := graph.Create(archive, nil, "Testing", "", nil)
6666
if err != nil {
6767
t.Fatal(err)
6868
}
@@ -122,7 +122,7 @@ func TestMount(t *testing.T) {
122122
if err != nil {
123123
t.Fatal(err)
124124
}
125-
image, err := graph.Create(archive, nil, "Testing", "")
125+
image, err := graph.Create(archive, nil, "Testing", "", nil)
126126
if err != nil {
127127
t.Fatal(err)
128128
}
@@ -166,7 +166,7 @@ func createTestImage(graph *Graph, t *testing.T) *Image {
166166
if err != nil {
167167
t.Fatal(err)
168168
}
169-
img, err := graph.Create(archive, nil, "Test image", "")
169+
img, err := graph.Create(archive, nil, "Test image", "", nil)
170170
if err != nil {
171171
t.Fatal(err)
172172
}
@@ -181,7 +181,7 @@ func TestDelete(t *testing.T) {
181181
t.Fatal(err)
182182
}
183183
assertNImages(graph, t, 0)
184-
img, err := graph.Create(archive, nil, "Bla bla", "")
184+
img, err := graph.Create(archive, nil, "Bla bla", "", nil)
185185
if err != nil {
186186
t.Fatal(err)
187187
}
@@ -192,11 +192,11 @@ func TestDelete(t *testing.T) {
192192
assertNImages(graph, t, 0)
193193

194194
// Test 2 create (same name) / 1 delete
195-
img1, err := graph.Create(archive, nil, "Testing", "")
195+
img1, err := graph.Create(archive, nil, "Testing", "", nil)
196196
if err != nil {
197197
t.Fatal(err)
198198
}
199-
if _, err = graph.Create(archive, nil, "Testing", ""); err != nil {
199+
if _, err = graph.Create(archive, nil, "Testing", "", nil); err != nil {
200200
t.Fatal(err)
201201
}
202202
assertNImages(graph, t, 2)

image.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type Image struct {
2424
ContainerConfig Config `json:"container_config,omitempty"`
2525
DockerVersion string `json:"docker_version,omitempty"`
2626
Author string `json:"author,omitempty"`
27+
Config *Config `json:"config,omitempty"`
2728
graph *Graph
2829
}
2930

runtime.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,58 @@ func (runtime *Runtime) containerRoot(id string) string {
7878
return path.Join(runtime.repository, id)
7979
}
8080

81+
func (runtime *Runtime) mergeConfig(userConf, imageConf *Config) {
82+
if userConf.Hostname != "" {
83+
userConf.Hostname = imageConf.Hostname
84+
}
85+
if userConf.User != "" {
86+
userConf.User = imageConf.User
87+
}
88+
if userConf.Memory == 0 {
89+
userConf.Memory = imageConf.Memory
90+
}
91+
if userConf.MemorySwap == 0 {
92+
userConf.MemorySwap = imageConf.MemorySwap
93+
}
94+
if userConf.PortSpecs == nil || len(userConf.PortSpecs) == 0 {
95+
userConf.PortSpecs = imageConf.PortSpecs
96+
}
97+
if !userConf.Tty {
98+
userConf.Tty = userConf.Tty
99+
}
100+
if !userConf.OpenStdin {
101+
userConf.OpenStdin = imageConf.OpenStdin
102+
}
103+
if !userConf.StdinOnce {
104+
userConf.StdinOnce = imageConf.StdinOnce
105+
}
106+
if userConf.Env == nil || len(userConf.Env) == 0 {
107+
userConf.Env = imageConf.Env
108+
}
109+
if userConf.Cmd == nil || len(userConf.Cmd) == 0 {
110+
userConf.Cmd = imageConf.Cmd
111+
}
112+
if userConf.Dns == nil || len(userConf.Dns) == 0 {
113+
userConf.Dns = imageConf.Dns
114+
}
115+
}
116+
81117
func (runtime *Runtime) Create(config *Config) (*Container, error) {
118+
82119
// Lookup image
83120
img, err := runtime.repositories.LookupImage(config.Image)
84121
if err != nil {
85122
return nil, err
86123
}
124+
125+
if img.Config != nil {
126+
runtime.mergeConfig(config, img.Config)
127+
}
128+
129+
if config.Cmd == nil {
130+
return nil, fmt.Errorf("No command specified")
131+
}
132+
87133
// Generate id
88134
id := GenerateId()
89135
// Generate default hostname
@@ -104,6 +150,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
104150
// FIXME: do we need to store this in the container?
105151
SysInitPath: sysInitPath,
106152
}
153+
107154
container.root = runtime.containerRoot(container.Id)
108155
// Step 1: create the container directory.
109156
// This doubles as a barrier to avoid race conditions.
@@ -265,7 +312,7 @@ func (runtime *Runtime) Destroy(container *Container) error {
265312

266313
// Commit creates a new filesystem image from the current state of a container.
267314
// The image can optionally be tagged into a repository
268-
func (runtime *Runtime) Commit(id, repository, tag, comment, author string) (*Image, error) {
315+
func (runtime *Runtime) Commit(id, repository, tag, comment, author string, config *Config) (*Image, error) {
269316
container := runtime.Get(id)
270317
if container == nil {
271318
return nil, fmt.Errorf("No such container: %s", id)
@@ -277,7 +324,7 @@ func (runtime *Runtime) Commit(id, repository, tag, comment, author string) (*Im
277324
return nil, err
278325
}
279326
// Create a new image from the container's base layers + a new layer from container changes
280-
img, err := runtime.graph.Create(rwTar, container, comment, author)
327+
img, err := runtime.graph.Create(rwTar, container, comment, author, config)
281328
if err != nil {
282329
return nil, err
283330
}

0 commit comments

Comments
 (0)