Пример #1
0
func (p *swarmProvisioner) ArchiveDeploy(a provision.App, archiveURL string, evt *event.Event) (imgID string, err error) {
	baseImage := image.GetBuildImage(a)
	buildingImage, err := image.AppNewImageName(a.GetName())
	if err != nil {
		return "", errors.WithStack(err)
	}
	client, err := chooseDBSwarmNode()
	if err != nil {
		return "", err
	}
	cmds := dockercommon.ArchiveDeployCmds(a, archiveURL)
	srvID, task, err := runOnceBuildCmds(client, a, cmds, baseImage, buildingImage, evt)
	if srvID != "" {
		defer removeServiceAndLog(client, srvID)
	}
	if err != nil {
		return "", err
	}
	_, err = commitPushBuildImage(client, buildingImage, task.Status.ContainerStatus.ContainerID, a)
	if err != nil {
		return "", err
	}
	err = deployProcesses(client, a, buildingImage, nil)
	if err != nil {
		return "", errors.WithStack(err)
	}
	return buildingImage, nil
}
Пример #2
0
func (s *S) TestGetImageFromAppPlatform(c *check.C) {
	app := provisiontest.NewFakeApp("myapp", "python", 1)
	img := image.GetBuildImage(app)
	repoNamespace, err := config.GetString("docker:repository-namespace")
	c.Assert(err, check.IsNil)
	c.Assert(img, check.Equals, fmt.Sprintf("%s/python:latest", repoNamespace))
}
Пример #3
0
func (s *S) TestArchiveDeployCanceledEvent(c *check.C) {
	err := s.newFakeImage(s.p, "tsuru/python:latest", nil)
	c.Assert(err, check.IsNil)
	app := provisiontest.NewFakeApp("myapp", "python", 1)
	routertest.FakeRouter.AddBackend(app.GetName())
	defer routertest.FakeRouter.RemoveBackend(app.GetName())
	evt, err := event.New(&event.Opts{
		Target:        event.Target{Type: "app", Value: "myapp"},
		Kind:          permission.PermAppDeploy,
		Owner:         s.token,
		Cancelable:    true,
		Allowed:       event.Allowed(permission.PermApp),
		AllowedCancel: event.Allowed(permission.PermApp),
	})
	c.Assert(err, check.IsNil)
	done := make(chan bool)
	go func() {
		defer close(done)
		img, depErr := s.p.archiveDeploy(app, image.GetBuildImage(app), "https://s3.amazonaws.com/wat/archive.tar.gz", evt)
		c.Assert(depErr, check.ErrorMatches, "deploy canceled by user action")
		c.Assert(img, check.Equals, "")
	}()
	time.Sleep(100 * time.Millisecond)
	err = evt.TryCancel("because yes", "[email protected]")
	c.Assert(err, check.IsNil)
	<-done
}
Пример #4
0
func (p *dockerProvisioner) ArchiveDeploy(app provision.App, archiveURL string, evt *event.Event) (string, error) {
	imageId, err := p.archiveDeploy(app, image.GetBuildImage(app), archiveURL, evt)
	if err != nil {
		return "", err
	}
	return imageId, p.deployAndClean(app, imageId, evt)
}
Пример #5
0
func (s *S) TestGetImageWithRegistry(c *check.C) {
	config.Set("docker:registry", "localhost:3030")
	defer config.Unset("docker:registry")
	app := provisiontest.NewFakeApp("myapp", "python", 1)
	img := image.GetBuildImage(app)
	repoNamespace, _ := config.GetString("docker:repository-namespace")
	expected := fmt.Sprintf("localhost:3030/%s/python:latest", repoNamespace)
	c.Assert(img, check.Equals, expected)
}
Пример #6
0
func (s *S) TestArchiveDeploy(c *check.C) {
	stopCh := s.stopContainers(s.server.URL(), 1)
	defer func() { <-stopCh }()
	err := s.newFakeImage(s.p, "tsuru/python:latest", nil)
	c.Assert(err, check.IsNil)
	app := provisiontest.NewFakeApp("myapp", "python", 1)
	routertest.FakeRouter.AddBackend(app.GetName())
	defer routertest.FakeRouter.RemoveBackend(app.GetName())
	img, err := s.p.archiveDeploy(app, image.GetBuildImage(app), "https://s3.amazonaws.com/wat/archive.tar.gz", nil)
	c.Assert(err, check.IsNil)
	c.Assert(img, check.Equals, "tsuru/app-myapp:v1")
}
Пример #7
0
func (s *S) TestGetImageAppWhenDeployIsMultipleOf10(c *check.C) {
	app := &app.App{Name: "app1", Platform: "python", Deploys: 20}
	err := s.storage.Apps().Insert(app)
	c.Assert(err, check.IsNil)
	cont := container.Container{ID: "bleble", Type: app.Platform, AppName: app.Name, Image: "tsuru/app1"}
	coll := s.p.Collection()
	err = coll.Insert(cont)
	c.Assert(err, check.IsNil)
	defer coll.Close()
	c.Assert(err, check.IsNil)
	defer coll.RemoveAll(bson.M{"id": cont.ID})
	img := image.GetBuildImage(app)
	repoNamespace, err := config.GetString("docker:repository-namespace")
	c.Assert(err, check.IsNil)
	c.Assert(img, check.Equals, fmt.Sprintf("%s/%s:latest", repoNamespace, app.Platform))
}
Пример #8
0
func (s *S) TestStart(c *check.C) {
	err := s.newFakeImage(s.p, "tsuru/python:latest", nil)
	c.Assert(err, check.IsNil)
	app := provisiontest.NewFakeApp("myapp", "python", 1)
	imageId := image.GetBuildImage(app)
	routertest.FakeRouter.AddBackend(app.GetName())
	defer routertest.FakeRouter.RemoveBackend(app.GetName())
	var buf bytes.Buffer
	cont, err := s.p.start(&container.Container{ProcessName: "web"}, app, imageId, &buf, "")
	c.Assert(err, check.IsNil)
	defer cont.Remove(s.p)
	c.Assert(cont.ID, check.Not(check.Equals), "")
	cont2, err := s.p.GetContainer(cont.ID)
	c.Assert(err, check.IsNil)
	c.Assert(cont2.Image, check.Equals, imageId)
	c.Assert(cont2.Status, check.Equals, provision.StatusStarting.String())
}
Пример #9
0
func (s *S) TestArchiveDeployRegisterRace(c *check.C) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(10))
	var p dockerProvisioner
	var registerCount int64
	server, err := testing.NewServer("127.0.0.1:0", nil, func(r *http.Request) {
		go func(path string) {
			parts := strings.Split(path, "/")
			if len(parts) == 4 && parts[3] == "start" {
				registerErr := p.RegisterUnit(nil, parts[2], nil)
				if registerErr == nil {
					atomic.AddInt64(&registerCount, 1)
				}
			}
		}(r.URL.Path)
	})
	c.Assert(err, check.IsNil)
	defer server.Stop()
	config.Set("docker:registry", "localhost:3030")
	defer config.Unset("docker:registry")
	err = p.Initialize()
	c.Assert(err, check.IsNil)
	p.cluster, err = cluster.New(nil, &cluster.MapStorage{},
		cluster.Node{Address: server.URL()})
	c.Assert(err, check.IsNil)
	err = s.newFakeImage(&p, "tsuru/python:latest", nil)
	c.Assert(err, check.IsNil)
	nTests := 100
	stopCh := s.stopContainers(server.URL(), uint(nTests))
	defer func() { <-stopCh }()
	wg := sync.WaitGroup{}
	for i := 0; i < nTests; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			name := fmt.Sprintf("myapp-%d", i)
			app := provisiontest.NewFakeApp(name, "python", 1)
			routertest.FakeRouter.AddBackend(app.GetName())
			defer routertest.FakeRouter.RemoveBackend(app.GetName())
			img, _ := p.archiveDeploy(app, image.GetBuildImage(app), "https://s3.amazonaws.com/wat/archive.tar.gz", nil)
			c.Assert(img, check.Equals, "localhost:3030/tsuru/app-"+name+":v1")
		}(i)
	}
	wg.Wait()
	c.Assert(registerCount, check.Equals, int64(nTests))
}
Пример #10
0
func (p *swarmProvisioner) UploadDeploy(a provision.App, archiveFile io.ReadCloser, fileSize int64, build bool, evt *event.Event) (string, error) {
	defer archiveFile.Close()
	if build {
		return "", errors.New("running UploadDeploy with build=true is not yet supported")
	}
	client, err := chooseDBSwarmNode()
	if err != nil {
		return "", err
	}
	baseImage := image.GetBuildImage(a)
	buildingImage, err := image.AppNewImageName(a.GetName())
	if err != nil {
		return "", errors.WithStack(err)
	}
	spec, err := serviceSpecForApp(tsuruServiceOpts{
		app:        a,
		image:      baseImage,
		isDeploy:   true,
		buildImage: buildingImage,
	})
	if err != nil {
		return "", err
	}
	spec.TaskTemplate.ContainerSpec.Command = []string{"/usr/bin/tail", "-f", "/dev/null"}
	spec.TaskTemplate.RestartPolicy.Condition = swarm.RestartPolicyConditionNone
	srv, err := client.CreateService(docker.CreateServiceOptions{
		ServiceSpec: *spec,
	})
	if err != nil {
		return "", errors.WithStack(err)
	}
	tasks, err := waitForTasks(client, srv.ID, swarm.TaskStateRunning)
	if err != nil {
		return "", err
	}
	client, err = clientForNode(client, tasks[0].NodeID)
	if err != nil {
		return "", err
	}
	contID := tasks[0].Status.ContainerStatus.ContainerID
	imageID, fileURI, err := dockercommon.UploadToContainer(client, contID, archiveFile, fileSize)
	removeErr := client.RemoveService(docker.RemoveServiceOptions{
		ID: srv.ID,
	})
	if removeErr != nil {
		return "", errors.WithStack(removeErr)
	}
	if err != nil {
		return "", errors.WithStack(err)
	}
	cmds := dockercommon.ArchiveDeployCmds(a, fileURI)
	opts := tsuruServiceOpts{
		app:        a,
		image:      imageID,
		isDeploy:   true,
		buildImage: buildingImage,
		constraints: []string{
			fmt.Sprintf("node.id == %s", tasks[0].NodeID),
		},
	}
	srvID, task, err := runOnceCmds(client, opts, cmds, evt, evt)
	if srvID != "" {
		defer removeServiceAndLog(client, srvID)
	}
	if err != nil {
		return "", err
	}
	_, err = commitPushBuildImage(client, buildingImage, task.Status.ContainerStatus.ContainerID, a)
	if err != nil {
		return "", err
	}
	err = deployProcesses(client, a, buildingImage, nil)
	if err != nil {
		return "", errors.WithStack(err)
	}
	return buildingImage, nil
}
Пример #11
0
func (p *dockerProvisioner) UploadDeploy(app provision.App, archiveFile io.ReadCloser, fileSize int64, build bool, evt *event.Event) (string, error) {
	if build {
		return "", errors.New("running UploadDeploy with build=true is not yet supported")
	}
	user, err := config.GetString("docker:user")
	if err != nil {
		user, _ = config.GetString("docker:ssh:user")
	}
	defer archiveFile.Close()
	imageName := image.GetBuildImage(app)
	options := docker.CreateContainerOptions{
		Config: &docker.Config{
			AttachStdout: true,
			AttachStderr: true,
			AttachStdin:  true,
			OpenStdin:    true,
			StdinOnce:    true,
			User:         user,
			Image:        imageName,
			Cmd:          []string{"/bin/bash", "-c", "tail -f /dev/null"},
		},
	}
	cluster := p.Cluster()
	schedOpts := &container.SchedulerOpts{
		AppName:       app.GetName(),
		ActionLimiter: p.ActionLimiter(),
	}
	addr, cont, err := cluster.CreateContainerSchedulerOpts(options, schedOpts, net.StreamInactivityTimeout)
	hostAddr := net.URLToHost(addr)
	if schedOpts.LimiterDone != nil {
		schedOpts.LimiterDone()
	}
	if err != nil {
		return "", err
	}
	defer func() {
		done := p.ActionLimiter().Start(hostAddr)
		cluster.RemoveContainer(docker.RemoveContainerOptions{ID: cont.ID, Force: true})
		done()
	}()
	done := p.ActionLimiter().Start(hostAddr)
	err = cluster.StartContainer(cont.ID, nil)
	done()
	if err != nil {
		return "", err
	}
	intermediateImageID, fileURI, err := dockercommon.UploadToContainer(cluster, cont.ID, archiveFile, fileSize)
	done = p.ActionLimiter().Start(hostAddr)
	stopErr := cluster.StopContainer(cont.ID, 10)
	done()
	if stopErr != nil {
		return "", stopErr
	}
	if err != nil {
		return "", err
	}
	imageId, err := p.archiveDeploy(app, intermediateImageID, fileURI, evt)
	if err != nil {
		return "", err
	}
	return imageId, p.deployAndClean(app, imageId, evt)
}