func (p *swarmProvisioner) RoutableAddresses(a provision.App) ([]url.URL, error) { client, err := chooseDBSwarmNode() if err != nil { return nil, err } imgID, err := image.AppCurrentImageName(a.GetName()) if err != nil { if err != image.ErrNoImagesAvailable { return nil, err } return nil, nil } webProcessName, err := image.GetImageWebProcessName(imgID) if err != nil { return nil, err } if webProcessName == "" { return nil, nil } srvName := serviceNameForApp(a, webProcessName) srv, err := client.InspectService(srvName) if err != nil { return nil, err } var pubPort uint32 if len(srv.Endpoint.Ports) > 0 { pubPort = srv.Endpoint.Ports[0].PublishedPort } if pubPort == 0 { return nil, nil } nodes, err := listValidNodes(client) if err != nil { return nil, err } for i := len(nodes) - 1; i >= 0; i-- { if nodes[i].Spec.Annotations.Labels[labelNodePoolName.String()] != a.GetPool() { nodes[i], nodes[len(nodes)-1] = nodes[len(nodes)-1], nodes[i] nodes = nodes[:len(nodes)-1] } } addrs := make([]url.URL, len(nodes)) for i, n := range nodes { addr := n.Spec.Labels[labelNodeDockerAddr.String()] host := tsuruNet.URLToHost(addr) addrs[i] = url.URL{ Scheme: "http", Host: fmt.Sprintf("%s:%d", host, pubPort), } } return addrs, nil }
func (p *dockerProvisioner) LogsEnabled(app provision.App) (bool, string, error) { const ( logBackendsEnv = "LOG_BACKENDS" logDocKeyFormat = "LOG_%s_DOC" tsuruLogBackendName = "tsuru" ) logConf := container.DockerLog{} isBS, err := logConf.IsBS(app.GetPool()) if err != nil { return false, "", err } if !isBS { driver, _, _ := logConf.LogOpts(app.GetPool()) msg := fmt.Sprintf("Logs not available through tsuru. Enabled log driver is %q.", driver) return false, msg, nil } config, err := bs.LoadConfig([]string{app.GetPool()}) if err != nil { return false, "", err } enabledBackends := config.PoolEntry(app.GetPool(), logBackendsEnv) if enabledBackends == "" { return true, "", nil } backendsList := strings.Split(enabledBackends, ",") for i := range backendsList { backendsList[i] = strings.TrimSpace(backendsList[i]) if backendsList[i] == tsuruLogBackendName { return true, "", nil } } var docs []string for _, backendName := range backendsList { keyName := fmt.Sprintf(logDocKeyFormat, strings.ToUpper(backendName)) backendDoc := config.PoolEntry(app.GetPool(), keyName) var docLine string if backendDoc == "" { docLine = fmt.Sprintf("* %s", backendName) } else { docLine = fmt.Sprintf("* %s: %s", backendName, backendDoc) } docs = append(docs, docLine) } fullDoc := fmt.Sprintf("Logs not available through tsuru. Enabled log backends are:\n%s", strings.Join(docs, "\n")) return false, fullDoc, nil }
func (c *Container) hostConfig(app provision.App, isDeploy bool) (*docker.HostConfig, error) { sharedBasedir, _ := config.GetString("docker:sharedfs:hostdir") sharedMount, _ := config.GetString("docker:sharedfs:mountpoint") sharedIsolation, _ := config.GetBool("docker:sharedfs:app-isolation") sharedSalt, _ := config.GetString("docker:sharedfs:salt") hostConfig := docker.HostConfig{ CPUShares: int64(app.GetCpuShare()), } if !isDeploy { hostConfig.Memory = app.GetMemory() hostConfig.MemorySwap = app.GetMemory() + app.GetSwap() hostConfig.RestartPolicy = docker.AlwaysRestart() hostConfig.PortBindings = map[docker.Port][]docker.PortBinding{ docker.Port(c.ExposedPort): {{HostIP: "", HostPort: ""}}, } pool := app.GetPool() driver, opts, logErr := LogOpts(pool) if logErr != nil { return nil, logErr } hostConfig.LogConfig = docker.LogConfig{ Type: driver, Config: opts, } } else { hostConfig.OomScoreAdj = 1000 } hostConfig.SecurityOpt, _ = config.GetList("docker:security-opts") if sharedBasedir != "" && sharedMount != "" { if sharedIsolation { var appHostDir string if sharedSalt != "" { h := crypto.SHA1.New() io.WriteString(h, sharedSalt+c.AppName) appHostDir = fmt.Sprintf("%x", h.Sum(nil)) } else { appHostDir = c.AppName } hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s/%s:%s:rw", sharedBasedir, appHostDir, sharedMount)) } else { hostConfig.Binds = append(hostConfig.Binds, fmt.Sprintf("%s:%s:rw", sharedBasedir, sharedMount)) } } return &hostConfig, nil }
func (p *dockerProvisioner) Nodes(app provision.App) ([]cluster.Node, error) { poolName := app.GetPool() nodes, err := p.Cluster().NodesForMetadata(map[string]string{"pool": poolName}) if err != nil { return nil, err } if len(nodes) > 0 { return nodes, nil } return nil, errors.Errorf("No nodes found with one of the following metadata: pool=%s", poolName) }
func (p *dockerProvisioner) MetricEnvs(app provision.App) map[string]string { bsContainer, err := nodecontainer.LoadNodeContainer(app.GetPool(), nodecontainer.BsDefaultName) if err != nil { return map[string]string{} } envs := bsContainer.EnvMap() for envName := range envs { if !strings.HasPrefix(envName, "METRICS_") { delete(envs, envName) } } return envs }
func (p *dockerProvisioner) MetricEnvs(app provision.App) map[string]string { envMap := map[string]string{} envs, err := bs.EnvListForEndpoint("", app.GetPool()) if err != nil { return envMap } for _, env := range envs { // TODO(cezarsa): ugly as hell if strings.HasPrefix(env, "METRICS_") { slice := strings.SplitN(env, "=", 2) envMap[slice[0]] = slice[1] } } return envMap }
func (p *dockerProvisioner) ImageDeploy(app provision.App, imageId string, evt *event.Event) (string, error) { cluster := p.Cluster() if !strings.Contains(imageId, ":") { imageId = fmt.Sprintf("%s:latest", imageId) } w := evt fmt.Fprintln(w, "---- Pulling image to tsuru ----") pullOpts := docker.PullImageOptions{ Repository: imageId, OutputStream: w, InactivityTimeout: net.StreamInactivityTimeout, } nodes, err := cluster.NodesForMetadata(map[string]string{"pool": app.GetPool()}) if err != nil { return "", err } node, _, err := p.scheduler.minMaxNodes(nodes, app.GetName(), "") if err != nil { return "", err } err = cluster.PullImage(pullOpts, docker.AuthConfiguration{}, node) if err != nil { return "", err } fmt.Fprintln(w, "---- Getting process from image ----") cmd := "cat /home/application/current/Procfile || cat /app/user/Procfile || cat /Procfile" var outBuf bytes.Buffer err = p.runCommandInContainer(imageId, cmd, app, &outBuf, nil) if err != nil { return "", err } newImage, err := dockercommon.PrepareImageForDeploy(dockercommon.PrepareImageArgs{ Client: cluster, App: app, ProcfileRaw: outBuf.String(), ImageId: imageId, AuthConfig: p.RegistryAuthConfig(), Out: w, }) if err != nil { return "", err } app.SetUpdatePlatform(true) return newImage, p.deploy(app, newImage, evt) }
func (p *dockerProvisioner) MetricEnvs(app provision.App) map[string]string { envMap := map[string]string{} bsConf, err := bs.LoadConfig() if err != nil { return envMap } envs, err := bsConf.EnvListForEndpoint("", app.GetPool()) if err != nil { return envMap } for _, env := range envs { if strings.HasPrefix(env, "METRICS_") { slice := strings.SplitN(env, "=", 2) envMap[slice[0]] = slice[1] } } return envMap }
func (p *dockerProvisioner) Nodes(app provision.App) ([]cluster.Node, error) { pool := app.GetPool() var ( pools []provision.Pool err error ) if pool == "" { pools, err = provision.ListPools(bson.M{"$or": []bson.M{{"teams": app.GetTeamOwner()}, {"teams": bson.M{"$in": app.GetTeamsName()}}}}) } else { pools, err = provision.ListPools(bson.M{"_id": pool}) } if err != nil { return nil, err } if len(pools) == 0 { query := bson.M{"default": true} pools, err = provision.ListPools(query) if err != nil { return nil, err } } if len(pools) == 0 { return nil, errNoDefaultPool } for _, pool := range pools { nodes, err := p.Cluster().NodesForMetadata(map[string]string{"pool": pool.Name}) if err != nil { return nil, errNoDefaultPool } if len(nodes) > 0 { return nodes, nil } } var nameList []string for _, pool := range pools { nameList = append(nameList, pool.Name) } poolsStr := strings.Join(nameList, ", pool=") return nil, fmt.Errorf("No nodes found with one of the following metadata: pool=%s", poolsStr) }