Example #1
0
func tagAndPushImage(c *workflow.Context) (err error) {
	// Tag and push to registry
	output.WriteHeader("Pushing image " + image + " to registry")
	cmd := exec.Command("docker", "push", image)
	err = cmd.Run()
	if err != nil {
		output.WriteError("Error in push: " + err.Error())
		stderr, err := cmd.StderrPipe()
		if err != nil {
			output.WriteData("Cannot get debug information")
			return err
		}

		spew := bufio.NewReader(stderr)

		for {
			line, _, err := spew.ReadLine()

			if err == io.EOF {
				return err
			}

			if err != nil {
				output.WriteData(err)
				return err
			}

			output.WriteData(string(line))
		}
	}

	output.WriteData("done")

	return
}
Example #2
0
func deployImage(c *workflow.Context) (err error) {
	// Report information about the build
	output.WriteHeader("Deploying")

	build := &datatypes.Build{
		App:   os.Getenv("REPO"),
		ID:    buildid,
		Image: image,
		User:  os.Getenv("USER"),
	}

	unitSlice := []*unit.UnitOption{
		{"Unit", "Description", "Flitter app " + repo + " deploy " + build.ID},
		{"Service", "TimeoutStartSec", "30m"},
		{"Service", "ExecStartPre", "/usr/bin/docker pull " + build.Image},
		{"Service", "ExecStartPre", "-/usr/bin/docker rm -f app-" + repo + "-" + build.ID},
		{"Service", "ExecStart", "/bin/sh -c '/usr/bin/docker run -P --name app-" + repo + "-" + build.ID + " --hostname " + repo + " -e HOST=$COREOS_PRIVATE_IPV4 " + build.Image + " '"},
		{"Service", "ExecStop", "/usr/bin/docker rm -f app-" + repo + "-" + build.ID},
	}

	if err := startUnit("app-"+repo, buildid, unitSlice); err != nil {
		output.WriteError("Fleet unit start failed: " + err.Error())
		output.WriteData("Please verify that fleet is online.")
		return err
	}

	return
}
Example #3
0
func buildImage(c *workflow.Context) (err error) {
	dir, ok := c.Arguments["tempdir"]
	if !ok {
		return errors.New("Impossible state")
	}

	// Build docker image
	image = config.RegistryHost + ":" + config.RegistryPort +
		"/" + os.Getenv("USER") + "/" + repo + ":" + sha[:7]
	// 192.168.45.117:5000/xena/mpd:1fc8018

	output.WriteHeader("Building docker image " + image)
	cmd := exec.Command("docker", "build", "-t", image, dir)
	cmd.Dir = dir
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stdout

	err = cmd.Run()
	if err != nil {
		output.WriteError(err.Error())
		return err
	}

	return
}
Example #4
0
func injectLayers(c *workflow.Context) (err error) {
	dir, ok := c.Arguments["tempdir"]
	if !ok {
		return errors.New("Impossible state")
	}

	// Inject some vars
	output.WriteHeader("Injecting flitter layers to Dockerfile")

	dockerfout, err := os.OpenFile(dir+"/Dockerfile", os.O_APPEND|os.O_WRONLY, 0666)
	if err != nil {
		output.WriteError("Could not inject things to Dockerfile")
		return err
	}

	_, err = dockerfout.Write([]byte("\nENV GIT_SHA " + sha + "\n"))
	if err != nil {
		output.WriteError("Error: " + err.Error())
		return err
	}

	dockerfout.Write([]byte("ENV BUILTBY " + os.Getenv("USER") + "\n"))
	dockerfout.Write([]byte("ENV APPNAME " + os.Getenv("REPO") + "\n"))
	dockerfout.Write([]byte("ENV BUILDID " + buildid))
	dockerfout.Close()

	output.WriteData("done")

	return
}
Example #5
0
func successMessage(c *workflow.Context) (err error) {
	// Print end message
	output.WriteHeader("Success")
	output.WriteData("Your app is in the docker registry as " + image)
	output.WriteData("Your build id is " + buildid)
	output.WriteData("")
	output.WriteData("You may access your app at http://" + repo + "." + config.Domain + " once it spins up")

	return
}
Example #6
0
// main is the entry point for cloudchaser, the build sentry.
func main() {
	flag.Parse()

	app := os.Getenv("REPO")
	user := os.Getenv("USER")

	client := etcd.NewClient([]string{*etcdmachine})

	output.WriteHeader("Checking permission")
	output.WriteData("user:   "******"app:    " + app)

	var allowedusers []string

	path := constants.ETCD_APPS + app + "/users"
	res, err := client.Get(path, false, false)
	if err != nil {
		output.WriteError("Permissions check failed: " + err.Error())
		output.WriteData("Do you have permission to deploy this app?")
		os.Exit(1)
	}

	rawusers := res.Node.Value

	err = json.Unmarshal([]byte(rawusers), &allowedusers)
	if err != nil {
		output.WriteError("Internal json decoding reply in allowed app users parsing")
		output.WriteData(err.Error())
		return
	}

	for _, username := range allowedusers {
		if strings.ToLower(username) == strings.ToLower(user) {
			goto allowed
		}
	}

	output.WriteError("User is not authorized to make builds")
	output.WriteData("I think you are " + user)
	output.WriteData("Please check the needed permissions and try again later.")

allowed:

	output.WriteData("")
	output.WriteData("Kicking off build")
	output.WriteData("")

	os.Exit(0)
}
Example #7
0
func validateDockerfile(c *workflow.Context) (err error) {
	dir, ok := c.Arguments["tempdir"]
	if !ok {
		return errors.New("Impossible state")
	}

	// Validate Docker image
	output.WriteHeader("Validating Dockerfile")

	fin, err := os.Open(dir + "/Dockerfile")
	if err != nil {
		output.WriteError("Could not validate Dockerfile")
		return err
	}

	exposed := false
	scanner := bufio.NewReader(fin)
	line, isPrefix, err := scanner.ReadLine()
	for err == nil && !isPrefix {
		s := string(line)

		split := strings.Split(s, " ")
		if len(split) == 0 {
			continue
		}

		if strings.ToUpper(split[0]) == "EXPOSE" {
			if exposed {
				output.WriteData("Multiple ports exposed")
				output.WriteData("Please make sure to only expose one port")
				output.WriteData("You can and will run into undefined behavior")
				output.WriteData("You have been warned")
				output.WriteData("")
				break
			} else {
				exposed = true
			}
		}

		line, isPrefix, err = scanner.ReadLine()
	}

	fin.Close()

	output.WriteData("done")

	return
}
Example #8
0
// main is the entrypoint for the builder
func main() {
	flag.Parse()

	if len(flag.Args()) < 3 {
		*help = true
	}

	if *help {
		fmt.Printf("Usage:\n")
		fmt.Printf("  builder [options] <repo> <branch> <sha>\n\n")
		flag.Usage()
		os.Exit(128)
	}

	config = NewConfig(*etcdhost)
	user = os.Getenv("USER")
	repo = flag.Arg(0)
	branch = flag.Arg(1)
	sha = flag.Arg(2)
	buildid = sha[0:8]

	output.WriteHeader("Building " + repo + " branch " + branch + " as " + user)

	c := workflow.New("builder")

	c.Use(
		makeTempDir,
		extractTarball,
		checkDockerfile,
		injectLayers,
		validateDockerfile,
		buildImage,
		tagAndPushImage,
		deployImage,
		successMessage,
	)

	err := c.Run()
	if err != nil {
		output.WriteError(err.Error())

		log.Fatal(err)
	}
}
Example #9
0
func extractTarball(c *workflow.Context) (err error) {
	// Extract branch to deploy
	output.WriteHeader("Extracting " + repo)

	dir, ok := c.Arguments["tempdir"]
	if !ok {
		return errors.New("Impossible state")
	}

	cmd := exec.Command("git", "archive", branch)

	fout, err := os.Create(dir + "/app.tar")
	if err != nil {
		return err
	}

	cmd.Stderr = os.Stderr

	out, err := cmd.Output()
	if err != nil {
		output.WriteHeader("Error in capturing tarball: " + err.Error())

		stderr, err := cmd.StderrPipe()
		if err != nil {
			output.WriteData("Cannot get debug information")
			return err
		}

		spew := bufio.NewReader(stderr)

		for {
			line, _, err := spew.ReadLine()

			if err == io.EOF {
				return err
			}

			if err != nil {
				output.WriteData(err)
				return err
			}

			output.WriteData(string(line))
		}
	}

	_, err = fout.Write(out)
	if err != nil {
		output.WriteHeader("Error in writing tarball: " + err.Error())
		return err
	}

	fout.Sync()
	fout.Close()

	output.WriteData("done")

	// Extract tarball
	cmd = exec.Command("tar", "xf", "app.tar")
	cmd.Dir = dir

	err = cmd.Run()
	if err != nil {
		output.WriteHeader("Error in extracting tarball: " + err.Error())
		return err
	}

	os.Remove(dir + "/app.tar")

	return nil
}