Ejemplo n.º 1
0
func (c *Container) Create(args *CreateArgs) error {
	securityOpts, _ := config.GetList("docker:security-opts")
	var exposedPorts map[docker.Port]struct{}
	if !args.Deploy {
		if c.ExposedPort == "" {
			c.ExposedPort = dockercommon.WebProcessDefaultPort() + "/tcp"
		}
		exposedPorts = map[docker.Port]struct{}{
			docker.Port(c.ExposedPort): {},
		}
	}
	var user string
	if args.Building {
		user = c.user()
	}
	routerName, err := args.App.GetRouter()
	if err != nil {
		return err
	}
	routerType, _, err := router.Type(routerName)
	if err != nil {
		return err
	}
	hostConf, err := c.hostConfig(args.App, args.Deploy)
	if err != nil {
		return err
	}
	conf := docker.Config{
		Image:        args.ImageID,
		Cmd:          args.Commands,
		Entrypoint:   []string{},
		ExposedPorts: exposedPorts,
		AttachStdin:  false,
		AttachStdout: false,
		AttachStderr: false,
		Memory:       hostConf.Memory,
		MemorySwap:   hostConf.MemorySwap,
		CPUShares:    hostConf.CPUShares,
		SecurityOpts: securityOpts,
		User:         user,
		Labels: map[string]string{
			"tsuru.container":    strconv.FormatBool(true),
			"tsuru.app.name":     args.App.GetName(),
			"tsuru.app.platform": args.App.GetPlatform(),
			"tsuru.process.name": c.ProcessName,
			"tsuru.router.name":  routerName,
			"tsuru.router.type":  routerType,
		},
	}
	c.addEnvsToConfig(args, strings.TrimSuffix(c.ExposedPort, "/tcp"), &conf)
	opts := docker.CreateContainerOptions{Name: c.Name, Config: &conf, HostConfig: hostConf}
	var nodeList []string
	if len(args.DestinationHosts) > 0 {
		var node cluster.Node
		node, err = args.Provisioner.GetNodeByHost(args.DestinationHosts[0])
		if err != nil {
			return err
		}
		nodeList = []string{node.Address}
	}
	schedulerOpts := &SchedulerOpts{
		AppName:       args.App.GetName(),
		ProcessName:   args.ProcessName,
		ActionLimiter: args.Provisioner.ActionLimiter(),
	}
	addr, cont, err := args.Provisioner.Cluster().CreateContainerSchedulerOpts(opts, schedulerOpts, net.StreamInactivityTimeout, nodeList...)
	hostAddr := net.URLToHost(addr)
	if schedulerOpts.LimiterDone != nil {
		schedulerOpts.LimiterDone()
	}
	if err != nil {
		log.Errorf("error on creating container in docker %s - %s", c.AppName, err)
		return err
	}
	c.ID = cont.ID
	c.HostAddr = hostAddr
	return nil
}
Ejemplo n.º 2
0
func serviceSpecForApp(opts tsuruServiceOpts) (*swarm.ServiceSpec, error) {
	var envs []string
	for _, envData := range opts.app.Envs() {
		envs = append(envs, fmt.Sprintf("%s=%s", envData.Name, envData.Value))
	}
	host, _ := config.GetString("host")
	envs = append(envs, fmt.Sprintf("%s=%s", "TSURU_HOST", host))
	var cmds []string
	var err error
	var endpointSpec *swarm.EndpointSpec
	var networks []swarm.NetworkAttachmentConfig
	var healthConfig *container.HealthConfig
	port := dockercommon.WebProcessDefaultPort()
	portInt, _ := strconv.Atoi(port)
	if !opts.isDeploy && !opts.isIsolatedRun {
		envs = append(envs, []string{
			fmt.Sprintf("%s=%s", "port", port),
			fmt.Sprintf("%s=%s", "PORT", port),
		}...)
		endpointSpec = &swarm.EndpointSpec{
			Mode: swarm.ResolutionModeVIP,
			Ports: []swarm.PortConfig{
				{TargetPort: uint32(portInt), PublishedPort: 0},
			},
		}
		networks = []swarm.NetworkAttachmentConfig{
			{Target: networkNameForApp(opts.app)},
		}
		extra := []string{extraRegisterCmds(opts.app)}
		cmds, _, err = dockercommon.LeanContainerCmdsWithExtra(opts.process, opts.image, opts.app, extra)
		if err != nil {
			return nil, errors.WithStack(err)
		}
		var yamlData provision.TsuruYamlData
		yamlData, err = image.GetImageTsuruYamlData(opts.image)
		if err != nil {
			return nil, errors.WithStack(err)
		}
		healthConfig = toHealthConfig(yamlData.Healthcheck, portInt)
	}
	restartCount := 0
	replicas := 0
	if opts.baseSpec != nil {
		replicas, err = strconv.Atoi(opts.baseSpec.Labels[labelProcessReplicas.String()])
		if err != nil && opts.baseSpec.Mode.Replicated != nil {
			replicas = int(*opts.baseSpec.Mode.Replicated.Replicas)
		}
		restartCount, _ = strconv.Atoi(opts.baseSpec.Labels[labelServiceRestart.String()])
	}
	if opts.processState.increment != 0 {
		replicas += opts.processState.increment
		if replicas < 0 {
			return nil, errors.New("cannot have less than 0 units")
		}
	} else if replicas == 0 && opts.processState.start {
		replicas = 1
	}
	routerName, err := opts.app.GetRouter()
	if err != nil {
		return nil, errors.WithStack(err)
	}
	routerType, _, err := router.Type(routerName)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	srvName := serviceNameForApp(opts.app, opts.process)
	if opts.isDeploy {
		replicas = 1
		srvName = fmt.Sprintf("%s-build", srvName)
	}
	if opts.isIsolatedRun {
		replicas = 1
		srvName = fmt.Sprintf("%sisolated-run", srvName)
	}
	uReplicas := uint64(replicas)
	if opts.processState.stop {
		uReplicas = 0
	}
	if opts.processState.restart {
		restartCount++
	}
	labels := map[string]string{
		labelService.String():            strconv.FormatBool(true),
		labelServiceDeploy.String():      strconv.FormatBool(opts.isDeploy),
		labelServiceIsolatedRun.String(): strconv.FormatBool(opts.isIsolatedRun),
		labelServiceBuildImage.String():  opts.buildImage,
		labelAppName.String():            opts.app.GetName(),
		labelAppProcess.String():         opts.process,
		labelAppPlatform.String():        opts.app.GetPlatform(),
		labelRouterName.String():         routerName,
		labelRouterType.String():         routerType,
		labelProcessReplicas.String():    strconv.Itoa(replicas),
		labelServiceRestart.String():     strconv.Itoa(restartCount),
		labelPoolName.String():           opts.app.GetPool(),
		labelProvisionerName.String():    "swarm",
	}
	user, err := config.GetString("docker:user")
	if err != nil {
		user, _ = config.GetString("docker:ssh:user")
	}
	opts.constraints = append(opts.constraints, fmt.Sprintf("node.labels.%s == %s", labelNodePoolName, opts.app.GetPool()))
	spec := swarm.ServiceSpec{
		TaskTemplate: swarm.TaskSpec{
			ContainerSpec: swarm.ContainerSpec{
				Image:       opts.image,
				Env:         envs,
				Labels:      labels,
				Command:     cmds,
				User:        user,
				Healthcheck: healthConfig,
			},
			Networks: networks,
			RestartPolicy: &swarm.RestartPolicy{
				Condition: swarm.RestartPolicyConditionAny,
			},
			Placement: &swarm.Placement{
				Constraints: opts.constraints,
			},
		},
		Networks:     networks,
		EndpointSpec: endpointSpec,
		Annotations: swarm.Annotations{
			Name:   srvName,
			Labels: labels,
		},
		Mode: swarm.ServiceMode{
			Replicated: &swarm.ReplicatedService{
				Replicas: &uReplicas,
			},
		},
	}
	return &spec, nil
}