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
}
Example #3
0
// 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
}
Example #4
0
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
}
Example #5
0
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
}
Example #6
0
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
		}
	}
}
Example #7
0
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)
	}
}
Example #8
0
// 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
}
Example #9
0
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
}
Example #10
0
// 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
}
Example #11
0
// 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
}
Example #12
0
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
		}
	}
}