Beispiel #1
0
func postContainersCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := parseForm(r); err != nil {
		return nil
	}
	var (
		out          engine.Env
		job          = eng.Job("create", r.Form.Get("name"))
		outWarnings  []string
		stdoutBuffer = bytes.NewBuffer(nil)
		warnings     = bytes.NewBuffer(nil)
	)
	if err := job.DecodeEnv(r.Body); err != nil {
		return err
	}
	// Read container ID from the first line of stdout
	job.Stdout.Add(stdoutBuffer)
	// Read warnings from stderr
	job.Stderr.Add(warnings)
	if err := job.Run(); err != nil {
		return err
	}
	// Parse warnings from stderr
	scanner := bufio.NewScanner(warnings)
	for scanner.Scan() {
		outWarnings = append(outWarnings, scanner.Text())
	}
	out.Set("Id", engine.Tail(stdoutBuffer, 1))
	out.SetList("Warnings", outWarnings)
	return writeJSON(w, http.StatusCreated, out)
}
Beispiel #2
0
func postCommit(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 (
		config       engine.Env
		env          engine.Env
		job          = eng.Job("commit", r.Form.Get("container"))
		stdoutBuffer = bytes.NewBuffer(nil)
	)
	if err := config.Decode(r.Body); err != nil {
		log.Errorf("%s", err)
	}

	if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
		job.Setenv("pause", "1")
	} else {
		job.Setenv("pause", r.FormValue("pause"))
	}

	job.Setenv("repo", r.Form.Get("repo"))
	job.Setenv("tag", r.Form.Get("tag"))
	job.Setenv("author", r.Form.Get("author"))
	job.Setenv("comment", r.Form.Get("comment"))
	job.SetenvSubEnv("config", &config)

	job.Stdout.Add(stdoutBuffer)
	if err := job.Run(); err != nil {
		return err
	}
	env.Set("Id", engine.Tail(stdoutBuffer, 1))
	return writeJSON(w, http.StatusCreated, env)
}
Beispiel #3
0
func TestMergeConfigOnCommit(t *testing.T) {
	eng := NewTestEngine(t)
	runtime := mkDaemonFromEngine(eng, t)
	defer runtime.Nuke()

	container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
	defer runtime.Destroy(container1)

	config, _, _, err := runconfig.Parse([]string{container1.ID, "cat /tmp/foo"}, nil)
	if err != nil {
		t.Error(err)
	}

	job := eng.Job("commit", container1.ID)
	job.Setenv("repo", "testrepo")
	job.Setenv("tag", "testtag")
	job.SetenvJson("config", config)
	var outputBuffer = bytes.NewBuffer(nil)
	job.Stdout.Add(outputBuffer)
	if err := job.Run(); err != nil {
		t.Error(err)
	}

	container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t)
	defer runtime.Destroy(container2)

	job = eng.Job("container_inspect", container1.Name)
	baseContainer, _ := job.Stdout.AddEnv()
	if err := job.Run(); err != nil {
		t.Error(err)
	}

	job = eng.Job("container_inspect", container2.Name)
	commitContainer, _ := job.Stdout.AddEnv()
	if err := job.Run(); err != nil {
		t.Error(err)
	}

	baseConfig := baseContainer.GetSubEnv("Config")
	commitConfig := commitContainer.GetSubEnv("Config")

	if commitConfig.Get("Env") != baseConfig.Get("Env") {
		t.Fatalf("Env config in committed container should be %v, was %v",
			baseConfig.Get("Env"), commitConfig.Get("Env"))
	}

	if baseConfig.Get("Cmd") != "[\"echo test \\u003e /tmp/foo\"]" {
		t.Fatalf("Cmd in base container should be [\"echo test \\u003e /tmp/foo\"], was %s",
			baseConfig.Get("Cmd"))
	}

	if commitConfig.Get("Cmd") != "[\"cat /tmp/foo\"]" {
		t.Fatalf("Cmd in committed container should be [\"cat /tmp/foo\"], was %s",
			commitConfig.Get("Cmd"))
	}
}
Beispiel #4
0
func createNamedTestContainer(eng *engine.Engine, config *runconfig.Config, f log.Fataler, name string) (shortId string) {
	job := eng.Job("create", name)
	if err := job.ImportEnv(config); err != nil {
		f.Fatal(err)
	}
	var outputBuffer = bytes.NewBuffer(nil)
	job.Stdout.Add(outputBuffer)
	if err := job.Run(); err != nil {
		f.Fatal(err)
	}
	return engine.Tail(outputBuffer, 1)
}
Beispiel #5
0
func TestContainerNameValidation(t *testing.T) {
	eng := NewTestEngine(t)
	daemon := mkDaemonFromEngine(eng, t)
	defer nuke(daemon)

	for _, test := range []struct {
		Name  string
		Valid bool
	}{
		{"abc-123_AAA.1", true},
		{"\000asdf", false},
	} {
		config, _, _, err := runconfig.Parse([]string{unitTestImageID, "echo test"}, nil)
		if err != nil {
			if !test.Valid {
				continue
			}
			t.Fatal(err)
		}

		var outputBuffer = bytes.NewBuffer(nil)
		job := eng.Job("create", test.Name)
		if err := job.ImportEnv(config); err != nil {
			t.Fatal(err)
		}
		job.Stdout.Add(outputBuffer)
		if err := job.Run(); err != nil {
			if !test.Valid {
				continue
			}
			t.Fatal(err)
		}

		container := daemon.Get(engine.Tail(outputBuffer, 1))

		if container.Name != "/"+test.Name {
			t.Fatalf("Expect /%s got %s", test.Name, container.Name)
		}

		if c := daemon.Get("/" + test.Name); c == nil {
			t.Fatalf("Couldn't retrieve test container as /%s", test.Name)
		} else if c.ID != container.ID {
			t.Fatalf("Container /%s has ID %s instead of %s", test.Name, c.ID, container.ID)
		}
	}

}
Beispiel #6
0
func postContainersWait(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if vars == nil {
		return fmt.Errorf("Missing parameter")
	}
	var (
		env          engine.Env
		stdoutBuffer = bytes.NewBuffer(nil)
		job          = eng.Job("wait", vars["name"])
	)
	job.Stdout.Add(stdoutBuffer)
	if err := job.Run(); err != nil {
		return err
	}

	env.Set("StatusCode", engine.Tail(stdoutBuffer, 1))
	return writeJSON(w, http.StatusOK, env)
}
Beispiel #7
0
func postAuth(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	var (
		authConfig, err = ioutil.ReadAll(r.Body)
		job             = eng.Job("auth")
		stdoutBuffer    = bytes.NewBuffer(nil)
	)
	if err != nil {
		return err
	}
	job.Setenv("authConfig", string(authConfig))
	job.Stdout.Add(stdoutBuffer)
	if err = job.Run(); err != nil {
		return err
	}
	if status := engine.Tail(stdoutBuffer, 1); status != "" {
		var env engine.Env
		env.Set("Status", status)
		return writeJSON(w, http.StatusOK, env)
	}
	w.WriteHeader(http.StatusNoContent)
	return nil
}
Beispiel #8
0
func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daemon.Container, string) {
	var (
		err          error
		id           string
		outputBuffer = bytes.NewBuffer(nil)
		strPort      string
		eng          = NewTestEngine(t)
		daemon       = mkDaemonFromEngine(eng, t)
		port         = 5554
		p            nat.Port
	)
	defer func() {
		if err != nil {
			daemon.Nuke()
		}
	}()

	for {
		port += 1
		strPort = strconv.Itoa(port)
		var cmd string
		if proto == "tcp" {
			cmd = "socat TCP-LISTEN:" + strPort + ",reuseaddr,fork EXEC:/bin/cat"
		} else if proto == "udp" {
			cmd = "socat UDP-RECVFROM:" + strPort + ",fork EXEC:/bin/cat"
		} else {
			t.Fatal(fmt.Errorf("Unknown protocol %v", proto))
		}
		ep := make(map[nat.Port]struct{}, 1)
		p = nat.Port(fmt.Sprintf("%s/%s", strPort, proto))
		ep[p] = struct{}{}

		jobCreate := eng.Job("create")
		jobCreate.Setenv("Image", unitTestImageID)
		jobCreate.SetenvList("Cmd", []string{"sh", "-c", cmd})
		jobCreate.SetenvList("PortSpecs", []string{fmt.Sprintf("%s/%s", strPort, proto)})
		jobCreate.SetenvJson("ExposedPorts", ep)
		jobCreate.Stdout.Add(outputBuffer)
		if err := jobCreate.Run(); err != nil {
			t.Fatal(err)
		}
		id = engine.Tail(outputBuffer, 1)
		// FIXME: this relies on the undocumented behavior of daemon.Create
		// which will return a nil error AND container if the exposed ports
		// are invalid. That behavior should be fixed!
		if id != "" {
			break
		}
		t.Logf("Port %v already in use, trying another one", strPort)

	}

	jobStart := eng.Job("start", id)
	portBindings := make(map[nat.Port][]nat.PortBinding)
	portBindings[p] = []nat.PortBinding{
		{},
	}
	if err := jobStart.SetenvJson("PortsBindings", portBindings); err != nil {
		t.Fatal(err)
	}
	if err := jobStart.Run(); err != nil {
		t.Fatal(err)
	}

	container := daemon.Get(id)
	if container == nil {
		t.Fatalf("Couldn't fetch test container %s", id)
	}

	setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
		for !container.State.IsRunning() {
			time.Sleep(10 * time.Millisecond)
		}
	})

	// Even if the state is running, lets give some time to lxc to spawn the process
	container.State.WaitStop(500 * time.Millisecond)

	strPort = container.NetworkSettings.Ports[p][0].HostPort
	return daemon, container, strPort
}