// run is responsible for preparing environment for actual build. // It accepts factoryFunc and an ordered array of SCMAuths. func run(builderFactory factoryFunc, scmAuths []scmauth.SCMAuth) { client, endpoint, err := dockerutil.NewHelper().GetClient() if err != nil { glog.Fatalf("Error obtaining docker client: %v", err) } buildStr := os.Getenv("BUILD") build := api.Build{} if err := latest.Codec.DecodeInto([]byte(buildStr), &build); err != nil { glog.Fatalf("Unable to parse build: %v", err) } var ( authcfg docker.AuthConfiguration authPresent bool ) output := build.Spec.Output.To != nil && len(build.Spec.Output.To.Name) != 0 if output { authcfg, authPresent = dockercfg.NewHelper().GetDockerAuth( build.Spec.Output.To.Name, dockercfg.PullAuthType, ) } if build.Spec.Source.SourceSecret != nil { if err := setupSourceSecret(build.Spec.Source.SourceSecret.Name, scmAuths); err != nil { glog.Fatalf("Cannot setup secret file for accessing private repository: %v", err) } } b := builderFactory(client, endpoint, authcfg, authPresent, &build) if err = b.Build(); err != nil { glog.Fatalf("Build error: %v", err) } if !output { glog.Warning("Build does not have an Output defined, no output image was pushed to a registry.") } }
// Build executes a Docker build func (d *DockerBuilder) Build() error { var push bool buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, d.urlTimeout, os.Stdin, d.gitClient) if err != nil { return err } if sourceInfo != nil { updateBuildRevision(d.client, d.build, sourceInfo) } if err := d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from build config %s ...", d.build.Name) // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Status.OutputDockerImageReference = d.build.Name } else { push = true } if err := d.dockerBuild(buildDir, d.build.Spec.Source.Secrets); err != nil { return err } defer removeImage(d.dockerClient, d.build.Status.OutputDockerImageReference) if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( d.build.Status.OutputDockerImageReference, dockercfg.PushAuthType, ) if authPresent { glog.V(4).Infof("Authenticating Docker push with user %q", pushAuthConfig.Username) } glog.Infof("Pushing image %s ...", d.build.Status.OutputDockerImageReference) if err := pushImage(d.dockerClient, d.build.Status.OutputDockerImageReference, pushAuthConfig); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Push successful") } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } if err = d.fetchSource(buildDir); err != nil { return err } if err = d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from %s/%s BuildConfig ...", d.build.Namespace, d.build.Name) var push bool // if there is no output target, set one up so the docker build logic // will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Spec.Output.To = &kapi.ObjectReference{ Kind: "DockerImage", Name: noOutputDefaultTag, } push = false } else { push = true } if err = d.dockerBuild(buildDir); err != nil { return err } defer removeImage(d.dockerClient, d.build.Spec.Output.To.Name) if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( d.build.Spec.Output.To.Name, dockercfg.PushAuthType, ) if authPresent { glog.V(3).Infof("Using Docker authentication provided") d.auth = pushAuthConfig } glog.Infof("Pushing %s image ...", d.build.Spec.Output.To.Name) if err := pushImage(d.dockerClient, d.build.Spec.Output.To.Name, d.auth); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Successfully pushed %s", d.build.Spec.Output.To.Name) } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } if err := fetchSource(buildDir, d.build, d.urlTimeout, os.Stdin, d.git); err != nil { return err } if err := d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from build config %s ...", d.build.Name) var push bool // if there is no output target, set one up so the docker build logic // will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Spec.Output.To = &kapi.ObjectReference{ Kind: "DockerImage", Name: noOutputDefaultTag, } push = false } else { push = true } if err := d.dockerBuild(buildDir); err != nil { return err } defer removeImage(d.dockerClient, d.build.Spec.Output.To.Name) if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( d.build.Spec.Output.To.Name, dockercfg.PushAuthType, ) if authPresent { glog.V(4).Infof("Authenticating Docker push with user %q", pushAuthConfig.Username) } glog.Infof("Pushing image %s ...", d.build.Spec.Output.To.Name) if err := pushImage(d.dockerClient, d.build.Spec.Output.To.Name, pushAuthConfig); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Push successful") } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } if err = d.fetchSource(buildDir); err != nil { return err } if err = d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from %s/%s BuildConfig ...", d.build.Namespace, d.build.Name) if err = d.dockerBuild(buildDir); err != nil { return err } tag := d.build.Parameters.Output.DockerImageReference defer removeImage(d.dockerClient, tag) dockerImageRef := d.build.Parameters.Output.DockerImageReference if len(dockerImageRef) != 0 { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( dockerImageRef, dockercfg.PushAuthType, ) if authPresent { glog.V(3).Infof("Using Docker authentication provided") d.auth = pushAuthConfig } glog.Infof("Pushing %s image ...", dockerImageRef) if err := pushImage(d.dockerClient, tag, d.auth); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Successfully pushed %s", dockerImageRef) } return nil }
func extractSourceFromImage(dockerClient DockerClient, image, buildDir string, paths []api.ImageSourcePath) error { glog.V(4).Infof("Extracting image source from %s", image) // Pre-pull image if a secret is specified pullSecret := os.Getenv(dockercfg.PullSourceAuthType) if len(pullSecret) > 0 { dockerAuth, present := dockercfg.NewHelper().GetDockerAuth(image, dockercfg.PullSourceAuthType) if present { dockerClient.PullImage(docker.PullImageOptions{Repository: image}, dockerAuth) } } // Create container to copy from container, err := dockerClient.CreateContainer(docker.CreateContainerOptions{ Config: &docker.Config{ Image: image, }, }) if err != nil { return fmt.Errorf("error creating source image container: %v", err) } defer dockerClient.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID}) tarHelper := tar.New() tarHelper.SetExclusionPattern(nil) for _, path := range paths { glog.V(4).Infof("Extracting path %s from container %s to %s", path.SourcePath, container.ID, path.DestinationDir) err := copyImageSource(dockerClient, container.ID, path.SourcePath, filepath.Join(buildDir, path.DestinationDir), tarHelper) if err != nil { return fmt.Errorf("error copying source path %s to %s: %v", path.SourcePath, path.DestinationDir, err) } } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { if d.build.Spec.Source.Git == nil && d.build.Spec.Source.Binary == nil && d.build.Spec.Source.Dockerfile == nil && d.build.Spec.Source.Images == nil { return fmt.Errorf("must provide a value for at least one of source, binary, images, or dockerfile") } var push bool pushTag := d.build.Status.OutputDockerImageReference buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, initialURLCheckTimeout, os.Stdin, d.gitClient) if err != nil { d.build.Status.Reason = api.StatusReasonFetchSourceFailed d.build.Status.Message = api.StatusMessageFetchSourceFailed if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } if sourceInfo != nil { glog.V(4).Infof("Setting build revision with details %#v", sourceInfo) revision := updateBuildRevision(d.build, sourceInfo) if updateErr := retryBuildStatusUpdate(d.build, d.client, revision); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } } if err = d.addBuildParameters(buildDir, sourceInfo); err != nil { return err } glog.V(4).Infof("Starting Docker build from build config %s ...", d.build.Name) // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Status.OutputDockerImageReference = d.build.Name } else { push = true } buildTag := randomBuildTag(d.build.Namespace, d.build.Name) dockerfilePath := d.getDockerfilePath(buildDir) imageNames := getDockerfileFrom(dockerfilePath) if len(imageNames) == 0 { return fmt.Errorf("no FROM image in Dockerfile") } for _, imageName := range imageNames { if imageName == "scratch" { glog.V(4).Infof("\nSkipping image \"scratch\"") continue } imageExists := true _, err = d.dockerClient.InspectImage(imageName) if err != nil { if err != docker.ErrNoSuchImage { return err } imageExists = false } // if forcePull or the image not exists on the node we should pull the image first if d.build.Spec.Strategy.DockerStrategy.ForcePull || !imageExists { pullAuthConfig, _ := dockercfg.NewHelper().GetDockerAuth( imageName, dockercfg.PullAuthType, ) glog.V(0).Infof("\nPulling image %s ...", imageName) if err = pullImage(d.dockerClient, imageName, pullAuthConfig); err != nil { d.build.Status.Reason = api.StatusReasonPullBuilderImageFailed d.build.Status.Message = api.StatusMessagePullBuilderImageFailed if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return fmt.Errorf("failed to pull image: %v", err) } } } if err = d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil { d.build.Status.Reason = api.StatusReasonDockerBuildFailed d.build.Status.Message = api.StatusMessageDockerBuildFailed if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } cname := containerName("docker", d.build.Name, d.build.Namespace, "post-commit") if err := execPostCommitHook(d.dockerClient, d.build.Spec.PostCommit, buildTag, cname); err != nil { d.build.Status.Reason = api.StatusReasonPostCommitHookFailed d.build.Status.Message = api.StatusMessagePostCommitHookFailed if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } if push { if err := tagImage(d.dockerClient, buildTag, pushTag); err != nil { return err } } if err := removeImage(d.dockerClient, buildTag); err != nil { glog.V(0).Infof("warning: Failed to remove temporary build tag %v: %v", buildTag, err) } if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( pushTag, dockercfg.PushAuthType, ) if authPresent { glog.V(4).Infof("Authenticating Docker push with user %q", pushAuthConfig.Username) } glog.V(0).Infof("\nPushing image %s ...", pushTag) if err := pushImage(d.dockerClient, pushTag, pushAuthConfig); err != nil { d.build.Status.Reason = api.StatusReasonPushImageToRegistryFailed d.build.Status.Message = api.StatusMessagePushImageToRegistryFailed if updateErr := retryBuildStatusUpdate(d.build, d.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return reportPushFailure(err, authPresent, pushAuthConfig) } glog.V(0).Infof("Push successful") } return nil }
func extractSourceFromImage(dockerClient DockerClient, image, buildDir string, imageSecretIndex int, paths []api.ImageSourcePath, forcePull bool) error { glog.V(4).Infof("Extracting image source from %s", image) dockerAuth := docker.AuthConfiguration{} if imageSecretIndex != -1 { pullSecret := os.Getenv(fmt.Sprintf("%s%d", dockercfg.PullSourceAuthType, imageSecretIndex)) if len(pullSecret) > 0 { authPresent := false dockerAuth, authPresent = dockercfg.NewHelper().GetDockerAuth(image, fmt.Sprintf("%s%d", dockercfg.PullSourceAuthType, imageSecretIndex)) if authPresent { glog.V(5).Infof("Registry server Address: %s", dockerAuth.ServerAddress) glog.V(5).Infof("Registry server User Name: %s", dockerAuth.Username) glog.V(5).Infof("Registry server Email: %s", dockerAuth.Email) passwordPresent := "<<empty>>" if len(dockerAuth.Password) > 0 { passwordPresent = "<<non-empty>>" } glog.V(5).Infof("Registry server Password: %s", passwordPresent) } } } exists := true if !forcePull { _, err := dockerClient.InspectImage(image) if err != nil && err == docker.ErrNoSuchImage { exists = false } else if err != nil { return err } } if !exists || forcePull { glog.V(0).Infof("Pulling image %q ...", image) if err := dockerClient.PullImage(docker.PullImageOptions{Repository: image}, dockerAuth); err != nil { return fmt.Errorf("error pulling image %v: %v", image, err) } } containerConfig := &docker.Config{Image: image} if inspect, err := dockerClient.InspectImage(image); err != nil { return err } else { // In case the Docker image does not specify the entrypoint if len(inspect.Config.Entrypoint) == 0 && len(inspect.Config.Cmd) == 0 { containerConfig.Entrypoint = []string{"/fake-entrypoint"} } } // Create container to copy from container, err := dockerClient.CreateContainer(docker.CreateContainerOptions{Config: containerConfig}) if err != nil { return fmt.Errorf("error creating source image container: %v", err) } defer dockerClient.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID}) tarHelper := tar.New() tarHelper.SetExclusionPattern(nil) for _, path := range paths { glog.V(4).Infof("Extracting path %s from container %s to %s", path.SourcePath, container.ID, path.DestinationDir) err := copyImageSource(dockerClient, container.ID, path.SourcePath, filepath.Join(buildDir, path.DestinationDir), tarHelper) if err != nil { return fmt.Errorf("error copying source path %s to %s: %v", path.SourcePath, path.DestinationDir, err) } } return nil }
// executes STI build based on configured builder, S2I builder factory and S2I config validator func (s *STIBuilder) Build() error { var push bool // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if s.build.Spec.Output.To == nil || len(s.build.Spec.Output.To.Name) == 0 { s.build.Spec.Output.To = &kapi.ObjectReference{ Kind: "DockerImage", Name: noOutputDefaultTag, } push = false } else { push = true } tag := s.build.Spec.Output.To.Name config := &stiapi.Config{ BuilderImage: s.build.Spec.Strategy.SourceStrategy.From.Name, DockerConfig: &stiapi.DockerConfig{Endpoint: s.dockerSocket}, Source: s.build.Spec.Source.Git.URI, ContextDir: s.build.Spec.Source.ContextDir, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), Tag: tag, ScriptsURL: s.build.Spec.Strategy.SourceStrategy.Scripts, Environment: buildEnvVars(s.build), LabelNamespace: api.DefaultDockerLabelNamespace, Incremental: s.build.Spec.Strategy.SourceStrategy.Incremental, ForcePull: s.build.Spec.Strategy.SourceStrategy.ForcePull, } if s.build.Spec.Revision != nil && s.build.Spec.Revision.Git != nil && s.build.Spec.Revision.Git.Commit != "" { config.Ref = s.build.Spec.Revision.Git.Commit } else if s.build.Spec.Source.Git.Ref != "" { config.Ref = s.build.Spec.Source.Git.Ref } allowedUIDs := os.Getenv("ALLOWED_UIDS") glog.V(2).Infof("The value of ALLOWED_UIDS is [%s]", allowedUIDs) if len(allowedUIDs) > 0 { err := config.AllowedUIDs.Set(allowedUIDs) if err != nil { return err } } if errs := s.configValidator.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } // If DockerCfgPath is provided in api.Config, then attempt to read the the // dockercfg file and get the authentication for pulling the builder image. config.PullAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(config.BuilderImage, dockercfg.PullAuthType) config.IncrementalAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(tag, dockercfg.PushAuthType) glog.V(2).Infof("Creating a new S2I builder with build config: %#v\n", describe.DescribeConfig(config)) builder, err := s.builderFactory.GetStrategy(config) if err != nil { return err } glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) // Set the HTTP and HTTPS proxies to be used by the S2I build. originalProxies := setHTTPProxy(s.build.Spec.Source.Git.HTTPProxy, s.build.Spec.Source.Git.HTTPSProxy) if _, err = builder.Build(config); err != nil { return err } // Reset proxies back to their original value. resetHTTPProxy(originalProxies) if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( tag, dockercfg.PushAuthType, ) if authPresent { glog.Infof("Using provided push secret for pushing %s image", tag) } else { glog.Infof("No push secret provided") } glog.Infof("Pushing %s image ...", tag) if err := pushImage(s.dockerClient, tag, pushAuthConfig); err != nil { // write extended error message to assist in problem resolution msg := fmt.Sprintf("Failed to push image. Response from registry is: %v", err) if authPresent { glog.Infof("Registry server Address: %s", pushAuthConfig.ServerAddress) glog.Infof("Registry server User Name: %s", pushAuthConfig.Username) glog.Infof("Registry server Email: %s", pushAuthConfig.Email) passwordPresent := "<<empty>>" if len(pushAuthConfig.Password) > 0 { passwordPresent = "<<non-empty>>" } glog.Infof("Registry server address: %s", passwordPresent) } return errors.New(msg) } glog.Infof("Successfully pushed %s", tag) glog.Flush() } return nil }
// Build executes STI build based on configured builder, S2I builder factory and S2I config validator func (s *STIBuilder) Build() error { var push bool contextDir := filepath.Clean(s.build.Spec.Source.ContextDir) if contextDir == "." || contextDir == "/" { contextDir = "" } buildDir, err := ioutil.TempDir("", "s2i-build") if err != nil { return err } srcDir := filepath.Join(buildDir, s2iapi.Source) if err := os.MkdirAll(srcDir, os.ModePerm); err != nil { return err } tmpDir := filepath.Join(buildDir, "tmp") if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { return err } download := &downloader{ s: s, in: os.Stdin, timeout: urlCheckTimeout, dir: srcDir, contextDir: contextDir, tmpDir: tmpDir, } // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if s.build.Spec.Output.To == nil || len(s.build.Spec.Output.To.Name) == 0 { s.build.Spec.Output.To = &kapi.ObjectReference{ Kind: "DockerImage", Name: noOutputDefaultTag, } push = false } else { push = true } tag := s.build.Spec.Output.To.Name git := s.build.Spec.Source.Git var ref string if s.build.Spec.Revision != nil && s.build.Spec.Revision.Git != nil && len(s.build.Spec.Revision.Git.Commit) != 0 { ref = s.build.Spec.Revision.Git.Commit } else if git != nil && len(git.Ref) != 0 { ref = git.Ref } sourceURI := &url.URL{ Scheme: "file", Path: srcDir, Fragment: ref, } config := &s2iapi.Config{ WorkingDir: buildDir, DockerConfig: &s2iapi.DockerConfig{Endpoint: s.dockerSocket}, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), LabelNamespace: api.DefaultDockerLabelNamespace, ScriptsURL: s.build.Spec.Strategy.SourceStrategy.Scripts, BuilderImage: s.build.Spec.Strategy.SourceStrategy.From.Name, Incremental: s.build.Spec.Strategy.SourceStrategy.Incremental, ForcePull: s.build.Spec.Strategy.SourceStrategy.ForcePull, Environment: buildEnvVars(s.build), DockerNetworkMode: getDockerNetworkMode(), Source: sourceURI.String(), Tag: tag, ContextDir: s.build.Spec.Source.ContextDir, } allowedUIDs := os.Getenv("ALLOWED_UIDS") glog.V(2).Infof("The value of ALLOWED_UIDS is [%s]", allowedUIDs) if len(allowedUIDs) > 0 { err := config.AllowedUIDs.Set(allowedUIDs) if err != nil { return err } } if errs := s.validator.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } // If DockerCfgPath is provided in api.Config, then attempt to read the the // dockercfg file and get the authentication for pulling the builder image. config.PullAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(config.BuilderImage, dockercfg.PullAuthType) config.IncrementalAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(tag, dockercfg.PushAuthType) glog.V(2).Infof("Creating a new S2I builder with build config: %#v\n", describe.DescribeConfig(config)) builder, err := s.builder.Builder(config, s2ibuild.Overrides{Downloader: download}) if err != nil { return err } glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) // Set the HTTP and HTTPS proxies to be used by the S2I build. var originalProxies map[string]string if git != nil { originalProxies = setHTTPProxy(git.HTTPProxy, git.HTTPSProxy) } if _, err = builder.Build(config); err != nil { return err } // Reset proxies back to their original value. resetHTTPProxy(originalProxies) if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( tag, dockercfg.PushAuthType, ) if authPresent { glog.Infof("Using provided push secret for pushing %s image", tag) } else { glog.Infof("No push secret provided") } glog.Infof("Pushing %s image ...", tag) if err := pushImage(s.dockerClient, tag, pushAuthConfig); err != nil { // write extended error message to assist in problem resolution msg := fmt.Sprintf("Failed to push image. Response from registry is: %v", err) if authPresent { glog.Infof("Registry server Address: %s", pushAuthConfig.ServerAddress) glog.Infof("Registry server User Name: %s", pushAuthConfig.Username) glog.Infof("Registry server Email: %s", pushAuthConfig.Email) passwordPresent := "<<empty>>" if len(pushAuthConfig.Password) > 0 { passwordPresent = "<<non-empty>>" } glog.Infof("Registry server Password: %s", passwordPresent) } return errors.New(msg) } glog.Infof("Successfully pushed %s", tag) glog.Flush() } return nil }
// Build executes STI build based on configured builder, S2I builder factory // and S2I config validator func (s *S2IBuilder) Build() error { if s.build.Spec.Strategy.SourceStrategy == nil { return errors.New("the source to image builder must be used with the source strategy") } contextDir := filepath.Clean(s.build.Spec.Source.ContextDir) if contextDir == "." || contextDir == "/" { contextDir = "" } buildDir, err := ioutil.TempDir("", "s2i-build") if err != nil { return err } srcDir := filepath.Join(buildDir, s2iapi.Source) if err = os.MkdirAll(srcDir, os.ModePerm); err != nil { return err } tmpDir := filepath.Join(buildDir, "tmp") if err = os.MkdirAll(tmpDir, os.ModePerm); err != nil { return err } download := &downloader{ s: s, in: os.Stdin, timeout: initialURLCheckTimeout, dir: srcDir, contextDir: contextDir, tmpDir: tmpDir, } var push bool // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if s.build.Spec.Output.To == nil || len(s.build.Spec.Output.To.Name) == 0 { s.build.Status.OutputDockerImageReference = s.build.Name } else { push = true } pushTag := s.build.Status.OutputDockerImageReference git := s.build.Spec.Source.Git var ref string if s.build.Spec.Revision != nil && s.build.Spec.Revision.Git != nil && len(s.build.Spec.Revision.Git.Commit) != 0 { ref = s.build.Spec.Revision.Git.Commit } else if git != nil && len(git.Ref) != 0 { ref = git.Ref } sourceURI := &url.URL{ Scheme: "file", Path: srcDir, Fragment: ref, } injections := s2iapi.VolumeList{} for _, s := range s.build.Spec.Source.Secrets { glog.V(3).Infof("Injecting secret %q into a build into %q", s.Secret.Name, filepath.Clean(s.DestinationDir)) secretSourcePath := filepath.Join(strategy.SecretBuildSourceBaseMountPath, s.Secret.Name) injections = append(injections, s2iapi.VolumeSpec{ Source: secretSourcePath, Destination: s.DestinationDir, }) } buildTag := randomBuildTag(s.build.Namespace, s.build.Name) scriptDownloadProxyConfig, err := scriptProxyConfig(s.build) if err != nil { return err } if scriptDownloadProxyConfig != nil { glog.V(0).Infof("Using HTTP proxy %v and HTTPS proxy %v for script download", scriptDownloadProxyConfig.HTTPProxy, scriptDownloadProxyConfig.HTTPSProxy) } var incremental bool if s.build.Spec.Strategy.SourceStrategy.Incremental != nil { incremental = *s.build.Spec.Strategy.SourceStrategy.Incremental } config := &s2iapi.Config{ WorkingDir: buildDir, DockerConfig: &s2iapi.DockerConfig{Endpoint: s.dockerSocket}, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), LabelNamespace: api.DefaultDockerLabelNamespace, ScriptsURL: s.build.Spec.Strategy.SourceStrategy.Scripts, BuilderImage: s.build.Spec.Strategy.SourceStrategy.From.Name, Incremental: incremental, IncrementalFromTag: pushTag, Environment: buildEnvVars(s.build), Labels: buildLabels(s.build), DockerNetworkMode: getDockerNetworkMode(), Source: sourceURI.String(), Tag: buildTag, ContextDir: s.build.Spec.Source.ContextDir, CGroupLimits: s.cgLimits, Injections: injections, ScriptDownloadProxyConfig: scriptDownloadProxyConfig, BlockOnBuild: true, } if s.build.Spec.Strategy.SourceStrategy.ForcePull { glog.V(4).Infof("With force pull true, setting policies to %s", s2iapi.PullAlways) config.BuilderPullPolicy = s2iapi.PullAlways config.RuntimeImagePullPolicy = s2iapi.PullAlways } else { glog.V(4).Infof("With force pull false, setting policies to %s", s2iapi.PullIfNotPresent) config.BuilderPullPolicy = s2iapi.PullIfNotPresent config.RuntimeImagePullPolicy = s2iapi.PullIfNotPresent } config.PreviousImagePullPolicy = s2iapi.PullAlways allowedUIDs := os.Getenv(api.AllowedUIDs) glog.V(4).Infof("The value of %s is [%s]", api.AllowedUIDs, allowedUIDs) if len(allowedUIDs) > 0 { err = config.AllowedUIDs.Set(allowedUIDs) if err != nil { return err } } dropCaps := os.Getenv(api.DropCapabilities) glog.V(4).Infof("The value of %s is [%s]", api.DropCapabilities, dropCaps) if len(dropCaps) > 0 { config.DropCapabilities = strings.Split(dropCaps, ",") } if s.build.Spec.Strategy.SourceStrategy.RuntimeImage != nil { runtimeImageName := s.build.Spec.Strategy.SourceStrategy.RuntimeImage.Name config.RuntimeImage = runtimeImageName t, _ := dockercfg.NewHelper().GetDockerAuth(runtimeImageName, dockercfg.PullAuthType) config.RuntimeAuthentication = s2iapi.AuthConfig{Username: t.Username, Password: t.Password, Email: t.Email, ServerAddress: t.ServerAddress} config.RuntimeArtifacts = copyToVolumeList(s.build.Spec.Strategy.SourceStrategy.RuntimeArtifacts) } // If DockerCfgPath is provided in api.Config, then attempt to read the // dockercfg file and get the authentication for pulling the builder image. t, _ := dockercfg.NewHelper().GetDockerAuth(config.BuilderImage, dockercfg.PullAuthType) config.PullAuthentication = s2iapi.AuthConfig{Username: t.Username, Password: t.Password, Email: t.Email, ServerAddress: t.ServerAddress} t, _ = dockercfg.NewHelper().GetDockerAuth(pushTag, dockercfg.PushAuthType) config.IncrementalAuthentication = s2iapi.AuthConfig{Username: t.Username, Password: t.Password, Email: t.Email, ServerAddress: t.ServerAddress} if errs := s.validator.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } glog.V(4).Infof("Creating a new S2I builder with build config: %#v\n", describe.Config(config)) builder, buildInfo, err := s.builder.Builder(config, s2ibuild.Overrides{Downloader: download}) if err != nil { s.build.Status.Reason, s.build.Status.Message = convertS2IFailureType(buildInfo.FailureReason.Reason, buildInfo.FailureReason.Message) if updateErr := retryBuildStatusUpdate(s.build, s.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) result, err := builder.Build(config) if err != nil { s.build.Status.Reason, s.build.Status.Message = convertS2IFailureType(result.BuildInfo.FailureReason.Reason, result.BuildInfo.FailureReason.Message) if updateErr := retryBuildStatusUpdate(s.build, s.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } cName := containerName("s2i", s.build.Name, s.build.Namespace, "post-commit") if err = execPostCommitHook(s.dockerClient, s.build.Spec.PostCommit, buildTag, cName); err != nil { s.build.Status.Reason = api.StatusReasonPostCommitHookFailed s.build.Status.Message = api.StatusMessagePostCommitHookFailed if updateErr := retryBuildStatusUpdate(s.build, s.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return err } if push { if err = tagImage(s.dockerClient, buildTag, pushTag); err != nil { return err } } if err = removeImage(s.dockerClient, buildTag); err != nil { glog.V(0).Infof("warning: Failed to remove temporary build tag %v: %v", buildTag, err) } if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( pushTag, dockercfg.PushAuthType, ) if authPresent { glog.V(3).Infof("Using provided push secret for pushing %s image", pushTag) } else { glog.V(3).Infof("No push secret provided") } glog.V(0).Infof("\nPushing image %s ...", pushTag) if err = pushImage(s.dockerClient, pushTag, pushAuthConfig); err != nil { s.build.Status.Reason = api.StatusReasonPushImageToRegistryFailed s.build.Status.Message = api.StatusMessagePushImageToRegistryFailed if updateErr := retryBuildStatusUpdate(s.build, s.client, nil); updateErr != nil { utilruntime.HandleError(fmt.Errorf("error: An error occured while updating the build status: %v", updateErr)) } return reportPushFailure(err, authPresent, pushAuthConfig) } glog.V(0).Infof("Push successful") } return nil }
// Build executes STI build based on configured builder, S2I builder factory and S2I config validator func (s *S2IBuilder) Build() error { var push bool contextDir := filepath.Clean(s.build.Spec.Source.ContextDir) if contextDir == "." || contextDir == "/" { contextDir = "" } buildDir, err := ioutil.TempDir("", "s2i-build") if err != nil { return err } srcDir := filepath.Join(buildDir, s2iapi.Source) if err := os.MkdirAll(srcDir, os.ModePerm); err != nil { return err } tmpDir := filepath.Join(buildDir, "tmp") if err := os.MkdirAll(tmpDir, os.ModePerm); err != nil { return err } download := &downloader{ s: s, in: os.Stdin, timeout: urlCheckTimeout, dir: srcDir, contextDir: contextDir, tmpDir: tmpDir, } // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if s.build.Spec.Output.To == nil || len(s.build.Spec.Output.To.Name) == 0 { s.build.Status.OutputDockerImageReference = s.build.Name } else { push = true } pushTag := s.build.Status.OutputDockerImageReference git := s.build.Spec.Source.Git var ref string if s.build.Spec.Revision != nil && s.build.Spec.Revision.Git != nil && len(s.build.Spec.Revision.Git.Commit) != 0 { ref = s.build.Spec.Revision.Git.Commit } else if git != nil && len(git.Ref) != 0 { ref = git.Ref } sourceURI := &url.URL{ Scheme: "file", Path: srcDir, Fragment: ref, } injections := s2iapi.InjectionList{} for _, s := range s.build.Spec.Source.Secrets { glog.V(3).Infof("Injecting secret %q into a build into %q", s.Secret.Name, filepath.Clean(s.DestinationDir)) secretSourcePath := filepath.Join(strategy.SecretBuildSourceBaseMountPath, s.Secret.Name) injections = append(injections, s2iapi.InjectPath{ SourcePath: secretSourcePath, DestinationDir: s.DestinationDir, }) } buildTag := randomBuildTag(s.build.Namespace, s.build.Name) config := &s2iapi.Config{ WorkingDir: buildDir, DockerConfig: &s2iapi.DockerConfig{Endpoint: s.dockerSocket}, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), LabelNamespace: api.DefaultDockerLabelNamespace, ScriptsURL: s.build.Spec.Strategy.SourceStrategy.Scripts, BuilderImage: s.build.Spec.Strategy.SourceStrategy.From.Name, Incremental: s.build.Spec.Strategy.SourceStrategy.Incremental, Environment: buildEnvVars(s.build), DockerNetworkMode: getDockerNetworkMode(), Source: sourceURI.String(), Tag: buildTag, ContextDir: s.build.Spec.Source.ContextDir, CGroupLimits: s.cgLimits, Injections: injections, } if s.build.Spec.Strategy.SourceStrategy.ForcePull { glog.V(4).Infof("With force pull true, setting policies to %s", s2iapi.PullAlways) config.PreviousImagePullPolicy = s2iapi.PullAlways config.BuilderPullPolicy = s2iapi.PullAlways } else { glog.V(4).Infof("With force pull false, setting policies to %s", s2iapi.PullIfNotPresent) config.PreviousImagePullPolicy = s2iapi.PullIfNotPresent config.BuilderPullPolicy = s2iapi.PullIfNotPresent } allowedUIDs := os.Getenv("ALLOWED_UIDS") glog.V(2).Infof("The value of ALLOWED_UIDS is [%s]", allowedUIDs) if len(allowedUIDs) > 0 { err := config.AllowedUIDs.Set(allowedUIDs) if err != nil { return err } } if errs := s.validator.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } // If DockerCfgPath is provided in api.Config, then attempt to read the the // dockercfg file and get the authentication for pulling the builder image. config.PullAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(config.BuilderImage, dockercfg.PullAuthType) config.IncrementalAuthentication, _ = dockercfg.NewHelper().GetDockerAuth(pushTag, dockercfg.PushAuthType) glog.V(2).Infof("Creating a new S2I builder with build config: %#v\n", describe.DescribeConfig(config)) builder, err := s.builder.Builder(config, s2ibuild.Overrides{Downloader: download}) if err != nil { return err } glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) if _, err = builder.Build(config); err != nil { return err } cname := containerName("s2i", s.build.Name, s.build.Namespace, "post-commit") if err := execPostCommitHook(s.dockerClient, s.build.Spec.PostCommit, buildTag, cname); err != nil { return err } if push { if err := tagImage(s.dockerClient, buildTag, pushTag); err != nil { return err } } if err := removeImage(s.dockerClient, buildTag); err != nil { glog.Warningf("Failed to remove temporary build tag %v: %v", buildTag, err) } if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( pushTag, dockercfg.PushAuthType, ) if authPresent { glog.Infof("Using provided push secret for pushing %s image", pushTag) } else { glog.Infof("No push secret provided") } glog.Infof("Pushing %s image ...", pushTag) if err := pushImage(s.dockerClient, pushTag, pushAuthConfig); err != nil { // write extended error message to assist in problem resolution msg := fmt.Sprintf("Failed to push image. Response from registry is: %v", err) if authPresent { glog.Infof("Registry server Address: %s", pushAuthConfig.ServerAddress) glog.Infof("Registry server User Name: %s", pushAuthConfig.Username) glog.Infof("Registry server Email: %s", pushAuthConfig.Email) passwordPresent := "<<empty>>" if len(pushAuthConfig.Password) > 0 { passwordPresent = "<<non-empty>>" } glog.Infof("Registry server Password: %s", passwordPresent) } return errors.New(msg) } glog.Infof("Successfully pushed %s", pushTag) glog.Flush() } return nil }
// Build executes the STI build func (s *STIBuilder) Build() error { tag := s.build.Parameters.Output.DockerImageReference config := &stiapi.Config{ BuilderImage: s.build.Parameters.Strategy.SourceStrategy.From.Name, DockerConfig: &stiapi.DockerConfig{Endpoint: s.dockerSocket}, Source: s.build.Parameters.Source.Git.URI, ContextDir: s.build.Parameters.Source.ContextDir, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), Tag: tag, ScriptsURL: s.build.Parameters.Strategy.SourceStrategy.Scripts, Environment: getBuildEnvVars(s.build), Incremental: s.build.Parameters.Strategy.SourceStrategy.Incremental, } if s.build.Parameters.Revision != nil && s.build.Parameters.Revision.Git != nil && s.build.Parameters.Revision.Git.Commit != "" { config.Ref = s.build.Parameters.Revision.Git.Commit } else if s.build.Parameters.Source.Git.Ref != "" { config.Ref = s.build.Parameters.Source.Git.Ref } if errs := validation.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } // If DockerCfgPath is provided in api.Config, then attempt to read the the // dockercfg file and get the authentication for pulling the builder image. if r, err := os.Open(config.DockerCfgPath); err == nil { config.PullAuthentication = stidocker.GetImageRegistryAuth(r, config.BuilderImage) glog.Infof("Using provided pull secret for pulling %s image", config.BuilderImage) } glog.V(2).Infof("Creating a new S2I builder with build config: %#v\n", describe.DescribeConfig(config)) builder, err := sti.GetStrategy(config) if err != nil { return err } defer removeImage(s.dockerClient, tag) glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) if _, err = builder.Build(config); err != nil { return err } dockerImageRef := s.build.Parameters.Output.DockerImageReference if len(dockerImageRef) != 0 { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( dockerImageRef, dockercfg.PushAuthType, ) if authPresent { glog.Infof("Using provided push secret for pushing %s image", dockerImageRef) s.auth = pushAuthConfig } glog.Infof("Pushing %s image ...", dockerImageRef) if err := pushImage(s.dockerClient, tag, s.auth); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Successfully pushed %s", dockerImageRef) glog.Flush() } return nil }
// Build executes the STI build func (s *STIBuilder) Build() error { var push bool // if there is no output target, set one up so the docker build logic // will still work, but we won't push it at the end. if s.build.Spec.Output.To == nil || len(s.build.Spec.Output.To.Name) == 0 { s.build.Spec.Output.To = &kapi.ObjectReference{ Kind: "DockerImage", Name: noOutputDefaultTag, } push = false } else { push = true } tag := s.build.Spec.Output.To.Name config := &stiapi.Config{ BuilderImage: s.build.Spec.Strategy.SourceStrategy.From.Name, DockerConfig: &stiapi.DockerConfig{Endpoint: s.dockerSocket}, Source: s.build.Spec.Source.Git.URI, ContextDir: s.build.Spec.Source.ContextDir, DockerCfgPath: os.Getenv(dockercfg.PullAuthType), Tag: tag, ScriptsURL: s.build.Spec.Strategy.SourceStrategy.Scripts, Environment: getBuildEnvVars(s.build), Incremental: s.build.Spec.Strategy.SourceStrategy.Incremental, ForcePull: s.build.Spec.Strategy.SourceStrategy.ForcePull, } if s.build.Spec.Revision != nil && s.build.Spec.Revision.Git != nil && s.build.Spec.Revision.Git.Commit != "" { config.Ref = s.build.Spec.Revision.Git.Commit } else if s.build.Spec.Source.Git.Ref != "" { config.Ref = s.build.Spec.Source.Git.Ref } if errs := validation.ValidateConfig(config); len(errs) != 0 { var buffer bytes.Buffer for _, ve := range errs { buffer.WriteString(ve.Error()) buffer.WriteString(", ") } return errors.New(buffer.String()) } // If DockerCfgPath is provided in api.Config, then attempt to read the the // dockercfg file and get the authentication for pulling the builder image. if r, err := os.Open(config.DockerCfgPath); err == nil { config.PullAuthentication = stidocker.GetImageRegistryAuth(r, config.BuilderImage) glog.Infof("Using provided pull secret for pulling %s image", config.BuilderImage) } glog.V(2).Infof("Creating a new S2I builder with build config: %#v\n", describe.DescribeConfig(config)) builder, err := sti.GetStrategy(config) if err != nil { return err } glog.V(4).Infof("Starting S2I build from %s/%s BuildConfig ...", s.build.Namespace, s.build.Name) origProxy := make(map[string]string) var setHttp, setHttps bool // set the http proxy to be used by the git clone performed by S2I if len(s.build.Spec.Source.Git.HTTPSProxy) != 0 { glog.V(2).Infof("Setting https proxy variables for Git to %s", s.build.Spec.Source.Git.HTTPSProxy) origProxy["HTTPS_PROXY"] = os.Getenv("HTTPS_PROXY") origProxy["https_proxy"] = os.Getenv("https_proxy") os.Setenv("HTTPS_PROXY", s.build.Spec.Source.Git.HTTPSProxy) os.Setenv("https_proxy", s.build.Spec.Source.Git.HTTPSProxy) setHttps = true } if len(s.build.Spec.Source.Git.HTTPProxy) != 0 { glog.V(2).Infof("Setting http proxy variables for Git to %s", s.build.Spec.Source.Git.HTTPSProxy) origProxy["HTTP_PROXY"] = os.Getenv("HTTP_PROXY") origProxy["http_proxy"] = os.Getenv("http_proxy") os.Setenv("HTTP_PROXY", s.build.Spec.Source.Git.HTTPProxy) os.Setenv("http_proxy", s.build.Spec.Source.Git.HTTPProxy) setHttp = true } if _, err = builder.Build(config); err != nil { return err } // reset http proxy env variables to original value if setHttps { glog.V(4).Infof("Resetting HTTPS_PROXY variable for Git to %s", origProxy["HTTPS_PROXY"]) os.Setenv("HTTPS_PROXY", origProxy["HTTPS_PROXY"]) glog.V(4).Infof("Resetting https_proxy variable for Git to %s", origProxy["https_proxy"]) os.Setenv("https_proxy", origProxy["https_proxy"]) } if setHttp { glog.V(4).Infof("Resetting HTTP_PROXY variable for Git to %s", origProxy["HTTP_PROXY"]) os.Setenv("HTTP_PROXY", origProxy["HTTP_PROXY"]) glog.V(4).Infof("Resetting http_proxy variable for Git to %s", origProxy["http_proxy"]) os.Setenv("http_proxy", origProxy["http_proxy"]) } if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( tag, dockercfg.PushAuthType, ) if authPresent { glog.Infof("Using provided push secret for pushing %s image", tag) s.auth = pushAuthConfig } glog.Infof("Pushing %s image ...", tag) if err := pushImage(s.dockerClient, tag, s.auth); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Successfully pushed %s", tag) glog.Flush() } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { var push bool pushTag := d.build.Status.OutputDockerImageReference buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, d.urlTimeout, os.Stdin, d.gitClient) if err != nil { return err } if sourceInfo != nil { updateBuildRevision(d.client, d.build, sourceInfo) } if err := d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from build config %s ...", d.build.Name) // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Status.OutputDockerImageReference = d.build.Name } else { push = true } buildTag := randomBuildTag(d.build.Namespace, d.build.Name) if err := d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil { return err } cname := containerName("docker", d.build.Name, d.build.Namespace, "post-commit") if err := execPostCommitHook(d.dockerClient, d.build.Spec.PostCommit, buildTag, cname); err != nil { return err } if push { if err := tagImage(d.dockerClient, buildTag, pushTag); err != nil { return err } } if err := removeImage(d.dockerClient, buildTag); err != nil { glog.Warningf("Failed to remove temporary build tag %v: %v", buildTag, err) } defer glog.Flush() if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( pushTag, dockercfg.PushAuthType, ) if authPresent { glog.V(4).Infof("Authenticating Docker push with user %q", pushAuthConfig.Username) } if sourceInfo != nil { repo, _ := parsers.ParseRepositoryTag(pushTag) pushTag2 := repo + ":" + strings.Replace(sourceInfo.Ref, "/", "-", -1) + "-" + sourceInfo.CommitID[:8] if err := tagImage(d.dockerClient, pushTag, pushTag2); err != nil { return err } glog.Infof("Pushing image %s ...", pushTag2) if err := pushImage(d.dockerClient, pushTag2, pushAuthConfig); err != nil { return fmt.Errorf("Failed to push image: %v", err) } if err := removeImage(d.dockerClient, pushTag2); err != nil { glog.Warningf("Failed to remove build tag %v: %v", pushTag2, err) } } glog.Infof("Pushing image %s ...", pushTag) if err := pushImage(d.dockerClient, pushTag, pushAuthConfig); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.Infof("Push successful") } return nil }
// Build executes a Docker build func (d *DockerBuilder) Build() error { if d.build.Spec.Source.Git == nil && d.build.Spec.Source.Binary == nil && d.build.Spec.Source.Dockerfile == nil && d.build.Spec.Source.Images == nil { return fmt.Errorf("must provide a value for at least one of source, binary, images, or dockerfile") } var push bool pushTag := d.build.Status.OutputDockerImageReference buildDir, err := ioutil.TempDir("", "docker-build") if err != nil { return err } sourceInfo, err := fetchSource(d.dockerClient, buildDir, d.build, d.urlTimeout, os.Stdin, d.gitClient) if err != nil { return err } if sourceInfo != nil { updateBuildRevision(d.client, d.build, sourceInfo) } if err := d.addBuildParameters(buildDir); err != nil { return err } glog.V(4).Infof("Starting Docker build from build config %s ...", d.build.Name) // if there is no output target, set one up so the docker build logic // (which requires a tag) will still work, but we won't push it at the end. if d.build.Spec.Output.To == nil || len(d.build.Spec.Output.To.Name) == 0 { d.build.Status.OutputDockerImageReference = d.build.Name } else { push = true } buildTag := randomBuildTag(d.build.Namespace, d.build.Name) if err := d.dockerBuild(buildDir, buildTag, d.build.Spec.Source.Secrets); err != nil { return err } cname := containerName("docker", d.build.Name, d.build.Namespace, "post-commit") if err := execPostCommitHook(d.dockerClient, d.build.Spec.PostCommit, buildTag, cname); err != nil { return err } if push { if err := tagImage(d.dockerClient, buildTag, pushTag); err != nil { return err } } if err := removeImage(d.dockerClient, buildTag); err != nil { glog.V(0).Infof("warning: Failed to remove temporary build tag %v: %v", buildTag, err) } if push { // Get the Docker push authentication pushAuthConfig, authPresent := dockercfg.NewHelper().GetDockerAuth( pushTag, dockercfg.PushAuthType, ) if authPresent { glog.V(4).Infof("Authenticating Docker push with user %q", pushAuthConfig.Username) } glog.V(1).Infof("Pushing image %s ...", pushTag) if err := pushImage(d.dockerClient, pushTag, pushAuthConfig); err != nil { return fmt.Errorf("Failed to push image: %v", err) } glog.V(1).Infof("Push successful") } return nil }