Beispiel #1
0
func TestLoadNonexistentFile(t *testing.T) {
	m, err := manifest.LoadFile("/foo/bar/hope/this/doesnt/exist")

	if assert.Nil(t, m) && assert.NotNil(t, err) {
		assert.Equal(t, err.Error(), "open /foo/bar/hope/this/doesnt/exist: no such file or directory")
	}
}
Beispiel #2
0
func main() {
	if len(os.Args) != 2 {
		fmt.Println("usage: build <src>")
		os.Exit(1)
	}
	defer handlePanic()

	src := os.Args[1]

	if src == "-" {
		extractTar()
	} else {
		cloneGit(src)
	}

	writeDockerAuth()

	m, err := manifest.LoadFile(fmt.Sprintf("src/%s", manifestPath))
	handleError(err)

	data, err := m.Raw()
	handleError(err)

	cwd, err := os.Getwd()
	handleError(err)

	output := manifest.NewOutput()
	str := output.Stream("build")

	handleError(os.Chdir("./src"))
	handleError(m.Build(".", app, str, cache))
	handleError(os.Chdir(cwd))
	handleError(m.Push(str, app, registryAddress, buildId, repository))

	_, err = rackClient.UpdateBuild(os.Getenv("APP"), os.Getenv("BUILD"), string(data), "complete", "")
	handleError(err)
}
Beispiel #3
0
func checkDockerfile() error {
	if df := filepath.Join(filepath.Dir(os.Args[0]), "docker-compose.yml"); exists(df) {
		m, err := manifest.LoadFile("docker-compose.yml")
		if err != nil {
			//This will get picked up later in the test suite
			return nil
		}
		checkMissingDockerFiles(m)
		return nil
	}

	title := "Dockerfile found"
	startCheck(title)

	//Skip if docker-compose file exists
	_, err := os.Stat("docker-compose.yml")
	if err == nil {
		return nil
	}

	_, err = os.Stat("Dockerfile")
	if err != nil {
		diagnose(Diagnosis{
			Title:       title,
			Description: "<fail>A Dockerfile is required to build an Image</fail>",
			Kind:        "fail",
			DocsLink:    "https://convox.com/guide/build/images",
		})
	} else {
		diagnose(Diagnosis{
			Title: title,
			Kind:  "success",
		})
	}
	return nil
}
Beispiel #4
0
func cmdStart(c *cli.Context) error {
	// go handleResize()

	id, err := currentId()
	if err != nil {
		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{Error: err})
	}

	err = dockerTest()
	if err != nil {
		return stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{ValidationError: err})
	}

	dir, app, err := stdcli.DirApp(c, filepath.Dir(c.String("file")))
	if err != nil {
		return stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{ValidationError: err})
	}

	appType := detectApplication(dir)
	m, err := manifest.LoadFile(c.String("file"))
	if err != nil {
		return stdcli.ExitError(err)
	}

	if err := m.Shift(c.Int("shift")); err != nil {
		return stdcli.ExitError(err)
	}

	if pcc, err := m.PortConflicts(); err != nil || len(pcc) > 0 {
		if err == nil {
			err = fmt.Errorf("ports in use: %v", pcc)
		}
		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
			ValidationError: err,
			AppType:         appType,
		})

		return stdcli.ExitError(err)
	}

	cache := !c.Bool("no-cache")
	sync := !c.Bool("no-sync")

	r := m.Run(dir, app, cache, sync)

	err = r.Start()
	if err != nil {
		return stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
			ValidationError: err,
			AppType:         appType,
		})
	}

	stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
		AppType: appType,
	})

	go handleInterrupt(r)

	return r.Wait()
}
Beispiel #5
0
func cmdStart(c *cli.Context) error {
	// go handleResize()
	var service string
	var command []string

	if len(c.Args()) > 0 {
		service = c.Args()[0]
	}

	if len(c.Args()) > 1 {
		command = c.Args()[1:]
	}

	id, err := currentId()
	if err != nil {
		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{Error: err})
	}

	err = dockerTest()
	if err != nil {
		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{ValidationError: err})
		return stdcli.Error(err)
	}

	dir, app, err := stdcli.DirApp(c, filepath.Dir(c.String("file")))
	if err != nil {
		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{ValidationError: err})
		return stdcli.Error(err)
	}

	appType := detectApplication(dir)
	m, err := manifest.LoadFile(c.String("file"))
	if err != nil {
		return stdcli.Error(err)
	}

	errs := m.Validate()
	if len(errs) > 0 {
		for _, e := range errs[1:] {
			stdcli.Error(e)
		}
		return stdcli.Error(errs[0])
	}

	if service != "" {
		_, ok := m.Services[service]
		if !ok {
			return stdcli.Error(fmt.Errorf("Service %s not found in manifest", service))
		}
	}

	if err := m.Shift(c.Int("shift")); err != nil {
		return stdcli.Error(err)
	}

	// one-off commands don't need port validation
	if len(command) == 0 {
		if pcc, err := m.PortConflicts(); err != nil || len(pcc) > 0 {
			if err == nil {
				err = fmt.Errorf("ports in use: %v", pcc)
			}
			stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
				ValidationError: err,
				AppType:         appType,
			})
			return stdcli.Error(err)
		}
	}

	cache := !c.Bool("no-cache")
	sync := !c.Bool("no-sync")

	r := m.Run(dir, app, manifest.RunOptions{
		Cache:   cache,
		Sync:    sync,
		Service: service,
		Command: command,
	})

	err = r.Start()
	if err != nil {
		r.Stop()

		stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
			ValidationError: err,
			AppType:         appType,
		})
		return stdcli.Error(err)
	}

	stdcli.QOSEventSend("cli-start", id, stdcli.QOSEventProperties{
		AppType: appType,
	})

	// Setup the local "cron jobs"
	for _, entry := range m.Services {
		labels := entry.LabelsByPrefix("convox.cron")
		processName := fmt.Sprintf("%s-%s", app, entry.Name)
		c := cron.New()

		for key, value := range labels {
			p, ok := r.Processes[processName]
			if !ok {
				continue
			}
			cronjob := models.NewCronJobFromLabel(key, value)

			rs := strings.NewReplacer("cron(", "0 ", ")", "")                 // cron pkg first field is in seconds so set to 0
			trigger := strings.TrimSuffix(rs.Replace(cronjob.Schedule), " *") // and doesn't recognize year so we trim it

			c.AddFunc(trigger, func() {
				cronProccesName := fmt.Sprintf("cron-%s-%04d", cronjob.Name, rand.Intn(9000))
				// Replace args with cron specific ones
				cronArgs := p.GenerateArgs(&manifest.ArgOptions{
					Command:     cronjob.Command,
					IgnorePorts: true,
					Name:        cronProccesName,
				})

				done := make(chan error)
				manifest.RunAsync(
					r.Output.Stream(cronProccesName),
					manifest.Docker(append([]string{"run"}, cronArgs...)...),
					done,
				)

				err := <-done
				if err != nil {
					fmt.Printf("error running %s: %s\n", cronProccesName, err.Error())
				}
			})
		}

		c.Start()
	}

	go handleInterrupt(r)

	return r.Wait()
}
Beispiel #6
0
func manifestFixture(name string) (*manifest.Manifest, error) {
	return manifest.LoadFile(fmt.Sprintf("fixtures/%s.yml", name))
}
Beispiel #7
0
func checkBuildDocker() error {
	title := "Image builds successfully"

	if df := filepath.Join(filepath.Dir(os.Args[0]), "docker-compose.yml"); exists(df) {
		m, err := manifest.LoadFile(df)
		if err != nil {
			//This will be handled later in the suite
			return nil
		}

		startCheck(title)

		_, app, err := stdcli.DirApp(docContext, ".")
		if err != nil {
			//This will be handled later in the suite
			return nil
		}

		s := make(chan string)
		output := []string{}

		go func() {
			for x := range s {
				output = append(output, x)
			}
		}()

		err = m.Build(".", app, s, manifest.BuildOptions{
			Cache: true,
		})

		if err != nil {
			message := ""
			for _, x := range output {
				message += fmt.Sprintf("<fail>%s</fail>\n", x)
			}
			diagnose(Diagnosis{
				Title:       title,
				Description: message,
				Kind:        "fail",
			})
		}

		diagnose(Diagnosis{
			Title: title,
			Kind:  "success",
		})
		return nil
	}

	startCheck(title)

	byts, err := exec.Command("docker", "build", ".").CombinedOutput()
	if err != nil {
		bytsArr := strings.Split(string(byts), "\n")
		message := ""
		for _, x := range bytsArr {
			message += fmt.Sprintf("<description>%s</description>\n", x)
		}
		diagnose(Diagnosis{
			Title:       title,
			Description: message,
			Kind:        "fail",
		})
		return nil
	}

	diagnose(Diagnosis{
		Title: title,
		Kind:  "success",
	})
	return nil
}
Beispiel #8
0
func cmdDoctor(c *cli.Context) error {
	docContext = c
	stdcli.Writef("### Setup\n")
	for _, check := range setupChecks {
		if err := check(); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Build: Image\n")
	for _, check := range buildImageChecks {
		if err := check(); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Build: Service\n")
	startCheck("<file>docker-compose.yml</file> found")
	_, err := os.Stat("docker-compose.yml")
	if err != nil {
		diagnose(Diagnosis{
			Title:       "<file>docker-compose.yml</file> found",
			Description: "<fail>A docker-compose.yml file is required to define Services</fail>",
			Kind:        "fail",
			DocsLink:    "https://convox.com/guide/services/",
		})
	} else {
		diagnose(Diagnosis{
			Title: "<file>docker-compose.yml</file> found",
			Kind:  "success",
		})
	}

	m, err := manifest.LoadFile("docker-compose.yml")
	checkManifestValid(m, err)
	for _, check := range buildServiceChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Build: Environment\n")
	for _, check := range buildEnvironmentChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Run: Balancer\n")
	for _, check := range runBalancerChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Run: Database\n")
	for _, check := range runDatabaseChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Run: Link\n")
	for _, check := range runLinkChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Development: Reloading\n")
	for _, check := range runReloadingChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n### Development: Commands\n")
	for _, check := range runCommandChecks {
		if err := check(m); err != nil {
			return stdcli.Error(err)
		}
	}

	stdcli.Writef("\n\n<success>Success:</success> Your app looks ready for development. \nRun it with `convox start`.\n\n")
	return nil
}