Example #1
0
func TestGetImagesJSONLegacyFormat(t *testing.T) {
	eng := engine.New()
	var called bool
	eng.Register("images", func(job *engine.Job) engine.Status {
		called = true
		outsLegacy := engine.NewTable("Created", 0)
		outsLegacy.Add(createEnvFromGetImagesJSONStruct(sampleImage))
		if _, err := outsLegacy.WriteListTo(job.Stdout); err != nil {
			return job.Error(err)
		}
		return engine.StatusOK
	})
	r := serveRequestUsingVersion("GET", "/images/json", "1.6", nil, eng, t)
	if !called {
		t.Fatal("handler was not called")
	}
	assertHttpNotError(r, t)
	assertContentType(r, "application/json", t)
	images := engine.NewTable("Created", 0)
	if _, err := images.ReadListFrom(r.Body.Bytes()); err != nil {
		t.Fatal(err)
	}
	if images.Len() != 1 {
		t.Fatalf("Expected 1 image, %d found", images.Len())
	}
	image := images.Data[0]
	if image.Get("Tag") != "test-tag" {
		t.Errorf("Expected tag 'test-tag', found '%s'", image.Get("Tag"))
	}
	if image.Get("Repository") != "test-name" {
		t.Errorf("Expected repository 'test-name', found '%s'", image.Get("Repository"))
	}
}
Example #2
0
func TestImageTagImageDelete(t *testing.T) {
	eng := NewTestEngine(t)
	defer mkRuntimeFromEngine(eng, t).Nuke()

	srv := mkServerFromEngine(eng, t)

	initialImages := getAllImages(eng, t)
	if err := eng.Job("tag", unitTestImageName, "utest", "tag1").Run(); err != nil {
		t.Fatal(err)
	}

	if err := eng.Job("tag", unitTestImageName, "utest/docker", "tag2").Run(); err != nil {
		t.Fatal(err)
	}

	if err := eng.Job("tag", unitTestImageName, "utest:5000/docker", "tag3").Run(); err != nil {
		t.Fatal(err)
	}

	images := getAllImages(eng, t)

	nExpected := len(initialImages.Data[0].GetList("RepoTags")) + 3
	nActual := len(images.Data[0].GetList("RepoTags"))
	if nExpected != nActual {
		t.Errorf("Expected %d images, %d found", nExpected, nActual)
	}

	if err := srv.DeleteImage("utest/docker:tag2", engine.NewTable("", 0), true, false, false); err != nil {
		t.Fatal(err)
	}

	images = getAllImages(eng, t)

	nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 2
	nActual = len(images.Data[0].GetList("RepoTags"))
	if nExpected != nActual {
		t.Errorf("Expected %d images, %d found", nExpected, nActual)
	}

	if err := srv.DeleteImage("utest:5000/docker:tag3", engine.NewTable("", 0), true, false, false); err != nil {
		t.Fatal(err)
	}

	images = getAllImages(eng, t)

	nExpected = len(initialImages.Data[0].GetList("RepoTags")) + 1
	nActual = len(images.Data[0].GetList("RepoTags"))

	if err := srv.DeleteImage("utest:tag1", engine.NewTable("", 0), true, false, false); err != nil {
		t.Fatal(err)
	}

	images = getAllImages(eng, t)

	if images.Len() != initialImages.Len() {
		t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
	}
}
Example #3
0
func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return err
	}

	var (
		buffer *bytes.Buffer
		job    = srv.Eng.Job("images")
	)

	job.Setenv("filter", r.Form.Get("filter"))
	job.Setenv("all", r.Form.Get("all"))

	if version >= 1.9 {
		job.Stdout.Add(w)
	} else {
		buffer = bytes.NewBuffer(nil)
		job.Stdout.Add(buffer)
	}

	if err := job.Run(); err != nil {
		return err
	}

	if version < 1.9 { // Send as a valid JSON array
		outs := engine.NewTable("Created", 0)
		if _, err := outs.ReadFrom(buffer); err != nil {
			return err
		}
		if version < 1.8 { // Convert to legacy format
			outsLegacy := engine.NewTable("Created", 0)
			for _, out := range outs.Data {
				for _, repoTag := range out.GetList("RepoTags") {
					parts := strings.Split(repoTag, ":")
					outLegacy := &engine.Env{}
					outLegacy.Set("Repository", parts[0])
					outLegacy.Set("Tag", parts[1])
					outLegacy.Set("ID", out.Get("ID"))
					outLegacy.SetInt64("Created", out.GetInt64("Created"))
					outLegacy.SetInt64("Size", out.GetInt64("Size"))
					outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize"))
					outsLegacy.Add(outLegacy)
				}
			}
			if _, err := outsLegacy.WriteListTo(w); err != nil {
				return err
			}
		} else if _, err := outs.WriteListTo(w); err != nil {
			return err
		}
	}

	return nil
}
Example #4
0
// Search queries the public registry for images matching the specified
// search terms, and returns the results.
//
// Argument syntax: search TERM
//
// Option environment:
//	'authConfig': json-encoded credentials to authenticate against the registry.
//		The search extends to images only accessible via the credentials.
//
//	'metaHeaders': extra HTTP headers to include in the request to the registry.
//		The headers should be passed as a json-encoded dictionary.
//
// Output:
//	Results are sent as a collection of structured messages (using engine.Table).
//	Each result is sent as a separate message.
//	Results are ordered by number of stars on the public registry.
func (s *Service) Search(job *engine.Job) engine.Status {
	if n := len(job.Args); n != 1 {
		return job.Errorf("Usage: %s TERM", job.Name)
	}
	var (
		term        = job.Args[0]
		metaHeaders = map[string][]string{}
		authConfig  = &AuthConfig{}
	)
	job.GetenvJson("authConfig", authConfig)
	job.GetenvJson("metaHeaders", metaHeaders)

	r, err := NewRegistry(authConfig, HTTPRequestFactory(metaHeaders), IndexServerAddress())
	if err != nil {
		return job.Error(err)
	}
	results, err := r.SearchRepositories(term)
	if err != nil {
		return job.Error(err)
	}
	outs := engine.NewTable("star_count", 0)
	for _, result := range results.Results {
		out := &engine.Env{}
		out.Import(result)
		outs.Add(out)
	}
	outs.ReverseSort()
	if _, err := outs.WriteListTo(job.Stdout); err != nil {
		return job.Error(err)
	}
	return engine.StatusOK
}
Example #5
0
func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return err
	}

	var (
		buffer *bytes.Buffer
		job    = srv.Eng.Job("search", r.Form.Get("term"))
	)
	if version >= 1.9 {
		job.Stdout.Add(w)
	} else {
		buffer = bytes.NewBuffer(nil)
		job.Stdout.Add(buffer)
	}
	if err := job.Run(); err != nil {
		return err
	}
	if version < 1.9 { // Send as a valid JSON array
		outs := engine.NewTable("", 0)
		if _, err := outs.ReadFrom(buffer); err != nil {
			return err
		}
		if _, err := outs.WriteListTo(w); err != nil {
			return err
		}
	}
	return nil
}
Example #6
0
func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if vars == nil {
		return fmt.Errorf("Missing parameter")
	}

	var (
		buffer *bytes.Buffer
		job    = srv.Eng.Job("history", vars["name"])
	)

	if version >= 1.9 {
		job.Stdout.Add(w)
	} else {
		buffer = bytes.NewBuffer(nil)
		job.Stdout.Add(buffer)
	}
	if err := job.Run(); err != nil {
		return err
	}
	if version < 1.9 { // Send as a valid JSON array
		outs := engine.NewTable("Created", 0)
		if _, err := outs.ReadFrom(buffer); err != nil {
			return err
		}
		if _, err := outs.WriteListTo(w); err != nil {
			return err
		}
	}
	return nil
}
Example #7
0
func TestDeleteImages(t *testing.T) {
	eng := NewTestEngine(t)
	//we expect errors, so we disable stderr
	eng.Stderr = ioutil.Discard
	defer mkRuntimeFromEngine(eng, t).Nuke()

	initialImages := getImages(eng, t, true, "")

	if err := eng.Job("tag", unitTestImageName, "test", "test").Run(); err != nil {
		t.Fatal(err)
	}

	images := getImages(eng, t, true, "")

	if len(images.Data[0].GetList("RepoTags")) != len(initialImages.Data[0].GetList("RepoTags"))+1 {
		t.Errorf("Expected %d images, %d found", len(initialImages.Data[0].GetList("RepoTags"))+1, len(images.Data[0].GetList("RepoTags")))
	}

	req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil)
	if err != nil {
		t.Fatal(err)
	}

	r := httptest.NewRecorder()
	if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
		t.Fatal(err)
	}
	if r.Code != http.StatusConflict {
		t.Fatalf("Expected http status 409-conflict, got %v", r.Code)
	}

	req2, err := http.NewRequest("DELETE", "/images/test:test", nil)
	if err != nil {
		t.Fatal(err)
	}

	r2 := httptest.NewRecorder()
	if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r2, t)
	if r2.Code != http.StatusOK {
		t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code)
	}

	outs := engine.NewTable("Created", 0)
	if _, err := outs.ReadListFrom(r2.Body.Bytes()); err != nil {
		t.Fatal(err)
	}
	if len(outs.Data) != 1 {
		t.Fatalf("Expected %d event (untagged), got %d", 1, len(outs.Data))
	}
	images = getImages(eng, t, false, "")

	if images.Len() != initialImages.Len() {
		t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
	}
}
Example #8
0
// docker主机上的容器
func dockerContainers(c *utils.Connection, data []byte) {
	dst := engine.NewTable("", 0)
	if _, err := dst.ReadListFrom(data); err != nil {
		log.Println("Read table error:", err)
	}
	if content, err := dst.ToListString(); err != nil {
		log.Println("Table to string error:", err)
	} else {
		log.Println("Containers:", content)
	}
}
Example #9
0
// Regression test for being able to untag an image with an existing
// container
func TestDeleteTagWithExistingContainers(t *testing.T) {
	eng := NewTestEngine(t)
	defer nuke(mkRuntimeFromEngine(eng, t))

	srv := mkServerFromEngine(eng, t)

	// Tag the image
	if err := eng.Job("tag", unitTestImageID, "utest", "tag1").Run(); err != nil {
		t.Fatal(err)
	}

	// Create a container from the image
	config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	id := createNamedTestContainer(eng, config, t, "testingtags")
	if id == "" {
		t.Fatal("No id returned")
	}

	job := srv.Eng.Job("containers")
	job.SetenvBool("all", true)
	outs, err := job.Stdout.AddListTable()
	if err != nil {
		t.Fatal(err)
	}
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	if len(outs.Data) != 1 {
		t.Fatalf("Expected 1 container got %d", len(outs.Data))
	}

	// Try to remove the tag
	imgs := engine.NewTable("", 0)
	if err := srv.DeleteImage("utest:tag1", imgs, true, false, false); err != nil {
		t.Fatal(err)
	}

	if len(imgs.Data) != 1 {
		t.Fatalf("Should only have deleted one untag %d", len(imgs.Data))
	}

	if untag := imgs.Data[0].Get("Untagged"); untag != "utest:tag1" {
		t.Fatalf("Expected %s got %s", unitTestImageID, untag)
	}
}
Example #10
0
func getImagesJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return err
	}

	var (
		err  error
		outs *engine.Table
		job  = eng.Job("images")
	)

	job.Setenv("filters", r.Form.Get("filters"))
	// FIXME this parameter could just be a match filter
	job.Setenv("filter", r.Form.Get("filter"))
	job.Setenv("all", r.Form.Get("all"))

	if version.GreaterThanOrEqualTo("1.7") {
		streamJSON(job, w, false)
	} else if outs, err = job.Stdout.AddListTable(); err != nil {
		return err
	}

	if err := job.Run(); err != nil {
		return err
	}

	if version.LessThan("1.7") && outs != nil { // Convert to legacy format
		outsLegacy := engine.NewTable("Created", 0)
		for _, out := range outs.Data {
			for _, repoTag := range out.GetList("RepoTags") {
				parts := strings.Split(repoTag, ":")
				outLegacy := &engine.Env{}
				outLegacy.Set("Repository", parts[0])
				outLegacy.Set("Tag", parts[1])
				outLegacy.Set("Id", out.Get("Id"))
				outLegacy.SetInt64("Created", out.GetInt64("Created"))
				outLegacy.SetInt64("Size", out.GetInt64("Size"))
				outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize"))
				outsLegacy.Add(outLegacy)
			}
		}
		w.Header().Set("Content-Type", "application/json")
		if _, err := outsLegacy.WriteListTo(w); err != nil {
			return err
		}
	}
	return nil
}
Example #11
0
// docker主机上的镜像
func dockerImages(c *utils.Connection, data []byte) {
	dst := engine.NewTable("", 0)
	if _, err := dst.ReadListFrom(data); err != nil {
		log.Println("Read table error:", err)
	}
	for _, env := range dst.Data {
		created, err := strconv.ParseInt(env.Get("Created"), 10, 64)
		if err == nil {
			image := &resource.Image{Host: c.Src, Created: created}
			registry.RegistryServer.RegisterImage(env.Get("Id"), image)
			log.Printf("Register image id:%s host:%s", env.Get("Id"), c.Src)
		} else {
			log.Printf("Parse image created time error:%s", err)
		}
	}
}
Example #12
0
func TestGetContainersJSON(t *testing.T) {
	eng := NewTestEngine(t)
	defer mkRuntimeFromEngine(eng, t).Nuke()
	srv := mkServerFromEngine(eng, t)

	job := eng.Job("containers")
	job.SetenvBool("all", true)
	outs, err := job.Stdout.AddTable()
	if err != nil {
		t.Fatal(err)
	}
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}
	beginLen := len(outs.Data)

	containerID := createTestContainer(eng, &docker.Config{
		Image: unitTestImageID,
		Cmd:   []string{"echo", "test"},
	}, t)

	if containerID == "" {
		t.Fatalf("Received empty container ID")
	}

	req, err := http.NewRequest("GET", "/containers/json?all=1", nil)
	if err != nil {
		t.Fatal(err)
	}

	r := httptest.NewRecorder()
	if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r, t)
	containers := engine.NewTable("", 0)
	if _, err := containers.ReadListFrom(r.Body.Bytes()); err != nil {
		t.Fatal(err)
	}
	if len(containers.Data) != beginLen+1 {
		t.Fatalf("Expected %d container, %d found (started with: %d)", beginLen+1, len(containers.Data), beginLen)
	}
	if id := containers.Data[0].Get("ID"); id != containerID {
		t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", containerID, id)
	}
}
Example #13
0
func getImagesJSON(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return err
	}

	var (
		err  error
		outs *engine.Table
		job  = eng.Job("images")
	)

	job.Setenv("filter", r.Form.Get("filter"))
	job.Setenv("all", r.Form.Get("all"))

	if version >= 1.7 {
		job.Stdout.Add(w)
	} else if outs, err = job.Stdout.AddListTable(); err != nil {
		return err
	}

	if err := job.Run(); err != nil {
		return err
	}

	if version < 1.7 && outs != nil { // Convert to legacy format
		outsLegacy := engine.NewTable("Created", 0)
		for _, out := range outs.Data {
			for _, repoTag := range out.GetList("RepoTags") {
				parts := strings.Split(repoTag, ":")
				outLegacy := &engine.Env{}
				outLegacy.Set("Repository", parts[0])
				outLegacy.Set("Tag", parts[1])
				outLegacy.Set("Id", out.Get("Id"))
				outLegacy.SetInt64("Created", out.GetInt64("Created"))
				outLegacy.SetInt64("Size", out.GetInt64("Size"))
				outLegacy.SetInt64("VirtualSize", out.GetInt64("VirtualSize"))
				outsLegacy.Add(outLegacy)
			}
		}
		if _, err := outsLegacy.WriteListTo(w); err != nil {
			return err
		}
	}
	return nil
}
Example #14
0
func (b *dockerClientBackend) ls() ([]string, error) {
	resp, err := b.client.call("GET", "/containers/json", "")
	if err != nil {
		return nil, fmt.Errorf("get: %v", err)
	}
	// FIXME: check for response error
	c := engine.NewTable("Created", 0)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read body: %v", err)
	}
	if _, err := c.ReadListFrom(body); err != nil {
		return nil, fmt.Errorf("readlist: %v", err)
	}
	names := []string{}
	for _, env := range c.Data {
		names = append(names, env.GetList("Names")[0][1:])
	}
	return names, nil
}
Example #15
0
func TestGetContainersChanges(t *testing.T) {
	eng := NewTestEngine(t)
	defer mkRuntimeFromEngine(eng, t).Nuke()
	srv := mkServerFromEngine(eng, t)

	// Create a container and remove a file
	containerID := createTestContainer(eng,
		&docker.Config{
			Image: unitTestImageID,
			Cmd:   []string{"/bin/rm", "/etc/passwd"},
		},
		t,
	)
	containerRun(eng, containerID, t)

	r := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/containers/"+containerID+"/changes", nil)
	if err != nil {
		t.Fatal(err)
	}
	if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r, t)
	outs := engine.NewTable("", 0)
	if _, err := outs.ReadListFrom(r.Body.Bytes()); err != nil {
		t.Fatal(err)
	}

	// Check the changelog
	success := false
	for _, elem := range outs.Data {
		if elem.Get("Path") == "/etc/passwd" && elem.GetInt("Kind") == 2 {
			success = true
		}
	}
	if !success {
		t.Fatalf("/etc/passwd as been removed but is not present in the diff")
	}
}
Example #16
0
func (t *tutumBackend) ls(ctx *beam.Message) error {
	resp, err := t.tutumDockerConnector.call("GET", "/containers/json", "")
	if err != nil {
		return fmt.Errorf("%s: get: %v", t.tutumDockerConnector.URL.String(), err)
	}
	c := engine.NewTable("Created", 0)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("%s: read body: %v", t.tutumDockerConnector.URL.String(), err)
	}
	if _, err := c.ReadListFrom(body); err != nil {
		return fmt.Errorf("%s: readlist: %v", t.tutumDockerConnector.URL.String(), err)
	}
	ids := []string{}
	for _, env := range c.Data {
		ids = append(ids, env.GetList("Id")[0])
	}
	if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: ids}); err != nil {
		return fmt.Errorf("%s: send response: %v", t.tutumDockerConnector.URL.String(), err)
	}
	return nil
}
Example #17
0
func TestGetImagesHistory(t *testing.T) {
	eng := NewTestEngine(t)
	defer mkRuntimeFromEngine(eng, t).Nuke()

	r := httptest.NewRecorder()

	req, err := http.NewRequest("GET", fmt.Sprintf("/images/%s/history", unitTestImageName), nil)
	if err != nil {
		t.Fatal(err)
	}
	if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r, t)

	outs := engine.NewTable("Created", 0)
	if _, err := outs.ReadListFrom(r.Body.Bytes()); err != nil {
		t.Fatal(err)
	}
	if len(outs.Data) != 1 {
		t.Errorf("Expected 1 line, %d found", len(outs.Data))
	}
}
Example #18
0
func (settings *NetworkSettings) PortMappingAPI() *engine.Table {
	var outs = engine.NewTable("", 0)
	for port, bindings := range settings.Ports {
		p, _ := parsePort(port.Port())
		if len(bindings) == 0 {
			out := &engine.Env{}
			out.SetInt("PublicPort", p)
			out.Set("Type", port.Proto())
			outs.Add(out)
			continue
		}
		for _, binding := range bindings {
			out := &engine.Env{}
			h, _ := parsePort(binding.HostPort)
			out.SetInt("PrivatePort", p)
			out.SetInt("PublicPort", h)
			out.Set("Type", port.Proto())
			out.Set("IP", binding.HostIp)
			outs.Add(out)
		}
	}
	return outs
}
Example #19
0
func (b *dockerClientBackend) ls(ctx *beam.Message) error {
	resp, err := b.client.call("GET", "/containers/json", "")
	if err != nil {
		return fmt.Errorf("get: %v", err)
	}
	// FIXME: check for response error
	c := engine.NewTable("Created", 0)
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read body: %v", err)
	}
	if _, err := c.ReadListFrom(body); err != nil {
		return fmt.Errorf("readlist: %v", err)
	}
	names := []string{}
	for _, env := range c.Data {
		names = append(names, env.GetList("Names")[0][1:])
	}
	if _, err := ctx.Ret.Send(&beam.Message{Verb: beam.Set, Args: names}); err != nil {
		return fmt.Errorf("send response: %v", err)
	}
	return nil
}
Example #20
0
func getContainersJSON(eng *engine.Engine, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return err
	}
	var (
		err  error
		outs *engine.Table
		job  = eng.Job("containers")
	)

	job.Setenv("all", r.Form.Get("all"))
	job.Setenv("size", r.Form.Get("size"))
	job.Setenv("since", r.Form.Get("since"))
	job.Setenv("before", r.Form.Get("before"))
	job.Setenv("limit", r.Form.Get("limit"))

	if version >= 1.5 {
		w.Header().Set("Content-Type", "application/json")
		job.Stdout.Add(w)
	} else if outs, err = job.Stdout.AddTable(); err != nil {
		return err
	}
	if err = job.Run(); err != nil {
		return err
	}
	if version < 1.5 { // Convert to legacy format
		for _, out := range outs.Data {
			ports := engine.NewTable("", 0)
			ports.ReadListFrom([]byte(out.Get("Ports")))
			out.Set("Ports", displayablePorts(ports))
		}
		if _, err = outs.WriteListTo(w); err != nil {
			return err
		}
	}
	return nil
}
Example #21
0
func (s *cloud) Install(eng *engine.Engine) error {
	eng.Register("cloud", func(job *engine.Job) engine.Status {
		if len(job.Args) < 3 {
			return job.Errorf("usage: %s <provider> <instance> <zone> <aditional> <provider> <args> <proto>://<addr>", job.Name)
		}
		instance := job.Args[1]
		zone := job.Args[2]
		var cloud Cloud
		var err error
		switch job.Args[0] {
		case "gce":
			if len(job.Args) < 4 {
				return job.Errorf("usage: %s gce <instance> <zone> <project>")
			}
			cloud, err = NewCloudGCE(job.Args[3])
			if err != nil {
				return job.Errorf("Unexpected error: %#v", err)
			}
		default:
			return job.Errorf("Unknown cloud provider: %s", job.Args[0])
		}
		ip, err := cloud.GetPublicIPAddress(instance, zone)
		instanceRunning := len(ip) > 0
		if !instanceRunning {
			log.Print("Instance doesn't exist, creating....")
			_, err = cloud.CreateInstance(instance, zone)
		}
		if err != nil {
			return job.Errorf("Unexpected error: %#v", err)
		}
		remotePort := 8000
		localPort := 8001
		apiVersion := "v1.10"
		tunnelUrl, err := url.Parse(fmt.Sprintf("http://localhost:%d/%s/containers/json", localPort, apiVersion))
		if err != nil {
			return job.Errorf("Unexpected error: %#v", err)
		}
		tunnel := Tunnel{*tunnelUrl}

		if !tunnel.isActive() {
			fmt.Printf("Creating tunnel")
			_, err = cloud.OpenSecureTunnel(instance, zone, localPort, remotePort)
			if err != nil {
				return job.Errorf("Failed to open tunnel: %#v", err)
			}
		}
		host := fmt.Sprintf("tcp://localhost:%d", localPort)
		client := newClient()
		client.setURL(host)
		client.version = apiVersion
		//job.Eng.Register("inspect", func(job *engine.Job) engine.Status {
		//	resp, err := client.call("GET", "/containers/
		job.Eng.Register("create", func(job *engine.Job) engine.Status {
			container := Container{
				Image: job.Getenv("Image"),
				Tty:   job.Getenv("Tty") == "true",
			}
			data, err := json.Marshal(container)
			resp, err := client.call("POST", "/containers/create", string(data))
			if err != nil {
				return job.Errorf("post: %v", err)
			}
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				return job.Errorf("read body: %#v", err)
			}
			var containerOut Container
			err = json.Unmarshal([]byte(body), &containerOut)
			_, err = job.Printf("%s\n", containerOut.Id)
			if err != nil {
				return job.Errorf("write body: %#v", err)
			}
			log.Printf("%s", string(body))
			return engine.StatusOK
		})

		job.Eng.Register("start", func(job *engine.Job) engine.Status {
			path := fmt.Sprintf("/containers/%s/start", job.Args[0])
			resp, err := client.call("POST", path, "{\"Binds\":[],\"ContainerIDFile\":\"\",\"LxcConf\":[],\"Privileged\":false,\"PortBindings\":{},\"Links\":null,\"PublishAllPorts\":false,\"Dns\":null,\"DnsSearch\":[],\"VolumesFrom\":[]}")
			if err != nil {
				return job.Errorf("post: %v", err)
			}
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				return job.Errorf("read body: %#v", err)
			}
			log.Printf("%s", string(body))
			return engine.StatusOK
		})

		job.Eng.Register("containers", func(job *engine.Job) engine.Status {
			path := fmt.Sprintf(
				"/containers/json?all=%s&size=%s&since=%s&before=%s&limit=%s",
				url.QueryEscape(job.Getenv("all")),
				url.QueryEscape(job.Getenv("size")),
				url.QueryEscape(job.Getenv("since")),
				url.QueryEscape(job.Getenv("before")),
				url.QueryEscape(job.Getenv("limit")),
			)
			resp, err := client.call("GET", path, "")
			if err != nil {
				return job.Errorf("get: %v", err)
			}
			// FIXME: check for response error
			c := engine.NewTable("Created", 0)
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				return job.Errorf("read body: %v", err)
			}
			fmt.Printf("---> '%s'\n", body)
			if _, err := c.ReadListFrom(body); err != nil {
				return job.Errorf("readlist: %v", err)
			}
			c.WriteListTo(job.Stdout)
			return engine.StatusOK
		})

		job.Eng.Register("container_delete", func(job *engine.Job) engine.Status {
			log.Printf("%#v", job.Args)
			path := "/containers/" + job.Args[0]

			resp, err := client.call("DELETE", path, "")
			if err != nil {
				return job.Errorf("delete: %v", err)
			}
			log.Printf("%#v", resp)
			return engine.StatusOK
		})

		job.Eng.Register("stop", func(job *engine.Job) engine.Status {
			log.Printf("%#v", job.Args)
			path := "/containers/" + job.Args[0] + "/stop"

			resp, err := client.call("POST", path, "")
			if err != nil {
				return job.Errorf("delete: %v", err)
			}
			log.Printf("%#v", resp)
			return engine.StatusOK
		})

		job.Eng.RegisterCatchall(func(job *engine.Job) engine.Status {
			log.Printf("%#v %#v %#v", *job, job.Env(), job.Args)
			return engine.StatusOK
		})
		return engine.StatusOK
	})
	return nil
}
Example #22
0
func (t *tutumBackend) Install(eng *engine.Engine) error {
	eng.Register("tutum", func(job *engine.Job) engine.Status {
		if len(job.Args) == 1 {
			tutumConnector = job.Args[0]
		}
		if !tutum.IsAuthenticated() {
			return job.Errorf("You need to provide your Tutum credentials in ~/.tutum or environment variables TUTUM_USER and TUTUM_APIKEY")
		}
		job.Eng.Register("containers", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/json?all=%s&limit=%s",
				url.QueryEscape(job.Getenv("all")),
				url.QueryEscape(job.Getenv("limit")),
			)
			resp, err := tutumConnectorCall("GET", path, "")
			if err != nil {
				return job.Errorf("%s: get: %v", path, err)
			}
			c := engine.NewTable("Created", 0)
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				return job.Errorf("%s: read body: %v", path, err)
			}
			if _, err := c.ReadListFrom(body); err != nil {
				return job.Errorf("%s: readlist: %v", path, err)
			}
			c.WriteListTo(job.Stdout)
			return engine.StatusOK
		})
		job.Eng.Register("create", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/create",
			)
			config := runconfig.ContainerConfigFromJob(job)
			data, err := json.Marshal(config)
			if err != nil {
				return job.Errorf("%s: json marshal: %v", path, err)
			}
			resp, err := tutumConnectorCall("POST", path, string(data))
			if err != nil {
				return job.Errorf("%s: post: %v", path, err)
			}
			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				return job.Errorf("%s: read body: %#v", path, err)
			}
			var containerOut struct {
				Id       string
				Warnings []string
			}
			err = json.Unmarshal([]byte(body), &containerOut)
			_, err = job.Printf("%s\n", containerOut.Id)
			if err != nil {
				return job.Errorf("%s: write body: %#v", path, err)
			}
			log.Printf("%s", string(body))
			return engine.StatusOK
		})
		job.Eng.Register("container_delete", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s?force=%s",
				job.Args[0],
				url.QueryEscape(job.Getenv("forceRemove")),
			)
			_, err := tutumConnectorCall("DELETE", path, "")
			if err != nil {
				return job.Errorf("%s: delete: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("start", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf("/containers/%s/start", job.Args[0])
			config := runconfig.ContainerConfigFromJob(job)
			data, err := json.Marshal(config)
			if err != nil {
				return job.Errorf("%s: json marshal: %v", path, err)
			}
			_, err = tutumConnectorCall("POST", path, string(data))
			if err != nil {
				return job.Errorf("%s: post: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("stop", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s/stop?t=%s",
				job.Args[0],
				url.QueryEscape(job.Getenv("t")),
			)
			_, err := tutumConnectorCall("POST", path, "")
			if err != nil {
				return job.Errorf("%s: post: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("kill", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s/kill?signal=%s",
				job.Args[0],
				job.Args[1],
			)
			_, err := tutumConnectorCall("POST", path, "")
			if err != nil {
				return job.Errorf("%s: post: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("restart", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s/restart?t=%s",
				job.Args[0],
				url.QueryEscape(job.Getenv("t")),
			)
			_, err := tutumConnectorCall("POST", path, "")
			if err != nil {
				return job.Errorf("%s: post: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("inspect", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s/json",
				job.Args[0],
			)
			resp, err := tutumConnectorCall("GET", path, "")
			if err != nil {
				return job.Errorf("%s: get: %v", path, err)
			}
			_, err = io.Copy(job.Stdout, resp.Body)
			if err != nil {
				return job.Errorf("%s: copy stream: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("logs", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := fmt.Sprintf(
				"/containers/%s/logs?stdout=%s&stderr=%s",
				job.Args[0],
				url.QueryEscape(job.Getenv("stdout")),
				url.QueryEscape(job.Getenv("stderr")),
			)
			resp, err := tutumConnectorCall("GET", path, "")
			if err != nil {
				return job.Errorf("%s: get: %v", path, err)
			}
			_, err = io.Copy(job.Stdout, resp.Body)
			if err != nil {
				return job.Errorf("%s: copy stream: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.Register("version", func(job *engine.Job) engine.Status {
			log.Printf("Received '%s' operation....", job.Name)
			path := "/version"
			resp, err := tutumConnectorCall("GET", path, "")
			if err != nil {
				return job.Errorf("%s: get: %v", path, err)
			}
			_, err = io.Copy(job.Stdout, resp.Body)
			if err != nil {
				return job.Errorf("%s: copy stream: %v", path, err)
			}
			return engine.StatusOK
		})
		job.Eng.RegisterCatchall(func(job *engine.Job) engine.Status {
			return job.Errorf("Operation not yet supported: %s", job.Name)
		})
		return engine.StatusOK
	})
	return nil
}
Example #23
0
func TestGetImagesJSON(t *testing.T) {
	eng := NewTestEngine(t)
	defer mkRuntimeFromEngine(eng, t).Nuke()
	srv := mkServerFromEngine(eng, t)

	job := eng.Job("images")
	initialImages, err := job.Stdout.AddListTable()
	if err != nil {
		t.Fatal(err)
	}
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	req, err := http.NewRequest("GET", "/images/json?all=0", nil)
	if err != nil {
		t.Fatal(err)
	}

	r := httptest.NewRecorder()

	if err := docker.ServeRequest(srv, docker.APIVERSION, r, req); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r, t)

	images := engine.NewTable("Created", 0)
	if _, err := images.ReadListFrom(r.Body.Bytes()); err != nil {
		t.Fatal(err)
	}

	if images.Len() != initialImages.Len() {
		t.Errorf("Expected %d image, %d found", initialImages.Len(), images.Len())
	}

	found := false
	for _, img := range images.Data {
		if strings.Contains(img.GetList("RepoTags")[0], unitTestImageName) {
			found = true
			break
		}
	}
	if !found {
		t.Errorf("Expected image %s, %+v found", unitTestImageName, images)
	}

	r2 := httptest.NewRecorder()

	// all=1

	initialImages = getAllImages(eng, t)

	req2, err := http.NewRequest("GET", "/images/json?all=true", nil)
	if err != nil {
		t.Fatal(err)
	}
	if err := docker.ServeRequest(srv, docker.APIVERSION, r2, req2); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r2, t)

	images2 := engine.NewTable("ID", 0)
	if _, err := images2.ReadListFrom(r2.Body.Bytes()); err != nil {
		t.Fatal(err)
	}

	if images2.Len() != initialImages.Len() {
		t.Errorf("Expected %d image, %d found", initialImages.Len(), images2.Len())
	}

	found = false
	for _, img := range images2.Data {
		if img.Get("ID") == unitTestImageID {
			found = true
			break
		}
	}
	if !found {
		t.Errorf("Retrieved image Id differs, expected %s, received %+v", unitTestImageID, images2)
	}

	r3 := httptest.NewRecorder()

	// filter=a
	req3, err := http.NewRequest("GET", "/images/json?filter=aaaaaaaaaa", nil)
	if err != nil {
		t.Fatal(err)
	}

	if err := docker.ServeRequest(srv, docker.APIVERSION, r3, req3); err != nil {
		t.Fatal(err)
	}
	assertHttpNotError(r3, t)

	images3 := engine.NewTable("ID", 0)
	if _, err := images3.ReadListFrom(r3.Body.Bytes()); err != nil {
		t.Fatal(err)
	}

	if images3.Len() != 0 {
		t.Errorf("Expected 0 image, %d found", images3.Len())
	}
}
Example #24
0
func (rax *RaxCloud) run(ctx *cli.Context, eng *engine.Engine) (err error) {
	if err = rax.configure(ctx); err == nil {
		if _, name, err := rax.findTargetHost(); err == nil {
			if name == "" {
				rax.createHost(DASS_TARGET_PREFIX + RandomString()[:12])
			}
		} else {
			return err
		}

		eng.Register("create", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := "/containers/create"
					config := runconfig.ContainerConfigFromJob(job)

					if data, err := json.Marshal(config); err != nil {
						return job.Errorf("marshaling failure : %v", err)
					} else if resp, err := client.Post(path, string(data)); err != nil {
						return job.Error(err)
					} else {
						var container struct {
							Id       string
							Warnings []string
						}

						if body, err := ioutil.ReadAll(resp.Body); err != nil {
							return job.Errorf("Failed to copy response body: %v", err)
						} else if err := json.Unmarshal([]byte(body), &container); err != nil {
							return job.Errorf("Failed to read container info from body: %v", err)
						} else {
							job.Printf("%s\n", container.Id)
						}
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("container_delete", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s?force=%s", job.Args[0], url.QueryEscape(job.Getenv("forceRemove")))

					if _, err := client.Delete(path, ""); err != nil {
						return job.Error(err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("containers", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/json?all=%s&limit=%s",
						url.QueryEscape(job.Getenv("all")), url.QueryEscape(job.Getenv("limit")))

					if resp, err := client.Get(path, ""); err != nil {
						return job.Error(err)
					} else {
						created := engine.NewTable("Created", 0)

						if body, err := ioutil.ReadAll(resp.Body); err != nil {
							return job.Errorf("Failed to copy response body: %v", err)
						} else if created.ReadListFrom(body); err != nil {
							return job.Errorf("Failed to read list from body: %v", err)
						} else {
							created.WriteListTo(job.Stdout)
						}
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("version", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := "/version"

					if resp, err := client.Get(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					} else if _, err := io.Copy(job.Stdout, resp.Body); err != nil {
						return job.Errorf("Failed to copy response body: %v", err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("start", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/start", job.Args[0])
					config := runconfig.ContainerConfigFromJob(job)

					if data, err := json.Marshal(config); err != nil {
						return job.Errorf("marshaling failure : %v", err)
					} else if _, err := client.Post(path, string(data)); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("stop", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/stop?t=%s", job.Args[0], url.QueryEscape(job.Getenv("t")))

					if _, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("kill", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/kill?signal=%s", job.Args[0], job.Args[1])

					if _, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("restart", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/restart?t=%s", url.QueryEscape(job.Getenv("t")))

					if _, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("inspect", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/json", job.Args[0])

					if resp, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					} else if _, err := io.Copy(job.Stdout, resp.Body); err != nil {
						return job.Errorf("Failed to copy response body: %v", err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("attach", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/attach?stream=%s&stdout=%s&stderr=%s", job.Args[0],
						url.QueryEscape(job.Getenv("stream")),
						url.QueryEscape(job.Getenv("stdout")),
						url.QueryEscape(job.Getenv("stderr")))

					if resp, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					} else if _, err := io.Copy(job.Stdout, resp.Body); err != nil {
						return job.Errorf("Failed to copy response body: %v", err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("pull", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/images/create?fromImage=%s&tag=%s", job.Args[0], url.QueryEscape(job.Getenv("tag")))

					if resp, err := client.Post(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					} else if _, err := io.Copy(job.Stdout, resp.Body); err != nil {
						return job.Errorf("Failed to copy response body: %v", err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.Register("logs", func(job *engine.Job) (status engine.Status) {
			if ctx, err := rax.getHostContext(); err == nil {
				defer ctx.Close()

				return ctx.exec(job, func(client HttpClient) (status engine.Status) {
					path := fmt.Sprintf("/containers/%s/logs?stdout=%s&stderr=%s", job.Args[0], url.QueryEscape(job.Getenv("stdout")), url.QueryEscape(job.Getenv("stderr")))

					if resp, err := client.Get(path, ""); err != nil {
						return job.Errorf("Failed call %s(path:%s): %v", job.Name, path, err)
					} else if _, err := io.Copy(job.Stdout, resp.Body); err != nil {
						return job.Errorf("Failed to copy response body: %v", err)
					}

					return engine.StatusOK
				})
			} else {
				return job.Errorf("Failed to create host context: %v", err)
			}
		})

		eng.RegisterCatchall(func(job *engine.Job) engine.Status {
			log.Printf("[UNIMPLEMENTED] %s %#v %#v %#v", job.Name, *job, job.Env(), job.Args)
			return engine.StatusOK
		})
	}

	return err
}
Example #25
0
func TestRmi(t *testing.T) {
	eng := NewTestEngine(t)
	srv := mkServerFromEngine(eng, t)
	defer mkRuntimeFromEngine(eng, t).Nuke()

	initialImages := getAllImages(eng, t)

	config, hostConfig, _, err := runconfig.Parse([]string{unitTestImageID, "echo", "test"}, nil)
	if err != nil {
		t.Fatal(err)
	}

	containerID := createTestContainer(eng, config, t)

	//To remove
	job := eng.Job("start", containerID)
	if err := job.ImportEnv(hostConfig); err != nil {
		t.Fatal(err)
	}
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	if err := eng.Job("wait", containerID).Run(); err != nil {
		t.Fatal(err)
	}

	job = eng.Job("commit", containerID)
	job.Setenv("repo", "test")
	var imageID string
	job.Stdout.AddString(&imageID)
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	if err := eng.Job("tag", imageID, "test", "0.1").Run(); err != nil {
		t.Fatal(err)
	}

	containerID = createTestContainer(eng, config, t)

	//To remove
	job = eng.Job("start", containerID)
	if err := job.ImportEnv(hostConfig); err != nil {
		t.Fatal(err)
	}
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	if err := eng.Job("wait", containerID).Run(); err != nil {
		t.Fatal(err)
	}

	job = eng.Job("commit", containerID)
	job.Setenv("repo", "test")
	if err := job.Run(); err != nil {
		t.Fatal(err)
	}

	images := getAllImages(eng, t)

	if images.Len()-initialImages.Len() != 2 {
		t.Fatalf("Expected 2 new images, found %d.", images.Len()-initialImages.Len())
	}

	if err = srv.DeleteImage(imageID, engine.NewTable("", 0), true, false, false); err != nil {
		t.Fatal(err)
	}

	images = getAllImages(eng, t)

	if images.Len()-initialImages.Len() != 1 {
		t.Fatalf("Expected 1 new image, found %d.", images.Len()-initialImages.Len())
	}

	for _, image := range images.Data {
		if strings.Contains(unitTestImageID, image.Get("Id")) {
			continue
		}
		if image.GetList("RepoTags")[0] == "<none>:<none>" {
			t.Fatalf("Expected tagged image, got untagged one.")
		}
	}
}
Example #26
0
func TestContainerOrphaning(t *testing.T) {

	// setup a temporary directory
	tmpDir, err := ioutil.TempDir("", "project")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpDir)

	// setup a CLI and server
	cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr)
	defer cleanup(globalEngine, t)
	srv := mkServerFromEngine(globalEngine, t)

	// closure to build something
	buildSomething := func(template string, image string) string {
		dockerfile := path.Join(tmpDir, "Dockerfile")
		replacer := strings.NewReplacer("{IMAGE}", unitTestImageID)
		contents := replacer.Replace(template)
		ioutil.WriteFile(dockerfile, []byte(contents), 0x777)
		if err := cli.CmdBuild("-t", image, tmpDir); err != nil {
			t.Fatal(err)
		}
		img, err := srv.ImageInspect(image)
		if err != nil {
			t.Fatal(err)
		}
		return img.ID
	}

	// build an image
	imageName := "orphan-test"
	template1 := `
	from {IMAGE}
	cmd ["/bin/echo", "holla"]
	`
	img1 := buildSomething(template1, imageName)

	// create a container using the fist image
	if err := cli.CmdRun(imageName); err != nil {
		t.Fatal(err)
	}

	// build a new image that splits lineage
	template2 := `
	from {IMAGE}
	cmd ["/bin/echo", "holla"]
	expose 22
	`
	buildSomething(template2, imageName)

	// remove the second image by name
	resp := engine.NewTable("", 0)
	if err := srv.DeleteImage(imageName, resp, true, false, false); err == nil {
		t.Fatal("Expected error, got none")
	}

	// see if we deleted the first image (and orphaned the container)
	for _, i := range resp.Data {
		if img1 == i.Get("Deleted") {
			t.Fatal("Orphaned image with container")
		}
	}

}