Пример #1
0
// Build is the CLI handler for 'godo build'
func Build(c *cli.Context) {
	cfg := config.ReadOrDie(c.String(FlagConfigFile))
	paths := PathsOrDie()

	dockerClient := docker.ClientOrDie()
	imgStr := fmt.Sprintf("%s:%s", cfg.Build.ImageName, cfg.Build.ImageTag)
	img, err := docker.ParseImageFromName(imgStr)
	if err != nil {
		log.Err("error parsing docker image %s (%s)", imgStr, err)
		os.Exit(1)
	}

	rmContainerCh := make(chan func())
	stdOutCh := make(chan docker.Log)
	stdErrCh := make(chan docker.Log)
	exitCodeCh := make(chan int)
	errCh := make(chan error)

	projName := filepath.Base(paths.CWD)
	binaryName := cfg.Build.GetOutputBinary(projName)
	go docker.Run(
		dockerClient,
		img,
		"build",
		paths.CWD,
		docker.ContainerGopath(cfg.Build.Gopath, paths.PackageName),
		fmt.Sprintf("go build -o %s .", binaryName),
		cfg.Build.Env,
		rmContainerCh,
		stdOutCh,
		stdErrCh,
		exitCodeCh,
		errCh,
	)

	for {
		select {
		case rmContainerFn := <-rmContainerCh:
			defer rmContainerFn()
		case l := <-stdOutCh:
			log.Info("%s", l)
		case l := <-stdErrCh:
			log.Warn("%s", l)
		case err := <-errCh:
			log.Err("%s", err)
			return
		case i := <-exitCodeCh:
			log.Info("exited with code %d", i)
			return
		}
	}

}
Пример #2
0
// DockerPush is the cli action for 'godo docker-push'
func DockerPush(c *cli.Context) {
	dockerClient := dockutil.ClientOrDie()
	cfg := config.ReadOrDie(c.String(FlagConfigFile))
	if cfg.Docker.ImageName == "" {
		log.Err("Docker image name was empty")
		os.Exit(1)
	}

	pio := docker.PushImageOptions{
		Name:         cfg.Docker.ImageName,
		Tag:          cfg.Docker.GetTag(),
		OutputStream: os.Stdout,
	}

	authFileLoc := cfg.Docker.Push.GetAuthFileLocation()
	authFile, err := os.Open(authFileLoc)
	if err != nil {
		log.Err("Reading Docker auth file %s [%s]", authFileLoc, err)
		os.Exit(1)
	}
	defer func() {
		if err := authFile.Close(); err != nil {
			log.Err("Closing Docker auth file %s [%s]", authFileLoc, err)
		}
	}()

	auths, err := docker.NewAuthConfigurations(authFile)
	if err != nil {
		log.Err("Parsing auth file %s [%s]", authFileLoc, err)
		os.Exit(1)
	}

	registry := "https://index.docker.io/v1/"
	spl := strings.Split(pio.Name, "/")
	if len(spl) == 3 {
		registry = spl[0]
	}

	auth, ok := auths.Configs[registry]
	if !ok {
		log.Err("Registry %s in your image %s is not in auth file %s ", registry, pio.Name, authFileLoc)
		os.Exit(1)
	}

	if err := dockerClient.PushImage(pio, auth); err != nil {
		log.Err("Pushing Docker image %s [%s]", pio.Name, err)
		os.Exit(1)
	}
	log.Info("Successfully pushed Docker image %s:%s", pio.Name, pio.Tag)
}
Пример #3
0
// DockerBuild is the CLI action for 'godo docker-build'
func DockerBuild(c *cli.Context) {
	dockerClient := dockutil.ClientOrDie()

	cfg := config.ReadOrDie(c.String(FlagConfigFile))
	if cfg.Docker.ImageName == "" {
		log.Err("Docker image name was empty")
		os.Exit(1)
	}

	dockerfileLocation := cfg.Docker.Build.GetDockerfileLocation()
	dockerfileBytes, err := ioutil.ReadFile(dockerfileLocation)
	if err != nil {
		log.Err("Reading Dockerfile %s [%s]", dockerfileLocation, err)
		os.Exit(1)
	}

	t := time.Now()
	buf := bytes.NewBuffer(nil)
	tr := tar.NewWriter(buf)
	tr.WriteHeader(&tar.Header{
		Name:       "Dockerfile",
		Size:       int64(len(dockerfileBytes)),
		ModTime:    t,
		AccessTime: t,
		ChangeTime: t,
	})
	tr.Write(dockerfileBytes)

	buildCtx, err := filepath.Abs(cfg.Docker.Build.Context.GetDirectory())
	if err != nil {
		log.Err("Invalid Docker build context %s [%s]", cfg.Docker.Build.Context.GetDirectory(), err)
		os.Exit(1)
	}

	skipSet := cfg.Docker.Build.Context.GetSkips()
	err = tarDir(buildCtx, tr, func(path string, fi os.FileInfo) bool {
		if _, ok := skipSet[path]; ok {
			return true
		}
		if strings.Contains(path, ".git") {
			return true
		}
		if fi.Name() == "Dockerfile" {
			return true
		}
		return false
	})
	if err != nil {
		log.Err("Archiving the build context directory %s [%s]", buildCtx, err)
		os.Exit(1)
	}

	if err := tr.Close(); err != nil {
		log.Err("Closing the build context archive preparing to send it to the Docker daemon [%s]", err)
		os.Exit(1)
	}

	opts := docker.BuildImageOptions{
		Name:           fmt.Sprintf("%s:%s", cfg.Docker.ImageName, cfg.Docker.GetTag()),
		InputStream:    buf,
		Dockerfile:     "Dockerfile",
		OutputStream:   os.Stdout,
		RmTmpContainer: true,
		Pull:           true,
	}
	if err := dockerClient.BuildImage(opts); err != nil {
		log.Err("Building image %s [%s]", cfg.Docker.ImageName, err)
		os.Exit(1)
	}
	log.Info("Successfully built Docker image %s", opts.Name)
}
Пример #4
0
// Custom is the CLI action for 'godo custom ...' commands
func Custom(c *cli.Context) {
	cfg := config.ReadOrDie(c.String(FlagConfigFile))
	if c.Bool(ListCustomFlag) {
		for _, customTarget := range cfg.Custom {
			log.Info("'%s' - %s", customTarget.Name, customTarget.Description)
		}
		return
	}
	if len(c.Args()) < 1 || c.Args()[0] == "" {
		log.Err("you must call this command as 'godo custom <target>'")
		os.Exit(1)
	}
	customName := c.Args()[0]
	customMap := make(map[string]config.CustomTarget)
	for _, customTarget := range cfg.Custom {
		customMap[customTarget.Name] = customTarget
	}
	target, ok := customMap[customName]
	if !ok {
		log.Err("no custom target '%s' found", customName)
		os.Exit(1)
	}

	dockerImage, err := docker.ParseImageFromName(fmt.Sprintf("%s:%s", target.ImageName, target.ImageTag))
	if err != nil {
		log.Err("invalid image name %s:%s (%s)", target.ImageName, target.ImageTag)
		os.Exit(1)
	}

	dockerCl := docker.ClientOrDie()
	paths := PathsOrDie()
	log.Info("executing %s in a %s:%s container", customName, target.ImageName, target.ImageTag)

	rmContainerCh := make(chan func())
	stdOutCh := make(chan docker.Log)
	stdErrCh := make(chan docker.Log)
	exitCodeCh := make(chan int)
	errCh := make(chan error)
	go docker.Run(
		dockerCl,
		dockerImage,
		customName,
		paths.CWD,
		target.MountTarget,
		target.Command,
		target.Envs,
		rmContainerCh,
		stdOutCh,
		stdErrCh,
		exitCodeCh,
		errCh,
	)

	for {
		select {
		case fn := <-rmContainerCh:
			defer fn()
		case l := <-stdOutCh:
			log.Info("%s", l)
		case l := <-stdErrCh:
			log.Warn("%s", l)
		case i := <-exitCodeCh:
			log.Info("exited with code %d", i)
			return
		case err := <-errCh:
			log.Err("%s", err)
			return
		}
	}
}