// RunStartBuild contains all the necessary functionality for the OpenShift cli start-build command func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, envParams []string, args []string, webhooks util.StringFlag) error { webhook := cmdutil.GetFlagString(cmd, "from-webhook") buildName := cmdutil.GetFlagString(cmd, "from-build") follow := cmdutil.GetFlagBool(cmd, "follow") commit := cmdutil.GetFlagString(cmd, "commit") waitForComplete := cmdutil.GetFlagBool(cmd, "wait") fromFile := cmdutil.GetFlagString(cmd, "from-file") fromDir := cmdutil.GetFlagString(cmd, "from-dir") fromRepo := cmdutil.GetFlagString(cmd, "from-repo") buildLogLevel := cmdutil.GetFlagString(cmd, "build-loglevel") switch { case len(webhook) > 0: if len(args) > 0 || len(buildName) > 0 || len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 { return cmdutil.UsageError(cmd, "The '--from-webhook' flag is incompatible with arguments and all '--from-*' flags") } path := cmdutil.GetFlagString(cmd, "git-repository") postReceivePath := cmdutil.GetFlagString(cmd, "git-post-receive") repo := git.NewRepository() return RunStartBuildWebHook(f, out, webhook, path, postReceivePath, repo) case len(args) != 1 && len(buildName) == 0: return cmdutil.UsageError(cmd, "Must pass a name of a build config or specify build name with '--from-build' flag") } namespace, _, err := f.DefaultNamespace() if err != nil { return err } var ( name = buildName resource = "builds" ) if len(name) == 0 && len(args) > 0 && len(args[0]) > 0 { mapper, _ := f.Object() resource, name, err = osutil.ResolveResource("buildconfigs", args[0], mapper) if err != nil { return err } switch resource { case "buildconfigs": // no special handling required case "builds": return fmt.Errorf("use --from-build to rerun your builds") default: return fmt.Errorf("invalid resource provided: %s", resource) } } if len(name) == 0 { return fmt.Errorf("a resource name is required either as an argument or by using --from-build") } if webhooks.Provided() { return RunListBuildWebHooks(f, out, cmd.Out(), name, resource, webhooks.String()) } client, _, err := f.Clients() if err != nil { return err } env, _, err := ParseEnv(envParams, in) if err != nil { return err } if len(buildLogLevel) > 0 { env = append(env, kapi.EnvVar{Name: "BUILD_LOGLEVEL", Value: buildLogLevel}) } request := &buildapi.BuildRequest{ ObjectMeta: kapi.ObjectMeta{Name: name}, } if len(env) > 0 { request.Env = env } if len(commit) > 0 { request.Revision = &buildapi.SourceRevision{ Type: buildapi.BuildSourceGit, Git: &buildapi.GitSourceRevision{ Commit: commit, }, } } git := git.NewRepository() var newBuild *buildapi.Build switch { case len(args) > 0 && (len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0): request := &buildapi.BinaryBuildRequestOptions{ ObjectMeta: kapi.ObjectMeta{ Name: name, Namespace: namespace, }, Commit: commit, } if newBuild, err = streamPathToBuild(git, in, cmd.Out(), client.BuildConfigs(namespace), fromDir, fromFile, fromRepo, request); err != nil { return err } case resource == "builds": if newBuild, err = client.Builds(namespace).Clone(request); err != nil { return err } case resource == "buildconfigs": if newBuild, err = client.BuildConfigs(namespace).Instantiate(request); err != nil { return err } default: return fmt.Errorf("invalid resource provided: %s", resource) } fmt.Fprintln(out, newBuild.Name) // mapper, typer := f.Object() // resourceMapper := &resource.Mapper{ObjectTyper: typer, RESTMapper: mapper, ClientMapper: f.ClientMapperForCommand()} // info, err := resourceMapper.InfoForObject(newBuild) // if err != nil { // return err // } // shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" // cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "started") var ( wg sync.WaitGroup exitErr error ) // Wait for the build to complete if waitForComplete { wg.Add(1) go func() { defer wg.Done() exitErr = WaitForBuildComplete(client.Builds(namespace), newBuild.Name) }() } // Stream the logs from the build if follow { wg.Add(1) go func() { defer wg.Done() opts := buildapi.BuildLogOptions{ Follow: true, NoWait: false, } rd, err := client.BuildLogs(namespace).Get(newBuild.Name, opts).Stream() if err != nil { fmt.Fprintf(cmd.Out(), "error getting logs: %v\n", err) return } defer rd.Close() if _, err = io.Copy(out, rd); err != nil { fmt.Fprintf(cmd.Out(), "error streaming logs: %v\n", err) } }() } wg.Wait() return exitErr }
// RunListBuildWebHooks prints the webhooks for the provided build config. func RunListBuildWebHooks(f *clientcmd.Factory, out, errOut io.Writer, name, resource, webhookFilter string) error { generic, github := false, false prefix := false switch webhookFilter { case "all": generic, github = true, true prefix = true case "generic": generic = true case "github": github = true default: return fmt.Errorf("--list-webhooks must be 'all', 'generic', or 'github'") } client, _, err := f.Clients() if err != nil { return err } namespace, _, err := f.DefaultNamespace() if err != nil { return err } switch resource { case "buildconfigs": // no special handling required case "builds": build, err := client.Builds(namespace).Get(name) if err != nil { return err } ref := build.Status.Config if ref == nil { return fmt.Errorf("the provided Build %q was not created from a BuildConfig and cannot have webhooks", name) } if len(ref.Namespace) > 0 { namespace = ref.Namespace } name = ref.Name default: return fmt.Errorf("invalid resource provided: %s", resource) } config, err := client.BuildConfigs(namespace).Get(name) if err != nil { return err } for _, t := range config.Spec.Triggers { hookType := "" switch { case t.GenericWebHook != nil && generic: if prefix { hookType = "generic " } case t.GitHubWebHook != nil && github: if prefix { hookType = "github " } default: continue } url, err := client.BuildConfigs(namespace).WebHookURL(name, &t) if err != nil { if err != osclient.ErrTriggerIsNotAWebHook { fmt.Fprintf(errOut, "error: unable to get webhook for %s: %v", name, err) } continue } fmt.Fprintf(out, "%s%s\n", hookType, url.String()) } return nil }
// RunStartBuild contains all the necessary functionality for the OpenShift cli start-build command func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, args []string, webhooks util.StringFlag) error { webhook := cmdutil.GetFlagString(cmd, "from-webhook") buildName := cmdutil.GetFlagString(cmd, "from-build") follow := cmdutil.GetFlagBool(cmd, "follow") commit := cmdutil.GetFlagString(cmd, "commit") waitForComplete := cmdutil.GetFlagBool(cmd, "wait") fromFile := cmdutil.GetFlagString(cmd, "from-file") fromDir := cmdutil.GetFlagString(cmd, "from-dir") fromRepo := cmdutil.GetFlagString(cmd, "from-repo") //shortOutput := false //mapper, _ := f.Object() switch { case len(webhook) > 0: if len(args) > 0 || len(buildName) > 0 || len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 { return cmdutil.UsageError(cmd, "The '--from-webhook' flag is incompatible with arguments and all '--from-*' flags") } path := cmdutil.GetFlagString(cmd, "git-repository") postReceivePath := cmdutil.GetFlagString(cmd, "git-post-receive") repo := git.NewRepository() return RunStartBuildWebHook(f, out, webhook, path, postReceivePath, repo) case len(args) != 1 && len(buildName) == 0: return cmdutil.UsageError(cmd, "Must pass a name of a build config or specify build name with '--from-build' flag") } name := buildName isBuild := true if len(name) == 0 { name = args[0] isBuild = false } if webhooks.Provided() { return RunListBuildWebHooks(f, out, cmd.Out(), name, isBuild, webhooks.String()) } client, _, err := f.Clients() if err != nil { return err } namespace, _, err := f.DefaultNamespace() if err != nil { return err } request := &buildapi.BuildRequest{ ObjectMeta: kapi.ObjectMeta{Name: name}, } if len(commit) > 0 { request.Revision = &buildapi.SourceRevision{ Type: buildapi.BuildSourceGit, Git: &buildapi.GitSourceRevision{ Commit: commit, }, } } git := git.NewRepository() var newBuild *buildapi.Build switch { case !isBuild && (len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0): request := &buildapi.BinaryBuildRequestOptions{ ObjectMeta: kapi.ObjectMeta{ Name: name, Namespace: namespace, }, Commit: commit, } if newBuild, err = streamPathToBuild(git, in, cmd.Out(), client.BuildConfigs(namespace), fromDir, fromFile, fromRepo, request); err != nil { return err } case isBuild: if newBuild, err = client.Builds(namespace).Clone(request); err != nil { return err } default: if newBuild, err = client.BuildConfigs(namespace).Instantiate(request); err != nil { return err } } //cmdutil.PrintSuccess(mapper, shortOutput, out, "Build", newBuild.Name, "started") fmt.Fprintln(out, newBuild.Name) var ( wg sync.WaitGroup exitErr error ) // Wait for the build to complete if waitForComplete { wg.Add(1) go func() { defer wg.Done() exitErr = WaitForBuildComplete(client.Builds(namespace), newBuild.Name) }() } // Stream the logs from the build if follow { wg.Add(1) go func() { defer wg.Done() opts := buildapi.BuildLogOptions{ Follow: true, NoWait: false, } rd, err := client.BuildLogs(namespace).Get(newBuild.Name, opts).Stream() if err != nil { fmt.Fprintf(cmd.Out(), "error getting logs: %v\n", err) return } defer rd.Close() if _, err = io.Copy(out, rd); err != nil { fmt.Fprintf(cmd.Out(), "error streaming logs: %v\n", err) } }() } wg.Wait() return exitErr }