func (s *S) TestDeleteAllAppImageNamesSimilarApps(c *check.C) { data := map[string]interface{}{"healthcheck": map[string]interface{}{"path": "/test"}} err := image.AppendAppImageName("myapp", "tsuru/app-myapp:v1") c.Assert(err, check.IsNil) err = image.SaveImageCustomData("tsuru/app-myapp:v1", data) c.Assert(err, check.IsNil) err = image.AppendAppImageName("myapp-dev", "tsuru/app-myapp-dev:v1") c.Assert(err, check.IsNil) err = image.SaveImageCustomData("tsuru/app-myapp-dev:v1", data) c.Assert(err, check.IsNil) err = image.DeleteAllAppImageNames("myapp") c.Assert(err, check.IsNil) _, err = image.ListAppImages("myapp") c.Assert(err, check.ErrorMatches, "not found") _, err = image.ListAppImages("myapp-dev") c.Assert(err, check.IsNil) yamlData, err := image.GetImageTsuruYamlData("tsuru/app-myapp:v1") c.Assert(err, check.IsNil) c.Assert(yamlData, check.DeepEquals, provision.TsuruYamlData{}) yamlData, err = image.GetImageTsuruYamlData("tsuru/app-myapp-dev:v1") c.Assert(err, check.IsNil) c.Assert(yamlData, check.DeepEquals, provision.TsuruYamlData{ Healthcheck: provision.TsuruYamlHealthcheck{Path: "/test"}, }) }
func (s *S) TestGetImageWebProcessName(c *check.C) { img1 := "tsuru/app-myapp:v1" customData1 := map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapp.py", "worker": "someworker", }, } err := image.SaveImageCustomData(img1, customData1) c.Assert(err, check.IsNil) img2 := "tsuru/app-myapp:v2" customData2 := map[string]interface{}{ "processes": map[string]interface{}{ "worker1": "python myapp.py", "worker2": "someworker", }, } err = image.SaveImageCustomData(img2, customData2) c.Assert(err, check.IsNil) img3 := "tsuru/app-myapp:v3" customData3 := map[string]interface{}{ "processes": map[string]interface{}{ "api": "python myapi.py", }, } err = image.SaveImageCustomData(img3, customData3) c.Assert(err, check.IsNil) img4 := "tsuru/app-myapp:v4" customData4 := map[string]interface{}{} err = image.SaveImageCustomData(img4, customData4) c.Assert(err, check.IsNil) web1, err := image.GetImageWebProcessName(img1) c.Check(err, check.IsNil) c.Check(web1, check.Equals, "web") web2, err := image.GetImageWebProcessName(img2) c.Check(err, check.IsNil) c.Check(web2, check.Equals, "web") web3, err := image.GetImageWebProcessName(img3) c.Check(err, check.IsNil) c.Check(web3, check.Equals, "api") web4, err := image.GetImageWebProcessName(img4) c.Check(err, check.IsNil) c.Check(web4, check.Equals, "") img5 := "tsuru/app-myapp:v5" web5, err := image.GetImageWebProcessName(img5) c.Check(err, check.IsNil) c.Check(web5, check.Equals, "") }
func (s *S) TestSwarmNodeUnits(c *check.C) { srv, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) defer srv.Stop() opts := provision.AddNodeOptions{Address: srv.URL()} err = s.p.AddNode(opts) c.Assert(err, check.IsNil) nodes, err := s.p.ListNodes(nil) c.Assert(err, check.IsNil) c.Assert(nodes, check.HasLen, 1) units, err := nodes[0].Units() c.Assert(err, check.IsNil) c.Assert(units, check.HasLen, 0) a := &app.App{Name: "myapp", TeamOwner: s.team.Name, Deploys: 1} err = app.CreateApp(a, s.user) c.Assert(err, check.IsNil) imgName := "myapp:v1" err = image.SaveImageCustomData(imgName, map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapp.py", }, }) c.Assert(err, check.IsNil) err = image.AppendAppImageName(a.GetName(), imgName) c.Assert(err, check.IsNil) err = s.p.AddUnits(a, 1, "web", nil) c.Assert(err, check.IsNil) units, err = nodes[0].Units() c.Assert(err, check.IsNil) c.Assert(units, check.HasLen, 1) }
func (s *S) TestHealthcheckErrorsAfterMaxTime(c *check.C) { a := app.App{Name: "myapp1"} imageName := "tsuru/app" customData := map[string]interface{}{ "healthcheck": map[string]interface{}{ "path": "/x/y", }, } err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) err = s.storage.Apps().Insert(a) c.Assert(err, check.IsNil) defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name}) url, _ := url.Parse("http://some-invalid-server-name.some-invalid-server-name.com:9123") host, port, _ := net.SplitHostPort(url.Host) cont := container.Container{AppName: a.Name, HostAddr: host, HostPort: port, Image: imageName} buf := bytes.Buffer{} config.Set("docker:healthcheck:max-time", -1) defer config.Unset("docker:healthcheck:max-time") done := make(chan struct{}) go func() { err = runHealthcheck(&cont, &buf) close(done) }() select { case <-time.After(5 * time.Second): c.Fatal("Timed out waiting for healthcheck to fail") case <-done: } c.Assert(err, check.ErrorMatches, "healthcheck fail.*lookup some-invalid-server-name.some-invalid-server-name.com.*no such host") }
func (s *S) TestSetRouterHealthcheckBackward(c *check.C) { app := provisiontest.NewFakeApp("myapp", "python", 1) imageName := "tsuru/img1" customData := map[string]interface{}{ "healthcheck": map[string]interface{}{ "path": "/x/y", "status": http.StatusCreated, "match": "ignored", "use_in_router": true, }, } err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) routertest.FakeRouter.AddBackend(app.GetName()) defer routertest.FakeRouter.RemoveBackend(app.GetName()) args := changeUnitsPipelineArgs{ app: app, provisioner: s.p, imageId: imageName, } cont1 := container.Container{ID: "ble-1", AppName: app.GetName(), ProcessName: "web", HostAddr: "127.0.0.1", HostPort: "1234"} context := action.FWContext{Previous: []container.Container{cont1}, Params: []interface{}{args}} _, err = setRouterHealthcheck.Forward(context) c.Assert(err, check.IsNil) hcData := routertest.FakeRouter.GetHealthcheck(app.GetName()) c.Assert(hcData, check.DeepEquals, router.HealthcheckData{ Path: "/x/y", Status: http.StatusCreated, }) bwcontext := action.BWContext{Params: []interface{}{args}} setRouterHealthcheck.Backward(bwcontext) hcData = routertest.FakeRouter.GetHealthcheck(app.GetName()) c.Assert(hcData, check.DeepEquals, router.HealthcheckData{Path: "/"}) }
func (s *S) TestAddNewRouteForwardNoWeb(c *check.C) { app := provisiontest.NewFakeApp("myapp", "python", 1) routertest.FakeRouter.AddBackend(app.GetName()) defer routertest.FakeRouter.RemoveBackend(app.GetName()) imageName := "tsuru/app-" + app.GetName() customData := map[string]interface{}{ "processes": map[string]interface{}{ "api": "python myapi.py", }, } err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) cont1 := container.Container{ID: "ble-1", AppName: app.GetName(), ProcessName: "api", HostAddr: "127.0.0.1", HostPort: "1234"} cont2 := container.Container{ID: "ble-2", AppName: app.GetName(), ProcessName: "api", HostAddr: "127.0.0.2", HostPort: "4321"} defer cont1.Remove(s.p) defer cont2.Remove(s.p) args := changeUnitsPipelineArgs{ app: app, provisioner: s.p, imageId: imageName, } context := action.FWContext{Previous: []container.Container{cont1, cont2}, Params: []interface{}{args}} r, err := addNewRoutes.Forward(context) c.Assert(err, check.IsNil) containers := r.([]container.Container) hasRoute := routertest.FakeRouter.HasRoute(app.GetName(), cont1.Address().String()) c.Assert(hasRoute, check.Equals, true) hasRoute = routertest.FakeRouter.HasRoute(app.GetName(), cont2.Address().String()) c.Assert(hasRoute, check.Equals, true) c.Assert(containers, check.HasLen, 2) c.Assert(containers[0].Routable, check.Equals, true) c.Assert(containers[0].ID, check.Equals, "ble-1") c.Assert(containers[1].Routable, check.Equals, true) c.Assert(containers[1].ID, check.Equals, "ble-2") }
func (s *S) TestHealthcheckDefaultCheck(c *check.C) { var requests []*http.Request server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requests = append(requests, r) w.WriteHeader(http.StatusOK) })) defer server.Close() a := app.App{Name: "myapp1"} imageName := "tsuru/app" customData := map[string]interface{}{ "healthcheck": map[string]interface{}{ "path": "/x/y", }, } err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) err = s.storage.Apps().Insert(a) c.Assert(err, check.IsNil) defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name}) url, _ := url.Parse(server.URL) host, port, _ := net.SplitHostPort(url.Host) cont := container.Container{AppName: a.Name, HostAddr: host, HostPort: port, Image: imageName} buf := bytes.Buffer{} err = runHealthcheck(&cont, &buf) c.Assert(err, check.IsNil) c.Assert(requests, check.HasLen, 1) c.Assert(requests[0].Method, check.Equals, "GET") c.Assert(requests[0].URL.Path, check.Equals, "/x/y") }
func (s *S) TestActionUpdateServicesForwardUpdateExisting(c *check.C) { srv, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) metadata := map[string]string{"m1": "v1", labelNodePoolName.String(): "p1"} opts := provision.AddNodeOptions{ Address: srv.URL(), Metadata: metadata, } err = s.p.AddNode(opts) c.Assert(err, check.IsNil) cli, err := chooseDBSwarmNode() c.Assert(err, check.IsNil) _, err = cli.CreateService(docker.CreateServiceOptions{ ServiceSpec: swarm.ServiceSpec{ TaskTemplate: swarm.TaskSpec{ ContainerSpec: swarm.ContainerSpec{ Command: []string{"oldcmd"}, }, }, Annotations: swarm.Annotations{ Name: "myapp-web", }, }, }) c.Assert(err, check.IsNil) a := &app.App{Name: "myapp", Platform: "whitespace", TeamOwner: s.team.Name} err = app.CreateApp(a, s.user) c.Assert(err, check.IsNil) imgName := "app:v1" err = image.SaveImageCustomData(imgName, map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapp.py", }, }) c.Assert(err, check.IsNil) args := &pipelineArgs{ client: cli, app: a, newImage: imgName, newImageSpec: processSpec{"web": processState{}}, currentImageSpec: processSpec{}, } processes, err := updateServices.Forward(action.FWContext{Params: []interface{}{args}}) c.Assert(err, check.IsNil) c.Assert(processes, check.DeepEquals, []string{"web"}) service, err := cli.InspectService("myapp-web") c.Assert(err, check.IsNil) c.Assert(service.Spec.TaskTemplate.ContainerSpec.Command, check.DeepEquals, []string{ "/bin/sh", "-lc", fmt.Sprintf( "[ -d /home/application/current ] && cd /home/application/current; %s && exec python myapp.py", extraRegisterCmds(a), ), }) }
func (s *S) TestSavePortInImageCustomData(c *check.C) { img1 := "tsuru/app-myapp:v1" customData1 := map[string]interface{}{ "exposedPort": "3434", } err := image.SaveImageCustomData(img1, customData1) c.Assert(err, check.IsNil) imageMetaData, err := image.GetImageCustomData(img1) c.Check(err, check.IsNil) c.Check(imageMetaData.ExposedPort, check.Equals, "3434") }
func (s *S) TestDeleteAllAppImageNamesRemovesCustomDataWithoutImages(c *check.C) { imgName := "tsuru/app-myapp:v1" data := map[string]interface{}{"healthcheck": map[string]interface{}{"path": "/test"}} err := image.SaveImageCustomData(imgName, data) c.Assert(err, check.IsNil) err = image.DeleteAllAppImageNames("myapp") c.Assert(err, check.ErrorMatches, "not found") yamlData, err := image.GetImageTsuruYamlData(imgName) c.Assert(err, check.IsNil) c.Assert(yamlData, check.DeepEquals, provision.TsuruYamlData{}) }
func (s *S) TestActionUpdateServicesBackwardNotInCurrent(c *check.C) { srv, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) metadata := map[string]string{"m1": "v1", labelNodePoolName.String(): "p1"} opts := provision.AddNodeOptions{ Address: srv.URL(), Metadata: metadata, } err = s.p.AddNode(opts) c.Assert(err, check.IsNil) cli, err := chooseDBSwarmNode() c.Assert(err, check.IsNil) a := &app.App{Name: "myapp", Platform: "whitespace", TeamOwner: s.team.Name} err = app.CreateApp(a, s.user) c.Assert(err, check.IsNil) _, err = cli.CreateService(docker.CreateServiceOptions{ ServiceSpec: swarm.ServiceSpec{ TaskTemplate: swarm.TaskSpec{ ContainerSpec: swarm.ContainerSpec{ Command: []string{"original-web"}, }, }, Annotations: swarm.Annotations{ Name: "myapp-web", }, }, }) c.Assert(err, check.IsNil) imgName := "app:v1" err = image.SaveImageCustomData(imgName, map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapp.py", }, }) c.Assert(err, check.IsNil) args := &pipelineArgs{ client: cli, app: a, currentImage: imgName, newImageSpec: processSpec{"web": processState{}}, currentImageSpec: processSpec{}, } updateServices.Backward(action.BWContext{ FWResult: []string{"web"}, Params: []interface{}{args}, }) _, err = cli.InspectService("myapp-web") c.Assert(err, check.ErrorMatches, "No such service.*") }
func (s *S) TestRunLeanContainersCmd(c *check.C) { imageId := "tsuru/app-sample" customData := map[string]interface{}{ "processes": map[string]interface{}{ "web": "python web.py", }, } err := image.SaveImageCustomData(imageId, customData) c.Assert(err, check.IsNil) cmds, process, err := LeanContainerCmds("web", imageId, nil) c.Assert(err, check.IsNil) c.Assert(process, check.Equals, "web") expected := []string{"/bin/sh", "-lc", "[ -d /home/application/current ] && cd /home/application/current; exec python web.py"} c.Assert(cmds, check.DeepEquals, expected) }
func (s *S) TestHealthcheckSuccessfulWithAllowedFailures(c *check.C) { var requests []*http.Request lock := sync.Mutex{} step := 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { lock.Lock() defer lock.Unlock() requests = append(requests, r) if step == 2 { w.WriteHeader(http.StatusOK) } else if step == 1 { w.WriteHeader(http.StatusBadGateway) } else { hj := w.(http.Hijacker) conn, _, _ := hj.Hijack() conn.Close() } step++ })) defer server.Close() a := app.App{Name: "myapp1"} customData := map[string]interface{}{ "healthcheck": map[string]interface{}{ "path": "/x/y", "allowed_failures": 1, }, } imageName := "tsuru/app" err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) err = s.storage.Apps().Insert(a) c.Assert(err, check.IsNil) defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name}) url, _ := url.Parse(server.URL) host, port, _ := net.SplitHostPort(url.Host) cont := container.Container{AppName: a.Name, HostAddr: host, HostPort: port, Image: imageName} buf := bytes.Buffer{} err = runHealthcheck(&cont, &buf) c.Assert(err, check.IsNil) c.Assert(buf.String(), check.Matches, `(?s).*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck fail.*?Trying again in 3s.*---> healthcheck successful.*`) c.Assert(requests, check.HasLen, 3) c.Assert(requests[0].Method, check.Equals, "GET") c.Assert(requests[0].URL.Path, check.Equals, "/x/y") c.Assert(requests[1].Method, check.Equals, "GET") c.Assert(requests[1].URL.Path, check.Equals, "/x/y") c.Assert(requests[2].Method, check.Equals, "GET") c.Assert(requests[2].URL.Path, check.Equals, "/x/y") }
func (s *S) newFakeImage(p *dockerProvisioner, repo string, customData map[string]interface{}) error { if customData == nil { customData = map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapp.py", }, } } var buf safe.Buffer opts := docker.PullImageOptions{Repository: repo, OutputStream: &buf} err := image.SaveImageCustomData(repo, customData) if err != nil && !mgo.IsDup(err) { return err } return p.Cluster().PullImage(opts, docker.AuthConfiguration{}) }
func (s *S) TestSaveImageCustomDataProcfile(c *check.C) { img1 := "tsuru/app-myapp:v1" customData1 := map[string]interface{}{ "exposedPort": "3434", "procfile": "worker1: python myapp.py\nworker2: someworker", } err := image.SaveImageCustomData(img1, customData1) c.Assert(err, check.IsNil) imageMetaData, err := image.GetImageCustomData(img1) c.Check(err, check.IsNil) c.Check(imageMetaData.ExposedPort, check.Equals, "3434") c.Check(imageMetaData.Processes, check.DeepEquals, map[string][]string{ "worker1": {"python myapp.py"}, "worker2": {"someworker"}, }) }
func (p *dockerProvisioner) RegisterUnit(a provision.App, unitId string, customData map[string]interface{}) error { cont, err := p.GetContainer(unitId) if err != nil { return err } if cont.Status == provision.StatusBuilding.String() { if cont.BuildingImage != "" && customData != nil { return image.SaveImageCustomData(cont.BuildingImage, customData) } return nil } err = cont.SetStatus(p, provision.StatusStarted, true) if err != nil { return err } return p.checkContainer(cont) }
func (s *S) TestRunLeanContainersCmdInvalidProcess(c *check.C) { imageId := "tsuru/app-sample" customData := map[string]interface{}{ "processes": map[string]interface{}{ "web": "python web.py", }, } err := image.SaveImageCustomData(imageId, customData) c.Assert(err, check.IsNil) cmds, process, err := LeanContainerCmds("worker", imageId, nil) c.Assert(err, check.NotNil) e, ok := err.(provision.InvalidProcessError) c.Assert(ok, check.Equals, true) c.Assert(e.Msg, check.Equals, `no command declared in Procfile for process "worker"`) c.Assert(process, check.Equals, "") c.Assert(cmds, check.IsNil) }
func (s *S) TestRunLeanContainersCmdNoProcessSpecified(c *check.C) { imageId := "tsuru/app-sample" customData := map[string]interface{}{ "processes": map[string]interface{}{ "web": "python web.py", "worker": "python worker.py", }, } err := image.SaveImageCustomData(imageId, customData) c.Assert(err, check.IsNil) cmds, process, err := LeanContainerCmds("", imageId, nil) c.Assert(err, check.NotNil) e, ok := err.(provision.InvalidProcessError) c.Assert(ok, check.Equals, true) c.Assert(e.Msg, check.Equals, "no process name specified and more than one declared in Procfile") c.Assert(process, check.Equals, "") c.Assert(cmds, check.IsNil) }
func (s *S) TestPullAppImageNamesRemovesCustomData(c *check.C) { img1Name := "tsuru/app-myapp:v1" err := image.AppendAppImageName("myapp", img1Name) c.Assert(err, check.IsNil) err = image.AppendAppImageName("myapp", "tsuru/app-myapp:v2") c.Assert(err, check.IsNil) err = image.AppendAppImageName("myapp", "tsuru/app-myapp:v3") c.Assert(err, check.IsNil) data := map[string]interface{}{"healthcheck": map[string]interface{}{"path": "/test"}} err = image.SaveImageCustomData(img1Name, data) c.Assert(err, check.IsNil) err = image.PullAppImageNames("myapp", []string{img1Name}) c.Assert(err, check.IsNil) images, err := image.ListAppImages("myapp") c.Assert(err, check.IsNil) c.Assert(images, check.DeepEquals, []string{"tsuru/app-myapp:v2", "tsuru/app-myapp:v3"}) yamlData, err := image.GetImageTsuruYamlData(img1Name) c.Assert(err, check.IsNil) c.Assert(yamlData, check.DeepEquals, provision.TsuruYamlData{}) }
func (s *S) TestRunLeanContainersCmdNoProcesses(c *check.C) { imageId := "tsuru/app-sample" customData := map[string]interface{}{} err := image.SaveImageCustomData(imageId, customData) c.Assert(err, check.IsNil) app := provisiontest.NewFakeApp("app-name", "python", 1) config.Set("host", "tsuru_host") defer config.Unset("host") tokenEnv := bind.EnvVar{ Name: "TSURU_APP_TOKEN", Value: "app_token", Public: true, } app.SetEnv(tokenEnv) cmds, process, err := LeanContainerCmds("", imageId, app) c.Assert(err, check.IsNil) c.Assert(process, check.Equals, "") expected := []string{"tsuru_unit_agent", "tsuru_host", "app_token", "app-name", "/var/lib/tsuru/start"} c.Assert(cmds, check.DeepEquals, expected) }
func (s *S) TestRemoveOldRoutesForward(c *check.C) { app := provisiontest.NewFakeApp("myapp", "python", 1) imageName := "tsuru/app-" + app.GetName() customData := map[string]interface{}{ "processes": map[string]interface{}{ "web": "python myapi.py", "worker": "tail -f /dev/null", }, } err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) routertest.FakeRouter.AddBackend(app.GetName()) defer routertest.FakeRouter.RemoveBackend(app.GetName()) cont1 := container.Container{ID: "ble-1", AppName: app.GetName(), ProcessName: "web", HostAddr: "127.0.0.1", HostPort: "1234"} cont2 := container.Container{ID: "ble-2", AppName: app.GetName(), ProcessName: "web", HostAddr: "127.0.0.2", HostPort: "4321"} cont3 := container.Container{ID: "ble-3", AppName: app.GetName(), ProcessName: "worker", HostAddr: "127.0.0.3", HostPort: "8080"} defer cont1.Remove(s.p) defer cont2.Remove(s.p) defer cont3.Remove(s.p) err = routertest.FakeRouter.AddRoute(app.GetName(), cont1.Address()) c.Assert(err, check.IsNil) err = routertest.FakeRouter.AddRoute(app.GetName(), cont2.Address()) c.Assert(err, check.IsNil) args := changeUnitsPipelineArgs{ app: app, toRemove: []container.Container{cont1, cont2, cont3}, provisioner: s.p, } context := action.FWContext{Previous: []container.Container{}, Params: []interface{}{args}} r, err := removeOldRoutes.Forward(context) c.Assert(err, check.IsNil) hasRoute := routertest.FakeRouter.HasRoute(app.GetName(), cont1.Address().String()) c.Assert(hasRoute, check.Equals, false) hasRoute = routertest.FakeRouter.HasRoute(app.GetName(), cont2.Address().String()) c.Assert(hasRoute, check.Equals, false) containers := r.([]container.Container) c.Assert(containers, check.DeepEquals, []container.Container{}) c.Assert(args.toRemove[0].Routable, check.Equals, true) c.Assert(args.toRemove[1].Routable, check.Equals, true) c.Assert(args.toRemove[2].Routable, check.Equals, false) }
func (s *S) TestHealthcheckWithMatch(c *check.C) { var requests []*http.Request server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requests = append(requests, r) if len(requests) == 1 { w.Write([]byte("invalid")) } else { w.Write([]byte("something")) } })) defer server.Close() a := app.App{Name: "myapp1"} customData := map[string]interface{}{ "healthcheck": map[string]interface{}{ "path": "/x/y", "method": "Get", "status": 200, "match": ".*some.*", }, } imageName := "tsuru/app" err := image.SaveImageCustomData(imageName, customData) c.Assert(err, check.IsNil) err = s.storage.Apps().Insert(a) c.Assert(err, check.IsNil) defer s.storage.Apps().RemoveAll(bson.M{"name": a.Name}) url, _ := url.Parse(server.URL) host, port, _ := net.SplitHostPort(url.Host) cont := container.Container{AppName: a.Name, HostAddr: host, HostPort: port, Image: imageName} buf := bytes.Buffer{} err = runHealthcheck(&cont, &buf) c.Assert(err, check.ErrorMatches, ".*unexpected result, expected \"(?s).*some.*\", got: invalid") c.Assert(requests, check.HasLen, 1) c.Assert(requests[0].Method, check.Equals, "GET") err = runHealthcheck(&cont, &buf) c.Assert(err, check.IsNil) c.Assert(requests, check.HasLen, 2) c.Assert(requests[1].URL.Path, check.Equals, "/x/y") c.Assert(requests[1].Method, check.Equals, "GET") }
func (p *swarmProvisioner) RegisterUnit(a provision.App, unitId string, customData map[string]interface{}) error { client, err := chooseDBSwarmNode() if err != nil { return err } tasks, err := client.ListTasks(docker.ListTasksOptions{ Filters: map[string][]string{ "label": {labelAppName.String() + "=" + a.GetName()}, }, }) if err != nil { return err } task, err := findTaskByContainerId(tasks, unitId) if err != nil { return err } units, err := tasksToUnits(client, []swarm.Task{*task}) if err != nil { return err } err = bindUnit(a, &units[0]) if err != nil { return err } if customData == nil { return nil } if task.Spec.ContainerSpec.Labels[labelServiceDeploy.String()] != "true" { return nil } buildingImage := task.Spec.ContainerSpec.Labels[labelServiceBuildImage.String()] if buildingImage == "" { return errors.Errorf("invalid build image label for build task: %#v", task) } return image.SaveImageCustomData(buildingImage, customData) }
func (s *S) TestActionUpdateServicesForwardFailureInMiddle(c *check.C) { srv, err := testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, check.IsNil) metadata := map[string]string{"m1": "v1", labelNodePoolName.String(): "p1"} opts := provision.AddNodeOptions{ Address: srv.URL(), Metadata: metadata, } err = s.p.AddNode(opts) c.Assert(err, check.IsNil) cli, err := chooseDBSwarmNode() c.Assert(err, check.IsNil) a := &app.App{Name: "myapp", Platform: "whitespace", TeamOwner: s.team.Name} err = app.CreateApp(a, s.user) c.Assert(err, check.IsNil) _, err = cli.CreateService(docker.CreateServiceOptions{ ServiceSpec: swarm.ServiceSpec{ TaskTemplate: swarm.TaskSpec{ ContainerSpec: swarm.ContainerSpec{ Command: []string{"original-web"}, }, }, Annotations: swarm.Annotations{ Name: "myapp-web", }, }, }) c.Assert(err, check.IsNil) srvWorker, err := cli.CreateService(docker.CreateServiceOptions{ ServiceSpec: swarm.ServiceSpec{ TaskTemplate: swarm.TaskSpec{ ContainerSpec: swarm.ContainerSpec{ Command: []string{"original-worker"}, }, }, Annotations: swarm.Annotations{ Name: "myapp-worker", }, }, }) c.Assert(err, check.IsNil) oldImg := "app:v1" err = image.SaveImageCustomData(oldImg, map[string]interface{}{ "processes": map[string]interface{}{ "web": "old1", "worker": "old2", }, }) c.Assert(err, check.IsNil) newImg := "app:v2" err = image.SaveImageCustomData(newImg, map[string]interface{}{ "processes": map[string]interface{}{ "web": "new1", "worker": "new2", }, }) c.Assert(err, check.IsNil) srv.CustomHandler("/services/"+srvWorker.ID, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("bad error")) })) spec := processSpec{"web": processState{}, "worker": processState{}} args := &pipelineArgs{ client: cli, app: a, newImage: newImg, newImageSpec: spec, currentImage: oldImg, currentImageSpec: spec, } processes, err := updateServices.Forward(action.FWContext{Params: []interface{}{args}}) c.Assert(err, check.ErrorMatches, ".*bad error") c.Assert(processes, check.IsNil) service, err := cli.InspectService("myapp-web") c.Assert(err, check.IsNil) c.Assert(service.Spec.TaskTemplate.ContainerSpec.Command, check.DeepEquals, []string{ "/bin/sh", "-lc", fmt.Sprintf( "[ -d /home/application/current ] && cd /home/application/current; %s && exec old1", extraRegisterCmds(a), ), }) service, err = cli.InspectService("myapp-worker") c.Assert(err, check.IsNil) c.Assert(service.Spec.TaskTemplate.ContainerSpec.Command, check.DeepEquals, []string{ "original-worker", }) }