Beispiel #1
0
func checkManifestValid(m *manifest.Manifest, parseError error) error {
	title := "<file>docker-compose.yml</file> valid"
	startCheck(title)

	if parseError != nil {
		diagnose(Diagnosis{
			Title:       title,
			Kind:        "fail",
			DocsLink:    "https://convox.com/docs/docker-compose-file/",
			Description: "<description>docker-compose.yml is not valid YAML</description>",
		})
		return nil
	}

	errs := m.Validate()
	if len(errs) > 0 {
		body := ""
		for _, err := range errs {
			body += fmt.Sprintf("<description>%s</description>\n", err.Error())
		}
		diagnose(Diagnosis{
			Title:       title,
			Kind:        "fail",
			DocsLink:    "https://convox.com/docs/docker-compose-file/",
			Description: body,
		})
		return nil
	}

	diagnose(Diagnosis{
		Kind:  "success",
		Title: title,
	})
	return nil
}
Beispiel #2
0
func (p *AWSProvider) BuildCopy(srcApp, id, destApp string) (*structs.Build, error) {
	srcA, err := p.AppGet(srcApp)
	if err != nil {
		return nil, err
	}

	srcB, err := p.BuildGet(srcApp, id)
	if err != nil {
		return nil, err
	}

	destA, err := p.AppGet(destApp)
	if err != nil {
		return nil, err
	}

	// make a .tgz file that is the source build manifest
	// with build directives removed, and image directives pointing to
	// fully qualified URLs of source build images
	var m manifest.Manifest
	err = yaml.Unmarshal([]byte(srcB.Manifest), &m)
	if err != nil {
		return nil, err
	}

	for name, entry := range m.Services {
		entry.Build.Context = ""
		entry.Image = p.registryTag(srcA, name, srcB.Id)
		m.Services[name] = entry
	}

	data, err := m.Raw()
	if err != nil {
		return nil, err
	}

	dir, err := ioutil.TempDir("", "source")
	if err != nil {
		return nil, err
	}

	err = os.Chmod(dir, 0755)
	if err != nil {
		return nil, err
	}

	err = ioutil.WriteFile(filepath.Join(dir, "docker-compose.yml"), data, 0644)
	if err != nil {
		return nil, err
	}

	tgz, err := createTarball(dir)
	if err != nil {
		return nil, err
	}

	// Build .tgz in context of destApp
	return p.BuildCreateTar(destA.Name, bytes.NewReader(tgz), "docker-compose.yml", fmt.Sprintf("Copy of %s %s", srcA.Name, srcB.Id), false)
}
Beispiel #3
0
func checkRunSh(m *manifest.Manifest) error {
	_, app, err := stdcli.DirApp(docContext, ".")
	if err != nil {
		fmt.Printf("ERROR: %+v\n", err)
	}

	for _, s := range manifestServices(m) {
		title := fmt.Sprintf("Service <service>%s</service> runs `sh`", s.Name)
		startCheck(title)

		r := m.Run(".", app, manifest.RunOptions{
			Service: s.Name,
			Command: []string{"echo", "hello"},
			Cache:   true,
			Quiet:   true,
		})

		err := r.Start()
		if err != nil {
			diagnose(Diagnosis{
				Title:       title,
				Kind:        "error",
				DocsLink:    "https://convox.com/guide/one-off-commands/",
				Description: fmt.Sprintf("Service <service>%s</service> does not run `sh` because of %q", s.Name, err),
			})
			continue
		}

		err = r.Wait()
		if err != nil {
			diagnose(Diagnosis{
				Title:       title,
				Kind:        "error",
				DocsLink:    "https://convox.com/guide/one-off-commands/",
				Description: fmt.Sprintf("Service <service>%s</service> does not exit from `sh` because of %q", s.Name, err),
			})
			continue
		}

		diagnose(Diagnosis{
			Title: title,
			Kind:  "success",
		})
	}
	return nil
}
Beispiel #4
0
func (r *Release) resolveLinks(app App, m *manifest.Manifest) (*manifest.Manifest, error) {
	// HACK: need an app of type structs.App for docker login.
	// Should be fixed/removed once proper logic is moved over to structs.App
	// That includes moving Formation() around
	sa := structs.App{
		Name:       app.Name,
		Release:    app.Release,
		Status:     app.Status,
		Outputs:    app.Outputs,
		Parameters: app.Parameters,
		Tags:       app.Tags,
	}
	endpoint, err := AppDockerLogin(sa)
	if err != nil {
		return m, fmt.Errorf("could not log into %q", endpoint)
	}

	for i, entry := range m.Services {
		var inspect []struct {
			Config struct {
				Env []string
			}
		}

		imageName := entry.Image

		cmd := exec.Command("docker", "pull", imageName)
		out, err := cmd.CombinedOutput()
		fmt.Printf("ns=kernel at=release.formation at=entry.pull imageName=%q out=%q err=%q\n", imageName, string(out), err)
		if err != nil {
			return m, fmt.Errorf("could not pull %q", imageName)
		}

		cmd = exec.Command("docker", "inspect", imageName)
		out, err = cmd.CombinedOutput()
		// fmt.Printf("ns=kernel at=release.formation at=entry.inspect imageName=%q out=%q err=%q\n", imageName, string(out), err)
		if err != nil {
			return m, fmt.Errorf("could not inspect %q", imageName)
		}

		err = json.Unmarshal(out, &inspect)
		if err != nil {
			fmt.Printf("ns=kernel at=release.formation at=entry.unmarshal err=%q\n", err)
			return m, fmt.Errorf("could not inspect %q", imageName)
		}

		entry.Exports = make(map[string]string)
		linkableEnvs := make([]string, len(entry.Environment))
		for k, v := range entry.Environment {
			val := fmt.Sprintf("%s=%s", k, v)
			linkableEnvs = append(linkableEnvs, val)
		}

		if len(inspect) == 1 {
			linkableEnvs = append(linkableEnvs, inspect[0].Config.Env...)
		}

		for _, val := range linkableEnvs {
			if strings.HasPrefix(val, "LINK_") {
				parts := strings.SplitN(val, "=", 2)
				if len(parts) == 2 {
					entry.Exports[parts[0]] = parts[1]
					m.Services[i] = entry
				}
			}
		}
	}

	for i, entry := range m.Services {
		entry.LinkVars = make(map[string]template.HTML)
		for _, link := range entry.Links {
			other, ok := m.Services[link]
			if !ok {
				return m, fmt.Errorf("Cannot find link %q", link)
			}

			scheme := other.Exports["LINK_SCHEME"]
			if scheme == "" {
				scheme = "tcp"
			}

			mb := m.GetBalancer(link)
			if mb == nil {
				// commented out to be less strict, just don't create the link
				//return m, fmt.Errorf("Cannot discover balancer for link %q", link)
				continue
			}
			host := fmt.Sprintf(`{ "Fn::If" : [ "Enabled%s", { "Fn::GetAtt" : [ "%s", "DNSName" ] }, "DISABLED" ] }`, UpperName(other.Name), mb.ResourceName())

			if len(other.Ports) == 0 {
				// commented out to be less strict, just don't create the link
				// return m, fmt.Errorf("Cannot link to %q because it does not expose ports in the manifest", link)
				continue
			}

			var port manifest.Port
			linkPort := other.Exports["LINK_PORT"]
			if linkPort == "" {
				port = other.Ports[0]
			} else {
				i, _ := strconv.Atoi(linkPort)
				if err != nil {
					return nil, err
				}

				var matchedPort = false
				for _, p := range other.Ports {
					if i == p.Container {
						port = p
						matchedPort = true
					}
				}

				if !matchedPort {
					return nil, fmt.Errorf("No Port matching %s found", linkPort)
				}
			}

			path := other.Exports["LINK_PATH"]

			var userInfo string
			if other.Exports["LINK_USERNAME"] != "" || other.Exports["LINK_PASSWORD"] != "" {
				userInfo = fmt.Sprintf("%s:%s@", other.Exports["LINK_USERNAME"], other.Exports["LINK_PASSWORD"])
			}

			html := fmt.Sprintf(`{ "Fn::Join": [ "", [ "%s", "://", "%s", %s, ":", "%s", "%s" ] ] }`,
				scheme, userInfo, host, port, path)

			prefix := strings.ToUpper(link) + "_"
			prefix = strings.Replace(prefix, "-", "_", -1)
			entry.LinkVars[prefix+"HOST"] = template.HTML(host)
			entry.LinkVars[prefix+"SCHEME"] = template.HTML(fmt.Sprintf("%q", scheme))
			entry.LinkVars[prefix+"PORT"] = template.HTML(fmt.Sprintf("%q", port))
			entry.LinkVars[prefix+"PASSWORD"] = template.HTML(fmt.Sprintf("%q", other.Exports["LINK_PASSWORD"]))
			entry.LinkVars[prefix+"USERNAME"] = template.HTML(fmt.Sprintf("%q", other.Exports["LINK_USERNAME"]))
			entry.LinkVars[prefix+"PATH"] = template.HTML(fmt.Sprintf("%q", path))
			entry.LinkVars[prefix+"URL"] = template.HTML(html)
			m.Services[i] = entry
		}
	}

	return m, nil
}
Beispiel #5
0
func (r *Release) resolveLinks(app App, manifest *manifest.Manifest) (*manifest.Manifest, error) {
	m := *manifest

	endpoint, err := AppDockerLogin(app)

	if err != nil {
		return &m, fmt.Errorf("could not log into %q", endpoint)
	}

	for i, entry := range m.Services {
		var inspect []struct {
			Config struct {
				Env []string
			}
		}

		imageName := entry.Image

		cmd := exec.Command("docker", "pull", imageName)
		out, err := cmd.CombinedOutput()
		fmt.Printf("ns=kernel at=release.formation at=entry.pull imageName=%q out=%q err=%q\n", imageName, string(out), err)
		if err != nil {
			return &m, fmt.Errorf("could not pull %q", imageName)
		}

		cmd = exec.Command("docker", "inspect", imageName)
		out, err = cmd.CombinedOutput()
		// fmt.Printf("ns=kernel at=release.formation at=entry.inspect imageName=%q out=%q err=%q\n", imageName, string(out), err)
		if err != nil {
			return &m, fmt.Errorf("could not inspect %q", imageName)
		}

		err = json.Unmarshal(out, &inspect)
		if err != nil {
			fmt.Printf("ns=kernel at=release.formation at=entry.unmarshal err=%q\n", err)
			return &m, fmt.Errorf("could not inspect %q", imageName)
		}

		entry.Exports = make(map[string]string)
		linkableEnvs := make([]string, len(entry.Environment))
		for k, v := range entry.Environment {
			val := fmt.Sprintf("%s=%s", k, v)
			linkableEnvs = append(linkableEnvs, val)
		}

		if len(inspect) == 1 {
			linkableEnvs = append(linkableEnvs, inspect[0].Config.Env...)
		}

		for _, val := range linkableEnvs {
			if strings.HasPrefix(val, "LINK_") {
				parts := strings.SplitN(val, "=", 2)
				if len(parts) == 2 {
					entry.Exports[parts[0]] = parts[1]
					m.Services[i] = entry
				}
			}
		}
	}

	for i, entry := range m.Services {
		entry.LinkVars = make(map[string]template.HTML)
		for _, link := range entry.Links {
			other, ok := m.Services[link]
			if !ok {
				return &m, fmt.Errorf("Cannot find link %q", link)
			}

			scheme := other.Exports["LINK_SCHEME"]
			if scheme == "" {
				scheme = "tcp"
			}

			mb := manifest.GetBalancer(link)
			if mb == nil {
				// commented out to be less strict, just don't create the link
				//return m, fmt.Errorf("Cannot discover balancer for link %q", link)
				continue
			}
			host := fmt.Sprintf(`{ "Fn::If" : [ "Enabled%s", { "Fn::GetAtt" : [ "%s", "DNSName" ] }, "DISABLED" ] }`, UpperName(other.Name), mb.ResourceName())

			if len(other.Ports) == 0 {
				// commented out to be less strict, just don't create the link
				// return m, fmt.Errorf("Cannot link to %q because it does not expose ports in the manifest", link)
				continue
			}

			port := other.Ports[0]

			path := other.Exports["LINK_PATH"]

			var userInfo string
			if other.Exports["LINK_USERNAME"] != "" || other.Exports["LINK_PASSWORD"] != "" {
				userInfo = fmt.Sprintf("%s:%s@", other.Exports["LINK_USERNAME"], other.Exports["LINK_PASSWORD"])
			}

			html := fmt.Sprintf(`{ "Fn::Join": [ "", [ "%s", "://", "%s", %s, ":", "%s", "%s" ] ] }`,
				scheme, userInfo, host, port, path)

			prefix := strings.ToUpper(link) + "_"
			prefix = strings.Replace(prefix, "-", "_", -1)
			entry.LinkVars[prefix+"HOST"] = template.HTML(host)
			entry.LinkVars[prefix+"SCHEME"] = template.HTML(fmt.Sprintf("%q", scheme))
			entry.LinkVars[prefix+"PORT"] = template.HTML(fmt.Sprintf("%q", port))
			entry.LinkVars[prefix+"PASSWORD"] = template.HTML(fmt.Sprintf("%q", other.Exports["LINK_PASSWORD"]))
			entry.LinkVars[prefix+"USERNAME"] = template.HTML(fmt.Sprintf("%q", other.Exports["LINK_USERNAME"]))
			entry.LinkVars[prefix+"PATH"] = template.HTML(fmt.Sprintf("%q", path))
			entry.LinkVars[prefix+"URL"] = template.HTML(html)
			m.Services[i] = entry
		}
	}

	return &m, nil
}