... | ... |
@@ -18,6 +18,7 @@ import ( |
18 | 18 |
"github.com/openshift/origin/pkg/cmd/cli/cmd/cluster" |
19 | 19 |
"github.com/openshift/origin/pkg/cmd/cli/cmd/dockerbuild" |
20 | 20 |
"github.com/openshift/origin/pkg/cmd/cli/cmd/importer" |
21 |
+ "github.com/openshift/origin/pkg/cmd/cli/cmd/rollout" |
|
21 | 22 |
"github.com/openshift/origin/pkg/cmd/cli/cmd/rsync" |
22 | 23 |
"github.com/openshift/origin/pkg/cmd/cli/cmd/set" |
23 | 24 |
"github.com/openshift/origin/pkg/cmd/cli/policy" |
... | ... |
@@ -105,6 +106,7 @@ func NewCommandCLI(name, fullName string, in io.Reader, out, errout io.Writer) * |
105 | 105 |
{ |
106 | 106 |
Message: "Build and Deploy Commands:", |
107 | 107 |
Commands: []*cobra.Command{ |
108 |
+ rollout.NewCmdRollout(fullName, f, out), |
|
108 | 109 |
cmd.NewCmdDeploy(fullName, f, out), |
109 | 110 |
cmd.NewCmdRollback(fullName, f, out), |
110 | 111 |
cmd.NewCmdNewBuild(fullName, f, in, out), |
111 | 112 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,463 @@ |
0 |
+package create |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "io" |
|
5 |
+ "strconv" |
|
6 |
+ |
|
7 |
+ "github.com/spf13/cobra" |
|
8 |
+ |
|
9 |
+ kapi "k8s.io/kubernetes/pkg/api" |
|
10 |
+ kclient "k8s.io/kubernetes/pkg/client/unversioned" |
|
11 |
+ kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
|
12 |
+ "k8s.io/kubernetes/pkg/kubectl/resource" |
|
13 |
+ "k8s.io/kubernetes/pkg/util/intstr" |
|
14 |
+ |
|
15 |
+ cmdutil "github.com/openshift/origin/pkg/cmd/util" |
|
16 |
+ "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
17 |
+ "github.com/openshift/origin/pkg/route/api" |
|
18 |
+ fileutil "github.com/openshift/origin/pkg/util/file" |
|
19 |
+) |
|
20 |
+ |
|
21 |
+const ( |
|
22 |
+ routeLong = ` |
|
23 |
+Expose containers externally via secured routes |
|
24 |
+ |
|
25 |
+Three types of secured routes are supported: edge, passthrough, and reencrypt. |
|
26 |
+If you wish to create unsecured routes, see "%[1]s expose -h" |
|
27 |
+` |
|
28 |
+) |
|
29 |
+ |
|
30 |
+// NewCmdCreateRoute is a macro command to create a secured route. |
|
31 |
+func NewCmdCreateRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
32 |
+ cmd := &cobra.Command{ |
|
33 |
+ Use: "route", |
|
34 |
+ Short: "Expose containers externally via secured routes", |
|
35 |
+ Long: fmt.Sprintf(routeLong, fullName), |
|
36 |
+ Run: cmdutil.DefaultSubCommandRun(out), |
|
37 |
+ } |
|
38 |
+ |
|
39 |
+ cmd.AddCommand(NewCmdCreateEdgeRoute(fullName, f, out)) |
|
40 |
+ cmd.AddCommand(NewCmdCreatePassthroughRoute(fullName, f, out)) |
|
41 |
+ cmd.AddCommand(NewCmdCreateReencryptRoute(fullName, f, out)) |
|
42 |
+ |
|
43 |
+ return cmd |
|
44 |
+} |
|
45 |
+ |
|
46 |
+const ( |
|
47 |
+ edgeRouteLong = ` |
|
48 |
+Create a route that uses edge TLS termination |
|
49 |
+ |
|
50 |
+Specify the service (either just its name or using type/name syntax) that the |
|
51 |
+generated route should expose via the --service flag.` |
|
52 |
+ |
|
53 |
+ edgeRouteExample = ` # Create an edge route named "my-route" that exposes frontend service. |
|
54 |
+ %[1]s create route edge my-route --service=frontend |
|
55 |
+ |
|
56 |
+ # Create an edge route that exposes the frontend service and specify a path. |
|
57 |
+ # If the route name is omitted, the service name will be re-used. |
|
58 |
+ %[1]s create route edge --service=frontend --path /assets` |
|
59 |
+) |
|
60 |
+ |
|
61 |
+// NewCmdCreateEdgeRoute is a macro command to create an edge route. |
|
62 |
+func NewCmdCreateEdgeRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
63 |
+ cmd := &cobra.Command{ |
|
64 |
+ Use: "edge [NAME] --service=SERVICE", |
|
65 |
+ Short: "Create a route that uses edge TLS termination", |
|
66 |
+ Long: edgeRouteLong, |
|
67 |
+ Example: fmt.Sprintf(edgeRouteExample, fullName), |
|
68 |
+ Run: func(cmd *cobra.Command, args []string) { |
|
69 |
+ err := CreateEdgeRoute(f, out, cmd, args) |
|
70 |
+ kcmdutil.CheckErr(err) |
|
71 |
+ }, |
|
72 |
+ } |
|
73 |
+ |
|
74 |
+ kcmdutil.AddValidateFlags(cmd) |
|
75 |
+ kcmdutil.AddOutputFlagsForMutation(cmd) |
|
76 |
+ cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
77 |
+ cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
78 |
+ cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
79 |
+ cmd.MarkFlagRequired("service") |
|
80 |
+ cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.") |
|
81 |
+ cmd.Flags().String("cert", "", "Path to a certificate file.") |
|
82 |
+ cmd.MarkFlagFilename("cert") |
|
83 |
+ cmd.Flags().String("key", "", "Path to a key file.") |
|
84 |
+ cmd.MarkFlagFilename("key") |
|
85 |
+ cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.") |
|
86 |
+ cmd.MarkFlagFilename("ca-cert") |
|
87 |
+ |
|
88 |
+ return cmd |
|
89 |
+} |
|
90 |
+ |
|
91 |
+// CreateEdgeRoute implements the behavior to run the create edge route command. |
|
92 |
+func CreateEdgeRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
93 |
+ oc, kc, err := f.Clients() |
|
94 |
+ if err != nil { |
|
95 |
+ return err |
|
96 |
+ } |
|
97 |
+ ns, _, err := f.DefaultNamespace() |
|
98 |
+ if err != nil { |
|
99 |
+ return err |
|
100 |
+ } |
|
101 |
+ serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
102 |
+ if err != nil { |
|
103 |
+ return err |
|
104 |
+ } |
|
105 |
+ routeName, err := resolveRouteName(args) |
|
106 |
+ if err != nil { |
|
107 |
+ return err |
|
108 |
+ } |
|
109 |
+ route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
110 |
+ if err != nil { |
|
111 |
+ return err |
|
112 |
+ } |
|
113 |
+ |
|
114 |
+ route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
115 |
+ route.Spec.Path = kcmdutil.GetFlagString(cmd, "path") |
|
116 |
+ |
|
117 |
+ route.Spec.TLS = new(api.TLSConfig) |
|
118 |
+ route.Spec.TLS.Termination = api.TLSTerminationEdge |
|
119 |
+ cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert")) |
|
120 |
+ if err != nil { |
|
121 |
+ return err |
|
122 |
+ } |
|
123 |
+ route.Spec.TLS.Certificate = string(cert) |
|
124 |
+ key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key")) |
|
125 |
+ if err != nil { |
|
126 |
+ return err |
|
127 |
+ } |
|
128 |
+ route.Spec.TLS.Key = string(key) |
|
129 |
+ caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert")) |
|
130 |
+ if err != nil { |
|
131 |
+ return err |
|
132 |
+ } |
|
133 |
+ route.Spec.TLS.CACertificate = string(caCert) |
|
134 |
+ |
|
135 |
+ route, err = oc.Routes(ns).Create(route) |
|
136 |
+ if err != nil { |
|
137 |
+ return err |
|
138 |
+ } |
|
139 |
+ mapper, typer := f.Object(false) |
|
140 |
+ resourceMapper := &resource.Mapper{ |
|
141 |
+ ObjectTyper: typer, |
|
142 |
+ RESTMapper: mapper, |
|
143 |
+ ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
144 |
+ } |
|
145 |
+ info, err := resourceMapper.InfoForObject(route, nil) |
|
146 |
+ if err != nil { |
|
147 |
+ return err |
|
148 |
+ } |
|
149 |
+ shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
150 |
+ kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
151 |
+ return nil |
|
152 |
+} |
|
153 |
+ |
|
154 |
+const ( |
|
155 |
+ passthroughRouteLong = ` |
|
156 |
+Create a route that uses passthrough TLS termination |
|
157 |
+ |
|
158 |
+Specify the service (either just its name or using type/name syntax) that the |
|
159 |
+generated route should expose via the --service flag.` |
|
160 |
+ |
|
161 |
+ passthroughRouteExample = ` # Create a passthrough route named "my-route" that exposes the frontend service. |
|
162 |
+ %[1]s create route passthrough my-route --service=frontend |
|
163 |
+ |
|
164 |
+ # Create a passthrough route that exposes the frontend service and specify |
|
165 |
+ # a hostname. If the route name is omitted, the service name will be re-used. |
|
166 |
+ %[1]s create route passthrough --service=frontend --hostname=www.example.com` |
|
167 |
+) |
|
168 |
+ |
|
169 |
+// NewCmdCreatePassthroughRoute is a macro command to create a passthrough route. |
|
170 |
+func NewCmdCreatePassthroughRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
171 |
+ cmd := &cobra.Command{ |
|
172 |
+ Use: "passthrough [NAME] --service=SERVICE", |
|
173 |
+ Short: "Create a route that uses passthrough TLS termination", |
|
174 |
+ Long: passthroughRouteLong, |
|
175 |
+ Example: fmt.Sprintf(passthroughRouteExample, fullName), |
|
176 |
+ Run: func(cmd *cobra.Command, args []string) { |
|
177 |
+ err := CreatePassthroughRoute(f, out, cmd, args) |
|
178 |
+ kcmdutil.CheckErr(err) |
|
179 |
+ }, |
|
180 |
+ } |
|
181 |
+ |
|
182 |
+ kcmdutil.AddValidateFlags(cmd) |
|
183 |
+ kcmdutil.AddOutputFlagsForMutation(cmd) |
|
184 |
+ cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
185 |
+ cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
186 |
+ cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
187 |
+ cmd.MarkFlagRequired("service") |
|
188 |
+ |
|
189 |
+ return cmd |
|
190 |
+} |
|
191 |
+ |
|
192 |
+// CreatePassthroughRoute implements the behavior to run the create passthrough route command. |
|
193 |
+func CreatePassthroughRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
194 |
+ oc, kc, err := f.Clients() |
|
195 |
+ if err != nil { |
|
196 |
+ return err |
|
197 |
+ } |
|
198 |
+ ns, _, err := f.DefaultNamespace() |
|
199 |
+ if err != nil { |
|
200 |
+ return err |
|
201 |
+ } |
|
202 |
+ serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
203 |
+ if err != nil { |
|
204 |
+ return err |
|
205 |
+ } |
|
206 |
+ routeName, err := resolveRouteName(args) |
|
207 |
+ if err != nil { |
|
208 |
+ return err |
|
209 |
+ } |
|
210 |
+ route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
211 |
+ if err != nil { |
|
212 |
+ return err |
|
213 |
+ } |
|
214 |
+ |
|
215 |
+ route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
216 |
+ |
|
217 |
+ route.Spec.TLS = new(api.TLSConfig) |
|
218 |
+ route.Spec.TLS.Termination = api.TLSTerminationPassthrough |
|
219 |
+ |
|
220 |
+ route, err = oc.Routes(ns).Create(route) |
|
221 |
+ if err != nil { |
|
222 |
+ return err |
|
223 |
+ } |
|
224 |
+ mapper, typer := f.Object(false) |
|
225 |
+ resourceMapper := &resource.Mapper{ |
|
226 |
+ ObjectTyper: typer, |
|
227 |
+ RESTMapper: mapper, |
|
228 |
+ ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
229 |
+ } |
|
230 |
+ info, err := resourceMapper.InfoForObject(route, nil) |
|
231 |
+ if err != nil { |
|
232 |
+ return err |
|
233 |
+ } |
|
234 |
+ shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
235 |
+ kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
236 |
+ return nil |
|
237 |
+} |
|
238 |
+ |
|
239 |
+const ( |
|
240 |
+ reencryptRouteLong = ` |
|
241 |
+Create a route that uses reencrypt TLS termination |
|
242 |
+ |
|
243 |
+Specify the service (either just its name or using type/name syntax) that the |
|
244 |
+generated route should expose via the --service flag. A destination CA certificate |
|
245 |
+is needed for reencrypt routes, specify one with the --dest-ca-cert flag.` |
|
246 |
+ |
|
247 |
+ reencryptRouteExample = ` # Create a route named "my-route" that exposes the frontend service. |
|
248 |
+ %[1]s create route reencrypt my-route --service=frontend --dest-ca-cert cert.cert |
|
249 |
+ |
|
250 |
+ # Create a reencrypt route that exposes the frontend service and re-use |
|
251 |
+ # the service name as the route name. |
|
252 |
+ %[1]s create route reencrypt --service=frontend --dest-ca-cert cert.cert` |
|
253 |
+) |
|
254 |
+ |
|
255 |
+// NewCmdCreateReencryptRoute is a macro command to create a reencrypt route. |
|
256 |
+func NewCmdCreateReencryptRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
257 |
+ cmd := &cobra.Command{ |
|
258 |
+ Use: "reencrypt [NAME] --dest-ca-cert=FILENAME --service=SERVICE", |
|
259 |
+ Short: "Create a route that uses reencrypt TLS termination", |
|
260 |
+ Long: reencryptRouteLong, |
|
261 |
+ Example: fmt.Sprintf(reencryptRouteExample, fullName), |
|
262 |
+ Run: func(cmd *cobra.Command, args []string) { |
|
263 |
+ err := CreateReencryptRoute(f, out, cmd, args) |
|
264 |
+ kcmdutil.CheckErr(err) |
|
265 |
+ }, |
|
266 |
+ } |
|
267 |
+ |
|
268 |
+ kcmdutil.AddValidateFlags(cmd) |
|
269 |
+ kcmdutil.AddOutputFlagsForMutation(cmd) |
|
270 |
+ cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
271 |
+ cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
272 |
+ cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
273 |
+ cmd.MarkFlagRequired("service") |
|
274 |
+ cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.") |
|
275 |
+ cmd.Flags().String("cert", "", "Path to a certificate file.") |
|
276 |
+ cmd.MarkFlagFilename("cert") |
|
277 |
+ cmd.Flags().String("key", "", "Path to a key file.") |
|
278 |
+ cmd.MarkFlagFilename("key") |
|
279 |
+ cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.") |
|
280 |
+ cmd.MarkFlagFilename("ca-cert") |
|
281 |
+ cmd.Flags().String("dest-ca-cert", "", "Path to a CA certificate file, used for securing the connection from the router to the destination.") |
|
282 |
+ cmd.MarkFlagRequired("dest-ca-cert") |
|
283 |
+ cmd.MarkFlagFilename("dest-ca-cert") |
|
284 |
+ |
|
285 |
+ return cmd |
|
286 |
+} |
|
287 |
+ |
|
288 |
+// CreateReencryptRoute implements the behavior to run the create reencrypt route command. |
|
289 |
+func CreateReencryptRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
290 |
+ oc, kc, err := f.Clients() |
|
291 |
+ if err != nil { |
|
292 |
+ return err |
|
293 |
+ } |
|
294 |
+ ns, _, err := f.DefaultNamespace() |
|
295 |
+ if err != nil { |
|
296 |
+ return err |
|
297 |
+ } |
|
298 |
+ serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
299 |
+ if err != nil { |
|
300 |
+ return err |
|
301 |
+ } |
|
302 |
+ routeName, err := resolveRouteName(args) |
|
303 |
+ if err != nil { |
|
304 |
+ return err |
|
305 |
+ } |
|
306 |
+ route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
307 |
+ if err != nil { |
|
308 |
+ return err |
|
309 |
+ } |
|
310 |
+ |
|
311 |
+ route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
312 |
+ route.Spec.Path = kcmdutil.GetFlagString(cmd, "path") |
|
313 |
+ |
|
314 |
+ route.Spec.TLS = new(api.TLSConfig) |
|
315 |
+ route.Spec.TLS.Termination = api.TLSTerminationReencrypt |
|
316 |
+ |
|
317 |
+ cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert")) |
|
318 |
+ if err != nil { |
|
319 |
+ return err |
|
320 |
+ } |
|
321 |
+ route.Spec.TLS.Certificate = string(cert) |
|
322 |
+ key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key")) |
|
323 |
+ if err != nil { |
|
324 |
+ return err |
|
325 |
+ } |
|
326 |
+ route.Spec.TLS.Key = string(key) |
|
327 |
+ caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert")) |
|
328 |
+ if err != nil { |
|
329 |
+ return err |
|
330 |
+ } |
|
331 |
+ route.Spec.TLS.CACertificate = string(caCert) |
|
332 |
+ destCACert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "dest-ca-cert")) |
|
333 |
+ if err != nil { |
|
334 |
+ return err |
|
335 |
+ } |
|
336 |
+ route.Spec.TLS.DestinationCACertificate = string(destCACert) |
|
337 |
+ |
|
338 |
+ route, err = oc.Routes(ns).Create(route) |
|
339 |
+ if err != nil { |
|
340 |
+ return err |
|
341 |
+ } |
|
342 |
+ mapper, typer := f.Object(false) |
|
343 |
+ resourceMapper := &resource.Mapper{ |
|
344 |
+ ObjectTyper: typer, |
|
345 |
+ RESTMapper: mapper, |
|
346 |
+ ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
347 |
+ } |
|
348 |
+ info, err := resourceMapper.InfoForObject(route, nil) |
|
349 |
+ if err != nil { |
|
350 |
+ return err |
|
351 |
+ } |
|
352 |
+ shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
353 |
+ kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
354 |
+ return nil |
|
355 |
+} |
|
356 |
+ |
|
357 |
+// unsecuredRoute will return a route with enough info so that it can direct traffic to |
|
358 |
+// the service provided by --service. Callers of this helper are responsible for providing |
|
359 |
+// tls configuration, path, and the hostname of the route. |
|
360 |
+func unsecuredRoute(kc *kclient.Client, namespace, routeName, serviceName, portString string) (*api.Route, error) { |
|
361 |
+ if len(routeName) == 0 { |
|
362 |
+ routeName = serviceName |
|
363 |
+ } |
|
364 |
+ |
|
365 |
+ svc, err := kc.Services(namespace).Get(serviceName) |
|
366 |
+ if err != nil { |
|
367 |
+ if len(portString) == 0 { |
|
368 |
+ return nil, fmt.Errorf("you need to provide a route port via --port when exposing a non-existent service") |
|
369 |
+ } |
|
370 |
+ return &api.Route{ |
|
371 |
+ ObjectMeta: kapi.ObjectMeta{ |
|
372 |
+ Name: routeName, |
|
373 |
+ }, |
|
374 |
+ Spec: api.RouteSpec{ |
|
375 |
+ To: api.RouteTargetReference{ |
|
376 |
+ Name: serviceName, |
|
377 |
+ }, |
|
378 |
+ Port: resolveRoutePort(portString), |
|
379 |
+ }, |
|
380 |
+ }, nil |
|
381 |
+ } |
|
382 |
+ |
|
383 |
+ ok, port := supportsTCP(svc) |
|
384 |
+ if !ok { |
|
385 |
+ return nil, fmt.Errorf("service %q doesn't support TCP", svc.Name) |
|
386 |
+ } |
|
387 |
+ |
|
388 |
+ route := &api.Route{ |
|
389 |
+ ObjectMeta: kapi.ObjectMeta{ |
|
390 |
+ Name: routeName, |
|
391 |
+ Labels: svc.Labels, |
|
392 |
+ }, |
|
393 |
+ Spec: api.RouteSpec{ |
|
394 |
+ To: api.RouteTargetReference{ |
|
395 |
+ Name: serviceName, |
|
396 |
+ }, |
|
397 |
+ }, |
|
398 |
+ } |
|
399 |
+ |
|
400 |
+ // If the service has multiple ports and the user didn't specify --port, |
|
401 |
+ // then default the route port to a service port name. |
|
402 |
+ if len(port.Name) > 0 && len(portString) == 0 { |
|
403 |
+ route.Spec.Port = resolveRoutePort(port.Name) |
|
404 |
+ } |
|
405 |
+ // --port uber alles |
|
406 |
+ if len(portString) > 0 { |
|
407 |
+ route.Spec.Port = resolveRoutePort(portString) |
|
408 |
+ } |
|
409 |
+ |
|
410 |
+ return route, nil |
|
411 |
+} |
|
412 |
+ |
|
413 |
+func resolveServiceName(f *clientcmd.Factory, resource string) (string, error) { |
|
414 |
+ if len(resource) == 0 { |
|
415 |
+ return "", fmt.Errorf("you need to provide a service name via --service") |
|
416 |
+ } |
|
417 |
+ mapper, _ := f.Object(false) |
|
418 |
+ rType, name, err := cmdutil.ResolveResource(kapi.Resource("services"), resource, mapper) |
|
419 |
+ if err != nil { |
|
420 |
+ return "", err |
|
421 |
+ } |
|
422 |
+ if rType != kapi.Resource("services") { |
|
423 |
+ return "", fmt.Errorf("cannot expose %v as routes", rType) |
|
424 |
+ } |
|
425 |
+ return name, nil |
|
426 |
+} |
|
427 |
+ |
|
428 |
+func resolveRouteName(args []string) (string, error) { |
|
429 |
+ switch len(args) { |
|
430 |
+ case 0: |
|
431 |
+ case 1: |
|
432 |
+ return args[0], nil |
|
433 |
+ default: |
|
434 |
+ return "", fmt.Errorf("multiple names provided. Please specify at most one") |
|
435 |
+ } |
|
436 |
+ return "", nil |
|
437 |
+} |
|
438 |
+ |
|
439 |
+func resolveRoutePort(portString string) *api.RoutePort { |
|
440 |
+ if len(portString) == 0 { |
|
441 |
+ return nil |
|
442 |
+ } |
|
443 |
+ var routePort intstr.IntOrString |
|
444 |
+ integer, err := strconv.Atoi(portString) |
|
445 |
+ if err != nil { |
|
446 |
+ routePort = intstr.FromString(portString) |
|
447 |
+ } else { |
|
448 |
+ routePort = intstr.FromInt(integer) |
|
449 |
+ } |
|
450 |
+ return &api.RoutePort{ |
|
451 |
+ TargetPort: routePort, |
|
452 |
+ } |
|
453 |
+} |
|
454 |
+ |
|
455 |
+func supportsTCP(svc *kapi.Service) (bool, kapi.ServicePort) { |
|
456 |
+ for _, port := range svc.Spec.Ports { |
|
457 |
+ if port.Protocol == kapi.ProtocolTCP { |
|
458 |
+ return true, port |
|
459 |
+ } |
|
460 |
+ } |
|
461 |
+ return false, kapi.ServicePort{} |
|
462 |
+} |
0 | 463 |
deleted file mode 100644 |
... | ... |
@@ -1,463 +0,0 @@ |
1 |
-package cmd |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "fmt" |
|
5 |
- "io" |
|
6 |
- "strconv" |
|
7 |
- |
|
8 |
- "github.com/spf13/cobra" |
|
9 |
- |
|
10 |
- kapi "k8s.io/kubernetes/pkg/api" |
|
11 |
- kclient "k8s.io/kubernetes/pkg/client/unversioned" |
|
12 |
- kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
|
13 |
- "k8s.io/kubernetes/pkg/kubectl/resource" |
|
14 |
- "k8s.io/kubernetes/pkg/util/intstr" |
|
15 |
- |
|
16 |
- cmdutil "github.com/openshift/origin/pkg/cmd/util" |
|
17 |
- "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
18 |
- "github.com/openshift/origin/pkg/route/api" |
|
19 |
- fileutil "github.com/openshift/origin/pkg/util/file" |
|
20 |
-) |
|
21 |
- |
|
22 |
-const ( |
|
23 |
- routeLong = ` |
|
24 |
-Expose containers externally via secured routes |
|
25 |
- |
|
26 |
-Three types of secured routes are supported: edge, passthrough, and reencrypt. |
|
27 |
-If you wish to create unsecured routes, see "%[1]s expose -h" |
|
28 |
-` |
|
29 |
-) |
|
30 |
- |
|
31 |
-// NewCmdCreateRoute is a macro command to create a secured route. |
|
32 |
-func NewCmdCreateRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
33 |
- cmd := &cobra.Command{ |
|
34 |
- Use: "route", |
|
35 |
- Short: "Expose containers externally via secured routes", |
|
36 |
- Long: fmt.Sprintf(routeLong, fullName), |
|
37 |
- Run: cmdutil.DefaultSubCommandRun(out), |
|
38 |
- } |
|
39 |
- |
|
40 |
- cmd.AddCommand(NewCmdCreateEdgeRoute(fullName, f, out)) |
|
41 |
- cmd.AddCommand(NewCmdCreatePassthroughRoute(fullName, f, out)) |
|
42 |
- cmd.AddCommand(NewCmdCreateReencryptRoute(fullName, f, out)) |
|
43 |
- |
|
44 |
- return cmd |
|
45 |
-} |
|
46 |
- |
|
47 |
-const ( |
|
48 |
- edgeRouteLong = ` |
|
49 |
-Create a route that uses edge TLS termination |
|
50 |
- |
|
51 |
-Specify the service (either just its name or using type/name syntax) that the |
|
52 |
-generated route should expose via the --service flag.` |
|
53 |
- |
|
54 |
- edgeRouteExample = ` # Create an edge route named "my-route" that exposes frontend service. |
|
55 |
- %[1]s create route edge my-route --service=frontend |
|
56 |
- |
|
57 |
- # Create an edge route that exposes the frontend service and specify a path. |
|
58 |
- # If the route name is omitted, the service name will be re-used. |
|
59 |
- %[1]s create route edge --service=frontend --path /assets` |
|
60 |
-) |
|
61 |
- |
|
62 |
-// NewCmdCreateEdgeRoute is a macro command to create an edge route. |
|
63 |
-func NewCmdCreateEdgeRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
64 |
- cmd := &cobra.Command{ |
|
65 |
- Use: "edge [NAME] --service=SERVICE", |
|
66 |
- Short: "Create a route that uses edge TLS termination", |
|
67 |
- Long: edgeRouteLong, |
|
68 |
- Example: fmt.Sprintf(edgeRouteExample, fullName), |
|
69 |
- Run: func(cmd *cobra.Command, args []string) { |
|
70 |
- err := CreateEdgeRoute(f, out, cmd, args) |
|
71 |
- kcmdutil.CheckErr(err) |
|
72 |
- }, |
|
73 |
- } |
|
74 |
- |
|
75 |
- kcmdutil.AddValidateFlags(cmd) |
|
76 |
- kcmdutil.AddOutputFlagsForMutation(cmd) |
|
77 |
- cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
78 |
- cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
79 |
- cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
80 |
- cmd.MarkFlagRequired("service") |
|
81 |
- cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.") |
|
82 |
- cmd.Flags().String("cert", "", "Path to a certificate file.") |
|
83 |
- cmd.MarkFlagFilename("cert") |
|
84 |
- cmd.Flags().String("key", "", "Path to a key file.") |
|
85 |
- cmd.MarkFlagFilename("key") |
|
86 |
- cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.") |
|
87 |
- cmd.MarkFlagFilename("ca-cert") |
|
88 |
- |
|
89 |
- return cmd |
|
90 |
-} |
|
91 |
- |
|
92 |
-// CreateEdgeRoute implements the behavior to run the create edge route command. |
|
93 |
-func CreateEdgeRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
94 |
- oc, kc, err := f.Clients() |
|
95 |
- if err != nil { |
|
96 |
- return err |
|
97 |
- } |
|
98 |
- ns, _, err := f.DefaultNamespace() |
|
99 |
- if err != nil { |
|
100 |
- return err |
|
101 |
- } |
|
102 |
- serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
103 |
- if err != nil { |
|
104 |
- return err |
|
105 |
- } |
|
106 |
- routeName, err := resolveRouteName(args) |
|
107 |
- if err != nil { |
|
108 |
- return err |
|
109 |
- } |
|
110 |
- route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
111 |
- if err != nil { |
|
112 |
- return err |
|
113 |
- } |
|
114 |
- |
|
115 |
- route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
116 |
- route.Spec.Path = kcmdutil.GetFlagString(cmd, "path") |
|
117 |
- |
|
118 |
- route.Spec.TLS = new(api.TLSConfig) |
|
119 |
- route.Spec.TLS.Termination = api.TLSTerminationEdge |
|
120 |
- cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert")) |
|
121 |
- if err != nil { |
|
122 |
- return err |
|
123 |
- } |
|
124 |
- route.Spec.TLS.Certificate = string(cert) |
|
125 |
- key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key")) |
|
126 |
- if err != nil { |
|
127 |
- return err |
|
128 |
- } |
|
129 |
- route.Spec.TLS.Key = string(key) |
|
130 |
- caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert")) |
|
131 |
- if err != nil { |
|
132 |
- return err |
|
133 |
- } |
|
134 |
- route.Spec.TLS.CACertificate = string(caCert) |
|
135 |
- |
|
136 |
- route, err = oc.Routes(ns).Create(route) |
|
137 |
- if err != nil { |
|
138 |
- return err |
|
139 |
- } |
|
140 |
- mapper, typer := f.Object(false) |
|
141 |
- resourceMapper := &resource.Mapper{ |
|
142 |
- ObjectTyper: typer, |
|
143 |
- RESTMapper: mapper, |
|
144 |
- ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
145 |
- } |
|
146 |
- info, err := resourceMapper.InfoForObject(route, nil) |
|
147 |
- if err != nil { |
|
148 |
- return err |
|
149 |
- } |
|
150 |
- shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
151 |
- kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
152 |
- return nil |
|
153 |
-} |
|
154 |
- |
|
155 |
-const ( |
|
156 |
- passthroughRouteLong = ` |
|
157 |
-Create a route that uses passthrough TLS termination |
|
158 |
- |
|
159 |
-Specify the service (either just its name or using type/name syntax) that the |
|
160 |
-generated route should expose via the --service flag.` |
|
161 |
- |
|
162 |
- passthroughRouteExample = ` # Create a passthrough route named "my-route" that exposes the frontend service. |
|
163 |
- %[1]s create route passthrough my-route --service=frontend |
|
164 |
- |
|
165 |
- # Create a passthrough route that exposes the frontend service and specify |
|
166 |
- # a hostname. If the route name is omitted, the service name will be re-used. |
|
167 |
- %[1]s create route passthrough --service=frontend --hostname=www.example.com` |
|
168 |
-) |
|
169 |
- |
|
170 |
-// NewCmdCreatePassthroughRoute is a macro command to create a passthrough route. |
|
171 |
-func NewCmdCreatePassthroughRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
172 |
- cmd := &cobra.Command{ |
|
173 |
- Use: "passthrough [NAME] --service=SERVICE", |
|
174 |
- Short: "Create a route that uses passthrough TLS termination", |
|
175 |
- Long: passthroughRouteLong, |
|
176 |
- Example: fmt.Sprintf(passthroughRouteExample, fullName), |
|
177 |
- Run: func(cmd *cobra.Command, args []string) { |
|
178 |
- err := CreatePassthroughRoute(f, out, cmd, args) |
|
179 |
- kcmdutil.CheckErr(err) |
|
180 |
- }, |
|
181 |
- } |
|
182 |
- |
|
183 |
- kcmdutil.AddValidateFlags(cmd) |
|
184 |
- kcmdutil.AddOutputFlagsForMutation(cmd) |
|
185 |
- cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
186 |
- cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
187 |
- cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
188 |
- cmd.MarkFlagRequired("service") |
|
189 |
- |
|
190 |
- return cmd |
|
191 |
-} |
|
192 |
- |
|
193 |
-// CreatePassthroughRoute implements the behavior to run the create passthrough route command. |
|
194 |
-func CreatePassthroughRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
195 |
- oc, kc, err := f.Clients() |
|
196 |
- if err != nil { |
|
197 |
- return err |
|
198 |
- } |
|
199 |
- ns, _, err := f.DefaultNamespace() |
|
200 |
- if err != nil { |
|
201 |
- return err |
|
202 |
- } |
|
203 |
- serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
204 |
- if err != nil { |
|
205 |
- return err |
|
206 |
- } |
|
207 |
- routeName, err := resolveRouteName(args) |
|
208 |
- if err != nil { |
|
209 |
- return err |
|
210 |
- } |
|
211 |
- route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
212 |
- if err != nil { |
|
213 |
- return err |
|
214 |
- } |
|
215 |
- |
|
216 |
- route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
217 |
- |
|
218 |
- route.Spec.TLS = new(api.TLSConfig) |
|
219 |
- route.Spec.TLS.Termination = api.TLSTerminationPassthrough |
|
220 |
- |
|
221 |
- route, err = oc.Routes(ns).Create(route) |
|
222 |
- if err != nil { |
|
223 |
- return err |
|
224 |
- } |
|
225 |
- mapper, typer := f.Object(false) |
|
226 |
- resourceMapper := &resource.Mapper{ |
|
227 |
- ObjectTyper: typer, |
|
228 |
- RESTMapper: mapper, |
|
229 |
- ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
230 |
- } |
|
231 |
- info, err := resourceMapper.InfoForObject(route, nil) |
|
232 |
- if err != nil { |
|
233 |
- return err |
|
234 |
- } |
|
235 |
- shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
236 |
- kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
237 |
- return nil |
|
238 |
-} |
|
239 |
- |
|
240 |
-const ( |
|
241 |
- reencryptRouteLong = ` |
|
242 |
-Create a route that uses reencrypt TLS termination |
|
243 |
- |
|
244 |
-Specify the service (either just its name or using type/name syntax) that the |
|
245 |
-generated route should expose via the --service flag. A destination CA certificate |
|
246 |
-is needed for reencrypt routes, specify one with the --dest-ca-cert flag.` |
|
247 |
- |
|
248 |
- reencryptRouteExample = ` # Create a route named "my-route" that exposes the frontend service. |
|
249 |
- %[1]s create route reencrypt my-route --service=frontend --dest-ca-cert cert.cert |
|
250 |
- |
|
251 |
- # Create a reencrypt route that exposes the frontend service and re-use |
|
252 |
- # the service name as the route name. |
|
253 |
- %[1]s create route reencrypt --service=frontend --dest-ca-cert cert.cert` |
|
254 |
-) |
|
255 |
- |
|
256 |
-// NewCmdCreateReencryptRoute is a macro command to create a reencrypt route. |
|
257 |
-func NewCmdCreateReencryptRoute(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
258 |
- cmd := &cobra.Command{ |
|
259 |
- Use: "reencrypt [NAME] --dest-ca-cert=FILENAME --service=SERVICE", |
|
260 |
- Short: "Create a route that uses reencrypt TLS termination", |
|
261 |
- Long: reencryptRouteLong, |
|
262 |
- Example: fmt.Sprintf(reencryptRouteExample, fullName), |
|
263 |
- Run: func(cmd *cobra.Command, args []string) { |
|
264 |
- err := CreateReencryptRoute(f, out, cmd, args) |
|
265 |
- kcmdutil.CheckErr(err) |
|
266 |
- }, |
|
267 |
- } |
|
268 |
- |
|
269 |
- kcmdutil.AddValidateFlags(cmd) |
|
270 |
- kcmdutil.AddOutputFlagsForMutation(cmd) |
|
271 |
- cmd.Flags().String("hostname", "", "Set a hostname for the new route") |
|
272 |
- cmd.Flags().String("port", "", "Name of the service port or number of the container port the route will route traffic to") |
|
273 |
- cmd.Flags().String("service", "", "Name of the service that the new route is exposing") |
|
274 |
- cmd.MarkFlagRequired("service") |
|
275 |
- cmd.Flags().String("path", "", "Path that the router watches to route traffic to the service.") |
|
276 |
- cmd.Flags().String("cert", "", "Path to a certificate file.") |
|
277 |
- cmd.MarkFlagFilename("cert") |
|
278 |
- cmd.Flags().String("key", "", "Path to a key file.") |
|
279 |
- cmd.MarkFlagFilename("key") |
|
280 |
- cmd.Flags().String("ca-cert", "", "Path to a CA certificate file.") |
|
281 |
- cmd.MarkFlagFilename("ca-cert") |
|
282 |
- cmd.Flags().String("dest-ca-cert", "", "Path to a CA certificate file, used for securing the connection from the router to the destination.") |
|
283 |
- cmd.MarkFlagRequired("dest-ca-cert") |
|
284 |
- cmd.MarkFlagFilename("dest-ca-cert") |
|
285 |
- |
|
286 |
- return cmd |
|
287 |
-} |
|
288 |
- |
|
289 |
-// CreateReencryptRoute implements the behavior to run the create reencrypt route command. |
|
290 |
-func CreateReencryptRoute(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { |
|
291 |
- oc, kc, err := f.Clients() |
|
292 |
- if err != nil { |
|
293 |
- return err |
|
294 |
- } |
|
295 |
- ns, _, err := f.DefaultNamespace() |
|
296 |
- if err != nil { |
|
297 |
- return err |
|
298 |
- } |
|
299 |
- serviceName, err := resolveServiceName(f, kcmdutil.GetFlagString(cmd, "service")) |
|
300 |
- if err != nil { |
|
301 |
- return err |
|
302 |
- } |
|
303 |
- routeName, err := resolveRouteName(args) |
|
304 |
- if err != nil { |
|
305 |
- return err |
|
306 |
- } |
|
307 |
- route, err := unsecuredRoute(kc, ns, routeName, serviceName, kcmdutil.GetFlagString(cmd, "port")) |
|
308 |
- if err != nil { |
|
309 |
- return err |
|
310 |
- } |
|
311 |
- |
|
312 |
- route.Spec.Host = kcmdutil.GetFlagString(cmd, "hostname") |
|
313 |
- route.Spec.Path = kcmdutil.GetFlagString(cmd, "path") |
|
314 |
- |
|
315 |
- route.Spec.TLS = new(api.TLSConfig) |
|
316 |
- route.Spec.TLS.Termination = api.TLSTerminationReencrypt |
|
317 |
- |
|
318 |
- cert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "cert")) |
|
319 |
- if err != nil { |
|
320 |
- return err |
|
321 |
- } |
|
322 |
- route.Spec.TLS.Certificate = string(cert) |
|
323 |
- key, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "key")) |
|
324 |
- if err != nil { |
|
325 |
- return err |
|
326 |
- } |
|
327 |
- route.Spec.TLS.Key = string(key) |
|
328 |
- caCert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "ca-cert")) |
|
329 |
- if err != nil { |
|
330 |
- return err |
|
331 |
- } |
|
332 |
- route.Spec.TLS.CACertificate = string(caCert) |
|
333 |
- destCACert, err := fileutil.LoadData(kcmdutil.GetFlagString(cmd, "dest-ca-cert")) |
|
334 |
- if err != nil { |
|
335 |
- return err |
|
336 |
- } |
|
337 |
- route.Spec.TLS.DestinationCACertificate = string(destCACert) |
|
338 |
- |
|
339 |
- route, err = oc.Routes(ns).Create(route) |
|
340 |
- if err != nil { |
|
341 |
- return err |
|
342 |
- } |
|
343 |
- mapper, typer := f.Object(false) |
|
344 |
- resourceMapper := &resource.Mapper{ |
|
345 |
- ObjectTyper: typer, |
|
346 |
- RESTMapper: mapper, |
|
347 |
- ClientMapper: resource.ClientMapperFunc(f.ClientForMapping), |
|
348 |
- } |
|
349 |
- info, err := resourceMapper.InfoForObject(route, nil) |
|
350 |
- if err != nil { |
|
351 |
- return err |
|
352 |
- } |
|
353 |
- shortOutput := kcmdutil.GetFlagString(cmd, "output") == "name" |
|
354 |
- kcmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created") |
|
355 |
- return nil |
|
356 |
-} |
|
357 |
- |
|
358 |
-// unsecuredRoute will return a route with enough info so that it can direct traffic to |
|
359 |
-// the service provided by --service. Callers of this helper are responsible for providing |
|
360 |
-// tls configuration, path, and the hostname of the route. |
|
361 |
-func unsecuredRoute(kc *kclient.Client, namespace, routeName, serviceName, portString string) (*api.Route, error) { |
|
362 |
- if len(routeName) == 0 { |
|
363 |
- routeName = serviceName |
|
364 |
- } |
|
365 |
- |
|
366 |
- svc, err := kc.Services(namespace).Get(serviceName) |
|
367 |
- if err != nil { |
|
368 |
- if len(portString) == 0 { |
|
369 |
- return nil, fmt.Errorf("you need to provide a route port via --port when exposing a non-existent service") |
|
370 |
- } |
|
371 |
- return &api.Route{ |
|
372 |
- ObjectMeta: kapi.ObjectMeta{ |
|
373 |
- Name: routeName, |
|
374 |
- }, |
|
375 |
- Spec: api.RouteSpec{ |
|
376 |
- To: api.RouteTargetReference{ |
|
377 |
- Name: serviceName, |
|
378 |
- }, |
|
379 |
- Port: resolveRoutePort(portString), |
|
380 |
- }, |
|
381 |
- }, nil |
|
382 |
- } |
|
383 |
- |
|
384 |
- ok, port := supportsTCP(svc) |
|
385 |
- if !ok { |
|
386 |
- return nil, fmt.Errorf("service %q doesn't support TCP", svc.Name) |
|
387 |
- } |
|
388 |
- |
|
389 |
- route := &api.Route{ |
|
390 |
- ObjectMeta: kapi.ObjectMeta{ |
|
391 |
- Name: routeName, |
|
392 |
- Labels: svc.Labels, |
|
393 |
- }, |
|
394 |
- Spec: api.RouteSpec{ |
|
395 |
- To: api.RouteTargetReference{ |
|
396 |
- Name: serviceName, |
|
397 |
- }, |
|
398 |
- }, |
|
399 |
- } |
|
400 |
- |
|
401 |
- // If the service has multiple ports and the user didn't specify --port, |
|
402 |
- // then default the route port to a service port name. |
|
403 |
- if len(port.Name) > 0 && len(portString) == 0 { |
|
404 |
- route.Spec.Port = resolveRoutePort(port.Name) |
|
405 |
- } |
|
406 |
- // --port uber alles |
|
407 |
- if len(portString) > 0 { |
|
408 |
- route.Spec.Port = resolveRoutePort(portString) |
|
409 |
- } |
|
410 |
- |
|
411 |
- return route, nil |
|
412 |
-} |
|
413 |
- |
|
414 |
-func resolveServiceName(f *clientcmd.Factory, resource string) (string, error) { |
|
415 |
- if len(resource) == 0 { |
|
416 |
- return "", fmt.Errorf("you need to provide a service name via --service") |
|
417 |
- } |
|
418 |
- mapper, _ := f.Object(false) |
|
419 |
- rType, name, err := cmdutil.ResolveResource(kapi.Resource("services"), resource, mapper) |
|
420 |
- if err != nil { |
|
421 |
- return "", err |
|
422 |
- } |
|
423 |
- if rType != kapi.Resource("services") { |
|
424 |
- return "", fmt.Errorf("cannot expose %v as routes", rType) |
|
425 |
- } |
|
426 |
- return name, nil |
|
427 |
-} |
|
428 |
- |
|
429 |
-func resolveRouteName(args []string) (string, error) { |
|
430 |
- switch len(args) { |
|
431 |
- case 0: |
|
432 |
- case 1: |
|
433 |
- return args[0], nil |
|
434 |
- default: |
|
435 |
- return "", fmt.Errorf("multiple names provided. Please specify at most one") |
|
436 |
- } |
|
437 |
- return "", nil |
|
438 |
-} |
|
439 |
- |
|
440 |
-func resolveRoutePort(portString string) *api.RoutePort { |
|
441 |
- if len(portString) == 0 { |
|
442 |
- return nil |
|
443 |
- } |
|
444 |
- var routePort intstr.IntOrString |
|
445 |
- integer, err := strconv.Atoi(portString) |
|
446 |
- if err != nil { |
|
447 |
- routePort = intstr.FromString(portString) |
|
448 |
- } else { |
|
449 |
- routePort = intstr.FromInt(integer) |
|
450 |
- } |
|
451 |
- return &api.RoutePort{ |
|
452 |
- TargetPort: routePort, |
|
453 |
- } |
|
454 |
-} |
|
455 |
- |
|
456 |
-func supportsTCP(svc *kapi.Service) (bool, kapi.ServicePort) { |
|
457 |
- for _, port := range svc.Spec.Ports { |
|
458 |
- if port.Protocol == kapi.ProtocolTCP { |
|
459 |
- return true, port |
|
460 |
- } |
|
461 |
- } |
|
462 |
- return false, kapi.ServicePort{} |
|
463 |
-} |
464 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,99 @@ |
0 |
+package rollout |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "fmt" |
|
4 |
+ "io" |
|
5 |
+ |
|
6 |
+ "github.com/spf13/cobra" |
|
7 |
+ "k8s.io/kubernetes/pkg/kubectl/cmd/rollout" |
|
8 |
+ |
|
9 |
+ "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+const ( |
|
13 |
+ rolloutLong = ` |
|
14 |
+Manage deployments. |
|
15 |
+` |
|
16 |
+) |
|
17 |
+ |
|
18 |
+// NewCmdRollout facilitates kubectl rollout subcommands |
|
19 |
+func NewCmdRollout(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
20 |
+ cmd := &cobra.Command{ |
|
21 |
+ Use: "rollout SUBCOMMAND", |
|
22 |
+ Short: "rollout manages a deployment", |
|
23 |
+ Long: rolloutLong, |
|
24 |
+ Run: func(cmd *cobra.Command, args []string) { |
|
25 |
+ cmd.Help() |
|
26 |
+ }, |
|
27 |
+ } |
|
28 |
+ |
|
29 |
+ // subcommands |
|
30 |
+ cmd.AddCommand(NewCmdRolloutHistory(fullName, f, out)) |
|
31 |
+ cmd.AddCommand(NewCmdRolloutPause(fullName, f, out)) |
|
32 |
+ cmd.AddCommand(NewCmdRolloutResume(fullName, f, out)) |
|
33 |
+ |
|
34 |
+ return cmd |
|
35 |
+} |
|
36 |
+ |
|
37 |
+const ( |
|
38 |
+ rolloutHistoryLong = ` |
|
39 |
+View the history of rollouts for a specific deployment config |
|
40 |
+ |
|
41 |
+You can also view more detailed information for a specific revision |
|
42 |
+by using the --revision flag. |
|
43 |
+` |
|
44 |
+ |
|
45 |
+ rolloutHistoryExample = ` # View the rollout history of a deployment |
|
46 |
+ %[1]s rollout history dc/nginx |
|
47 |
+ |
|
48 |
+ # View the details of deployment revision 3 |
|
49 |
+ %[1]s rollout history dc/nginx --revision=3` |
|
50 |
+) |
|
51 |
+ |
|
52 |
+// NewCmdRolloutHistory is a wrapper for the Kubernetes cli rollout history command |
|
53 |
+func NewCmdRolloutHistory(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
54 |
+ cmd := rollout.NewCmdRolloutHistory(f.Factory, out) |
|
55 |
+ cmd.Long = rolloutHistoryLong |
|
56 |
+ cmd.Example = fmt.Sprintf(rolloutHistoryExample, fullName) |
|
57 |
+ return cmd |
|
58 |
+} |
|
59 |
+ |
|
60 |
+const ( |
|
61 |
+ rolloutPauseLong = ` |
|
62 |
+Mark the provided resource as paused |
|
63 |
+ |
|
64 |
+Paused resources will not be reconciled by a controller. |
|
65 |
+Use \"%[1]s rollout resume\" to resume a paused resource.` |
|
66 |
+ |
|
67 |
+ rolloutPauseExample = ` # Mark the nginx deployment as paused. Any current state of |
|
68 |
+ # the deployment will continue its function, new updates to the deployment will not |
|
69 |
+ # have an effect as long as the deployment is paused. |
|
70 |
+ %[1]s rollout pause dc/nginx` |
|
71 |
+) |
|
72 |
+ |
|
73 |
+// NewCmdRolloutPause is a wrapper for the Kubernetes cli rollout pause command |
|
74 |
+func NewCmdRolloutPause(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
75 |
+ cmd := rollout.NewCmdRolloutPause(f.Factory, out) |
|
76 |
+ cmd.Long = rolloutPauseLong |
|
77 |
+ cmd.Example = fmt.Sprintf(rolloutPauseExample, fullName) |
|
78 |
+ return cmd |
|
79 |
+} |
|
80 |
+ |
|
81 |
+const ( |
|
82 |
+ rolloutResumeLong = ` |
|
83 |
+Resume a paused resource |
|
84 |
+ |
|
85 |
+Paused resources will not be reconciled by a controller. By resuming a |
|
86 |
+resource, we allow it to be reconciled again.` |
|
87 |
+ |
|
88 |
+ rolloutResumeExample = ` # Resume an already paused deployment |
|
89 |
+ %[1]s rollout resume dc/nginx` |
|
90 |
+) |
|
91 |
+ |
|
92 |
+// NewCmdRolloutResume is a wrapper for the Kubernetes cli rollout resume command |
|
93 |
+func NewCmdRolloutResume(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
|
94 |
+ cmd := rollout.NewCmdRolloutResume(f.Factory, out) |
|
95 |
+ cmd.Long = rolloutResumeLong |
|
96 |
+ cmd.Example = fmt.Sprintf(rolloutResumeExample, fullName) |
|
97 |
+ return cmd |
|
98 |
+} |
... | ... |
@@ -20,13 +20,18 @@ import ( |
20 | 20 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
21 | 21 |
) |
22 | 22 |
|
23 |
-func tab(original string) string { |
|
24 |
- lines := []string{} |
|
25 |
- scanner := bufio.NewScanner(strings.NewReader(original)) |
|
23 |
+func adjustCmdExamples(cmd *cobra.Command, parentName string, name string) { |
|
24 |
+ for _, subCmd := range cmd.Commands() { |
|
25 |
+ adjustCmdExamples(subCmd, parentName, cmd.Name()) |
|
26 |
+ } |
|
27 |
+ cmd.Example = strings.Replace(cmd.Example, "kubectl", parentName, -1) |
|
28 |
+ tabbing := " " |
|
29 |
+ examples := []string{} |
|
30 |
+ scanner := bufio.NewScanner(strings.NewReader(cmd.Example)) |
|
26 | 31 |
for scanner.Scan() { |
27 |
- lines = append(lines, " "+scanner.Text()) |
|
32 |
+ examples = append(examples, tabbing+strings.TrimSpace(scanner.Text())) |
|
28 | 33 |
} |
29 |
- return strings.Join(lines, "\n") |
|
34 |
+ cmd.Example = strings.Join(examples, "\n") |
|
30 | 35 |
} |
31 | 36 |
|
32 | 37 |
const ( |
... | ... |
@@ -163,7 +168,7 @@ func NewCmdCreate(parentName string, f *clientcmd.Factory, out io.Writer) *cobra |
163 | 163 |
cmd.Example = fmt.Sprintf(createExample, parentName) |
164 | 164 |
|
165 | 165 |
// create subcommands |
166 |
- cmd.AddCommand(NewCmdCreateRoute(parentName, f, out)) |
|
166 |
+ cmd.AddCommand(create.NewCmdCreateRoute(parentName, f, out)) |
|
167 | 167 |
cmd.AddCommand(create.NewCmdCreatePolicyBinding(create.PolicyBindingRecommendedName, parentName+" create "+create.PolicyBindingRecommendedName, f, out)) |
168 | 168 |
cmd.AddCommand(create.NewCmdCreateDeploymentConfig(create.DeploymentConfigRecommendedName, parentName+" create "+create.DeploymentConfigRecommendedName, f, out)) |
169 | 169 |
cmd.AddCommand(create.NewCmdCreateClusterQuota(create.ClusterQuotaRecommendedName, parentName+" create "+create.ClusterQuotaRecommendedName, f, out)) |
... | ... |
@@ -504,6 +509,7 @@ JSON and YAML formats are accepted.` |
504 | 504 |
cat pod.json | %[1]s apply -f -` |
505 | 505 |
) |
506 | 506 |
|
507 |
+// NewCmdApply is a wrapper for the Kubernetes cli apply command |
|
507 | 508 |
func NewCmdApply(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
508 | 509 |
cmd := kcmd.NewCmdApply(f.Factory, out) |
509 | 510 |
cmd.Long = applyLong |
... | ... |
@@ -526,6 +532,7 @@ resourcequotas (quota), namespaces (ns) or endpoints (ep).` |
526 | 526 |
%[1]s explain pods.spec.containers` |
527 | 527 |
) |
528 | 528 |
|
529 |
+// NewCmdExplain is a wrapper for the Kubernetes cli explain command |
|
529 | 530 |
func NewCmdExplain(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
530 | 531 |
cmd := kcmd.NewCmdExplain(f.Factory, out) |
531 | 532 |
cmd.Long = explainLong |
... | ... |
@@ -556,6 +563,7 @@ to change to output destination. |
556 | 556 |
` |
557 | 557 |
) |
558 | 558 |
|
559 |
+// NewCmdConvert is a wrapper for the Kubernetes cli convert command |
|
559 | 560 |
func NewCmdConvert(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { |
560 | 561 |
cmd := kcmd.NewCmdConvert(f.Factory, out) |
561 | 562 |
cmd.Long = convertLong |
... | ... |
@@ -598,6 +606,7 @@ saved copy to include the latest resource version.` |
598 | 598 |
%[1]s edit svc/docker-registry --output-version=v1beta3 -o json` |
599 | 599 |
) |
600 | 600 |
|
601 |
+// NewCmdEdit is a wrapper for the Kubernetes cli edit command |
|
601 | 602 |
func NewCmdEdit(fullName string, f *clientcmd.Factory, out, errout io.Writer) *cobra.Command { |
602 | 603 |
cmd := kcmd.NewCmdEdit(f.Factory, out, errout) |
603 | 604 |
cmd.Long = editLong |
... | ... |
@@ -622,6 +631,7 @@ Reference: https://github.com/kubernetes/kubernetes/blob/master/docs/user-guide/ |
622 | 622 |
%[1]s %[2]s set preferences.some true` |
623 | 623 |
) |
624 | 624 |
|
625 |
+// NewCmdConfig is a wrapper for the Kubernetes cli config command |
|
625 | 626 |
func NewCmdConfig(parentName, name string) *cobra.Command { |
626 | 627 |
pathOptions := &kclientcmd.PathOptions{ |
627 | 628 |
GlobalFile: cmdconfig.RecommendedHomeFile, |
... | ... |
@@ -641,17 +651,3 @@ func NewCmdConfig(parentName, name string) *cobra.Command { |
641 | 641 |
adjustCmdExamples(cmd, parentName, name) |
642 | 642 |
return cmd |
643 | 643 |
} |
644 |
- |
|
645 |
-func adjustCmdExamples(cmd *cobra.Command, parentName string, name string) { |
|
646 |
- for _, subCmd := range cmd.Commands() { |
|
647 |
- adjustCmdExamples(subCmd, parentName, cmd.Name()) |
|
648 |
- } |
|
649 |
- cmd.Example = strings.Replace(cmd.Example, "kubectl", parentName, -1) |
|
650 |
- tabbing := " " |
|
651 |
- examples := []string{} |
|
652 |
- scanner := bufio.NewScanner(strings.NewReader(cmd.Example)) |
|
653 |
- for scanner.Scan() { |
|
654 |
- examples = append(examples, tabbing+strings.TrimSpace(scanner.Text())) |
|
655 |
- } |
|
656 |
- cmd.Example = strings.Join(examples, "\n") |
|
657 |
-} |