func (o *ReconcileClusterRolesOptions) Complete(cmd *cobra.Command, f *clientcmd.Factory, args []string) error { oclient, _, err := f.Clients() if err != nil { return err } o.RoleClient = oclient.ClusterRoles() o.Output = kcmdutil.GetFlagString(cmd, "output") mapper, _ := f.Object() for _, resourceString := range args { resource, name, err := osutil.ResolveResource(authorizationapi.Resource("clusterroles"), resourceString, mapper) if err != nil { return err } if resource != authorizationapi.Resource("clusterroles") { return fmt.Errorf("%v is not a valid resource type for this command", resource) } if len(name) == 0 { return fmt.Errorf("%s did not contain a name", resourceString) } o.RolesToReconcile = append(o.RolesToReconcile, name) } return nil }
func (o *ReconcileClusterRoleBindingsOptions) Complete(cmd *cobra.Command, f *clientcmd.Factory, args []string, excludeUsers, excludeGroups []string) error { oclient, _, err := f.Clients() if err != nil { return err } o.RoleBindingClient = oclient.ClusterRoleBindings() o.Output = kcmdutil.GetFlagString(cmd, "output") o.ExcludeSubjects = authorizationapi.BuildSubjects(excludeUsers, excludeGroups, uservalidation.ValidateUserName, uservalidation.ValidateGroupName) mapper, _ := f.Object() for _, resourceString := range args { resource, name, err := ocmdutil.ResolveResource("clusterroles", resourceString, mapper) if err != nil { return err } if resource != "clusterroles" { return fmt.Errorf("%s is not a valid resource type for this command", resource) } if len(name) == 0 { return fmt.Errorf("%s did not contain a name", resourceString) } o.RolesToReconcile = append(o.RolesToReconcile, name) } return nil }
// Complete completes the required options for build-chain func (o *BuildChainOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string, out io.Writer) error { if len(args) != 1 { return cmdutil.UsageError(cmd, "Must pass an image stream tag. If only an image stream name is specified, 'latest' will be used for the tag.") } // Setup client oc, _, _, err := f.Clients() if err != nil { return err } o.c, o.t = oc, oc resource := unversioned.GroupResource{} mapper, _ := f.Object(false) resource, o.name, err = osutil.ResolveResource(imageapi.Resource("imagestreamtags"), args[0], mapper) if err != nil { return err } switch resource { case imageapi.Resource("imagestreamtags"): o.name = imageapi.NormalizeImageStreamTag(o.name) glog.V(4).Infof("Using %q as the image stream tag to look dependencies for", o.name) default: return fmt.Errorf("invalid resource provided: %v", resource) } // Setup namespace if o.allNamespaces { // TODO: Handle different uses of build-chain; user and admin projectList, err := oc.Projects().List(kapi.ListOptions{}) if err != nil { return err } for _, project := range projectList.Items { glog.V(4).Infof("Found namespace %q", project.Name) o.namespaces.Insert(project.Name) } } namespace, _, err := f.DefaultNamespace() if err != nil { return err } o.defaultNamespace = namespace glog.V(4).Infof("Using %q as the namespace for %q", o.defaultNamespace, o.name) o.namespaces.Insert(namespace) glog.V(4).Infof("Will look for deps in %s", strings.Join(o.namespaces.List(), ",")) return nil }
func resolveServiceName(f *clientcmd.Factory, resource string) (string, error) { if len(resource) == 0 { return "", fmt.Errorf("you need to provide a service name via --service") } mapper, _ := f.Object() rType, name, err := cmdutil.ResolveResource("services", resource, mapper) if err != nil { return "", err } if rType != "services" { return "", fmt.Errorf("cannot expose %s as routes", rType) } return name, nil }
func (o *StartBuildOptions) Complete(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, cmdFullName string, args []string) error { o.In = in o.Out = out o.ErrOut = cmd.OutOrStderr() o.Git = git.NewRepository() o.ClientConfig = f.OpenShiftClientConfig o.Mapper, _ = f.Object(false) webhook := o.FromWebhook buildName := o.FromBuild fromFile := o.FromFile fromDir := o.FromDir fromRepo := o.FromRepo buildLogLevel := o.LogLevel outputFormat := kcmdutil.GetFlagString(cmd, "output") if outputFormat != "name" && outputFormat != "" { return kcmdutil.UsageError(cmd, "Unsupported output format: %s", outputFormat) } o.ShortOutput = outputFormat == "name" switch { case len(webhook) > 0: if len(args) > 0 || len(buildName) > 0 || len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 { return kcmdutil.UsageError(cmd, "The '--from-webhook' flag is incompatible with arguments and all '--from-*' flags") } return nil case len(args) != 1 && len(buildName) == 0: return kcmdutil.UsageError(cmd, "Must pass a name of a build config or specify build name with '--from-build' flag.\nUse \"%s get bc\" to list all available build configs.", cmdFullName) } if len(buildName) != 0 && (len(fromFile) != 0 || len(fromDir) != 0 || len(fromRepo) != 0) { // TODO: we should support this, it should be possible to clone a build to run again with new uploaded artifacts. // Doing so requires introducing a new clonebinary endpoint. return kcmdutil.UsageError(cmd, "Cannot use '--from-build' flag with binary builds") } o.AsBinary = len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 namespace, _, err := f.DefaultNamespace() if err != nil { return err } client, _, err := f.Clients() if err != nil { return err } o.Client = client var ( name = buildName resource = buildapi.Resource("builds") ) if len(name) == 0 && len(args) > 0 && len(args[0]) > 0 { mapper, _ := f.Object(false) resource, name, err = cmdutil.ResolveResource(buildapi.Resource("buildconfigs"), args[0], mapper) if err != nil { return err } switch resource { case buildapi.Resource("buildconfigs"): // no special handling required case buildapi.Resource("builds"): if len(o.ListWebhooks) == 0 { return fmt.Errorf("use --from-build to rerun your builds") } default: return fmt.Errorf("invalid resource provided: %v", resource) } } // when listing webhooks, allow --from-build to lookup a build config if resource == buildapi.Resource("builds") && len(o.ListWebhooks) > 0 { 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 } if len(name) == 0 { return fmt.Errorf("a resource name is required either as an argument or by using --from-build") } o.Namespace = namespace o.Name = name env, _, err := cmdutil.ParseEnv(o.Env, in) if err != nil { return err } if len(buildLogLevel) > 0 { env = append(env, kapi.EnvVar{Name: "BUILD_LOGLEVEL", Value: buildLogLevel}) } o.EnvVar = env return nil }
func TestResolveResource(t *testing.T) { mapper := clientcmd.ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: registered.RESTMapper()}} tests := []struct { name string defaultResource string resourceString string expectedResource string expectedName string expectedErr bool }{ { name: "invalid case #1", defaultResource: "", resourceString: "a/b/c", expectedResource: "", expectedName: "", expectedErr: true, }, { name: "invalid case #2", defaultResource: "", resourceString: "foo/bar", expectedResource: "", expectedName: "", expectedErr: true, }, { name: "empty resource string case #1", defaultResource: "", resourceString: "", expectedResource: "", expectedName: "", expectedErr: false, }, { name: "empty resource string case #2", defaultResource: "", resourceString: "bar", expectedResource: "", expectedName: "bar", expectedErr: false, }, { name: "empty resource string case #3", defaultResource: "foo", resourceString: "bar", expectedResource: "foo", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) short name", defaultResource: "foo", resourceString: "rc/bar", expectedResource: "replicationcontrollers", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #1", defaultResource: "foo", resourceString: "replicationcontroller/bar", expectedResource: "replicationcontrollers", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #2", defaultResource: "foo", resourceString: "replicationcontrollers/bar", expectedResource: "replicationcontrollers", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #3", defaultResource: "foo", resourceString: "ReplicationControllers/bar", expectedResource: "replicationcontrollers", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #4", defaultResource: "foo", resourceString: "ReplicationControllers/bar", expectedResource: "replicationcontrollers", expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #5", defaultResource: "foo", resourceString: "ReplicationControllers/Bar", expectedResource: "replicationcontrollers", expectedName: "Bar", expectedErr: false, }, { name: "(ORIGIN) short name", defaultResource: "foo", resourceString: "bc/bar", expectedResource: "buildconfigs", expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #1", defaultResource: "foo", resourceString: "buildconfig/bar", expectedResource: "buildconfigs", expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #2", defaultResource: "foo", resourceString: "buildconfigs/bar", expectedResource: "buildconfigs", expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #3", defaultResource: "foo", resourceString: "BuildConfigs/bar", expectedResource: "buildconfigs", expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #4", defaultResource: "foo", resourceString: "BuildConfigs/bar", expectedResource: "buildconfigs", expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #5", defaultResource: "foo", resourceString: "BuildConfigs/Bar", expectedResource: "buildconfigs", expectedName: "Bar", expectedErr: false, }, } for _, test := range tests { gotResource, gotName, gotErr := util.ResolveResource(test.defaultResource, test.resourceString, mapper) if gotErr != nil && !test.expectedErr { t.Errorf("%s: expected no error, got %v", test.name, gotErr) continue } if gotErr == nil && test.expectedErr { t.Errorf("%s: expected error but got none", test.name) continue } if gotResource != test.expectedResource { t.Errorf("%s: expected resource type %s, got %s", test.name, test.expectedResource, gotResource) continue } if gotName != test.expectedName { t.Errorf("%s: expected resource name %s, got %s", test.name, test.expectedName, gotName) continue } } }
func (f *Factory) PodForResource(resource string, timeout time.Duration) (string, error) { sortBy := func(pods []*api.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } namespace, _, err := f.DefaultNamespace() if err != nil { return "", err } mapper, _ := f.Object(false) resourceType, name, err := util.ResolveResource(api.Resource("pods"), resource, mapper) if err != nil { return "", err } switch resourceType { case api.Resource("pods"): return name, nil case api.Resource("replicationcontrollers"): kc, err := f.Client() if err != nil { return "", err } rc, err := kc.ReplicationControllers(namespace).Get(name) if err != nil { return "", err } selector := labels.SelectorFromSet(rc.Spec.Selector) pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case deployapi.Resource("deploymentconfigs"): oc, kc, err := f.Clients() if err != nil { return "", err } dc, err := oc.DeploymentConfigs(namespace).Get(name) if err != nil { return "", err } selector := labels.SelectorFromSet(dc.Spec.Selector) pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case extensions.Resource("daemonsets"): kc, err := f.Client() if err != nil { return "", err } ds, err := kc.Extensions().DaemonSets(namespace).Get(name) if err != nil { return "", err } selector, err := unversioned.LabelSelectorAsSelector(ds.Spec.Selector) if err != nil { return "", err } pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case extensions.Resource("jobs"): kc, err := f.Client() if err != nil { return "", err } job, err := kc.Extensions().Jobs(namespace).Get(name) if err != nil { return "", err } return podNameForJob(job, kc, timeout, sortBy) case batch.Resource("jobs"): kc, err := f.Client() if err != nil { return "", err } job, err := kc.Batch().Jobs(namespace).Get(name) if err != nil { return "", err } return podNameForJob(job, kc, timeout, sortBy) default: return "", fmt.Errorf("remote shell for %s is not supported", resourceType) } }
// 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 }
func (o *StartBuildOptions) Complete(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, args []string) error { o.In = in o.Out = out o.ErrOut = cmd.Out() o.Git = git.NewRepository() o.ClientConfig = f.OpenShiftClientConfig webhook := o.FromWebhook buildName := o.FromBuild fromFile := o.FromFile fromDir := o.FromDir fromRepo := o.FromRepo buildLogLevel := o.LogLevel switch { case len(webhook) > 0: if len(args) > 0 || len(buildName) > 0 || len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 { return kcmdutil.UsageError(cmd, "The '--from-webhook' flag is incompatible with arguments and all '--from-*' flags") } return nil case len(args) != 1 && len(buildName) == 0: return kcmdutil.UsageError(cmd, "Must pass a name of a build config or specify build name with '--from-build' flag") } o.AsBinary = len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0 namespace, _, err := f.DefaultNamespace() if err != nil { return err } client, _, err := f.Clients() if err != nil { return err } o.Client = client var ( name = buildName resource = buildapi.Resource("builds") ) if len(name) == 0 && len(args) > 0 && len(args[0]) > 0 { mapper, _ := f.Object(false) resource, name, err = cmdutil.ResolveResource(buildapi.Resource("buildconfigs"), args[0], mapper) if err != nil { return err } switch resource { case buildapi.Resource("buildconfigs"): // no special handling required case buildapi.Resource("builds"): if len(o.ListWebhooks) == 0 { return fmt.Errorf("use --from-build to rerun your builds") } default: return fmt.Errorf("invalid resource provided: %v", resource) } } // when listing webhooks, allow --from-build to lookup a build config if resource == buildapi.Resource("builds") && len(o.ListWebhooks) > 0 { 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 } if len(name) == 0 { return fmt.Errorf("a resource name is required either as an argument or by using --from-build") } o.Namespace = namespace o.Name = name env, _, err := cmdutil.ParseEnv(o.Env, in) if err != nil { return err } if len(buildLogLevel) > 0 { env = append(env, kapi.EnvVar{Name: "BUILD_LOGLEVEL", Value: buildLogLevel}) } o.EnvVar = env return nil }
// Complete completes all the required options. func (o *CancelBuildOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string, in io.Reader, out io.Writer) error { o.In = in o.Out = out o.ErrOut = cmd.OutOrStderr() o.ReportError = func(err error) { o.HasError = true fmt.Fprintf(o.ErrOut, "error: %s\n", err.Error()) } if len(args) == 0 { return kcmdutil.UsageError(cmd, "Must pass a name of a build or a buildconfig to cancel") } namespace, _, err := f.DefaultNamespace() if err != nil { return err } if len(o.States) == 0 { // If --state is not specified, set the default to "new", "pending" and // "running". o.States = []string{"new", "pending", "running"} } else { for _, state := range o.States { if len(state) > 0 && !isStateCancellable(state) { return kcmdutil.UsageError(cmd, "The '--state' flag has invalid value. Must be one of 'new', 'pending', or 'running'") } } } client, _, err := f.Clients() if err != nil { return err } o.Namespace = namespace o.Client = client o.BuildLister = buildclient.NewOSClientBuildClient(client) o.BuildClient = client.Builds(namespace) o.Mapper, _ = f.Object(false) for _, item := range args { resource, name, err := cmdutil.ResolveResource(buildapi.Resource("builds"), item, o.Mapper) if err != nil { return err } switch resource { case buildapi.Resource("buildconfigs"): list, err := buildutil.BuildConfigBuilds(o.BuildLister, o.Namespace, name, nil) if err != nil { return err } for _, b := range list.Items { o.BuildNames = append(o.BuildNames, b.Name) } case buildapi.Resource("builds"): o.BuildNames = append(o.BuildNames, strings.TrimSpace(name)) default: return fmt.Errorf("invalid resource provided: %v", resource) } } return nil }
// RunCancelBuild implements all the necessary functionality for CancelBuild. func (o *CancelBuildOptions) RunCancelBuild() error { var builds []*buildapi.Build for _, name := range o.BuildNames { build, err := o.BuildClient.Get(name) if err != nil { o.ReportError(fmt.Errorf("build %s/%s not found", o.Namespace, name)) continue } stateMatch := false for _, state := range o.States { if strings.ToLower(string(build.Status.Phase)) == state { stateMatch = true break } } if stateMatch && !buildutil.IsBuildComplete(build) { builds = append(builds, build) } } if o.DumpLogs { for _, b := range builds { // Do not attempt to get logs from build that was not scheduled. if b.Status.Phase == buildapi.BuildPhaseNew { continue } opts := buildapi.BuildLogOptions{NoWait: true} response, err := o.Client.BuildLogs(o.Namespace).Get(b.Name, opts).Do().Raw() if err != nil { o.ReportError(fmt.Errorf("unable to fetch logs for %s/%s: %v", b.Namespace, b.Name, err)) continue } fmt.Fprintf(o.Out, "==== Build %s/%s logs ====\n", b.Namespace, b.Name) fmt.Fprint(o.Out, string(response)) } } var wg sync.WaitGroup for _, b := range builds { wg.Add(1) go func(build *buildapi.Build) { defer wg.Done() err := wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) { build.Status.Cancelled = true _, err := o.BuildClient.Update(build) switch { case err == nil: return true, nil case kapierrors.IsConflict(err): build, err = o.BuildClient.Get(build.Name) return false, err } return true, err }) if err != nil { o.ReportError(fmt.Errorf("build %s/%s failed to update: %v", build.Namespace, build.Name, err)) return } // Make sure the build phase is really cancelled. err = wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) { updatedBuild, err := o.BuildClient.Get(build.Name) if err != nil { return true, err } return updatedBuild.Status.Phase == buildapi.BuildPhaseCancelled, nil }) if err != nil { o.ReportError(fmt.Errorf("build %s/%s failed to cancel: %v", build.Namespace, build.Name, err)) return } resource, name, _ := cmdutil.ResolveResource(buildapi.Resource("builds"), build.Name, o.Mapper) kcmdutil.PrintSuccess(o.Mapper, false, o.Out, resource.Resource, name, "cancelled") }(b) } wg.Wait() if o.Restart { for _, b := range builds { request := &buildapi.BuildRequest{ObjectMeta: kapi.ObjectMeta{Name: b.Name}} build, err := o.BuildClient.Clone(request) if err != nil { o.ReportError(fmt.Errorf("build %s/%s failed to restart: %v", b.Namespace, b.Name, err)) continue } resource, name, _ := cmdutil.ResolveResource(buildapi.Resource("builds"), build.Name, o.Mapper) kcmdutil.PrintSuccess(o.Mapper, false, o.Out, resource.Resource, name, fmt.Sprintf("restarted build %q", b.Name)) } } if o.HasError { return errors.New("failure during the build cancellation") } return nil }
func TestResolveResource(t *testing.T) { mapper := clientcmd.ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: registered.RESTMapper()}} tests := []struct { name string defaultResource unversioned.GroupResource resourceString string expectedResource unversioned.GroupResource expectedName string expectedErr bool }{ { name: "invalid case #1", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "a/b/c", expectedResource: unversioned.GroupResource{}, expectedName: "", expectedErr: true, }, { name: "invalid case #2", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "foo/bar", expectedResource: unversioned.GroupResource{}, expectedName: "", expectedErr: true, }, { name: "empty resource string case #1", defaultResource: unversioned.GroupResource{Resource: ""}, resourceString: "", expectedResource: unversioned.GroupResource{Resource: ""}, expectedName: "", expectedErr: false, }, { name: "empty resource string case #2", defaultResource: unversioned.GroupResource{Resource: ""}, resourceString: "bar", expectedResource: unversioned.GroupResource{Resource: ""}, expectedName: "bar", expectedErr: false, }, { name: "empty resource string case #3", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "bar", expectedResource: unversioned.GroupResource{Resource: "foo"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) short name", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "rc/bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #1", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "replicationcontroller/bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #2", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "replicationcontrollers/bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #3", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "ReplicationControllers/bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #4", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "ReplicationControllers/bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "bar", expectedErr: false, }, { name: "(KUBE) long name, case insensitive #5", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "ReplicationControllers/Bar", expectedResource: unversioned.GroupResource{Resource: "replicationcontrollers"}, expectedName: "Bar", expectedErr: false, }, { name: "(ORIGIN) short name", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "bc/bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #1", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "buildconfig/bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #2", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "buildconfigs/bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #3", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "BuildConfigs/bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #4", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "BuildConfigs/bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "bar", expectedErr: false, }, { name: "(ORIGIN) long name, case insensitive #5", defaultResource: unversioned.GroupResource{Resource: "foo"}, resourceString: "BuildConfigs/Bar", expectedResource: unversioned.GroupResource{Resource: "buildconfigs"}, expectedName: "Bar", expectedErr: false, }, { name: "singular, implicit api group", defaultResource: unversioned.GroupResource{}, resourceString: "job/myjob", expectedResource: unversioned.GroupResource{Group: "extensions", Resource: "jobs"}, expectedName: "myjob", expectedErr: false, }, { name: "singular, explicit extensions api group", defaultResource: unversioned.GroupResource{}, resourceString: "job.extensions/myjob", expectedResource: unversioned.GroupResource{Group: "extensions", Resource: "jobs"}, expectedName: "myjob", expectedErr: false, }, { name: "singular, explicit batch api group", defaultResource: unversioned.GroupResource{}, resourceString: "job.batch/myjob", expectedResource: unversioned.GroupResource{Group: "batch", Resource: "jobs"}, expectedName: "myjob", expectedErr: false, }, { name: "shortname, implicit api group", defaultResource: unversioned.GroupResource{}, resourceString: "hpa/myhpa", expectedResource: unversioned.GroupResource{Group: "extensions", Resource: "horizontalpodautoscalers"}, expectedName: "myhpa", expectedErr: false, }, { name: "shortname, explicit extensions api group", defaultResource: unversioned.GroupResource{}, resourceString: "hpa.extensions/myhpa", expectedResource: unversioned.GroupResource{Group: "extensions", Resource: "horizontalpodautoscalers"}, expectedName: "myhpa", expectedErr: false, }, { name: "shortname, explicit autoscaling api group", defaultResource: unversioned.GroupResource{}, resourceString: "hpa.autoscaling/myhpa", expectedResource: unversioned.GroupResource{Group: "autoscaling", Resource: "horizontalpodautoscalers"}, expectedName: "myhpa", expectedErr: false, }, } for _, test := range tests { gotResource, gotName, gotErr := util.ResolveResource(test.defaultResource, test.resourceString, mapper) if gotErr != nil && !test.expectedErr { t.Errorf("%s: expected no error, got %v", test.name, gotErr) continue } if gotErr == nil && test.expectedErr { t.Errorf("%s: expected error but got none", test.name) continue } if !reflect.DeepEqual(gotResource, test.expectedResource) { t.Errorf("%s: expected resource type %#v, got %#v", test.name, test.expectedResource, gotResource) continue } if gotName != test.expectedName { t.Errorf("%s: expected resource name %s, got %s", test.name, test.expectedName, gotName) continue } } }