... | ... |
@@ -588,6 +588,48 @@ _oc_project() |
588 | 588 |
must_have_one_noun=() |
589 | 589 |
} |
590 | 590 |
|
591 |
+_oc_projects() |
|
592 |
+{ |
|
593 |
+ last_command="oc_projects" |
|
594 |
+ commands=() |
|
595 |
+ |
|
596 |
+ flags=() |
|
597 |
+ two_word_flags=() |
|
598 |
+ flags_with_completion=() |
|
599 |
+ flags_completion=() |
|
600 |
+ |
|
601 |
+ flags+=("--short") |
|
602 |
+ flags+=("-q") |
|
603 |
+ flags+=("--api-version=") |
|
604 |
+ flags+=("--as=") |
|
605 |
+ flags+=("--certificate-authority=") |
|
606 |
+ flags_with_completion+=("--certificate-authority") |
|
607 |
+ flags_completion+=("_filedir") |
|
608 |
+ flags+=("--client-certificate=") |
|
609 |
+ flags_with_completion+=("--client-certificate") |
|
610 |
+ flags_completion+=("_filedir") |
|
611 |
+ flags+=("--client-key=") |
|
612 |
+ flags_with_completion+=("--client-key") |
|
613 |
+ flags_completion+=("_filedir") |
|
614 |
+ flags+=("--cluster=") |
|
615 |
+ flags+=("--config=") |
|
616 |
+ flags_with_completion+=("--config") |
|
617 |
+ flags_completion+=("_filedir") |
|
618 |
+ flags+=("--context=") |
|
619 |
+ flags+=("--google-json-key=") |
|
620 |
+ flags+=("--insecure-skip-tls-verify") |
|
621 |
+ flags+=("--log-flush-frequency=") |
|
622 |
+ flags+=("--match-server-version") |
|
623 |
+ flags+=("--namespace=") |
|
624 |
+ two_word_flags+=("-n") |
|
625 |
+ flags+=("--server=") |
|
626 |
+ flags+=("--token=") |
|
627 |
+ flags+=("--user=") |
|
628 |
+ |
|
629 |
+ must_have_one_flag=() |
|
630 |
+ must_have_one_noun=() |
|
631 |
+} |
|
632 |
+ |
|
591 | 633 |
_oc_explain() |
592 | 634 |
{ |
593 | 635 |
last_command="oc_explain" |
... | ... |
@@ -8851,6 +8893,7 @@ _oc() |
8851 | 8851 |
commands+=("new-app") |
8852 | 8852 |
commands+=("status") |
8853 | 8853 |
commands+=("project") |
8854 |
+ commands+=("projects") |
|
8854 | 8855 |
commands+=("explain") |
8855 | 8856 |
commands+=("cluster") |
8856 | 8857 |
commands+=("deploy") |
... | ... |
@@ -4176,6 +4176,48 @@ _openshift_cli_project() |
4176 | 4176 |
must_have_one_noun=() |
4177 | 4177 |
} |
4178 | 4178 |
|
4179 |
+_openshift_cli_projects() |
|
4180 |
+{ |
|
4181 |
+ last_command="openshift_cli_projects" |
|
4182 |
+ commands=() |
|
4183 |
+ |
|
4184 |
+ flags=() |
|
4185 |
+ two_word_flags=() |
|
4186 |
+ flags_with_completion=() |
|
4187 |
+ flags_completion=() |
|
4188 |
+ |
|
4189 |
+ flags+=("--short") |
|
4190 |
+ flags+=("-q") |
|
4191 |
+ flags+=("--api-version=") |
|
4192 |
+ flags+=("--as=") |
|
4193 |
+ flags+=("--certificate-authority=") |
|
4194 |
+ flags_with_completion+=("--certificate-authority") |
|
4195 |
+ flags_completion+=("_filedir") |
|
4196 |
+ flags+=("--client-certificate=") |
|
4197 |
+ flags_with_completion+=("--client-certificate") |
|
4198 |
+ flags_completion+=("_filedir") |
|
4199 |
+ flags+=("--client-key=") |
|
4200 |
+ flags_with_completion+=("--client-key") |
|
4201 |
+ flags_completion+=("_filedir") |
|
4202 |
+ flags+=("--cluster=") |
|
4203 |
+ flags+=("--config=") |
|
4204 |
+ flags_with_completion+=("--config") |
|
4205 |
+ flags_completion+=("_filedir") |
|
4206 |
+ flags+=("--context=") |
|
4207 |
+ flags+=("--google-json-key=") |
|
4208 |
+ flags+=("--insecure-skip-tls-verify") |
|
4209 |
+ flags+=("--log-flush-frequency=") |
|
4210 |
+ flags+=("--match-server-version") |
|
4211 |
+ flags+=("--namespace=") |
|
4212 |
+ two_word_flags+=("-n") |
|
4213 |
+ flags+=("--server=") |
|
4214 |
+ flags+=("--token=") |
|
4215 |
+ flags+=("--user=") |
|
4216 |
+ |
|
4217 |
+ must_have_one_flag=() |
|
4218 |
+ must_have_one_noun=() |
|
4219 |
+} |
|
4220 |
+ |
|
4179 | 4221 |
_openshift_cli_explain() |
4180 | 4222 |
{ |
4181 | 4223 |
last_command="openshift_cli_explain" |
... | ... |
@@ -12439,6 +12481,7 @@ _openshift_cli() |
12439 | 12439 |
commands+=("new-app") |
12440 | 12440 |
commands+=("status") |
12441 | 12441 |
commands+=("project") |
12442 |
+ commands+=("projects") |
|
12442 | 12443 |
commands+=("explain") |
12443 | 12444 |
commands+=("cluster") |
12444 | 12445 |
commands+=("deploy") |
... | ... |
@@ -1621,6 +1621,19 @@ Switch to another project |
1621 | 1621 |
==== |
1622 | 1622 |
|
1623 | 1623 |
|
1624 |
+== oc projects |
|
1625 |
+Display existing projects |
|
1626 |
+ |
|
1627 |
+==== |
|
1628 |
+ |
|
1629 |
+[options="nowrap"] |
|
1630 |
+---- |
|
1631 |
+ # Display the projects that currently exist |
|
1632 |
+ oc |
|
1633 |
+---- |
|
1634 |
+==== |
|
1635 |
+ |
|
1636 |
+ |
|
1624 | 1637 |
== oc proxy |
1625 | 1638 |
Run a proxy to the Kubernetes API server |
1626 | 1639 |
|
... | ... |
@@ -97,6 +97,7 @@ func NewCommandCLI(name, fullName string, in io.Reader, out, errout io.Writer) * |
97 | 97 |
cmd.NewCmdNewApplication(fullName, f, out), |
98 | 98 |
cmd.NewCmdStatus(cmd.StatusRecommendedName, fullName+" "+cmd.StatusRecommendedName, f, out), |
99 | 99 |
cmd.NewCmdProject(fullName+" project", f, out), |
100 |
+ cmd.NewCmdProjects(fullName, f, out), |
|
100 | 101 |
cmd.NewCmdExplain(fullName, f, out), |
101 | 102 |
cluster.NewCmdCluster(cluster.ClusterRecommendedName, fullName+" "+cluster.ClusterRecommendedName, f, out), |
102 | 103 |
}, |
... | ... |
@@ -66,7 +66,6 @@ func NewCmdProject(fullName string, f *clientcmd.Factory, out io.Writer) *cobra. |
66 | 66 |
Short: "Switch to another project", |
67 | 67 |
Long: projectLong, |
68 | 68 |
Example: fmt.Sprintf(projectExample, fullName), |
69 |
- Aliases: []string{"projects"}, |
|
70 | 69 |
Run: func(cmd *cobra.Command, args []string) { |
71 | 70 |
options.PathOptions = cliconfig.NewPathOptions(cmd) |
72 | 71 |
|
73 | 72 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,175 @@ |
0 |
+package cmd |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "io" |
|
5 |
+ |
|
6 |
+ "k8s.io/kubernetes/pkg/client/restclient" |
|
7 |
+ clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api" |
|
8 |
+ kubecmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config" |
|
9 |
+ kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
|
10 |
+ |
|
11 |
+ "github.com/openshift/origin/pkg/client" |
|
12 |
+ cliconfig "github.com/openshift/origin/pkg/cmd/cli/config" |
|
13 |
+ "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
14 |
+ "github.com/openshift/origin/pkg/project/api" |
|
15 |
+ |
|
16 |
+ "github.com/spf13/cobra" |
|
17 |
+) |
|
18 |
+ |
|
19 |
+type ProjectsOptions struct { |
|
20 |
+ Config clientcmdapi.Config |
|
21 |
+ ClientConfig *restclient.Config |
|
22 |
+ Client *client.Client |
|
23 |
+ Out io.Writer |
|
24 |
+ PathOptions *kubecmdconfig.PathOptions |
|
25 |
+ |
|
26 |
+ DisplayShort bool |
|
27 |
+} |
|
28 |
+ |
|
29 |
+const ( |
|
30 |
+ projectsLong = ` |
|
31 |
+Display information about the current active project and existing projects on the server. |
|
32 |
+ |
|
33 |
+For advanced configuration, or to manage the contents of your config file, use the 'config' |
|
34 |
+command.` |
|
35 |
+ |
|
36 |
+ projectsExample = ` # Display the projects that currently exist |
|
37 |
+ %[1]s` |
|
38 |
+) |
|
39 |
+ |
|
40 |
+// NewCmdProjects implements the OpenShift cli rollback command |
|
41 |
+func NewCmdProjects(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
42 |
+ options := &ProjectsOptions{} |
|
43 |
+ |
|
44 |
+ cmd := &cobra.Command{ |
|
45 |
+ Use: "projects", |
|
46 |
+ Short: "Display existing projects", |
|
47 |
+ Long: projectsLong, |
|
48 |
+ Example: fmt.Sprintf(projectsExample, fullName), |
|
49 |
+ Run: func(cmd *cobra.Command, args []string) { |
|
50 |
+ options.PathOptions = cliconfig.NewPathOptions(cmd) |
|
51 |
+ |
|
52 |
+ if err := options.Complete(f, args, out); err != nil { |
|
53 |
+ kcmdutil.CheckErr(kcmdutil.UsageError(cmd, err.Error())) |
|
54 |
+ } |
|
55 |
+ |
|
56 |
+ if err := options.RunProjects(); err != nil { |
|
57 |
+ kcmdutil.CheckErr(err) |
|
58 |
+ } |
|
59 |
+ }, |
|
60 |
+ } |
|
61 |
+ |
|
62 |
+ cmd.Flags().BoolVarP(&options.DisplayShort, "short", "q", false, "If true, display only the project names") |
|
63 |
+ return cmd |
|
64 |
+} |
|
65 |
+ |
|
66 |
+func (o *ProjectsOptions) Complete(f *clientcmd.Factory, args []string, out io.Writer) error { |
|
67 |
+ if len(args) > 0 { |
|
68 |
+ return fmt.Errorf("no arguments should be passed") |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ var err error |
|
72 |
+ o.Config, err = f.OpenShiftClientConfig.RawConfig() |
|
73 |
+ if err != nil { |
|
74 |
+ return err |
|
75 |
+ } |
|
76 |
+ |
|
77 |
+ o.ClientConfig, err = f.OpenShiftClientConfig.ClientConfig() |
|
78 |
+ if err != nil { |
|
79 |
+ return err |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ o.Client, _, err = f.Clients() |
|
83 |
+ if err != nil { |
|
84 |
+ return err |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ o.Out = out |
|
88 |
+ |
|
89 |
+ return nil |
|
90 |
+} |
|
91 |
+ |
|
92 |
+// RunProjects lists all projects a user belongs to |
|
93 |
+func (o ProjectsOptions) RunProjects() error { |
|
94 |
+ config := o.Config |
|
95 |
+ clientCfg := o.ClientConfig |
|
96 |
+ out := o.Out |
|
97 |
+ |
|
98 |
+ currentContext := config.Contexts[config.CurrentContext] |
|
99 |
+ currentProject := currentContext.Namespace |
|
100 |
+ |
|
101 |
+ var currentProjectExists bool = false |
|
102 |
+ var currentProjectErr error = nil |
|
103 |
+ |
|
104 |
+ client := o.Client |
|
105 |
+ |
|
106 |
+ if len(currentProject) > 0 { |
|
107 |
+ if _, currentProjectErr := client.Projects().Get(currentProject); currentProjectErr == nil { |
|
108 |
+ currentProjectExists = true |
|
109 |
+ } |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+ defaultContextName := cliconfig.GetContextNickname(currentContext.Namespace, currentContext.Cluster, currentContext.AuthInfo) |
|
113 |
+ |
|
114 |
+ var msg string |
|
115 |
+ var current string |
|
116 |
+ projects, err := getProjects(client) |
|
117 |
+ if err == nil { |
|
118 |
+ switch len(projects) { |
|
119 |
+ case 0: |
|
120 |
+ msg += "You are not a member of any projects. You can request a project to be created with the 'new-project' command." |
|
121 |
+ case 1: |
|
122 |
+ msg += fmt.Sprintf("You have one project on this server: %q.", api.DisplayNameAndNameForProject(&projects[0])) |
|
123 |
+ default: |
|
124 |
+ asterisk := "" |
|
125 |
+ count := 0 |
|
126 |
+ if !o.DisplayShort { |
|
127 |
+ msg += "You have access to the following projects and can switch between them with 'oc project <projectname>':\n" |
|
128 |
+ asterisk = " * " |
|
129 |
+ } |
|
130 |
+ for _, project := range projects { |
|
131 |
+ count = count + 1 |
|
132 |
+ displayName := project.Annotations["openshift.io/display-name"] |
|
133 |
+ linebreak := "\n" |
|
134 |
+ if len(displayName) == 0 { |
|
135 |
+ displayName = project.Annotations["displayName"] |
|
136 |
+ } |
|
137 |
+ |
|
138 |
+ current = "" |
|
139 |
+ if currentProjectExists && currentProject == project.Name && !o.DisplayShort { |
|
140 |
+ current = " (current)" |
|
141 |
+ } |
|
142 |
+ if len(displayName) > 0 && displayName != project.Name && !o.DisplayShort { |
|
143 |
+ msg += fmt.Sprintf("\n * %s (%s)%s", displayName, project.Name, current) |
|
144 |
+ } else { |
|
145 |
+ if o.DisplayShort && count == 1 { |
|
146 |
+ linebreak = "" |
|
147 |
+ } |
|
148 |
+ msg += fmt.Sprintf(linebreak+asterisk+"%s%s", project.Name, current) |
|
149 |
+ } |
|
150 |
+ } |
|
151 |
+ } |
|
152 |
+ fmt.Println(msg) |
|
153 |
+ |
|
154 |
+ if len(projects) > 0 && !o.DisplayShort { |
|
155 |
+ if !currentProjectExists { |
|
156 |
+ if clientcmd.IsForbidden(currentProjectErr) { |
|
157 |
+ fmt.Printf("you do not have rights to view project %q. Please switch to an existing one.", currentProject) |
|
158 |
+ } |
|
159 |
+ return currentProjectErr |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ // if they specified a project name and got a generated context, then only show the information they care about. They won't recognize |
|
163 |
+ // a context name they didn't choose |
|
164 |
+ if config.CurrentContext == defaultContextName { |
|
165 |
+ fmt.Fprintf(out, "\nUsing project %q on server %q.\n", currentProject, clientCfg.Host) |
|
166 |
+ } else { |
|
167 |
+ fmt.Fprintf(out, "\nUsing project %q from context named %q on server %q.\n", currentProject, config.CurrentContext, clientCfg.Host) |
|
168 |
+ } |
|
169 |
+ } |
|
170 |
+ return nil |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ return err |
|
174 |
+} |
... | ... |
@@ -303,6 +303,17 @@ os::test::junit::declare_suite_end |
303 | 303 |
# service accounts should not be allowed to request new projects |
304 | 304 |
os::cmd::expect_failure_and_text "oc new-project --token="$( oc sa get-token builder )" will-fail" 'Error from server: You may not request a new project via this API' |
305 | 305 |
|
306 |
+# test oc projects |
|
307 |
+os::cmd::expect_failure_and_text 'oc projects test_arg' 'no arguments' |
|
308 |
+os::cmd::expect_success_and_text 'oc projects' 'You have access' |
|
309 |
+# log in as a test user and expect no projects |
|
310 |
+os::cmd::expect_success 'oc login -u test -p test' |
|
311 |
+os::cmd::expect_success_and_text 'oc projects' 'You are not a member of any projects' |
|
312 |
+# add a project and expect text for a single project |
|
313 |
+os::cmd::expect_success_and_text 'oc new-project test4; sleep 2; oc projects' 'You have one project on this server: "test4".' |
|
314 |
+os::cmd::expect_success_and_text 'oc new-project test5; sleep 2; oc projects' 'You have access' |
|
315 |
+echo 'projects command ok' |
|
316 |
+ |
|
306 | 317 |
os::test::junit::declare_suite_start "cmd/basicresources/patch" |
307 | 318 |
# Validate patching works correctly |
308 | 319 |
oc login -u system:admin |
... | ... |
@@ -95,9 +95,9 @@ os::cmd::expect_success_and_text 'openshift start --help' 'Start an all-in-one s |
95 | 95 |
os::cmd::expect_success_and_text 'openshift start master --help' 'Start a master' |
96 | 96 |
os::cmd::expect_success_and_text 'openshift start node --help' 'Start a node' |
97 | 97 |
os::cmd::expect_success_and_text 'oc project --help' 'Switch to another project' |
98 |
-os::cmd::expect_success_and_text 'oc projects --help' 'Switch to another project' |
|
98 |
+os::cmd::expect_success_and_text 'oc projects --help' 'existing projects' |
|
99 | 99 |
os::cmd::expect_success_and_text 'openshift cli project --help' 'Switch to another project' |
100 |
-os::cmd::expect_success_and_text 'openshift cli projects --help' 'Switch to another project' |
|
100 |
+os::cmd::expect_success_and_text 'openshift cli projects --help' 'current active project and existing projects on the server' |
|
101 | 101 |
os::cmd::expect_success_and_text 'oc get --help' 'oc' |
102 | 102 |
|
103 | 103 |
# help for given command through help command must be consistent |
... | ... |
@@ -108,7 +108,7 @@ os::cmd::expect_success_and_text 'openshift help start' 'Start an all-in-one ser |
108 | 108 |
os::cmd::expect_success_and_text 'openshift help start master' 'Start a master' |
109 | 109 |
os::cmd::expect_success_and_text 'openshift help start node' 'Start a node' |
110 | 110 |
os::cmd::expect_success_and_text 'oc help project' 'Switch to another project' |
111 |
-os::cmd::expect_success_and_text 'oc help projects' 'Switch to another project' |
|
111 |
+os::cmd::expect_success_and_text 'oc help projects' 'current active project and existing projects on the server' |
|
112 | 112 |
|
113 | 113 |
# runnable commands with required flags must error consistently |
114 | 114 |
os::cmd::expect_failure_and_text 'oc get' 'Required resource not specified' |