Example #1
0
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"},
	})
}
Example #2
0
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, "")
}
Example #3
0
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)
}
Example #4
0
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")
}
Example #5
0
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: "/"})
}
Example #6
0
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")
}
Example #7
0
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")
}
Example #8
0
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),
		),
	})
}
Example #9
0
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")
}
Example #10
0
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{})
}
Example #11
0
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.*")
}
Example #12
0
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)
}
Example #13
0
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")
}
Example #14
0
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{})
}
Example #15
0
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"},
	})
}
Example #16
0
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)
}
Example #17
0
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)
}
Example #18
0
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)
}
Example #19
0
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{})
}
Example #20
0
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)
}
Example #21
0
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)
}
Example #22
0
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")
}
Example #23
0
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)
}
Example #24
0
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",
	})
}