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 }
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) }
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 }
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 }
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 }