Browse code

Implement an `oc extract` command to make it easy to use secrets

Makes running local workflows that depend on secrets and config maps
easier to test.

Clayton Coleman authored on 2016/06/22 08:37:10
Showing 19 changed files
... ...
@@ -9328,6 +9328,68 @@ _oc_export()
9328 9328
     noun_aliases=()
9329 9329
 }
9330 9330
 
9331
+_oc_extract()
9332
+{
9333
+    last_command="oc_extract"
9334
+    commands=()
9335
+
9336
+    flags=()
9337
+    two_word_flags=()
9338
+    flags_with_completion=()
9339
+    flags_completion=()
9340
+
9341
+    flags+=("--confirm")
9342
+    flags+=("--filename=")
9343
+    flags_with_completion+=("--filename")
9344
+    flags_completion+=("_filedir")
9345
+    two_word_flags+=("-f")
9346
+    flags_with_completion+=("-f")
9347
+    flags_completion+=("_filedir")
9348
+    flags+=("--keys=")
9349
+    flags+=("--no-headers")
9350
+    flags+=("--output=")
9351
+    two_word_flags+=("-o")
9352
+    flags+=("--output-version=")
9353
+    flags+=("--show-all")
9354
+    flags+=("-a")
9355
+    flags+=("--show-labels")
9356
+    flags+=("--sort-by=")
9357
+    flags+=("--template=")
9358
+    flags_with_completion+=("--template")
9359
+    flags_completion+=("_filedir")
9360
+    flags+=("--to=")
9361
+    flags+=("--api-version=")
9362
+    flags+=("--as=")
9363
+    flags+=("--certificate-authority=")
9364
+    flags_with_completion+=("--certificate-authority")
9365
+    flags_completion+=("_filedir")
9366
+    flags+=("--client-certificate=")
9367
+    flags_with_completion+=("--client-certificate")
9368
+    flags_completion+=("_filedir")
9369
+    flags+=("--client-key=")
9370
+    flags_with_completion+=("--client-key")
9371
+    flags_completion+=("_filedir")
9372
+    flags+=("--cluster=")
9373
+    flags+=("--config=")
9374
+    flags_with_completion+=("--config")
9375
+    flags_completion+=("_filedir")
9376
+    flags+=("--context=")
9377
+    flags+=("--insecure-skip-tls-verify")
9378
+    flags+=("--log-flush-frequency=")
9379
+    flags+=("--loglevel=")
9380
+    flags+=("--logspec=")
9381
+    flags+=("--match-server-version")
9382
+    flags+=("--namespace=")
9383
+    two_word_flags+=("-n")
9384
+    flags+=("--server=")
9385
+    flags+=("--token=")
9386
+    flags+=("--user=")
9387
+
9388
+    must_have_one_flag=()
9389
+    must_have_one_noun=()
9390
+    noun_aliases=()
9391
+}
9392
+
9331 9393
 _oc_policy_who-can()
9332 9394
 {
9333 9395
     last_command="oc_policy_who-can"
... ...
@@ -10830,6 +10892,7 @@ _oc()
10830 10830
     commands+=("patch")
10831 10831
     commands+=("process")
10832 10832
     commands+=("export")
10833
+    commands+=("extract")
10833 10834
     commands+=("policy")
10834 10835
     commands+=("convert")
10835 10836
     commands+=("import")
... ...
@@ -13634,6 +13634,69 @@ _openshift_cli_export()
13634 13634
     noun_aliases=()
13635 13635
 }
13636 13636
 
13637
+_openshift_cli_extract()
13638
+{
13639
+    last_command="openshift_cli_extract"
13640
+    commands=()
13641
+
13642
+    flags=()
13643
+    two_word_flags=()
13644
+    flags_with_completion=()
13645
+    flags_completion=()
13646
+
13647
+    flags+=("--confirm")
13648
+    flags+=("--filename=")
13649
+    flags_with_completion+=("--filename")
13650
+    flags_completion+=("_filedir")
13651
+    two_word_flags+=("-f")
13652
+    flags_with_completion+=("-f")
13653
+    flags_completion+=("_filedir")
13654
+    flags+=("--keys=")
13655
+    flags+=("--no-headers")
13656
+    flags+=("--output=")
13657
+    two_word_flags+=("-o")
13658
+    flags+=("--output-version=")
13659
+    flags+=("--show-all")
13660
+    flags+=("-a")
13661
+    flags+=("--show-labels")
13662
+    flags+=("--sort-by=")
13663
+    flags+=("--template=")
13664
+    flags_with_completion+=("--template")
13665
+    flags_completion+=("_filedir")
13666
+    flags+=("--to=")
13667
+    flags+=("--api-version=")
13668
+    flags+=("--as=")
13669
+    flags+=("--certificate-authority=")
13670
+    flags_with_completion+=("--certificate-authority")
13671
+    flags_completion+=("_filedir")
13672
+    flags+=("--client-certificate=")
13673
+    flags_with_completion+=("--client-certificate")
13674
+    flags_completion+=("_filedir")
13675
+    flags+=("--client-key=")
13676
+    flags_with_completion+=("--client-key")
13677
+    flags_completion+=("_filedir")
13678
+    flags+=("--cluster=")
13679
+    flags+=("--config=")
13680
+    flags_with_completion+=("--config")
13681
+    flags_completion+=("_filedir")
13682
+    flags+=("--context=")
13683
+    flags+=("--google-json-key=")
13684
+    flags+=("--insecure-skip-tls-verify")
13685
+    flags+=("--log-flush-frequency=")
13686
+    flags+=("--loglevel=")
13687
+    flags+=("--logspec=")
13688
+    flags+=("--match-server-version")
13689
+    flags+=("--namespace=")
13690
+    two_word_flags+=("-n")
13691
+    flags+=("--server=")
13692
+    flags+=("--token=")
13693
+    flags+=("--user=")
13694
+
13695
+    must_have_one_flag=()
13696
+    must_have_one_noun=()
13697
+    noun_aliases=()
13698
+}
13699
+
13637 13700
 _openshift_cli_policy_who-can()
13638 13701
 {
13639 13702
     last_command="openshift_cli_policy_who-can"
... ...
@@ -15124,6 +15187,7 @@ _openshift_cli()
15124 15124
     commands+=("patch")
15125 15125
     commands+=("process")
15126 15126
     commands+=("export")
15127
+    commands+=("extract")
15127 15128
     commands+=("policy")
15128 15129
     commands+=("convert")
15129 15130
     commands+=("import")
... ...
@@ -9489,6 +9489,68 @@ _oc_export()
9489 9489
     noun_aliases=()
9490 9490
 }
9491 9491
 
9492
+_oc_extract()
9493
+{
9494
+    last_command="oc_extract"
9495
+    commands=()
9496
+
9497
+    flags=()
9498
+    two_word_flags=()
9499
+    flags_with_completion=()
9500
+    flags_completion=()
9501
+
9502
+    flags+=("--confirm")
9503
+    flags+=("--filename=")
9504
+    flags_with_completion+=("--filename")
9505
+    flags_completion+=("_filedir")
9506
+    two_word_flags+=("-f")
9507
+    flags_with_completion+=("-f")
9508
+    flags_completion+=("_filedir")
9509
+    flags+=("--keys=")
9510
+    flags+=("--no-headers")
9511
+    flags+=("--output=")
9512
+    two_word_flags+=("-o")
9513
+    flags+=("--output-version=")
9514
+    flags+=("--show-all")
9515
+    flags+=("-a")
9516
+    flags+=("--show-labels")
9517
+    flags+=("--sort-by=")
9518
+    flags+=("--template=")
9519
+    flags_with_completion+=("--template")
9520
+    flags_completion+=("_filedir")
9521
+    flags+=("--to=")
9522
+    flags+=("--api-version=")
9523
+    flags+=("--as=")
9524
+    flags+=("--certificate-authority=")
9525
+    flags_with_completion+=("--certificate-authority")
9526
+    flags_completion+=("_filedir")
9527
+    flags+=("--client-certificate=")
9528
+    flags_with_completion+=("--client-certificate")
9529
+    flags_completion+=("_filedir")
9530
+    flags+=("--client-key=")
9531
+    flags_with_completion+=("--client-key")
9532
+    flags_completion+=("_filedir")
9533
+    flags+=("--cluster=")
9534
+    flags+=("--config=")
9535
+    flags_with_completion+=("--config")
9536
+    flags_completion+=("_filedir")
9537
+    flags+=("--context=")
9538
+    flags+=("--insecure-skip-tls-verify")
9539
+    flags+=("--log-flush-frequency=")
9540
+    flags+=("--loglevel=")
9541
+    flags+=("--logspec=")
9542
+    flags+=("--match-server-version")
9543
+    flags+=("--namespace=")
9544
+    two_word_flags+=("-n")
9545
+    flags+=("--server=")
9546
+    flags+=("--token=")
9547
+    flags+=("--user=")
9548
+
9549
+    must_have_one_flag=()
9550
+    must_have_one_noun=()
9551
+    noun_aliases=()
9552
+}
9553
+
9492 9554
 _oc_policy_who-can()
9493 9555
 {
9494 9556
     last_command="oc_policy_who-can"
... ...
@@ -10991,6 +11053,7 @@ _oc()
10991 10991
     commands+=("patch")
10992 10992
     commands+=("process")
10993 10993
     commands+=("export")
10994
+    commands+=("extract")
10994 10995
     commands+=("policy")
10995 10996
     commands+=("convert")
10996 10997
     commands+=("import")
... ...
@@ -13795,6 +13795,69 @@ _openshift_cli_export()
13795 13795
     noun_aliases=()
13796 13796
 }
13797 13797
 
13798
+_openshift_cli_extract()
13799
+{
13800
+    last_command="openshift_cli_extract"
13801
+    commands=()
13802
+
13803
+    flags=()
13804
+    two_word_flags=()
13805
+    flags_with_completion=()
13806
+    flags_completion=()
13807
+
13808
+    flags+=("--confirm")
13809
+    flags+=("--filename=")
13810
+    flags_with_completion+=("--filename")
13811
+    flags_completion+=("_filedir")
13812
+    two_word_flags+=("-f")
13813
+    flags_with_completion+=("-f")
13814
+    flags_completion+=("_filedir")
13815
+    flags+=("--keys=")
13816
+    flags+=("--no-headers")
13817
+    flags+=("--output=")
13818
+    two_word_flags+=("-o")
13819
+    flags+=("--output-version=")
13820
+    flags+=("--show-all")
13821
+    flags+=("-a")
13822
+    flags+=("--show-labels")
13823
+    flags+=("--sort-by=")
13824
+    flags+=("--template=")
13825
+    flags_with_completion+=("--template")
13826
+    flags_completion+=("_filedir")
13827
+    flags+=("--to=")
13828
+    flags+=("--api-version=")
13829
+    flags+=("--as=")
13830
+    flags+=("--certificate-authority=")
13831
+    flags_with_completion+=("--certificate-authority")
13832
+    flags_completion+=("_filedir")
13833
+    flags+=("--client-certificate=")
13834
+    flags_with_completion+=("--client-certificate")
13835
+    flags_completion+=("_filedir")
13836
+    flags+=("--client-key=")
13837
+    flags_with_completion+=("--client-key")
13838
+    flags_completion+=("_filedir")
13839
+    flags+=("--cluster=")
13840
+    flags+=("--config=")
13841
+    flags_with_completion+=("--config")
13842
+    flags_completion+=("_filedir")
13843
+    flags+=("--context=")
13844
+    flags+=("--google-json-key=")
13845
+    flags+=("--insecure-skip-tls-verify")
13846
+    flags+=("--log-flush-frequency=")
13847
+    flags+=("--loglevel=")
13848
+    flags+=("--logspec=")
13849
+    flags+=("--match-server-version")
13850
+    flags+=("--namespace=")
13851
+    two_word_flags+=("-n")
13852
+    flags+=("--server=")
13853
+    flags+=("--token=")
13854
+    flags+=("--user=")
13855
+
13856
+    must_have_one_flag=()
13857
+    must_have_one_noun=()
13858
+    noun_aliases=()
13859
+}
13860
+
13798 13861
 _openshift_cli_policy_who-can()
13799 13862
 {
13800 13863
     last_command="openshift_cli_policy_who-can"
... ...
@@ -15285,6 +15348,7 @@ _openshift_cli()
15285 15285
     commands+=("patch")
15286 15286
     commands+=("process")
15287 15287
     commands+=("export")
15288
+    commands+=("extract")
15288 15289
     commands+=("policy")
15289 15290
     commands+=("convert")
15290 15291
     commands+=("import")
... ...
@@ -1428,6 +1428,25 @@ Expose a replicated application as a service or route
1428 1428
 ====
1429 1429
 
1430 1430
 
1431
+== oc extract
1432
+Extract secrets or config maps to disk
1433
+
1434
+====
1435
+
1436
+[options="nowrap"]
1437
+----
1438
+  # extract the secret "test" to the current directory
1439
+  oc extract secret/test
1440
+
1441
+  # extract the config map "nginx" to the /tmp directory
1442
+  oc extract configmap/nginx --to=/tmp
1443
+
1444
+  # extract only the key "nginx.conf" from config map "nginx" to the /tmp directory
1445
+  oc extract configmap/nginx --to=/tmp --keys=nginx.conf
1446
+----
1447
+====
1448
+
1449
+
1431 1450
 == oc get
1432 1451
 Display one or many resources
1433 1452
 
... ...
@@ -125,6 +125,7 @@ oc-exec.1
125 125
 oc-explain.1
126 126
 oc-export.1
127 127
 oc-expose.1
128
+oc-extract.1
128 129
 oc-get.1
129 130
 oc-import-app.json.1
130 131
 oc-import-docker-compose.1
... ...
@@ -201,6 +201,7 @@ openshift-cli-exec.1
201 201
 openshift-cli-explain.1
202 202
 openshift-cli-export.1
203 203
 openshift-cli-expose.1
204
+openshift-cli-extract.1
204 205
 openshift-cli-get.1
205 206
 openshift-cli-import-app.json.1
206 207
 openshift-cli-import-docker-compose.1
... ...
@@ -52,7 +52,7 @@ to generate the API structure for a template to which you can add parameters and
52 52
 
53 53
 .PP
54 54
 \fB\-f\fP, \fB\-\-filename\fP=[]
55
-    Filename, directory, or URL to file to use to edit the resource.
55
+    Filename, directory, or URL to file for the resource to export.
56 56
 
57 57
 .PP
58 58
 \fB\-\-no\-headers\fP=false
59 59
new file mode 100644
... ...
@@ -0,0 +1,168 @@
0
+.TH "OC" "1" " Openshift CLI User Manuals" "Openshift" "June 2016"  ""
1
+
2
+
3
+.SH NAME
4
+.PP
5
+oc extract \- Extract secrets or config maps to disk
6
+
7
+
8
+.SH SYNOPSIS
9
+.PP
10
+\fBoc extract\fP [OPTIONS]
11
+
12
+
13
+.SH DESCRIPTION
14
+.PP
15
+Extract files out of secrets and config maps
16
+
17
+.PP
18
+The extract command makes it easy to download the contents of a config map or secret into a directory.
19
+Each key in the config map or secret is created as a separate file with the name of the key, as it
20
+is when you mount a secret or config map into a container.
21
+
22
+.PP
23
+You can limit which keys are extracted with the \-\-only=NAME flag, or set the directory to extract to
24
+with \-\-to=DIRECTORY.
25
+
26
+
27
+.SH OPTIONS
28
+.PP
29
+\fB\-\-confirm\fP=false
30
+    Overwrite files that already exist.
31
+
32
+.PP
33
+\fB\-f\fP, \fB\-\-filename\fP=[]
34
+    Filename, directory, or URL to file to identify to extract the resource.
35
+
36
+.PP
37
+\fB\-\-keys\fP=[]
38
+    An optional list of keys to extract (default is all keys).
39
+
40
+.PP
41
+\fB\-\-no\-headers\fP=false
42
+    When using the default output, don't print headers.
43
+
44
+.PP
45
+\fB\-o\fP, \fB\-\-output\fP=""
46
+    Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
47
+\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
48
+\[la]http://releases.k8s.io/release-1.3/docs/user-guide/jsonpath.md\[ra]].
49
+
50
+.PP
51
+\fB\-\-output\-version\fP=""
52
+    Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
53
+
54
+.PP
55
+\fB\-a\fP, \fB\-\-show\-all\fP=true
56
+    When printing, show all resources (false means hide terminated pods.)
57
+
58
+.PP
59
+\fB\-\-show\-labels\fP=false
60
+    When printing, show all labels as the last column (default hide labels column)
61
+
62
+.PP
63
+\fB\-\-sort\-by\fP=""
64
+    If non\-empty, sort list types using this field specification.  The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
65
+
66
+.PP
67
+\fB\-\-template\fP=""
68
+    Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [
69
+\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]].
70
+
71
+.PP
72
+\fB\-\-to\fP=""
73
+    Directory to extract files to.
74
+
75
+
76
+.SH OPTIONS INHERITED FROM PARENT COMMANDS
77
+.PP
78
+\fB\-\-api\-version\fP=""
79
+    DEPRECATED: The API version to use when talking to the server
80
+
81
+.PP
82
+\fB\-\-as\fP=""
83
+    Username to impersonate for the operation.
84
+
85
+.PP
86
+\fB\-\-certificate\-authority\fP=""
87
+    Path to a cert. file for the certificate authority.
88
+
89
+.PP
90
+\fB\-\-client\-certificate\fP=""
91
+    Path to a client certificate file for TLS.
92
+
93
+.PP
94
+\fB\-\-client\-key\fP=""
95
+    Path to a client key file for TLS.
96
+
97
+.PP
98
+\fB\-\-cluster\fP=""
99
+    The name of the kubeconfig cluster to use
100
+
101
+.PP
102
+\fB\-\-config\fP=""
103
+    Path to the config file to use for CLI requests.
104
+
105
+.PP
106
+\fB\-\-context\fP=""
107
+    The name of the kubeconfig context to use
108
+
109
+.PP
110
+\fB\-\-google\-json\-key\fP=""
111
+    The Google Cloud Platform Service Account JSON Key to use for authentication.
112
+
113
+.PP
114
+\fB\-\-insecure\-skip\-tls\-verify\fP=false
115
+    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
116
+
117
+.PP
118
+\fB\-\-log\-flush\-frequency\fP=0
119
+    Maximum number of seconds between log flushes
120
+
121
+.PP
122
+\fB\-\-match\-server\-version\fP=false
123
+    Require server version to match client version
124
+
125
+.PP
126
+\fB\-n\fP, \fB\-\-namespace\fP=""
127
+    If present, the namespace scope for this CLI request.
128
+
129
+.PP
130
+\fB\-\-server\fP=""
131
+    The address and port of the Kubernetes API server
132
+
133
+.PP
134
+\fB\-\-token\fP=""
135
+    Bearer token for authentication to the API server.
136
+
137
+.PP
138
+\fB\-\-user\fP=""
139
+    The name of the kubeconfig user to use
140
+
141
+
142
+.SH EXAMPLE
143
+.PP
144
+.RS
145
+
146
+.nf
147
+  # extract the secret "test" to the current directory
148
+  oc extract secret/test
149
+
150
+  # extract the config map "nginx" to the /tmp directory
151
+  oc extract configmap/nginx \-\-to=/tmp
152
+
153
+  # extract only the key "nginx.conf" from config map "nginx" to the /tmp directory
154
+  oc extract configmap/nginx \-\-to=/tmp \-\-keys=nginx.conf
155
+
156
+.fi
157
+.RE
158
+
159
+
160
+.SH SEE ALSO
161
+.PP
162
+\fBoc(1)\fP,
163
+
164
+
165
+.SH HISTORY
166
+.PP
167
+June 2016, Ported from the Kubernetes man\-doc generator
... ...
@@ -89,7 +89,7 @@ cluster under the 'adm' subcommand.
89 89
 
90 90
 .SH SEE ALSO
91 91
 .PP
92
-\fBoc\-types(1)\fP, \fBoc\-login(1)\fP, \fBoc\-new\-project(1)\fP, \fBoc\-new\-app(1)\fP, \fBoc\-status(1)\fP, \fBoc\-project(1)\fP, \fBoc\-projects(1)\fP, \fBoc\-explain(1)\fP, \fBoc\-cluster(1)\fP, \fBoc\-rollout(1)\fP, \fBoc\-deploy(1)\fP, \fBoc\-rollback(1)\fP, \fBoc\-new\-build(1)\fP, \fBoc\-start\-build(1)\fP, \fBoc\-cancel\-build(1)\fP, \fBoc\-import\-image(1)\fP, \fBoc\-tag(1)\fP, \fBoc\-get(1)\fP, \fBoc\-describe(1)\fP, \fBoc\-edit(1)\fP, \fBoc\-set(1)\fP, \fBoc\-label(1)\fP, \fBoc\-annotate(1)\fP, \fBoc\-expose(1)\fP, \fBoc\-delete(1)\fP, \fBoc\-scale(1)\fP, \fBoc\-autoscale(1)\fP, \fBoc\-secrets(1)\fP, \fBoc\-serviceaccounts(1)\fP, \fBoc\-logs(1)\fP, \fBoc\-rsh(1)\fP, \fBoc\-rsync(1)\fP, \fBoc\-port\-forward(1)\fP, \fBoc\-debug(1)\fP, \fBoc\-exec(1)\fP, \fBoc\-proxy(1)\fP, \fBoc\-attach(1)\fP, \fBoc\-run(1)\fP, \fBoc\-adm(1)\fP, \fBoc\-create(1)\fP, \fBoc\-replace(1)\fP, \fBoc\-apply(1)\fP, \fBoc\-patch(1)\fP, \fBoc\-process(1)\fP, \fBoc\-export(1)\fP, \fBoc\-policy(1)\fP, \fBoc\-convert(1)\fP, \fBoc\-import(1)\fP, \fBoc\-logout(1)\fP, \fBoc\-config(1)\fP, \fBoc\-whoami(1)\fP, \fBoc\-completion(1)\fP, \fBoc\-env(1)\fP, \fBoc\-volumes(1)\fP, \fBoc\-build\-logs(1)\fP, \fBoc\-ex(1)\fP, \fBoc\-version(1)\fP, \fBoc\-options(1)\fP,
92
+\fBoc\-types(1)\fP, \fBoc\-login(1)\fP, \fBoc\-new\-project(1)\fP, \fBoc\-new\-app(1)\fP, \fBoc\-status(1)\fP, \fBoc\-project(1)\fP, \fBoc\-projects(1)\fP, \fBoc\-explain(1)\fP, \fBoc\-cluster(1)\fP, \fBoc\-rollout(1)\fP, \fBoc\-deploy(1)\fP, \fBoc\-rollback(1)\fP, \fBoc\-new\-build(1)\fP, \fBoc\-start\-build(1)\fP, \fBoc\-cancel\-build(1)\fP, \fBoc\-import\-image(1)\fP, \fBoc\-tag(1)\fP, \fBoc\-get(1)\fP, \fBoc\-describe(1)\fP, \fBoc\-edit(1)\fP, \fBoc\-set(1)\fP, \fBoc\-label(1)\fP, \fBoc\-annotate(1)\fP, \fBoc\-expose(1)\fP, \fBoc\-delete(1)\fP, \fBoc\-scale(1)\fP, \fBoc\-autoscale(1)\fP, \fBoc\-secrets(1)\fP, \fBoc\-serviceaccounts(1)\fP, \fBoc\-logs(1)\fP, \fBoc\-rsh(1)\fP, \fBoc\-rsync(1)\fP, \fBoc\-port\-forward(1)\fP, \fBoc\-debug(1)\fP, \fBoc\-exec(1)\fP, \fBoc\-proxy(1)\fP, \fBoc\-attach(1)\fP, \fBoc\-run(1)\fP, \fBoc\-adm(1)\fP, \fBoc\-create(1)\fP, \fBoc\-replace(1)\fP, \fBoc\-apply(1)\fP, \fBoc\-patch(1)\fP, \fBoc\-process(1)\fP, \fBoc\-export(1)\fP, \fBoc\-extract(1)\fP, \fBoc\-policy(1)\fP, \fBoc\-convert(1)\fP, \fBoc\-import(1)\fP, \fBoc\-logout(1)\fP, \fBoc\-config(1)\fP, \fBoc\-whoami(1)\fP, \fBoc\-completion(1)\fP, \fBoc\-env(1)\fP, \fBoc\-volumes(1)\fP, \fBoc\-build\-logs(1)\fP, \fBoc\-ex(1)\fP, \fBoc\-version(1)\fP, \fBoc\-options(1)\fP,
93 93
 
94 94
 
95 95
 .SH HISTORY
... ...
@@ -52,7 +52,7 @@ to generate the API structure for a template to which you can add parameters and
52 52
 
53 53
 .PP
54 54
 \fB\-f\fP, \fB\-\-filename\fP=[]
55
-    Filename, directory, or URL to file to use to edit the resource.
55
+    Filename, directory, or URL to file for the resource to export.
56 56
 
57 57
 .PP
58 58
 \fB\-\-no\-headers\fP=false
59 59
new file mode 100644
... ...
@@ -0,0 +1,168 @@
0
+.TH "OPENSHIFT CLI" "1" " Openshift CLI User Manuals" "Openshift" "June 2016"  ""
1
+
2
+
3
+.SH NAME
4
+.PP
5
+openshift cli extract \- Extract secrets or config maps to disk
6
+
7
+
8
+.SH SYNOPSIS
9
+.PP
10
+\fBopenshift cli extract\fP [OPTIONS]
11
+
12
+
13
+.SH DESCRIPTION
14
+.PP
15
+Extract files out of secrets and config maps
16
+
17
+.PP
18
+The extract command makes it easy to download the contents of a config map or secret into a directory.
19
+Each key in the config map or secret is created as a separate file with the name of the key, as it
20
+is when you mount a secret or config map into a container.
21
+
22
+.PP
23
+You can limit which keys are extracted with the \-\-only=NAME flag, or set the directory to extract to
24
+with \-\-to=DIRECTORY.
25
+
26
+
27
+.SH OPTIONS
28
+.PP
29
+\fB\-\-confirm\fP=false
30
+    Overwrite files that already exist.
31
+
32
+.PP
33
+\fB\-f\fP, \fB\-\-filename\fP=[]
34
+    Filename, directory, or URL to file to identify to extract the resource.
35
+
36
+.PP
37
+\fB\-\-keys\fP=[]
38
+    An optional list of keys to extract (default is all keys).
39
+
40
+.PP
41
+\fB\-\-no\-headers\fP=false
42
+    When using the default output, don't print headers.
43
+
44
+.PP
45
+\fB\-o\fP, \fB\-\-output\fP=""
46
+    Output format. One of: json|yaml|wide|name|go\-template=...|go\-template\-file=...|jsonpath=...|jsonpath\-file=... See golang template [
47
+\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] and jsonpath template [
48
+\[la]http://releases.k8s.io/release-1.3/docs/user-guide/jsonpath.md\[ra]].
49
+
50
+.PP
51
+\fB\-\-output\-version\fP=""
52
+    Output the formatted object with the given group version (for ex: 'extensions/v1beta1').
53
+
54
+.PP
55
+\fB\-a\fP, \fB\-\-show\-all\fP=true
56
+    When printing, show all resources (false means hide terminated pods.)
57
+
58
+.PP
59
+\fB\-\-show\-labels\fP=false
60
+    When printing, show all labels as the last column (default hide labels column)
61
+
62
+.PP
63
+\fB\-\-sort\-by\fP=""
64
+    If non\-empty, sort list types using this field specification.  The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
65
+
66
+.PP
67
+\fB\-\-template\fP=""
68
+    Template string or path to template file to use when \-o=go\-template, \-o=go\-template\-file. The template format is golang templates [
69
+\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]].
70
+
71
+.PP
72
+\fB\-\-to\fP=""
73
+    Directory to extract files to.
74
+
75
+
76
+.SH OPTIONS INHERITED FROM PARENT COMMANDS
77
+.PP
78
+\fB\-\-api\-version\fP=""
79
+    DEPRECATED: The API version to use when talking to the server
80
+
81
+.PP
82
+\fB\-\-as\fP=""
83
+    Username to impersonate for the operation.
84
+
85
+.PP
86
+\fB\-\-certificate\-authority\fP=""
87
+    Path to a cert. file for the certificate authority.
88
+
89
+.PP
90
+\fB\-\-client\-certificate\fP=""
91
+    Path to a client certificate file for TLS.
92
+
93
+.PP
94
+\fB\-\-client\-key\fP=""
95
+    Path to a client key file for TLS.
96
+
97
+.PP
98
+\fB\-\-cluster\fP=""
99
+    The name of the kubeconfig cluster to use
100
+
101
+.PP
102
+\fB\-\-config\fP=""
103
+    Path to the config file to use for CLI requests.
104
+
105
+.PP
106
+\fB\-\-context\fP=""
107
+    The name of the kubeconfig context to use
108
+
109
+.PP
110
+\fB\-\-google\-json\-key\fP=""
111
+    The Google Cloud Platform Service Account JSON Key to use for authentication.
112
+
113
+.PP
114
+\fB\-\-insecure\-skip\-tls\-verify\fP=false
115
+    If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
116
+
117
+.PP
118
+\fB\-\-log\-flush\-frequency\fP=0
119
+    Maximum number of seconds between log flushes
120
+
121
+.PP
122
+\fB\-\-match\-server\-version\fP=false
123
+    Require server version to match client version
124
+
125
+.PP
126
+\fB\-n\fP, \fB\-\-namespace\fP=""
127
+    If present, the namespace scope for this CLI request.
128
+
129
+.PP
130
+\fB\-\-server\fP=""
131
+    The address and port of the Kubernetes API server
132
+
133
+.PP
134
+\fB\-\-token\fP=""
135
+    Bearer token for authentication to the API server.
136
+
137
+.PP
138
+\fB\-\-user\fP=""
139
+    The name of the kubeconfig user to use
140
+
141
+
142
+.SH EXAMPLE
143
+.PP
144
+.RS
145
+
146
+.nf
147
+  # extract the secret "test" to the current directory
148
+  openshift cli extract secret/test
149
+
150
+  # extract the config map "nginx" to the /tmp directory
151
+  openshift cli extract configmap/nginx \-\-to=/tmp
152
+
153
+  # extract only the key "nginx.conf" from config map "nginx" to the /tmp directory
154
+  openshift cli extract configmap/nginx \-\-to=/tmp \-\-keys=nginx.conf
155
+
156
+.fi
157
+.RE
158
+
159
+
160
+.SH SEE ALSO
161
+.PP
162
+\fBopenshift\-cli(1)\fP,
163
+
164
+
165
+.SH HISTORY
166
+.PP
167
+June 2016, Ported from the Kubernetes man\-doc generator
... ...
@@ -91,7 +91,7 @@ cluster under the 'adm' subcommand.
91 91
 
92 92
 .SH SEE ALSO
93 93
 .PP
94
-\fBopenshift(1)\fP, \fBopenshift\-cli\-types(1)\fP, \fBopenshift\-cli\-login(1)\fP, \fBopenshift\-cli\-new\-project(1)\fP, \fBopenshift\-cli\-new\-app(1)\fP, \fBopenshift\-cli\-status(1)\fP, \fBopenshift\-cli\-project(1)\fP, \fBopenshift\-cli\-projects(1)\fP, \fBopenshift\-cli\-explain(1)\fP, \fBopenshift\-cli\-cluster(1)\fP, \fBopenshift\-cli\-rollout(1)\fP, \fBopenshift\-cli\-deploy(1)\fP, \fBopenshift\-cli\-rollback(1)\fP, \fBopenshift\-cli\-new\-build(1)\fP, \fBopenshift\-cli\-start\-build(1)\fP, \fBopenshift\-cli\-cancel\-build(1)\fP, \fBopenshift\-cli\-import\-image(1)\fP, \fBopenshift\-cli\-tag(1)\fP, \fBopenshift\-cli\-get(1)\fP, \fBopenshift\-cli\-describe(1)\fP, \fBopenshift\-cli\-edit(1)\fP, \fBopenshift\-cli\-set(1)\fP, \fBopenshift\-cli\-label(1)\fP, \fBopenshift\-cli\-annotate(1)\fP, \fBopenshift\-cli\-expose(1)\fP, \fBopenshift\-cli\-delete(1)\fP, \fBopenshift\-cli\-scale(1)\fP, \fBopenshift\-cli\-autoscale(1)\fP, \fBopenshift\-cli\-secrets(1)\fP, \fBopenshift\-cli\-serviceaccounts(1)\fP, \fBopenshift\-cli\-logs(1)\fP, \fBopenshift\-cli\-rsh(1)\fP, \fBopenshift\-cli\-rsync(1)\fP, \fBopenshift\-cli\-port\-forward(1)\fP, \fBopenshift\-cli\-debug(1)\fP, \fBopenshift\-cli\-exec(1)\fP, \fBopenshift\-cli\-proxy(1)\fP, \fBopenshift\-cli\-attach(1)\fP, \fBopenshift\-cli\-run(1)\fP, \fBopenshift\-cli\-adm(1)\fP, \fBopenshift\-cli\-create(1)\fP, \fBopenshift\-cli\-replace(1)\fP, \fBopenshift\-cli\-apply(1)\fP, \fBopenshift\-cli\-patch(1)\fP, \fBopenshift\-cli\-process(1)\fP, \fBopenshift\-cli\-export(1)\fP, \fBopenshift\-cli\-policy(1)\fP, \fBopenshift\-cli\-convert(1)\fP, \fBopenshift\-cli\-import(1)\fP, \fBopenshift\-cli\-logout(1)\fP, \fBopenshift\-cli\-config(1)\fP, \fBopenshift\-cli\-whoami(1)\fP, \fBopenshift\-cli\-completion(1)\fP, \fBopenshift\-cli\-env(1)\fP, \fBopenshift\-cli\-volumes(1)\fP, \fBopenshift\-cli\-build\-logs(1)\fP, \fBopenshift\-cli\-ex(1)\fP, \fBopenshift\-cli\-options(1)\fP,
94
+\fBopenshift(1)\fP, \fBopenshift\-cli\-types(1)\fP, \fBopenshift\-cli\-login(1)\fP, \fBopenshift\-cli\-new\-project(1)\fP, \fBopenshift\-cli\-new\-app(1)\fP, \fBopenshift\-cli\-status(1)\fP, \fBopenshift\-cli\-project(1)\fP, \fBopenshift\-cli\-projects(1)\fP, \fBopenshift\-cli\-explain(1)\fP, \fBopenshift\-cli\-cluster(1)\fP, \fBopenshift\-cli\-rollout(1)\fP, \fBopenshift\-cli\-deploy(1)\fP, \fBopenshift\-cli\-rollback(1)\fP, \fBopenshift\-cli\-new\-build(1)\fP, \fBopenshift\-cli\-start\-build(1)\fP, \fBopenshift\-cli\-cancel\-build(1)\fP, \fBopenshift\-cli\-import\-image(1)\fP, \fBopenshift\-cli\-tag(1)\fP, \fBopenshift\-cli\-get(1)\fP, \fBopenshift\-cli\-describe(1)\fP, \fBopenshift\-cli\-edit(1)\fP, \fBopenshift\-cli\-set(1)\fP, \fBopenshift\-cli\-label(1)\fP, \fBopenshift\-cli\-annotate(1)\fP, \fBopenshift\-cli\-expose(1)\fP, \fBopenshift\-cli\-delete(1)\fP, \fBopenshift\-cli\-scale(1)\fP, \fBopenshift\-cli\-autoscale(1)\fP, \fBopenshift\-cli\-secrets(1)\fP, \fBopenshift\-cli\-serviceaccounts(1)\fP, \fBopenshift\-cli\-logs(1)\fP, \fBopenshift\-cli\-rsh(1)\fP, \fBopenshift\-cli\-rsync(1)\fP, \fBopenshift\-cli\-port\-forward(1)\fP, \fBopenshift\-cli\-debug(1)\fP, \fBopenshift\-cli\-exec(1)\fP, \fBopenshift\-cli\-proxy(1)\fP, \fBopenshift\-cli\-attach(1)\fP, \fBopenshift\-cli\-run(1)\fP, \fBopenshift\-cli\-adm(1)\fP, \fBopenshift\-cli\-create(1)\fP, \fBopenshift\-cli\-replace(1)\fP, \fBopenshift\-cli\-apply(1)\fP, \fBopenshift\-cli\-patch(1)\fP, \fBopenshift\-cli\-process(1)\fP, \fBopenshift\-cli\-export(1)\fP, \fBopenshift\-cli\-extract(1)\fP, \fBopenshift\-cli\-policy(1)\fP, \fBopenshift\-cli\-convert(1)\fP, \fBopenshift\-cli\-import(1)\fP, \fBopenshift\-cli\-logout(1)\fP, \fBopenshift\-cli\-config(1)\fP, \fBopenshift\-cli\-whoami(1)\fP, \fBopenshift\-cli\-completion(1)\fP, \fBopenshift\-cli\-env(1)\fP, \fBopenshift\-cli\-volumes(1)\fP, \fBopenshift\-cli\-build\-logs(1)\fP, \fBopenshift\-cli\-ex(1)\fP, \fBopenshift\-cli\-options(1)\fP,
95 95
 
96 96
 
97 97
 .SH HISTORY
... ...
@@ -9,6 +9,8 @@ set -o pipefail
9 9
 OS_ROOT=$(dirname "${BASH_SOURCE}")/..
10 10
 source "${OS_ROOT}/hack/lib/init.sh"
11 11
 
12
+cd ${OS_ROOT}
13
+
12 14
 # ensure we have the latest compiled binaries
13 15
 "${OS_ROOT}/hack/build-go.sh"
14 16
 
... ...
@@ -17,8 +19,6 @@ if [[ "${platform}" != "linux/amd64" ]]; then
17 17
   echo "WARNING: Generating completions on ${platform} may not be identical to running on linux/amd64 due to conditional compilation."
18 18
 fi
19 19
 
20
-#"${OS_ROOT}/hack/build-go.sh" tools/genbashcomp
21
-
22 20
 OUTPUT_REL_DIR=${1:-""}
23 21
 OUTPUT_DIR_ROOT="${OS_ROOT}/${OUTPUT_REL_DIR}/contrib/completions"
24 22
 
... ...
@@ -157,6 +157,7 @@ func NewCommandCLI(name, fullName string, in io.Reader, out, errout io.Writer) *
157 157
 				cmd.NewCmdPatch(fullName, f, out),
158 158
 				cmd.NewCmdProcess(fullName, f, out),
159 159
 				cmd.NewCmdExport(fullName, f, in, out),
160
+				cmd.NewCmdExtract(fullName, f, in, out, errout),
160 161
 				policy.NewCmdPolicy(policy.PolicyRecommendedName, fullName+" "+policy.PolicyRecommendedName, f, out),
161 162
 				cmd.NewCmdConvert(fullName, f, out),
162 163
 				importer.NewCmdImport(fullName, f, in, out, errout),
... ...
@@ -68,7 +68,7 @@ func NewCmdExport(fullName string, f *clientcmd.Factory, in io.Reader, out io.Wr
68 68
 	cmd.Flags().Bool("raw", false, "If true, do not alter the resources in any way after they are loaded.")
69 69
 	cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
70 70
 	cmd.Flags().Bool("all-namespaces", false, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
71
-	cmd.Flags().StringSliceVarP(&filenames, "filename", "f", filenames, "Filename, directory, or URL to file to use to edit the resource.")
71
+	cmd.Flags().StringSliceVarP(&filenames, "filename", "f", filenames, "Filename, directory, or URL to file for the resource to export.")
72 72
 	cmd.MarkFlagFilename("filename")
73 73
 	cmd.Flags().Bool("all", true, "DEPRECATED: all is ignored, specifying a resource without a name selects all the instances of that resource")
74 74
 	cmd.Flags().MarkDeprecated("all", "all is ignored because specifying a resource without a name selects all the instances of that resource")
75 75
new file mode 100644
... ...
@@ -0,0 +1,174 @@
0
+package cmd
1
+
2
+import (
3
+	"bytes"
4
+	"fmt"
5
+	"io"
6
+	"io/ioutil"
7
+	"os"
8
+	"path/filepath"
9
+
10
+	"github.com/spf13/cobra"
11
+
12
+	kapi "k8s.io/kubernetes/pkg/api"
13
+	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
14
+	"k8s.io/kubernetes/pkg/kubectl/resource"
15
+	"k8s.io/kubernetes/pkg/runtime"
16
+	"k8s.io/kubernetes/pkg/util/sets"
17
+
18
+	cmdutil "github.com/openshift/origin/pkg/cmd/util"
19
+	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
20
+)
21
+
22
+const (
23
+	extractLong = `
24
+Extract files out of secrets and config maps
25
+
26
+The extract command makes it easy to download the contents of a config map or secret into a directory.
27
+Each key in the config map or secret is created as a separate file with the name of the key, as it
28
+is when you mount a secret or config map into a container.
29
+
30
+You can limit which keys are extracted with the --only=NAME flag, or set the directory to extract to
31
+with --to=DIRECTORY.`
32
+
33
+	extractExample = `  # extract the secret "test" to the current directory
34
+  %[1]s extract secret/test
35
+
36
+  # extract the config map "nginx" to the /tmp directory
37
+  %[1]s extract configmap/nginx --to=/tmp
38
+
39
+  # extract only the key "nginx.conf" from config map "nginx" to the /tmp directory
40
+  %[1]s extract configmap/nginx --to=/tmp --keys=nginx.conf`
41
+)
42
+
43
+type ExtractOptions struct {
44
+	Out, Err        io.Writer
45
+	Filenames       []string
46
+	OnlyKeys        []string
47
+	TargetDirectory string
48
+	Overwrite       bool
49
+
50
+	VisitorFn             func(resource.VisitorFunc) error
51
+	ExtractFileContentsFn func(runtime.Object) (map[string][]byte, bool, error)
52
+}
53
+
54
+func NewCmdExtract(fullName string, f *clientcmd.Factory, in io.Reader, out, errOut io.Writer) *cobra.Command {
55
+	options := &ExtractOptions{
56
+		Out: out,
57
+		Err: errOut,
58
+	}
59
+	cmd := &cobra.Command{
60
+		Use:     "extract RESOURCE/NAME [--to=DIRECTORY] [--keys=KEY ...]",
61
+		Short:   "Extract secrets or config maps to disk",
62
+		Long:    extractLong,
63
+		Example: fmt.Sprintf(extractExample, fullName),
64
+		Run: func(cmd *cobra.Command, args []string) {
65
+			kcmdutil.CheckErr(options.Complete(f, in, out, cmd, args))
66
+			kcmdutil.CheckErr(options.Validate())
67
+			err := options.Run()
68
+			if err == cmdutil.ErrExit {
69
+				os.Exit(1)
70
+			}
71
+			kcmdutil.CheckErr(err)
72
+		},
73
+	}
74
+	cmd.Flags().BoolVar(&options.Overwrite, "confirm", options.Overwrite, "Overwrite files that already exist.")
75
+	cmd.Flags().StringVar(&options.TargetDirectory, "to", options.TargetDirectory, "Directory to extract files to.")
76
+	cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to identify to extract the resource.")
77
+	cmd.MarkFlagFilename("filename")
78
+	cmd.Flags().StringSliceVar(&options.OnlyKeys, "keys", options.OnlyKeys, "An optional list of keys to extract (default is all keys).")
79
+	kcmdutil.AddPrinterFlags(cmd)
80
+	return cmd
81
+}
82
+
83
+func (o *ExtractOptions) Complete(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra.Command, args []string) error {
84
+	o.ExtractFileContentsFn = f.ExtractFileContents
85
+
86
+	cmdNamespace, explicit, err := f.DefaultNamespace()
87
+	if err != nil {
88
+		return err
89
+	}
90
+
91
+	mapper, typer := f.Object(false)
92
+	b := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()).
93
+		NamespaceParam(cmdNamespace).DefaultNamespace().
94
+		FilenameParam(explicit, false, o.Filenames...).
95
+		ResourceNames("", args...).
96
+		ContinueOnError().
97
+		Flatten()
98
+
99
+	o.VisitorFn = b.Do().Visit
100
+	return nil
101
+}
102
+
103
+func (o *ExtractOptions) Validate() error {
104
+	return nil
105
+}
106
+
107
+func name(info *resource.Info) string {
108
+	return fmt.Sprintf("%s/%s", info.Mapping.Resource, info.Name)
109
+}
110
+
111
+func (o *ExtractOptions) Run() error {
112
+	count := 0
113
+	contains := sets.NewString(o.OnlyKeys...)
114
+	err := o.VisitorFn(func(info *resource.Info, err error) error {
115
+		if err != nil {
116
+			return fmt.Errorf("%s: %v", name(info), err)
117
+		}
118
+		contents, ok, err := o.ExtractFileContentsFn(info.Object)
119
+		if err != nil {
120
+			return fmt.Errorf("%s: %v", name(info), err)
121
+		}
122
+		if !ok {
123
+			fmt.Fprintf(o.Err, "warning: %s does not support extraction\n", name(info))
124
+			return nil
125
+		}
126
+		count++
127
+		var errs []error
128
+		for k, v := range contents {
129
+			if contains.Len() == 0 || contains.Has(k) {
130
+				target := filepath.Join(o.TargetDirectory, k)
131
+				if err := writeToDisk(target, v, o.Overwrite, o.Out); err != nil {
132
+					if os.IsExist(err) {
133
+						err = fmt.Errorf("file exists, pass --confirm to overwrite")
134
+					}
135
+					errs = append(errs, fmt.Errorf("%s: %v", k, err))
136
+				}
137
+			}
138
+		}
139
+		if len(errs) > 0 {
140
+			return fmt.Errorf(kcmdutil.MultipleErrors("error: ", errs))
141
+		}
142
+		return nil
143
+	})
144
+	if err != nil {
145
+		return err
146
+	}
147
+	if count == 0 {
148
+		return fmt.Errorf("you must specify at least one resource to extract")
149
+	}
150
+	return nil
151
+}
152
+
153
+func writeToDisk(path string, data []byte, overwrite bool, out io.Writer) error {
154
+	if overwrite {
155
+		if err := ioutil.WriteFile(path, data, 0600); err != nil {
156
+			return err
157
+		}
158
+	} else {
159
+		f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
160
+		if err != nil {
161
+			return err
162
+		}
163
+		if _, err := io.Copy(f, bytes.NewBuffer(data)); err != nil {
164
+			f.Close()
165
+			return err
166
+		}
167
+		if err := f.Close(); err != nil {
168
+			return err
169
+		}
170
+	}
171
+	fmt.Fprintf(out, "%s\n", path)
172
+	return nil
173
+}
... ...
@@ -573,6 +573,23 @@ func (f *Factory) UpdateObjectEnvironment(obj runtime.Object, fn func(*[]api.Env
573 573
 	return false, fmt.Errorf("object does not contain any environment variables")
574 574
 }
575 575
 
576
+// ExtractFileContents returns a map of keys to contents, false if the object cannot support such an
577
+// operation, or an error.
578
+func (f *Factory) ExtractFileContents(obj runtime.Object) (map[string][]byte, bool, error) {
579
+	switch t := obj.(type) {
580
+	case *api.Secret:
581
+		return t.Data, true, nil
582
+	case *api.ConfigMap:
583
+		out := make(map[string][]byte)
584
+		for k, v := range t.Data {
585
+			out[k] = []byte(v)
586
+		}
587
+		return out, true, nil
588
+	default:
589
+		return nil, false, nil
590
+	}
591
+}
592
+
576 593
 // UpdatePodSpecForObject update the pod specification for the provided object
577 594
 // TODO: move to upstream
578 595
 func (f *Factory) UpdatePodSpecForObject(obj runtime.Object, fn func(*api.PodSpec) error) (bool, error) {
... ...
@@ -35,6 +35,15 @@ os::cmd::expect_success_and_text 'oc secrets new from-file .dockercfg=${HOME}/do
35 35
 # check to make sure malformed names fail as expected
36 36
 os::cmd::expect_failure_and_text 'oc secrets new bad-name .docker=cfg=${HOME}/dockerconfig' "error: Key names or file paths cannot contain '='."
37 37
 
38
+workingdir="$( mktemp -d )"
39
+os::cmd::expect_success_and_text "oc extract secret/dockercfg --to '${workingdir}'" '.dockercfg'
40
+os::cmd::expect_success_and_text "cat '${workingdir}/.dockercfg'" 'sample-user'
41
+os::cmd::expect_failure_and_text "oc extract secret/dockercfg --to '${workingdir}'" 'error: .dockercfg: file exists, pass --confirm to overwrite'
42
+os::cmd::expect_failure_and_text "oc extract secret/dockercfg secret/dockercfg --to '${workingdir}'" 'error: .dockercfg: file exists, pass --confirm to overwrite'
43
+os::cmd::expect_success_and_text "oc extract secret/dockercfg secret/dockercfg --to '${workingdir}' --confirm" '.dockercfg'
44
+os::cmd::expect_success_and_text "oc extract secret/dockercfg --to '${workingdir}' --confirm" '.dockercfg'
45
+os::cmd::expect_success "oc extract secret/dockercfg --to '${workingdir}' --confirm | xargs rm"
46
+
38 47
 # attach secrets to service account
39 48
 # single secret with prefix
40 49
 os::cmd::expect_success 'oc secrets add deployer dockercfg'