func (s *S) TestAppNewImageName(c *check.C) { img1, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img1, check.Equals, "tsuru/app-myapp:v1") img2, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img2, check.Equals, "tsuru/app-myapp:v2") img3, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img3, check.Equals, "tsuru/app-myapp:v3") }
func (s *S) TestAppNewImageNameWithRegistry(c *check.C) { config.Set("docker:registry", "localhost:3030") defer config.Unset("docker:registry") img1, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img1, check.Equals, "localhost:3030/tsuru/app-myapp:v1") img2, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img2, check.Equals, "localhost:3030/tsuru/app-myapp:v2") img3, err := image.AppNewImageName("myapp") c.Assert(err, check.IsNil) c.Assert(img3, check.Equals, "localhost:3030/tsuru/app-myapp:v3") }
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 }
func (p *dockerProvisioner) deployPipeline(app provision.App, imageId string, commands []string, evt *event.Event) (string, error) { actions := []*action.Action{ &insertEmptyContainerInDB, &createContainer, &setContainerID, &startContainer, &updateContainerInDB, &followLogsAndCommit, } pipeline := action.NewPipeline(actions...) buildingImage, err := image.AppNewImageName(app.GetName()) if err != nil { return "", log.WrapError(errors.Errorf("error getting new image name for app %s", app.GetName())) } var writer io.Writer = evt if evt == nil { writer = ioutil.Discard } args := runContainerActionsArgs{ app: app, imageID: imageId, commands: commands, writer: writer, isDeploy: true, buildingImage: buildingImage, provisioner: p, event: evt, } err = pipeline.Execute(args) if err != nil { log.Errorf("error on execute deploy pipeline for app %s - %s", app.GetName(), err) return "", err } return buildingImage, nil }
func (s *S) TestFollowLogsAndCommitForward(c *check.C) { err := s.newFakeImage(s.p, "tsuru/python", nil) c.Assert(err, check.IsNil) app := provisiontest.NewFakeApp("mightyapp", "python", 1) nextImgName, err := image.AppNewImageName(app.GetName()) c.Assert(err, check.IsNil) cont := container.Container{AppName: "mightyapp", ID: "myid123", BuildingImage: nextImgName} err = cont.Create(&container.CreateArgs{ App: app, ImageID: "tsuru/python", Commands: []string{"foo"}, Provisioner: s.p, }) c.Assert(err, check.IsNil) buf := safe.NewBuffer(nil) args := runContainerActionsArgs{writer: buf, provisioner: s.p} context := action.FWContext{Params: []interface{}{args}, Previous: cont} imageId, err := followLogsAndCommit.Forward(context) c.Assert(err, check.IsNil) c.Assert(imageId, check.Equals, "tsuru/app-mightyapp:v1") c.Assert(buf.String(), check.Not(check.Equals), "") var dbCont container.Container coll := s.p.Collection() defer coll.Close() err = coll.Find(bson.M{"id": cont.ID}).One(&dbCont) c.Assert(err, check.NotNil) c.Assert(err.Error(), check.Equals, "not found") _, err = s.p.Cluster().InspectContainer(cont.ID) c.Assert(err, check.NotNil) c.Assert(err.Error(), check.Matches, "No such container.*") err = s.p.Cluster().RemoveImage("tsuru/app-mightyapp:v1") c.Assert(err, check.IsNil) }
func (s *S) TestProvisionAddUnitsToHostForwardWithoutHost(c *check.C) { p, err := s.startMultipleServersCluster() c.Assert(err, check.IsNil) app := provisiontest.NewFakeApp("myapp-2", "python", 0) defer p.Destroy(app) p.Provision(app) coll := p.Collection() defer coll.Close() imageId, err := image.AppNewImageName(app.GetName()) c.Assert(err, check.IsNil) err = s.newFakeImage(p, imageId, nil) c.Assert(err, check.IsNil) args := changeUnitsPipelineArgs{ app: app, toAdd: map[string]*containersToAdd{"web": {Quantity: 3}}, imageId: imageId, provisioner: p, } context := action.FWContext{Params: []interface{}{args}} result, err := provisionAddUnitsToHost.Forward(context) c.Assert(err, check.IsNil) containers := result.([]container.Container) c.Assert(containers, check.HasLen, 3) addrs := []string{containers[0].HostAddr, containers[1].HostAddr, containers[2].HostAddr} sort.Strings(addrs) isValid := reflect.DeepEqual(addrs, []string{"127.0.0.1", "localhost", "localhost"}) || reflect.DeepEqual(addrs, []string{"127.0.0.1", "127.0.0.1", "localhost"}) if !isValid { clusterNodes, _ := p.Cluster().UnfilteredNodes() c.Fatalf("Expected multiple hosts, got: %#v\nAvailable nodes: %#v", containers, clusterNodes) } count, err := coll.Find(bson.M{"appname": app.GetName()}).Count() c.Assert(err, check.IsNil) c.Assert(count, check.Equals, 3) }
func (s *S) TestProvisionAddUnitsToHostForward(c *check.C) { p, err := s.startMultipleServersCluster() c.Assert(err, check.IsNil) app := provisiontest.NewFakeApp("myapp-2", "python", 0) defer p.Destroy(app) p.Provision(app) coll := p.Collection() defer coll.Close() coll.Insert(container.Container{ID: "container-id", AppName: app.GetName(), Version: "container-version", Image: "tsuru/python"}) defer coll.RemoveAll(bson.M{"appname": app.GetName()}) imageId, err := image.AppNewImageName(app.GetName()) c.Assert(err, check.IsNil) err = s.newFakeImage(p, imageId, nil) c.Assert(err, check.IsNil) args := changeUnitsPipelineArgs{ app: app, toHost: "localhost", toAdd: map[string]*containersToAdd{"web": {Quantity: 2}}, imageId: imageId, provisioner: p, } context := action.FWContext{Params: []interface{}{args}} result, err := provisionAddUnitsToHost.Forward(context) c.Assert(err, check.IsNil) containers := result.([]container.Container) c.Assert(containers, check.HasLen, 2) c.Assert(containers[0].HostAddr, check.Equals, "localhost") c.Assert(containers[1].HostAddr, check.Equals, "localhost") count, err := coll.Find(bson.M{"appname": app.GetName()}).Count() c.Assert(err, check.IsNil) c.Assert(count, check.Equals, 3) }
func PrepareImageForDeploy(args PrepareImageArgs) (string, error) { fmt.Fprintf(args.Out, "---- Inspecting image %q ----\n", args.ImageId) procfile := image.GetProcessesFromProcfile(args.ProcfileRaw) imageInspect, err := args.Client.InspectImage(args.ImageId) if err != nil { return "", err } if len(procfile) == 0 { fmt.Fprintln(args.Out, " ---> Procfile not found, using entrypoint and cmd") procfile["web"] = append(imageInspect.Config.Entrypoint, imageInspect.Config.Cmd...) } for k, v := range procfile { fmt.Fprintf(args.Out, " ---> Process %q found with commands: %q\n", k, v) } newImage, err := image.AppNewImageName(args.App.GetName()) if err != nil { return "", err } imageInfo := strings.Split(newImage, ":") repo, tag := strings.Join(imageInfo[:len(imageInfo)-1], ":"), imageInfo[len(imageInfo)-1] err = args.Client.TagImage(args.ImageId, docker.TagImageOptions{Repo: repo, Tag: tag, Force: true}) if err != nil { return "", err } registry, err := config.GetString("docker:registry") if err != nil { return "", err } fmt.Fprintf(args.Out, "---- Pushing image %q to tsuru ----\n", newImage) pushOpts := docker.PushImageOptions{ Name: repo, Tag: tag, Registry: registry, OutputStream: args.Out, InactivityTimeout: net.StreamInactivityTimeout, RawJSONStream: true, } err = args.Client.PushImage(pushOpts, args.AuthConfig) if err != nil { return "", err } imageData := image.ImageMetadata{ Name: newImage, Processes: procfile, } if len(imageInspect.Config.ExposedPorts) > 1 { return "", errors.New("Too many ports. You should especify which one you want to.") } for k := range imageInspect.Config.ExposedPorts { imageData.ExposedPort = string(k) } err = imageData.Save() if err != nil { return "", err } return newImage, nil }
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 }