func (s *S) TestNodeContainerDelete(c *check.C) { err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Env: []string{"A=2"}, }, }) c.Assert(err, check.IsNil) request, err := http.NewRequest("DELETE", "/1.2/nodecontainers/c1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) all, err := nodecontainer.AllNodeContainers() c.Assert(err, check.IsNil) c.Assert(all, check.DeepEquals, []nodecontainer.NodeContainerConfigGroup{ {Name: "c1", ConfigPools: map[string]nodecontainer.NodeContainerConfig{ "p1": {Name: "c1", Config: docker.Config{Env: []string{"A=2"}}}, }}, }) c.Assert(eventtest.EventDesc{ Target: event.Target{Type: event.TargetTypeNodeContainer, Value: "c1"}, Owner: s.token.GetUserName(), Kind: "nodecontainer.delete", StartCustomData: []map[string]interface{}{ {"name": ":name", "value": "c1"}, }, }, eventtest.HasEvent) s.provisioner.UpgradeNodeContainer("c1", "p1", ioutil.Discard) request, err = http.NewRequest("DELETE", "/1.2/nodecontainers/c1?pool=p1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder = httptest.NewRecorder() server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) all, err = nodecontainer.AllNodeContainers() c.Assert(err, check.IsNil) c.Assert(all, check.DeepEquals, []nodecontainer.NodeContainerConfigGroup{}) c.Assert(s.provisioner.HasNodeContainer("c1", "p1"), check.Equals, true) }
func (s *S) TestNodeContainerUpgradeNotFound(c *check.C) { err := nodecontainer.AddNewContainer("otherpool", &nodecontainer.NodeContainerConfig{ Name: "c2", PinnedImage: "tsuru/c1@sha256:abcef384829283eff", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) tt := []struct { name string pool string }{ {"c1", ""}, {"c2", "theonepool"}, } server := RunServer(true) for _, t := range tt { recorder := httptest.NewRecorder() form := url.Values{} if t.pool != "" { form.Set("pool", t.pool) } request, errReq := http.NewRequest("POST", "/docker/nodecontainers/"+t.name+"/upgrade", strings.NewReader(form.Encode())) c.Assert(errReq, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusNotFound) } }
func (s *S) TestNodeContainerUpgrade(c *check.C) { err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c1", PinnedImage: "tsuru/c1@sha256:abcef384829283eff", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) recorder := httptest.NewRecorder() request, err := http.NewRequest("POST", "/docker/nodecontainers/c1/upgrade", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) c.Assert(recorder.Header().Get("Content-Type"), check.Equals, "application/x-json-stream") all, err := nodecontainer.AllNodeContainers() c.Assert(err, check.IsNil) c.Assert(all, check.DeepEquals, []nodecontainer.NodeContainerConfigGroup{ {Name: "c1", ConfigPools: map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c1", Config: docker.Config{Env: []string{"A=1"}, Image: "img1"}}, }}, }) c.Assert(eventtest.EventDesc{ Target: event.Target{Type: event.TargetTypeNodeContainer, Value: "c1"}, Owner: s.token.GetUserName(), Kind: "nodecontainer.update.upgrade", StartCustomData: []map[string]interface{}{ {"name": ":name", "value": "c1"}, }, }, eventtest.HasEvent) }
func (s *S) TestNodeContainerUpdateLimited(c *check.C) { err := nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{Name: "c1", Config: docker.Config{Image: "img1"}}) c.Assert(err, check.IsNil) t := userWithPermission(c, permission.Permission{ Scheme: permission.PermNodecontainerUpdate, Context: permission.Context(permission.CtxPool, "p1"), }) values, err := form.EncodeToValues(nodecontainer.NodeContainerConfig{Name: "c1"}) c.Assert(err, check.IsNil) reader := strings.NewReader(values.Encode()) request, err := http.NewRequest("POST", "/1.2/nodecontainers/c1", reader) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+t.GetValue()) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusForbidden) values.Set("pool", "p1") reader = strings.NewReader(values.Encode()) request, err = http.NewRequest("POST", "/1.2/nodecontainers/c1", reader) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+t.GetValue()) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") recorder = httptest.NewRecorder() server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) }
func (s *S) TestEnsureContainersStartedOnlyChild(c *check.C) { err := nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "myregistry/tsuru/bs", }, }) c.Assert(err, check.IsNil) p, err := dockertest.StartMultipleServersCluster() c.Assert(err, check.IsNil) defer p.Destroy() clust := p.Cluster() nodes, err := clust.Nodes() c.Assert(err, check.IsNil) c.Assert(nodes, check.HasLen, 2) nodes[0].Metadata["pool"] = "p1" _, err = p.Cluster().UpdateNode(nodes[0]) c.Assert(err, check.IsNil) nodes[1].Metadata["pool"] = "p2" _, err = p.Cluster().UpdateNode(nodes[1]) c.Assert(err, check.IsNil) buf := safe.NewBuffer(nil) err = ensureContainersStarted(p, buf, true, nil) c.Assert(err, check.IsNil) client, err := docker.NewClient(nodes[0].Address) c.Assert(err, check.IsNil) containers, err := client.ListContainers(docker.ListContainersOptions{All: true}) c.Assert(err, check.IsNil) c.Assert(containers, check.HasLen, 1) client2, err := docker.NewClient(nodes[1].Address) c.Assert(err, check.IsNil) containers2, err := client2.ListContainers(docker.ListContainersOptions{All: true}) c.Assert(err, check.IsNil) c.Assert(containers2, check.HasLen, 0) }
func (s *S) TestNodeContainerListLimited(c *check.C) { err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Env: []string{"A=2"}, }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p3", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Env: []string{"A=3"}, }, }) c.Assert(err, check.IsNil) t := userWithPermission(c, permission.Permission{ Scheme: permission.PermNodecontainerRead, Context: permission.Context(permission.CtxPool, "p3"), }) request, err := http.NewRequest("GET", "/1.2/nodecontainers", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+t.GetValue()) recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) var configEntries []nodecontainer.NodeContainerConfigGroup json.Unmarshal(recorder.Body.Bytes(), &configEntries) sort.Sort(nodecontainer.NodeContainerConfigGroupSlice(configEntries)) c.Assert(configEntries, check.DeepEquals, []nodecontainer.NodeContainerConfigGroup{ {Name: "c1", ConfigPools: map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c1", Config: docker.Config{Image: "img1", Env: []string{"A=1"}}}, "p3": {Name: "c1", Config: docker.Config{Env: []string{"A=3"}}}, }}, }) }
func (s *S) TestEnsureContainersStartedPinImgInChild(c *check.C) { err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "myrootimg", }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "myregistry/tsuru/bs", }, }) c.Assert(err, check.IsNil) server, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) defer server.Stop() server.CustomHandler("/images/create", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) server.DefaultHandler().ServeHTTP(w, r) w.Write([]byte(pullOutputDigest)) })) p, err := dockertest.NewFakeDockerProvisioner(server.URL()) c.Assert(err, check.IsNil) defer p.Destroy() node, err := p.Cluster().GetNode(server.URL()) c.Assert(err, check.IsNil) node.Metadata["pool"] = "p1" _, err = p.Cluster().UpdateNode(node) c.Assert(err, check.IsNil) buf := safe.NewBuffer(nil) err = ensureContainersStarted(p, buf, true, nil) c.Assert(err, check.IsNil) all, err := nodecontainer.LoadNodeContainersForPoolsMerge("c1", false) c.Assert(err, check.IsNil) c.Assert(all, check.DeepEquals, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c1", PinnedImage: "", Config: docker.Config{Image: "myrootimg"}}, "p1": {Name: "c1", PinnedImage: "myregistry/tsuru/bs@" + digest, Config: docker.Config{Image: "myregistry/tsuru/bs"}}, }) }
func (s *S) TestNodeContainerInfo(c *check.C) { err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Env: []string{"A=2"}, }, }) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{ Name: "c2", Config: docker.Config{ Image: "img1", Env: []string{"B=1"}, }, }) c.Assert(err, check.IsNil) request, err := http.NewRequest("GET", "/1.2/nodecontainers/c1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) var configEntries map[string]nodecontainer.NodeContainerConfig json.Unmarshal(recorder.Body.Bytes(), &configEntries) c.Assert(configEntries, check.DeepEquals, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c1", Config: docker.Config{Image: "img1", Env: []string{"A=1"}}}, "p1": {Name: "c1", Config: docker.Config{Env: []string{"A=2"}}}, }) }
func (s *S) TestEnsureContainersStartedAlreadyPinned(c *check.C) { config.Set("docker:bs:image", "myregistry/tsuru/bs") _, err := nodecontainer.InitializeBS() c.Assert(err, check.IsNil) cont, err := nodecontainer.LoadNodeContainer("", nodecontainer.BsDefaultName) c.Assert(err, check.IsNil) cont.PinnedImage = "myregistry/tsuru/bs@" + digest err = nodecontainer.AddNewContainer("", cont) c.Assert(err, check.IsNil) server, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) defer server.Stop() server.CustomHandler("/images/create", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) server.DefaultHandler().ServeHTTP(w, r) w.Write([]byte(pullOutputDigest)) })) p, err := dockertest.NewFakeDockerProvisioner(server.URL()) c.Assert(err, check.IsNil) defer p.Destroy() client, err := docker.NewClient(server.URL()) c.Assert(err, check.IsNil) err = client.PullImage(docker.PullImageOptions{ Repository: "base", }, docker.AuthConfiguration{}) c.Assert(err, check.IsNil) _, err = client.CreateContainer(docker.CreateContainerOptions{ Name: nodecontainer.BsDefaultName, Config: &docker.Config{Image: "base"}, HostConfig: &docker.HostConfig{}, }) c.Assert(err, check.IsNil) buf := safe.NewBuffer(nil) err = ensureContainersStarted(p, buf, true, nil) c.Assert(err, check.IsNil) containers, err := client.ListContainers(docker.ListContainersOptions{All: true}) c.Assert(err, check.IsNil) c.Assert(containers, check.HasLen, 1) container, err := client.InspectContainer(containers[0].ID) c.Assert(err, check.IsNil) c.Assert(container.Name, check.Equals, nodecontainer.BsDefaultName) c.Assert(container.Config.Image, check.Equals, "myregistry/tsuru/bs@"+digest) c.Assert(container.HostConfig.RestartPolicy, check.Equals, docker.AlwaysRestart()) c.Assert(container.State.Running, check.Equals, true) nodeContainer, err := nodecontainer.LoadNodeContainer("", nodecontainer.BsDefaultName) c.Assert(err, check.IsNil) c.Assert(nodeContainer.PinnedImage, check.Equals, "myregistry/tsuru/bs@"+digest) }
// title: node container create // path: /docker/nodecontainers // method: POST // consume: application/x-www-form-urlencoded // responses: // 200: Ok // 400: Invald data // 401: Unauthorized func nodeContainerCreate(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { err = r.ParseForm() if err != nil { return err } dec := form.NewDecoder(nil) dec.IgnoreUnknownKeys(true) dec.IgnoreCase(true) var config nodecontainer.NodeContainerConfig err = dec.DecodeValues(&config, r.Form) if err != nil { return err } poolName := r.FormValue("pool") var ctxs []permission.PermissionContext if poolName != "" { ctxs = append(ctxs, permission.Context(permission.CtxPool, poolName)) } if !permission.Check(t, permission.PermNodecontainerCreate, ctxs...) { return permission.ErrUnauthorized } evt, err := event.New(&event.Opts{ Target: event.Target{Type: event.TargetTypeNodeContainer, Value: config.Name}, Kind: permission.PermNodecontainerCreate, Owner: t, CustomData: event.FormToCustomData(r.Form), Allowed: event.Allowed(permission.PermPoolReadEvents, ctxs...), }) if err != nil { return err } defer func() { evt.Done(err) }() err = nodecontainer.AddNewContainer(poolName, &config) if err != nil { if _, ok := err.(nodecontainer.ValidationErr); ok { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } return err } return nil }
func (s *S) TestLoadNodeContainersForPools(c *check.C) { err := nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "myregistry/tsuru/bs", }, }) c.Assert(err, check.IsNil) result, err := nodecontainer.LoadNodeContainersForPools("c1") c.Assert(err, check.IsNil) c.Assert(result, check.DeepEquals, map[string]nodecontainer.NodeContainerConfig{ "p1": { Name: "c1", Config: docker.Config{ Image: "myregistry/tsuru/bs", }, }, }) }
func (s *S) TestNodeContainerDeleteKillsRunningContainers(c *check.C) { err := nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "img", Env: []string{"A=2"}, }, }) c.Assert(err, check.IsNil) s.provisioner.UpgradeNodeContainer("c1", "p1", ioutil.Discard) c.Assert(s.provisioner.HasNodeContainer("c1", "p1"), check.Equals, true) request, err := http.NewRequest("DELETE", "/1.2/nodecontainers/c1?pool=p1&kill=1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) c.Assert(s.provisioner.HasNodeContainer("c1", "p1"), check.Equals, false) }
func (s *S) TestNodeContainerDeleteNotFound(c *check.C) { err := nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{ Name: "c1", Config: docker.Config{ Image: "img1", Env: []string{"A=1"}, }, }) c.Assert(err, check.IsNil) request, err := http.NewRequest("DELETE", "/1.2/nodecontainers/c1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusNotFound) c.Assert(recorder.Body.String(), check.Equals, "node container \"c1\" not found for pool \"\"\n") request, err = http.NewRequest("DELETE", "/1.2/nodecontainers/c1?pool=p1", nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder = httptest.NewRecorder() server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) }
func (s *S) TestServiceSpecForNodeContainer(c *check.C) { c1 := nodecontainer.NodeContainerConfig{ Name: "swarmbs", Config: docker.Config{ Image: "bsimg", Env: []string{ "A=1", "B=2", }, Labels: map[string]string{"label1": "val1"}, }, HostConfig: docker.HostConfig{ RestartPolicy: docker.AlwaysRestart(), Privileged: true, Binds: []string{"/xyz:/abc:ro"}, }, } err := nodecontainer.AddNewContainer("", &c1) c.Assert(err, check.IsNil) serviceSpec, err := serviceSpecForNodeContainer("swarmbs", "") c.Assert(err, check.IsNil) expectedLabels := map[string]string{ "label1": "val1", "tsuru.nodecontainer.name": "swarmbs", "tsuru.nodecontainer": "true", "tsuru.node.pool": "", "tsuru.node.provisioner": "swarm", } expected := &swarm.ServiceSpec{ Annotations: swarm.Annotations{ Name: "node-container-swarmbs-all", Labels: expectedLabels, }, Mode: swarm.ServiceMode{Global: &swarm.GlobalService{}}, TaskTemplate: swarm.TaskSpec{ ContainerSpec: swarm.ContainerSpec{ Image: "bsimg", Env: []string{"A=1", "B=2"}, Labels: expectedLabels, Mounts: []mount.Mount{ { Type: mount.TypeBind, Source: "/xyz", Target: "/abc", ReadOnly: true, }, }, }, Placement: &swarm.Placement{Constraints: []string(nil)}, }, } c.Assert(serviceSpec, check.DeepEquals, expected) err = nodecontainer.AddNewContainer("p1", &c1) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("p2", &c1) c.Assert(err, check.IsNil) serviceSpec, err = serviceSpecForNodeContainer("swarmbs", "p1") c.Assert(err, check.IsNil) c.Assert(serviceSpec.TaskTemplate.Placement.Constraints, check.DeepEquals, []string{"node.labels.pool == p1"}) serviceSpec, err = serviceSpecForNodeContainer("swarmbs", "") c.Assert(err, check.IsNil) constraints := sort.StringSlice(serviceSpec.TaskTemplate.Placement.Constraints) constraints.Sort() c.Assert([]string(constraints), check.DeepEquals, []string{"node.labels.pool != p1", "node.labels.pool != p2"}) }
func (s *S) TestEnsureContainersStarted(c *check.C) { c1 := nodecontainer.NodeContainerConfig{ Name: "bs", Config: docker.Config{ Image: "bsimg", Env: []string{ "A=1", "B=2", }, }, HostConfig: docker.HostConfig{ RestartPolicy: docker.AlwaysRestart(), Privileged: true, Binds: []string{"/xyz:/abc:rw"}, }, } err := nodecontainer.AddNewContainer("", &c1) c.Assert(err, check.IsNil) c2 := c1 c2.Name = "sysdig" c2.Config.Image = "sysdigimg" c2.Config.Env = []string{"X=Z"} err = nodecontainer.AddNewContainer("", &c2) c.Assert(err, check.IsNil) p, err := dockertest.StartMultipleServersCluster() c.Assert(err, check.IsNil) nodes, err := p.Cluster().Nodes() c.Assert(err, check.IsNil) for i, n := range nodes { n.Metadata["pool"] = fmt.Sprintf("p-%d", i) _, err = p.Cluster().UpdateNode(n) c.Assert(err, check.IsNil) } var createBodies []string var names []string var mut sync.Mutex server := p.Servers()[0] server.CustomHandler("/containers/create", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mut.Lock() defer mut.Unlock() data, _ := ioutil.ReadAll(r.Body) createBodies = append(createBodies, string(data)) names = append(names, r.URL.Query().Get("name")) r.Body = ioutil.NopCloser(bytes.NewBuffer(data)) server.DefaultHandler().ServeHTTP(w, r) })) defer p.Destroy() buf := safe.NewBuffer(nil) err = ensureContainersStarted(p, buf, true, nil) c.Assert(err, check.IsNil) parts := strings.Split(buf.String(), "\n") c.Assert(parts, check.HasLen, 5) sort.Strings(parts) c.Assert(parts[1], check.Matches, `relaunching node container "bs" in the node http://127.0.0.1:\d+/ \[p-0\]`) c.Assert(parts[2], check.Matches, `relaunching node container "bs" in the node http://localhost:\d+/ \[p-1\]`) c.Assert(parts[3], check.Matches, `relaunching node container "sysdig" in the node http://127.0.0.1:\d+/ \[p-0\]`) c.Assert(parts[4], check.Matches, `relaunching node container "sysdig" in the node http://localhost:\d+/ \[p-1\]`) c.Assert(createBodies, check.HasLen, 2) c.Assert(names, check.HasLen, 2) sort.Strings(names) c.Assert(names, check.DeepEquals, []string{"bs", "sysdig"}) sort.Strings(createBodies) result := make([]struct { docker.Config HostConfig docker.HostConfig }, 2) err = json.Unmarshal([]byte(createBodies[0]), &result[0]) c.Assert(err, check.IsNil) err = json.Unmarshal([]byte(createBodies[1]), &result[1]) c.Assert(err, check.IsNil) c.Assert(result, check.DeepEquals, []struct { docker.Config HostConfig docker.HostConfig }{ { Config: docker.Config{Env: []string{"DOCKER_ENDPOINT=" + server.URL(), "A=1", "B=2"}, Image: "bsimg", Labels: map[string]string{ "tsuru.node.address": server.URL(), "tsuru.node.pool": "p-0", "tsuru.node.provisioner": "fake", "tsuru.nodecontainer": "true", }}, HostConfig: docker.HostConfig{ Binds: []string{"/xyz:/abc:rw"}, Privileged: true, RestartPolicy: docker.RestartPolicy{Name: "always"}, LogConfig: docker.LogConfig{}, }, }, { Config: docker.Config{Env: []string{"DOCKER_ENDPOINT=" + server.URL(), "X=Z"}, Image: "sysdigimg", Labels: map[string]string{ "tsuru.node.address": server.URL(), "tsuru.node.pool": "p-0", "tsuru.node.provisioner": "fake", "tsuru.nodecontainer": "true", }}, HostConfig: docker.HostConfig{ Binds: []string{"/xyz:/abc:rw"}, Privileged: true, RestartPolicy: docker.RestartPolicy{Name: "always"}, LogConfig: docker.LogConfig{}, }, }, }) nodeContainer, err := nodecontainer.LoadNodeContainer("", nodecontainer.BsDefaultName) c.Assert(err, check.IsNil) c.Assert(nodeContainer.PinnedImage, check.Equals, "") client, err := docker.NewClient(p.Servers()[0].URL()) c.Assert(err, check.IsNil) containers, err := client.ListContainers(docker.ListContainersOptions{All: true}) c.Assert(err, check.IsNil) c.Assert(containers, check.HasLen, 2) client, err = docker.NewClient(p.Servers()[1].URL()) c.Assert(err, check.IsNil) containers, err = client.ListContainers(docker.ListContainersOptions{All: true}) c.Assert(err, check.IsNil) c.Assert(containers, check.HasLen, 2) }
func migrateBSEnvs() error { scheme, err := config.GetString("auth:scheme") if err != nil { scheme = nativeSchemeName } app.AuthScheme, err = auth.GetScheme(scheme) if err != nil { return err } _, err = nodecontainer.InitializeBS() if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() var entry map[string]interface{} err = conn.Collection("bsconfig").FindId("bs").One(&entry) if err != nil { if err == mgo.ErrNotFound { return nil } return err } image, _ := entry["image"].(string) envs, _ := entry["envs"].([]interface{}) var baseEnvs []string for _, envEntry := range envs { mapEntry, _ := envEntry.(map[string]interface{}) if mapEntry == nil { continue } name, _ := mapEntry["name"].(string) value, _ := mapEntry["value"].(string) baseEnvs = append(baseEnvs, fmt.Sprintf("%s=%s", name, value)) } bsNodeContainer, err := nodecontainer.LoadNodeContainer("", nodecontainer.BsDefaultName) if err != nil { return err } if len(baseEnvs) > 0 { bsNodeContainer.Config.Env = append(bsNodeContainer.Config.Env, baseEnvs...) } bsNodeContainer.PinnedImage = image err = nodecontainer.AddNewContainer("", bsNodeContainer) if err != nil { return err } pools, _ := entry["pools"].([]interface{}) for _, poolData := range pools { poolMap, _ := poolData.(map[string]interface{}) if poolMap == nil { continue } poolName, _ := poolMap["name"].(string) if poolName == "" { continue } envs, _ := poolMap["envs"].([]interface{}) var toAdd []string for _, envEntry := range envs { mapEntry, _ := envEntry.(map[string]interface{}) if mapEntry == nil { continue } name, _ := mapEntry["name"].(string) value, _ := mapEntry["value"].(string) toAdd = append(toAdd, fmt.Sprintf("%s=%s", name, value)) } if len(toAdd) > 0 { bsCont := nodecontainer.NodeContainerConfig{Name: nodecontainer.BsDefaultName} bsCont.Config.Env = append(bsCont.Config.Env, toAdd...) err = nodecontainer.AddNewContainer(poolName, &bsCont) if err != nil { return err } } } return nil }
func (s *S) TestNodeContainerUpdate(c *check.C) { doReq := func(cont nodecontainer.NodeContainerConfig, expected map[string]nodecontainer.NodeContainerConfig, pool ...string) { values, err := form.EncodeToValues(cont) c.Assert(err, check.IsNil) if len(pool) > 0 { values.Set("pool", pool[0]) } reader := strings.NewReader(values.Encode()) request, err := http.NewRequest("POST", "/1.2/nodecontainers/"+cont.Name, reader) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") recorder := httptest.NewRecorder() server := RunServer(true) server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) request, err = http.NewRequest("GET", "/1.2/nodecontainers/"+cont.Name, nil) c.Assert(err, check.IsNil) request.Header.Set("Authorization", "bearer "+s.token.GetValue()) recorder = httptest.NewRecorder() server.ServeHTTP(recorder, request) c.Assert(recorder.Code, check.Equals, http.StatusOK) var configEntries map[string]nodecontainer.NodeContainerConfig json.Unmarshal(recorder.Body.Bytes(), &configEntries) if len(pool) > 0 { for _, p := range pool { sort.Strings(configEntries[p].Config.Env) sort.Strings(expected[p].Config.Env) } } sort.Strings(configEntries[""].Config.Env) sort.Strings(expected[""].Config.Env) c.Assert(configEntries, check.DeepEquals, expected) } err := nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{Name: "c1", Config: docker.Config{Image: "img1"}}) c.Assert(err, check.IsNil) err = nodecontainer.AddNewContainer("", &nodecontainer.NodeContainerConfig{Name: "c2", Config: docker.Config{Image: "img2"}}) c.Assert(err, check.IsNil) doReq(nodecontainer.NodeContainerConfig{Name: "c1"}, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c1", Config: docker.Config{Image: "img1"}}, }) c.Assert(eventtest.EventDesc{ Target: event.Target{Type: event.TargetTypeNodeContainer, Value: "c1"}, Owner: s.token.GetUserName(), Kind: "nodecontainer.update", StartCustomData: []map[string]interface{}{ {"name": "Name", "value": "c1"}, }, }, eventtest.HasEvent) doReq(nodecontainer.NodeContainerConfig{ Name: "c2", Config: docker.Config{Env: []string{"A=1"}}, HostConfig: docker.HostConfig{Memory: 256, Privileged: true}, }, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c2", Config: docker.Config{Env: []string{"A=1"}, Image: "img2"}, HostConfig: docker.HostConfig{Memory: 256, Privileged: true}}, }) doReq(nodecontainer.NodeContainerConfig{ Name: "c2", Config: docker.Config{Env: []string{"Z=9"}}, HostConfig: docker.HostConfig{Memory: 256}, }, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c2", Config: docker.Config{Env: []string{"A=1", "Z=9"}, Image: "img2"}, HostConfig: docker.HostConfig{Memory: 256, Privileged: true}}, }) err = nodecontainer.AddNewContainer("p1", &nodecontainer.NodeContainerConfig{Name: "c2"}) c.Assert(err, check.IsNil) doReq(nodecontainer.NodeContainerConfig{ Name: "c2", Config: docker.Config{Env: []string{"X=1"}}, }, map[string]nodecontainer.NodeContainerConfig{ "": {Name: "c2", Config: docker.Config{Env: []string{"A=1", "Z=9"}, Image: "img2"}, HostConfig: docker.HostConfig{Memory: 256, Privileged: true}}, "p1": {Name: "c2", Config: docker.Config{Env: []string{"X=1"}}}, }, "p1") }