Browse code

oc: port rollout command from kubectl

Michail Kargakis authored on 2016/05/18 00:42:57
Showing 6 changed files
... ...
@@ -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
-}
... ...
@@ -23,7 +23,6 @@ var MissingCommands = sets.NewString(
23 23
 	"cordon",
24 24
 	"drain",
25 25
 	"uncordon",
26
-	"rollout",
27 26
 )
28 27
 
29 28
 // WhitelistedCommands is the list of commands we're never going to have in oc