示例#1
0
// Build handles the `docker build` equivalent execution, returning the
// success/failure details.
func (builder *Layered) Build(config *api.Config) (*api.Result, error) {
	buildResult := &api.Result{}

	if config.HasOnBuild && config.BlockOnBuild {
		buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
			utilstatus.ReasonOnBuildForbidden,
			utilstatus.ReasonMessageOnBuildForbidden,
		)
		return buildResult, errors.New("builder image uses ONBUILD instructions but ONBUILD is not allowed")
	}

	if config.BuilderImage == "" {
		buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
			utilstatus.ReasonGenericS2IBuildFailed,
			utilstatus.ReasonMessageGenericS2iBuildFailed,
		)
		return buildResult, errors.New("builder image name cannot be empty")
	}

	if err := builder.CreateDockerfile(config); err != nil {
		buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
			utilstatus.ReasonDockerfileCreateFailed,
			utilstatus.ReasonMessageDockerfileCreateFailed,
		)
		return buildResult, err
	}

	glog.V(2).Info("Creating application source code image")
	tarStream := builder.tar.CreateTarStreamReader(filepath.Join(config.WorkingDir, "upload"), false)
	defer tarStream.Close()

	newBuilderImage := fmt.Sprintf("s2i-layered-temp-image-%d", time.Now().UnixNano())

	outReader, outWriter := io.Pipe()
	opts := docker.BuildImageOptions{
		Name:         newBuilderImage,
		Stdin:        tarStream,
		Stdout:       outWriter,
		CGroupLimits: config.CGroupLimits,
	}
	docker.StreamContainerIO(outReader, nil, func(s string) { glog.V(2).Info(s) })

	glog.V(2).Infof("Building new image %s with scripts and sources already inside", newBuilderImage)
	if err := builder.docker.BuildImage(opts); err != nil {
		buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
			utilstatus.ReasonDockerImageBuildFailed,
			utilstatus.ReasonMessageDockerImageBuildFailed,
		)
		return buildResult, err
	}

	// upon successful build we need to modify current config
	builder.config.LayeredBuild = true
	// new image name
	builder.config.BuilderImage = newBuilderImage
	// see CreateDockerfile, conditional copy, location of scripts
	scriptsIncluded := checkValidDirWithContents(path.Join(config.WorkingDir, api.UploadScripts))
	glog.V(2).Infof("Scripts dir has contents %v", scriptsIncluded)
	if scriptsIncluded {
		builder.config.ScriptsURL = "image://" + path.Join(getDestination(config), "scripts")
	} else {
		var err error
		builder.config.ScriptsURL, err = builder.docker.GetScriptsURL(newBuilderImage)
		if err != nil {
			buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
				utilstatus.ReasonGenericS2IBuildFailed,
				utilstatus.ReasonMessageGenericS2iBuildFailed,
			)
			return buildResult, err
		}
	}

	glog.V(2).Infof("Building %s using sti-enabled image", builder.config.Tag)
	if err := builder.scripts.Execute(api.Assemble, config.AssembleUser, builder.config); err != nil {
		buildResult.BuildInfo.FailureReason = utilstatus.NewFailureReason(
			utilstatus.ReasonAssembleFailed,
			utilstatus.ReasonMessageAssembleFailed,
		)
		switch e := err.(type) {
		case s2ierr.ContainerError:
			return buildResult, s2ierr.NewAssembleError(builder.config.Tag, e.Output, e)
		default:
			return buildResult, err
		}
	}
	buildResult.Success = true

	return buildResult, nil
}
示例#2
0
文件: layered.go 项目: jhadvig/origin
func (b *Layered) Build(config *api.Config) (*api.Result, error) {
	if err := b.CreateDockerfile(config); err != nil {
		return nil, err
	}

	glog.V(2).Info("Creating application source code image")
	tarStream, err := b.SourceTar(config)
	if err != nil {
		return nil, err
	}
	defer tarStream.Close()

	newBuilderImage := fmt.Sprintf("%s-%d", b.config.BuilderImage, time.Now().UnixNano())
	outReader, outWriter := io.Pipe()
	defer outReader.Close()
	defer outWriter.Close()
	opts := docker.BuildImageOptions{
		Name:   newBuilderImage,
		Stdin:  tarStream,
		Stdout: outWriter,
	}

	// goroutine to stream container's output
	go func(reader io.Reader) {
		scanner := bufio.NewReader(reader)
		for {
			text, err := scanner.ReadString('\n')
			if err != nil {
				// we're ignoring ErrClosedPipe, as this is information
				// the docker container ended streaming logs
				if glog.V(2) && err != io.ErrClosedPipe {
					glog.Errorf("Error reading docker stdout, %v", err)
				}
				break
			}
			glog.V(2).Info(text)
		}
	}(outReader)

	glog.V(2).Infof("Building new image %s with scripts and sources already inside", newBuilderImage)
	if err = b.docker.BuildImage(opts); err != nil {
		return nil, err
	}

	// upon successful build we need to modify current config
	b.config.LayeredBuild = true
	// new image name
	b.config.BuilderImage = newBuilderImage
	// the scripts are inside the image
	b.config.ScriptsURL = "image://" + filepath.Join(getDestination(config), "scripts")

	glog.V(2).Infof("Building %s using sti-enabled image", b.config.Tag)
	if err := b.scripts.Execute(api.Assemble, b.config); err != nil {
		switch e := err.(type) {
		case errors.ContainerError:
			return nil, errors.NewAssembleError(b.config.Tag, e.Output, e)
		default:
			return nil, err
		}
	}

	return &api.Result{
		Success: true,
	}, nil
}
示例#3
0
文件: layered.go 项目: rootfs/origin
// Build handles the `docker build` equivalent execution, returning the
// success/failure details.
func (builder *Layered) Build(config *api.Config) (*api.Result, error) {
	if config.HasOnBuild && config.BlockOnBuild {
		return nil, fmt.Errorf("builder image uses ONBUILD instructions but ONBUILD is not allowed")
	}

	if err := builder.CreateDockerfile(config); err != nil {
		return nil, err
	}

	glog.V(2).Info("Creating application source code image")
	tarStream, err := builder.SourceTar(config)
	if err != nil {
		return nil, err
	}
	defer tarStream.Close()

	namedReference, err := reference.ParseNamed(builder.config.BuilderImage)
	if err != nil {
		return nil, err
	}
	newBuilderImage := fmt.Sprintf("%s:s2i-layered-%d", namedReference.Name(), time.Now().UnixNano())

	outReader, outWriter := io.Pipe()
	defer outReader.Close()
	defer outWriter.Close()
	opts := docker.BuildImageOptions{
		Name:         newBuilderImage,
		Stdin:        tarStream,
		Stdout:       outWriter,
		CGroupLimits: config.CGroupLimits,
	}
	// goroutine to stream container's output
	go func(reader io.Reader) {
		scanner := bufio.NewReader(reader)
		for {
			text, err := scanner.ReadString('\n')
			if err != nil {
				// we're ignoring ErrClosedPipe, as this is information
				// the docker container ended streaming logs
				if glog.Is(2) && err != io.ErrClosedPipe && err != io.EOF {
					glog.Errorf("Error reading docker stdout, %v", err)
				}
				break
			}
			glog.V(2).Info(text)
		}
	}(outReader)

	glog.V(2).Infof("Building new image %s with scripts and sources already inside", newBuilderImage)
	if err = builder.docker.BuildImage(opts); err != nil {
		return nil, err
	}

	// upon successful build we need to modify current config
	builder.config.LayeredBuild = true
	// new image name
	builder.config.BuilderImage = newBuilderImage
	// see CreateDockerfile, conditional copy, location of scripts
	scriptsIncluded := checkValidDirWithContents(path.Join(config.WorkingDir, api.UploadScripts))
	glog.V(2).Infof("Scripts dir has contents %v", scriptsIncluded)
	if scriptsIncluded {
		builder.config.ScriptsURL = "image://" + path.Join(getDestination(config), "scripts")
	} else {
		builder.config.ScriptsURL, err = builder.docker.GetScriptsURL(newBuilderImage)
		if err != nil {
			return nil, err
		}
	}

	glog.V(2).Infof("Building %s using sti-enabled image", builder.config.Tag)
	if err := builder.scripts.Execute(api.Assemble, config.AssembleUser, builder.config); err != nil {
		switch e := err.(type) {
		case errors.ContainerError:
			return nil, errors.NewAssembleError(builder.config.Tag, e.Output, e)
		default:
			return nil, err
		}
	}

	return &api.Result{
		Success: true,
	}, nil
}
示例#4
0
//Build handles the `docker build` equivalent execution, returning the success/failure details
func (b *Layered) Build(config *api.Config) (*api.Result, error) {
	if err := b.CreateDockerfile(config); err != nil {
		return nil, err
	}

	glog.V(2).Info("Creating application source code image")
	tarStream, err := b.SourceTar(config)
	if err != nil {
		return nil, err
	}
	defer tarStream.Close()

	dockerImageReference, err := docker.ParseDockerImageReference(b.config.BuilderImage)
	if err != nil {
		return nil, err
	}
	// if we fall down this path via oc new-app, the builder image will be a docker image ref ending
	// with a @<hex image id> instead of a tag; simply appending the time stamp to the end of a
	// hex image id ref is not kosher with the docker API; so we remove the ID piece, and then
	// construct the new image name
	var newBuilderImage string
	if len(dockerImageReference.ID) == 0 {
		newBuilderImage = fmt.Sprintf("%s-%d", b.config.BuilderImage, time.Now().UnixNano())
	} else {
		if len(dockerImageReference.Registry) > 0 {
			newBuilderImage = fmt.Sprintf("%s/", dockerImageReference.Registry)
		}
		if len(dockerImageReference.Namespace) > 0 {
			newBuilderImage = fmt.Sprintf("%s%s/", newBuilderImage, dockerImageReference.Namespace)
		}
		newBuilderImage = fmt.Sprintf("%s%s:s2i-layered-%d", newBuilderImage, dockerImageReference.Name, time.Now().UnixNano())
	}

	outReader, outWriter := io.Pipe()
	defer outReader.Close()
	defer outWriter.Close()
	opts := docker.BuildImageOptions{
		Name:         newBuilderImage,
		Stdin:        tarStream,
		Stdout:       outWriter,
		CGroupLimits: config.CGroupLimits,
	}
	// goroutine to stream container's output
	go func(reader io.Reader) {
		scanner := bufio.NewReader(reader)
		for {
			text, err := scanner.ReadString('\n')
			if err != nil {
				// we're ignoring ErrClosedPipe, as this is information
				// the docker container ended streaming logs
				if glog.V(2) && err != io.ErrClosedPipe {
					glog.Errorf("Error reading docker stdout, %v", err)
				}
				break
			}
			glog.V(2).Info(text)
		}
	}(outReader)

	glog.V(2).Infof("Building new image %s with scripts and sources already inside", newBuilderImage)
	if err = b.docker.BuildImage(opts); err != nil {
		return nil, err
	}

	// upon successful build we need to modify current config
	b.config.LayeredBuild = true
	// new image name
	b.config.BuilderImage = newBuilderImage
	// see CreateDockerfile, conditional copy, location of scripts
	scriptsIncluded := checkValidDirWithContents(path.Join(config.WorkingDir, api.UploadScripts))
	glog.V(2).Infof("Scripts dir has contents %v", scriptsIncluded)
	if scriptsIncluded {
		b.config.ScriptsURL = "image://" + path.Join(getDestination(config), "scripts")
	} else {
		b.config.ScriptsURL, err = b.docker.GetScriptsURL(newBuilderImage)
		if err != nil {
			return nil, err
		}
	}

	glog.V(2).Infof("Building %s using sti-enabled image", b.config.Tag)
	if err := b.scripts.Execute(api.Assemble, config.AssembleUser, b.config); err != nil {
		switch e := err.(type) {
		case errors.ContainerError:
			return nil, errors.NewAssembleError(b.config.Tag, e.Output, e)
		default:
			return nil, err
		}
	}

	return &api.Result{
		Success: true,
	}, nil
}