merge graph in graph

This commit is contained in:
creack 2013-03-21 06:35:57 -07:00
commit eef9659c95
7 changed files with 63 additions and 33 deletions

View File

@ -387,7 +387,7 @@ func (srv *Server) CmdImport(stdin io.ReadCloser, stdout io.Writer, args ...stri
}
archive = ProgressReader(resp.Body, int(resp.ContentLength), stdout)
}
img, err := srv.runtime.graph.Create(archive, "", "Imported from "+src)
img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src)
if err != nil {
return err
}
@ -737,33 +737,22 @@ func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string)
func (srv *Server) CmdCommit(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout,
"commit", "[OPTIONS] CONTAINER [DEST]",
"commit", "[OPTIONS] CONTAINER [REPOSITORY [TAG]]",
"Create a new image from a container's changes")
if err := cmd.Parse(args); err != nil {
return nil
}
containerName, imgName := cmd.Arg(0), cmd.Arg(1)
if containerName == "" || imgName == "" {
containerName, repository, tag := cmd.Arg(0), cmd.Arg(1), cmd.Arg(2)
if containerName == "" {
cmd.Usage()
return nil
}
if container := srv.runtime.Get(containerName); container != nil {
// FIXME: freeze the container before copying it to avoid data corruption?
// FIXME: this shouldn't be in commands.
rwTar, err := container.ExportRw()
if err != nil {
return err
}
// Create a new image from the container's base layers + a new layer from container changes
img, err := srv.runtime.graph.Create(rwTar, container.Image, "")
if err != nil {
return err
}
fmt.Fprintln(stdout, img.Id)
return nil
img, err := srv.runtime.Commit(containerName, repository, tag)
if err != nil {
return err
}
return errors.New("No such container: " + containerName)
fmt.Fprintln(stdout, img.Id)
return nil
}
func (srv *Server) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...string) error {

View File

@ -46,7 +46,7 @@ func TestCommitRun(t *testing.T) {
if err != nil {
t.Error(err)
}
img, err := runtime.graph.Create(rwTar, container1.Image, "unit test commited image")
img, err := runtime.graph.Create(rwTar, container1, "unit test commited image")
if err != nil {
t.Error(err)
}

View File

@ -47,13 +47,17 @@ func (graph *Graph) Get(id string) (*Image, error) {
return img, nil
}
func (graph *Graph) Create(layerData Archive, parent, comment string) (*Image, error) {
func (graph *Graph) Create(layerData Archive, container *Container, comment string) (*Image, error) {
img := &Image{
Id: GenerateId(),
Parent: parent,
Comment: comment,
Created: time.Now(),
}
if container != nil {
img.Parent = container.Image
img.ParentContainer = container.Id
img.ParentCommand = append([]string{container.Path}, container.Args...)
}
if err := graph.Register(layerData, img); err != nil {
return nil, err
}

View File

@ -35,7 +35,7 @@ func TestGraphCreate(t *testing.T) {
if err != nil {
t.Fatal(err)
}
image, err := graph.Create(archive, "", "Testing")
image, err := graph.Create(archive, nil, "Testing")
if err != nil {
t.Fatal(err)
}
@ -92,7 +92,7 @@ func TestMount(t *testing.T) {
if err != nil {
t.Fatal(err)
}
image, err := graph.Create(archive, "", "Testing")
image, err := graph.Create(archive, nil, "Testing")
if err != nil {
t.Fatal(err)
}
@ -128,7 +128,7 @@ func TestDelete(t *testing.T) {
t.Fatal(err)
}
assertNImages(graph, t, 0)
img, err := graph.Create(archive, "", "Bla bla")
img, err := graph.Create(archive, nil, "Bla bla")
if err != nil {
t.Fatal(err)
}
@ -139,11 +139,11 @@ func TestDelete(t *testing.T) {
assertNImages(graph, t, 0)
// Test 2 create (same name) / 1 delete
img1, err := graph.Create(archive, "foo", "Testing")
img1, err := graph.Create(archive, nil, "Testing")
if err != nil {
t.Fatal(err)
}
if _, err = graph.Create(archive, "foo", "Testing"); err != nil {
if _, err = graph.Create(archive, nil, "Testing"); err != nil {
t.Fatal(err)
}
assertNImages(graph, t, 2)

View File

@ -15,11 +15,13 @@ import (
)
type Image struct {
Id string `json:"id"`
Parent string `json:"parent,omitempty"`
Comment string `json:"comment,omitempty"`
Created time.Time `json:"created"`
graph *Graph
Id string `json:"id"`
Parent string `json:"parent,omitempty"`
Comment string `json:"comment,omitempty"`
Created time.Time `json:"created"`
ParentContainer string `json:-`
ParentCommand []string `json:-`
graph *Graph
}
func LoadImage(root string) (*Image, error) {

View File

@ -200,6 +200,33 @@ func (runtime *Runtime) Destroy(container *Container) error {
return 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(id, repository, tag string) (*Image, error) {
container := runtime.Get(id)
if container == nil {
return nil, fmt.Errorf("No such container: %s", id)
}
// FIXME: freeze the container before copying it to avoid data corruption?
// FIXME: this shouldn't be in commands.
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, "")
if err != nil {
return nil, err
}
// Register the image if needed
if repository != "" {
if err := runtime.repositories.Set(repository, tag, img.Id); err != nil {
return img, err
}
}
return img, nil
}
func (runtime *Runtime) restore() error {
dir, err := ioutil.ReadDir(runtime.repository)
if err != nil {

View File

@ -2,9 +2,11 @@ package docker
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
type TagStore struct {
@ -60,6 +62,12 @@ func (store *TagStore) Reload() error {
}
func (store *TagStore) Set(repoName, tag, revision string) error {
if strings.Contains(repoName, ":") {
return fmt.Errorf("Illegal repository name: %s", repoName)
}
if strings.Contains(repoName, ":") {
return fmt.Errorf("Illegal tag name: %s", tag)
}
if err := store.Reload(); err != nil {
return err
}