diff --git a/contrib/completions/bash/oc b/contrib/completions/bash/oc index fb6bc77f9f98..462f94deae5c 100644 --- a/contrib/completions/bash/oc +++ b/contrib/completions/bash/oc @@ -10737,96 +10737,6 @@ _oc_edit() noun_aliases=() } -_oc_env() -{ - last_command="oc_env" - commands=() - - flags=() - two_word_flags=() - local_nonpersistent_flags=() - flags_with_completion=() - flags_completion=() - - flags+=("--all") - local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") - flags+=("--containers=") - two_word_flags+=("-c") - local_nonpersistent_flags+=("--containers=") - flags+=("--dry-run") - local_nonpersistent_flags+=("--dry-run") - flags+=("--env=") - two_word_flags+=("-e") - local_nonpersistent_flags+=("--env=") - flags+=("--filename=") - flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - two_word_flags+=("-f") - flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - local_nonpersistent_flags+=("--filename=") - flags+=("--from=") - local_nonpersistent_flags+=("--from=") - flags+=("--list") - local_nonpersistent_flags+=("--list") - flags+=("--local") - local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") - flags+=("--output=") - two_word_flags+=("-o") - local_nonpersistent_flags+=("--output=") - flags+=("--overwrite") - local_nonpersistent_flags+=("--overwrite") - flags+=("--prefix=") - local_nonpersistent_flags+=("--prefix=") - flags+=("--resolve") - local_nonpersistent_flags+=("--resolve") - flags+=("--resource-version=") - local_nonpersistent_flags+=("--resource-version=") - flags+=("--selector=") - two_word_flags+=("-l") - local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") - flags+=("--as=") - flags+=("--as-group=") - flags+=("--cache-dir=") - flags+=("--certificate-authority=") - flags+=("--client-certificate=") - flags+=("--client-key=") - flags+=("--cluster=") - flags+=("--config=") - flags+=("--context=") - flags+=("--insecure-skip-tls-verify") - flags+=("--loglevel=") - flags+=("--logspec=") - flags+=("--match-server-version") - flags+=("--namespace=") - flags_with_completion+=("--namespace") - flags_completion+=("__oc_get_namespaces") - two_word_flags+=("-n") - flags_with_completion+=("-n") - flags_completion+=("__oc_get_namespaces") - flags+=("--request-timeout=") - flags+=("--server=") - two_word_flags+=("-s") - flags+=("--token=") - flags+=("--user=") - - must_have_one_flag=() - must_have_one_noun=() - noun_aliases=() -} - _oc_ex_build-chain() { last_command="oc_ex_build-chain" @@ -15108,28 +15018,27 @@ _oc_set_build-hook() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--command") local_nonpersistent_flags+=("--command") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") flags+=("--post-commit") local_nonpersistent_flags+=("--post-commit") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--script=") @@ -15137,14 +15046,6 @@ _oc_set_build-hook() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15188,21 +15089,17 @@ _oc_set_build-secret() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15210,21 +15107,16 @@ _oc_set_build-secret() local_nonpersistent_flags+=("--pull") flags+=("--push") local_nonpersistent_flags+=("--push") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--source") local_nonpersistent_flags+=("--source") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15268,8 +15160,6 @@ _oc_set_deployment-hook() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--container=") two_word_flags+=("-c") local_nonpersistent_flags+=("--container=") @@ -15282,17 +15172,15 @@ _oc_set_deployment-hook() local_nonpersistent_flags+=("--failure-policy=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") flags+=("--mid") local_nonpersistent_flags+=("--mid") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15300,19 +15188,14 @@ _oc_set_deployment-hook() local_nonpersistent_flags+=("--post") flags+=("--pre") local_nonpersistent_flags+=("--pre") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--volumes=") local_nonpersistent_flags+=("--volumes=") flags+=("--as=") @@ -15358,8 +15241,6 @@ _oc_set_env() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--containers=") two_word_flags+=("-c") local_nonpersistent_flags+=("--containers=") @@ -15370,10 +15251,10 @@ _oc_set_env() local_nonpersistent_flags+=("--env=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--from=") local_nonpersistent_flags+=("--from=") @@ -15381,8 +15262,6 @@ _oc_set_env() local_nonpersistent_flags+=("--list") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15390,6 +15269,9 @@ _oc_set_env() local_nonpersistent_flags+=("--overwrite") flags+=("--prefix=") local_nonpersistent_flags+=("--prefix=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--resolve") local_nonpersistent_flags+=("--resolve") flags+=("--resource-version=") @@ -15397,14 +15279,6 @@ _oc_set_env() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15517,39 +15391,30 @@ _oc_set_image-lookup() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--enabled") local_nonpersistent_flags+=("--enabled") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--list") local_nonpersistent_flags+=("--list") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15593,8 +15458,6 @@ _oc_set_probe() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--containers=") two_word_flags+=("-c") local_nonpersistent_flags+=("--containers=") @@ -15604,10 +15467,10 @@ _oc_set_probe() local_nonpersistent_flags+=("--failure-threshold=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--get-url=") local_nonpersistent_flags+=("--get-url=") @@ -15617,8 +15480,6 @@ _oc_set_probe() local_nonpersistent_flags+=("--liveness") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--open-tcp=") local_nonpersistent_flags+=("--open-tcp=") flags+=("--output=") @@ -15628,21 +15489,16 @@ _oc_set_probe() local_nonpersistent_flags+=("--period-seconds=") flags+=("--readiness") local_nonpersistent_flags+=("--readiness") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--success-threshold=") local_nonpersistent_flags+=("--success-threshold=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--timeout-seconds=") local_nonpersistent_flags+=("--timeout-seconds=") flags+=("--as=") @@ -15764,37 +15620,28 @@ _oc_set_route-backends() local_nonpersistent_flags+=("--adjust") flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--equal") local_nonpersistent_flags+=("--equal") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--zero") local_nonpersistent_flags+=("--zero") flags+=("--as=") @@ -15840,8 +15687,6 @@ _oc_set_triggers() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--auto") local_nonpersistent_flags+=("--auto") flags+=("--containers=") @@ -15851,10 +15696,10 @@ _oc_set_triggers() local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--from-bitbucket") local_nonpersistent_flags+=("--from-bitbucket") @@ -15874,11 +15719,12 @@ _oc_set_triggers() local_nonpersistent_flags+=("--local") flags+=("--manual") local_nonpersistent_flags+=("--manual") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--remove-all") @@ -15886,14 +15732,6 @@ _oc_set_triggers() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15939,8 +15777,6 @@ _oc_set_volumes() local_nonpersistent_flags+=("--add") flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--claim-class=") local_nonpersistent_flags+=("--claim-class=") flags+=("--claim-mode=") @@ -15962,10 +15798,10 @@ _oc_set_volumes() local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") @@ -15974,8 +15810,6 @@ _oc_set_volumes() local_nonpersistent_flags+=("--mount-path=") flags+=("--name=") local_nonpersistent_flags+=("--name=") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15983,6 +15817,11 @@ _oc_set_volumes() local_nonpersistent_flags+=("--overwrite") flags+=("--path=") local_nonpersistent_flags+=("--path=") + flags+=("--read-only") + local_nonpersistent_flags+=("--read-only") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--secret-name=") @@ -15990,18 +15829,10 @@ _oc_set_volumes() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--source=") local_nonpersistent_flags+=("--source=") flags+=("--sub-path=") local_nonpersistent_flags+=("--sub-path=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--type=") two_word_flags+=("-t") local_nonpersistent_flags+=("--type=") @@ -16354,117 +16185,6 @@ _oc_version() noun_aliases=() } -_oc_volumes() -{ - last_command="oc_volumes" - commands=() - - flags=() - two_word_flags=() - local_nonpersistent_flags=() - flags_with_completion=() - flags_completion=() - - flags+=("--add") - local_nonpersistent_flags+=("--add") - flags+=("--all") - local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") - flags+=("--claim-class=") - local_nonpersistent_flags+=("--claim-class=") - flags+=("--claim-mode=") - local_nonpersistent_flags+=("--claim-mode=") - flags+=("--claim-name=") - local_nonpersistent_flags+=("--claim-name=") - flags+=("--claim-size=") - local_nonpersistent_flags+=("--claim-size=") - flags+=("--configmap-name=") - local_nonpersistent_flags+=("--configmap-name=") - flags+=("--confirm") - local_nonpersistent_flags+=("--confirm") - flags+=("--containers=") - two_word_flags+=("-c") - local_nonpersistent_flags+=("--containers=") - flags+=("--default-mode=") - local_nonpersistent_flags+=("--default-mode=") - flags+=("--dry-run") - local_nonpersistent_flags+=("--dry-run") - flags+=("--filename=") - flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - two_word_flags+=("-f") - flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - local_nonpersistent_flags+=("--filename=") - flags+=("--local") - local_nonpersistent_flags+=("--local") - flags+=("--mount-path=") - two_word_flags+=("-m") - local_nonpersistent_flags+=("--mount-path=") - flags+=("--name=") - local_nonpersistent_flags+=("--name=") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") - flags+=("--output=") - two_word_flags+=("-o") - local_nonpersistent_flags+=("--output=") - flags+=("--overwrite") - local_nonpersistent_flags+=("--overwrite") - flags+=("--path=") - local_nonpersistent_flags+=("--path=") - flags+=("--remove") - local_nonpersistent_flags+=("--remove") - flags+=("--secret-name=") - local_nonpersistent_flags+=("--secret-name=") - flags+=("--selector=") - two_word_flags+=("-l") - local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--source=") - local_nonpersistent_flags+=("--source=") - flags+=("--sub-path=") - local_nonpersistent_flags+=("--sub-path=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") - flags+=("--type=") - two_word_flags+=("-t") - local_nonpersistent_flags+=("--type=") - flags+=("--as=") - flags+=("--as-group=") - flags+=("--cache-dir=") - flags+=("--certificate-authority=") - flags+=("--client-certificate=") - flags+=("--client-key=") - flags+=("--cluster=") - flags+=("--config=") - flags+=("--context=") - flags+=("--insecure-skip-tls-verify") - flags+=("--loglevel=") - flags+=("--logspec=") - flags+=("--match-server-version") - flags+=("--namespace=") - flags_with_completion+=("--namespace") - flags_completion+=("__oc_get_namespaces") - two_word_flags+=("-n") - flags_with_completion+=("-n") - flags_completion+=("__oc_get_namespaces") - flags+=("--request-timeout=") - flags+=("--server=") - two_word_flags+=("-s") - flags+=("--token=") - flags+=("--user=") - - must_have_one_flag=() - must_have_one_noun=() - noun_aliases=() -} - _oc_wait() { last_command="oc_wait" @@ -16600,7 +16320,6 @@ _oc_root_command() commands+=("delete") commands+=("describe") commands+=("edit") - commands+=("env") commands+=("ex") commands+=("exec") commands+=("explain") @@ -16644,7 +16363,6 @@ _oc_root_command() commands+=("tag") commands+=("types") commands+=("version") - commands+=("volumes") commands+=("wait") commands+=("whoami") diff --git a/contrib/completions/zsh/oc b/contrib/completions/zsh/oc index 9feecd004afe..3b090bb30d6e 100644 --- a/contrib/completions/zsh/oc +++ b/contrib/completions/zsh/oc @@ -10879,96 +10879,6 @@ _oc_edit() noun_aliases=() } -_oc_env() -{ - last_command="oc_env" - commands=() - - flags=() - two_word_flags=() - local_nonpersistent_flags=() - flags_with_completion=() - flags_completion=() - - flags+=("--all") - local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") - flags+=("--containers=") - two_word_flags+=("-c") - local_nonpersistent_flags+=("--containers=") - flags+=("--dry-run") - local_nonpersistent_flags+=("--dry-run") - flags+=("--env=") - two_word_flags+=("-e") - local_nonpersistent_flags+=("--env=") - flags+=("--filename=") - flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - two_word_flags+=("-f") - flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - local_nonpersistent_flags+=("--filename=") - flags+=("--from=") - local_nonpersistent_flags+=("--from=") - flags+=("--list") - local_nonpersistent_flags+=("--list") - flags+=("--local") - local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") - flags+=("--output=") - two_word_flags+=("-o") - local_nonpersistent_flags+=("--output=") - flags+=("--overwrite") - local_nonpersistent_flags+=("--overwrite") - flags+=("--prefix=") - local_nonpersistent_flags+=("--prefix=") - flags+=("--resolve") - local_nonpersistent_flags+=("--resolve") - flags+=("--resource-version=") - local_nonpersistent_flags+=("--resource-version=") - flags+=("--selector=") - two_word_flags+=("-l") - local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") - flags+=("--as=") - flags+=("--as-group=") - flags+=("--cache-dir=") - flags+=("--certificate-authority=") - flags+=("--client-certificate=") - flags+=("--client-key=") - flags+=("--cluster=") - flags+=("--config=") - flags+=("--context=") - flags+=("--insecure-skip-tls-verify") - flags+=("--loglevel=") - flags+=("--logspec=") - flags+=("--match-server-version") - flags+=("--namespace=") - flags_with_completion+=("--namespace") - flags_completion+=("__oc_get_namespaces") - two_word_flags+=("-n") - flags_with_completion+=("-n") - flags_completion+=("__oc_get_namespaces") - flags+=("--request-timeout=") - flags+=("--server=") - two_word_flags+=("-s") - flags+=("--token=") - flags+=("--user=") - - must_have_one_flag=() - must_have_one_noun=() - noun_aliases=() -} - _oc_ex_build-chain() { last_command="oc_ex_build-chain" @@ -15250,28 +15160,27 @@ _oc_set_build-hook() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--command") local_nonpersistent_flags+=("--command") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") flags+=("--post-commit") local_nonpersistent_flags+=("--post-commit") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--script=") @@ -15279,14 +15188,6 @@ _oc_set_build-hook() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15330,21 +15231,17 @@ _oc_set_build-secret() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15352,21 +15249,16 @@ _oc_set_build-secret() local_nonpersistent_flags+=("--pull") flags+=("--push") local_nonpersistent_flags+=("--push") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--source") local_nonpersistent_flags+=("--source") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15410,8 +15302,6 @@ _oc_set_deployment-hook() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--container=") two_word_flags+=("-c") local_nonpersistent_flags+=("--container=") @@ -15424,17 +15314,15 @@ _oc_set_deployment-hook() local_nonpersistent_flags+=("--failure-policy=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") flags+=("--mid") local_nonpersistent_flags+=("--mid") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15442,19 +15330,14 @@ _oc_set_deployment-hook() local_nonpersistent_flags+=("--post") flags+=("--pre") local_nonpersistent_flags+=("--pre") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--volumes=") local_nonpersistent_flags+=("--volumes=") flags+=("--as=") @@ -15500,8 +15383,6 @@ _oc_set_env() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--containers=") two_word_flags+=("-c") local_nonpersistent_flags+=("--containers=") @@ -15512,10 +15393,10 @@ _oc_set_env() local_nonpersistent_flags+=("--env=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--from=") local_nonpersistent_flags+=("--from=") @@ -15523,8 +15404,6 @@ _oc_set_env() local_nonpersistent_flags+=("--list") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -15532,6 +15411,9 @@ _oc_set_env() local_nonpersistent_flags+=("--overwrite") flags+=("--prefix=") local_nonpersistent_flags+=("--prefix=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--resolve") local_nonpersistent_flags+=("--resolve") flags+=("--resource-version=") @@ -15539,14 +15421,6 @@ _oc_set_env() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15659,39 +15533,30 @@ _oc_set_image-lookup() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--enabled") local_nonpersistent_flags+=("--enabled") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--list") local_nonpersistent_flags+=("--list") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -15735,8 +15600,6 @@ _oc_set_probe() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--containers=") two_word_flags+=("-c") local_nonpersistent_flags+=("--containers=") @@ -15746,10 +15609,10 @@ _oc_set_probe() local_nonpersistent_flags+=("--failure-threshold=") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--get-url=") local_nonpersistent_flags+=("--get-url=") @@ -15759,8 +15622,6 @@ _oc_set_probe() local_nonpersistent_flags+=("--liveness") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--open-tcp=") local_nonpersistent_flags+=("--open-tcp=") flags+=("--output=") @@ -15770,21 +15631,16 @@ _oc_set_probe() local_nonpersistent_flags+=("--period-seconds=") flags+=("--readiness") local_nonpersistent_flags+=("--readiness") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--success-threshold=") local_nonpersistent_flags+=("--success-threshold=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--timeout-seconds=") local_nonpersistent_flags+=("--timeout-seconds=") flags+=("--as=") @@ -15906,37 +15762,28 @@ _oc_set_route-backends() local_nonpersistent_flags+=("--adjust") flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--dry-run") local_nonpersistent_flags+=("--dry-run") flags+=("--equal") local_nonpersistent_flags+=("--equal") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--zero") local_nonpersistent_flags+=("--zero") flags+=("--as=") @@ -15982,8 +15829,6 @@ _oc_set_triggers() flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--auto") local_nonpersistent_flags+=("--auto") flags+=("--containers=") @@ -15993,10 +15838,10 @@ _oc_set_triggers() local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--from-bitbucket") local_nonpersistent_flags+=("--from-bitbucket") @@ -16016,11 +15861,12 @@ _oc_set_triggers() local_nonpersistent_flags+=("--local") flags+=("--manual") local_nonpersistent_flags+=("--manual") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--remove-all") @@ -16028,14 +15874,6 @@ _oc_set_triggers() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--as=") flags+=("--as-group=") flags+=("--cache-dir=") @@ -16081,8 +15919,6 @@ _oc_set_volumes() local_nonpersistent_flags+=("--add") flags+=("--all") local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") flags+=("--claim-class=") local_nonpersistent_flags+=("--claim-class=") flags+=("--claim-mode=") @@ -16104,10 +15940,10 @@ _oc_set_volumes() local_nonpersistent_flags+=("--dry-run") flags+=("--filename=") flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") two_word_flags+=("-f") flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") + flags_completion+=("__oc_handle_filename_extension_flag json|yaml|yml") local_nonpersistent_flags+=("--filename=") flags+=("--local") local_nonpersistent_flags+=("--local") @@ -16116,8 +15952,6 @@ _oc_set_volumes() local_nonpersistent_flags+=("--mount-path=") flags+=("--name=") local_nonpersistent_flags+=("--name=") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") flags+=("--output=") two_word_flags+=("-o") local_nonpersistent_flags+=("--output=") @@ -16125,6 +15959,11 @@ _oc_set_volumes() local_nonpersistent_flags+=("--overwrite") flags+=("--path=") local_nonpersistent_flags+=("--path=") + flags+=("--read-only") + local_nonpersistent_flags+=("--read-only") + flags+=("--recursive") + flags+=("-R") + local_nonpersistent_flags+=("--recursive") flags+=("--remove") local_nonpersistent_flags+=("--remove") flags+=("--secret-name=") @@ -16132,18 +15971,10 @@ _oc_set_volumes() flags+=("--selector=") two_word_flags+=("-l") local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") flags+=("--source=") local_nonpersistent_flags+=("--source=") flags+=("--sub-path=") local_nonpersistent_flags+=("--sub-path=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") flags+=("--type=") two_word_flags+=("-t") local_nonpersistent_flags+=("--type=") @@ -16496,117 +16327,6 @@ _oc_version() noun_aliases=() } -_oc_volumes() -{ - last_command="oc_volumes" - commands=() - - flags=() - two_word_flags=() - local_nonpersistent_flags=() - flags_with_completion=() - flags_completion=() - - flags+=("--add") - local_nonpersistent_flags+=("--add") - flags+=("--all") - local_nonpersistent_flags+=("--all") - flags+=("--allow-missing-template-keys") - local_nonpersistent_flags+=("--allow-missing-template-keys") - flags+=("--claim-class=") - local_nonpersistent_flags+=("--claim-class=") - flags+=("--claim-mode=") - local_nonpersistent_flags+=("--claim-mode=") - flags+=("--claim-name=") - local_nonpersistent_flags+=("--claim-name=") - flags+=("--claim-size=") - local_nonpersistent_flags+=("--claim-size=") - flags+=("--configmap-name=") - local_nonpersistent_flags+=("--configmap-name=") - flags+=("--confirm") - local_nonpersistent_flags+=("--confirm") - flags+=("--containers=") - two_word_flags+=("-c") - local_nonpersistent_flags+=("--containers=") - flags+=("--default-mode=") - local_nonpersistent_flags+=("--default-mode=") - flags+=("--dry-run") - local_nonpersistent_flags+=("--dry-run") - flags+=("--filename=") - flags_with_completion+=("--filename") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - two_word_flags+=("-f") - flags_with_completion+=("-f") - flags_completion+=("__oc_handle_filename_extension_flag yaml|yml|json") - local_nonpersistent_flags+=("--filename=") - flags+=("--local") - local_nonpersistent_flags+=("--local") - flags+=("--mount-path=") - two_word_flags+=("-m") - local_nonpersistent_flags+=("--mount-path=") - flags+=("--name=") - local_nonpersistent_flags+=("--name=") - flags+=("--no-headers") - local_nonpersistent_flags+=("--no-headers") - flags+=("--output=") - two_word_flags+=("-o") - local_nonpersistent_flags+=("--output=") - flags+=("--overwrite") - local_nonpersistent_flags+=("--overwrite") - flags+=("--path=") - local_nonpersistent_flags+=("--path=") - flags+=("--remove") - local_nonpersistent_flags+=("--remove") - flags+=("--secret-name=") - local_nonpersistent_flags+=("--secret-name=") - flags+=("--selector=") - two_word_flags+=("-l") - local_nonpersistent_flags+=("--selector=") - flags+=("--show-labels") - local_nonpersistent_flags+=("--show-labels") - flags+=("--sort-by=") - local_nonpersistent_flags+=("--sort-by=") - flags+=("--source=") - local_nonpersistent_flags+=("--source=") - flags+=("--sub-path=") - local_nonpersistent_flags+=("--sub-path=") - flags+=("--template=") - flags_with_completion+=("--template") - flags_completion+=("_filedir") - local_nonpersistent_flags+=("--template=") - flags+=("--type=") - two_word_flags+=("-t") - local_nonpersistent_flags+=("--type=") - flags+=("--as=") - flags+=("--as-group=") - flags+=("--cache-dir=") - flags+=("--certificate-authority=") - flags+=("--client-certificate=") - flags+=("--client-key=") - flags+=("--cluster=") - flags+=("--config=") - flags+=("--context=") - flags+=("--insecure-skip-tls-verify") - flags+=("--loglevel=") - flags+=("--logspec=") - flags+=("--match-server-version") - flags+=("--namespace=") - flags_with_completion+=("--namespace") - flags_completion+=("__oc_get_namespaces") - two_word_flags+=("-n") - flags_with_completion+=("-n") - flags_completion+=("__oc_get_namespaces") - flags+=("--request-timeout=") - flags+=("--server=") - two_word_flags+=("-s") - flags+=("--token=") - flags+=("--user=") - - must_have_one_flag=() - must_have_one_noun=() - noun_aliases=() -} - _oc_wait() { last_command="oc_wait" @@ -16742,7 +16462,6 @@ _oc_root_command() commands+=("delete") commands+=("describe") commands+=("edit") - commands+=("env") commands+=("ex") commands+=("exec") commands+=("explain") @@ -16786,7 +16505,6 @@ _oc_root_command() commands+=("tag") commands+=("types") commands+=("version") - commands+=("volumes") commands+=("wait") commands+=("whoami") diff --git a/docs/cli.md b/docs/cli.md index 0eaa056e1c9f..0d7443b4ccc4 100755 --- a/docs/cli.md +++ b/docs/cli.md @@ -449,35 +449,35 @@ For example, to edit the service `docker-registry` in JSON using the `v1` API fo $ oc edit svc/docker-registry --output-version=v1 -o json ``` -### oc env +### oc set env This updates the environment on a resource with a pod template. The general form is: ```bash -$ oc env / = = +$ oc set env / = = ``` For example: ```bash -$ oc env dc/app DB_USER=user DB_PASS=pass +$ oc set env dc/app DB_USER=user DB_PASS=pass ``` -### oc volume +### oc set volume This controls the storage associated with various resources. The general form is: ```bash -$ oc volume / -- +$ oc set volume / -- ``` where *action* is one of `add`, `remove`, `list` and *options* depends on *action*. For example, to arrange for the deployment configuration `registry` to access the host *_/opt_* directory, use: ```bash -$ oc volume dc/registry --add --mount-path=/opt +$ oc set volume dc/registry --add --mount-path=/opt ``` ### oc label diff --git a/docs/man/man1/.files_generated_oc b/docs/man/man1/.files_generated_oc index 662f3092663e..278f10abe0da 100644 --- a/docs/man/man1/.files_generated_oc +++ b/docs/man/man1/.files_generated_oc @@ -191,7 +191,6 @@ oc-delete.1 oc-deploy.1 oc-describe.1 oc-edit.1 -oc-env.1 oc-ex-build-chain.1 oc-ex-config-patch.1 oc-ex-config.1 @@ -308,7 +307,6 @@ oc-status.1 oc-tag.1 oc-types.1 oc-version.1 -oc-volumes.1 oc-wait.1 oc-whoami.1 oc.1 diff --git a/docs/man/man1/oc-env.1 b/docs/man/man1/oc-env.1 deleted file mode 100644 index b6fd7a0f9896..000000000000 --- a/docs/man/man1/oc-env.1 +++ /dev/null @@ -1,3 +0,0 @@ -This file is autogenerated, but we've stopped checking such files into the -repository to reduce the need for rebases. Please run hack/generate-docs.sh to -populate this file. diff --git a/docs/man/man1/oc-volumes.1 b/docs/man/man1/oc-volumes.1 deleted file mode 100644 index b6fd7a0f9896..000000000000 --- a/docs/man/man1/oc-volumes.1 +++ /dev/null @@ -1,3 +0,0 @@ -This file is autogenerated, but we've stopped checking such files into the -repository to reduce the need for rebases. Please run hack/generate-docs.sh to -populate this file. diff --git a/hack/lib/start.sh b/hack/lib/start.sh index 0f31bd425bbe..5bb9567808f1 100644 --- a/hack/lib/start.sh +++ b/hack/lib/start.sh @@ -631,7 +631,7 @@ function os::start::registry() { # For testing purposes, ensure the quota objects are always up to date in the registry by # disabling project cache. oc adm registry --config="${ADMIN_KUBECONFIG}" --images="${USE_IMAGES}" --enforce-quota -o json | \ - oc env --config="${ADMIN_KUBECONFIG}" -f - --output json "REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_PROJECTCACHETTL=0" | \ + oc set env --config="${ADMIN_KUBECONFIG}" --local -f - --output json "REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_PROJECTCACHETTL=0" | \ oc create --config="${ADMIN_KUBECONFIG}" -f - } readonly -f os::start::registry diff --git a/pkg/oc/admin/router/router.go b/pkg/oc/admin/router/router.go index ce0411608f04..c4e37fc22740 100644 --- a/pkg/oc/admin/router/router.go +++ b/pkg/oc/admin/router/router.go @@ -279,7 +279,7 @@ func NewCmdRouter(f kcmdutil.Factory, parentName, name string, out, errout io.Wr cmd.Flags().StringVar(&cfg.ForceSubdomain, "force-subdomain", "", "A router path format to force on all routes used by this router (will ignore the route host value)") cmd.Flags().StringVar(&cfg.ImageTemplate.Format, "images", cfg.ImageTemplate.Format, "The image to base this router on - ${component} will be replaced with --type") cmd.Flags().BoolVar(&cfg.ImageTemplate.Latest, "latest-images", cfg.ImageTemplate.Latest, "If true, attempt to use the latest images for the router instead of the latest release.") - cmd.Flags().StringVar(&cfg.Ports, "ports", cfg.Ports, "A comma delimited list of ports or port pairs that set the port in the router pod containerPort and hostPort. It also sets service port and targetPort to expose on the router pod. This does not modify the env variables. That can be done using oc env or by editing the router's dc. This is used when host-network=false.") + cmd.Flags().StringVar(&cfg.Ports, "ports", cfg.Ports, "A comma delimited list of ports or port pairs that set the port in the router pod containerPort and hostPort. It also sets service port and targetPort to expose on the router pod. This does not modify the env variables. That can be done using oc set env or by editing the router's dc. This is used when host-network=false.") cmd.Flags().StringVar(&cfg.RouterCanonicalHostname, "router-canonical-hostname", cfg.RouterCanonicalHostname, "CanonicalHostname is the external host name for the router that can be used as a CNAME for the host requested for this route. This value is optional and may not be set in all cases.") cmd.Flags().Int32Var(&cfg.Replicas, "replicas", cfg.Replicas, "The replication factor of the router; commonly 2 when high availability is desired.") cmd.Flags().StringVar(&cfg.Labels, "labels", cfg.Labels, "A set of labels to uniquely identify the router and its components.") diff --git a/pkg/oc/cli/cli.go b/pkg/oc/cli/cli.go index 7b75e547e64b..4d59b3553d4e 100644 --- a/pkg/oc/cli/cli.go +++ b/pkg/oc/cli/cli.go @@ -211,8 +211,6 @@ func NewCommandCLI(name, fullName string, in io.Reader, out, errout io.Writer) * "options", "deploy", // These commands are deprecated and should not appear in help - moved(fullName, "set env", cmds, set.NewCmdEnv(fullName, f, ioStreams)), - moved(fullName, "set volume", cmds, set.NewCmdVolume(fullName, f, ioStreams)), moved(fullName, "logs", cmds, cmd.NewCmdBuildLogs(fullName, f, ioStreams)), moved(fullName, "secrets link", secretcmds, secrets.NewCmdLinkSecret("add", fullName, f, ioStreams)), moved(fullName, "create secret", secretcmds, secrets.NewCmdCreateSecret(secrets.NewSecretRecommendedCommandName, fullName, f, ioStreams)), diff --git a/pkg/oc/cli/cmd/example.go b/pkg/oc/cli/cmd/example.go index 745493bf263b..4ed7b55b00ba 100644 --- a/pkg/oc/cli/cmd/example.go +++ b/pkg/oc/cli/cmd/example.go @@ -2,13 +2,15 @@ package cmd import ( "fmt" - "io" - "os" "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" + + "github.com/openshift/origin/pkg/oc/util/ocscheme" ) var ( @@ -21,39 +23,56 @@ var ( ) type TYPEOptions struct { - In io.Reader - Out, ErrOut io.Writer + PrintFlags *genericclioptions.PrintFlags + + Printer printers.ResourcePrinter + DryRun bool + + genericclioptions.IOStreams } -// NewCmdTYPE implements a TYPE command +// NewTYPEOptions returns a TYPEOptions with proper defaults. // This is an example type for templating. -func NewCmdTYPE(fullName string, f kcmdutil.Factory, in io.Reader, out, errout io.Writer) *cobra.Command { - options := &TYPEOptions{ - In: in, - Out: out, - ErrOut: errout, +func NewTYPEOptions(streams genericclioptions.IOStreams) *TYPEOptions { + return &TYPEOptions{ + PrintFlags: genericclioptions.NewPrintFlags("action performed").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, } +} + +// NewCmdTYPE implements a TYPE command +// This is an example type for templating. +func NewCmdTYPE(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewTYPEOptions(streams) cmd := &cobra.Command{ Use: "NAME [...]", Short: "A short description", Long: internalTYPELong, Example: fmt.Sprintf(internalTYPEExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } + + o.PrintFlags.AddFlags(cmd) + kcmdutil.AddDryRunFlag(cmd) + return cmd } -func (o *TYPEOptions) Complete(f kcmdutil.Factory, c *cobra.Command, args []string) error { +func (o *TYPEOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { + var err error + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err + } + return nil } diff --git a/pkg/oc/cli/cmd/helper.go b/pkg/oc/cli/cmd/helper.go index 85ab3cfc6761..fd095e59642b 100644 --- a/pkg/oc/cli/cmd/helper.go +++ b/pkg/oc/cli/cmd/helper.go @@ -1,10 +1,12 @@ package cmd import ( + "fmt" "strings" "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" ) // parseNamespaceResourceName parses the value and returns namespace, resource and the @@ -35,3 +37,14 @@ func getFlagStringArray(cmd *cobra.Command, flag string) []string { } return s } + +func GetObjectName(info *resource.Info) string { + if info.Mapping != nil { + return fmt.Sprintf("%s/%s", info.Mapping.Resource.Resource, info.Name) + } + gvk := info.Object.GetObjectKind().GroupVersionKind() + if len(gvk.Group) == 0 { + return fmt.Sprintf("%s/%s", strings.ToLower(gvk.Kind), info.Name) + } + return fmt.Sprintf("%s.%s/%s\n", strings.ToLower(gvk.Kind), gvk.Group, info.Name) +} diff --git a/pkg/oc/cli/cmd/set/buildhook.go b/pkg/oc/cli/cmd/set/buildhook.go index 14b18ea8f59e..eaae4cc283d7 100644 --- a/pkg/oc/cli/cmd/set/buildhook.go +++ b/pkg/oc/cli/cmd/set/buildhook.go @@ -2,21 +2,22 @@ package set import ( "fmt" - "io" - "os" + "github.com/golang/glog" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" - buildapi "github.com/openshift/origin/pkg/build/apis/build" - "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" + buildv1 "github.com/openshift/api/build/v1" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -52,126 +53,98 @@ var ( ) type BuildHookOptions struct { - Out io.Writer - Err io.Writer - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Filenames []string - Selector string - All bool - Output string - - Cmd *cobra.Command - - Local bool - ShortOutput bool - Mapper meta.RESTMapper - Client dynamic.Interface - - PrintObject func([]*resource.Info) error + PrintFlags *genericclioptions.PrintFlags + Selector string + All bool + Local bool Script string Entrypoint bool Remove bool PostCommit bool - Command []string + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Namespace string + ExplicitNamespace bool + Command []string + Resources []string + DryRun bool + + resource.FilenameOptions + genericclioptions.IOStreams +} + +func NewBuildHookOptions(streams genericclioptions.IOStreams) *BuildHookOptions { + return &BuildHookOptions{ + PrintFlags: genericclioptions.NewPrintFlags("hooks updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + } } // NewCmdBuildHook implements the set build-hook command func NewCmdBuildHook(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &BuildHookOptions{ - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewBuildHookOptions(streams) cmd := &cobra.Command{ Use: "build-hook BUILDCONFIG --post-commit [--command] [--script] -- CMD", Short: "Update a build hook on a build config", Long: buildHookLong, Example: fmt.Sprintf(buildHookExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter build configs") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all build configs in the namespace") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.PostCommit, "post-commit", options.PostCommit, "If true, set the post-commit build hook on a build config") - cmd.Flags().BoolVar(&options.Entrypoint, "command", options.Entrypoint, "If true, set the entrypoint of the hook container to the given command") - cmd.Flags().StringVar(&options.Script, "script", options.Script, "Specify a script to run for the build-hook") - cmd.Flags().BoolVar(&options.Remove, "remove", options.Remove, "If true, remove the build hook.") - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter build configs") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all build configs in the namespace") + cmd.Flags().BoolVar(&o.PostCommit, "post-commit", o.PostCommit, "If true, set the post-commit build hook on a build config") + cmd.Flags().BoolVar(&o.Entrypoint, "command", o.Entrypoint, "If true, set the entrypoint of the hook container to the given command") + cmd.Flags().StringVar(&o.Script, "script", o.Script, "Specify a script to run for the build-hook") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove the build hook.") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) return cmd } func (o *BuildHookOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - resources := args + o.Resources = args if i := cmd.ArgsLenAtDash(); i != -1 { - resources = args[:i] + o.Resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageErrorf(cmd, "one or more build configs must be specified as or /") } - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - o.Cmd = cmd - - mapper, err := f.ToRESTMapper() + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - LabelSelectorParam(o.Selector). - ResourceNames("buildconfigs", resources...). - Flatten() + o.Builder = f.NewBuilder - if !o.Local { - o.Builder = o.Builder. - LabelSelectorParam(o.Selector). - ResourceNames("buildconfigs", resources...) - if o.All { - o.Builder.ResourceTypes("buildconfigs").SelectAllParam(o.All) - } + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, o.Out) + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper - clientConfig, err := f.ToRESTConfig() if err != nil { return err @@ -185,7 +158,6 @@ func (o *BuildHookOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args } func (o *BuildHookOptions) Validate() error { - if !o.PostCommit { return fmt.Errorf("you must specify a type of hook to set") } @@ -212,18 +184,32 @@ func (o *BuildHookOptions) Validate() error { } func (o *BuildHookOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + + if !o.Local { + b = b. + LabelSelectorParam(o.Selector). + ResourceNames("buildconfigs", o.Resources...). + Latest() + if o.All { + b = b.ResourceTypes("buildconfigs").SelectAllParam(o.All) } - infos = loaded } - patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { - bc, ok := info.Object.(*buildapi.BuildConfig) + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err + } + + patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { + bc, ok := info.Object.(*buildv1.BuildConfig) if !ok { return false, nil } @@ -235,39 +221,41 @@ func (o *BuildHookOptions) Run() error { return fmt.Errorf("%s/%s is not a build config", infos[0].Mapping.Resource, infos[0].Name) } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return o.PrintObject(infos) - } - - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) + continue + } + + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } continue } actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - fmt.Fprintf(o.Err, "error: %v\n", err) - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch build hook: %v\n", err)) continue } - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, actual, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) } -func (o *BuildHookOptions) updateBuildConfig(bc *buildapi.BuildConfig) { +func (o *BuildHookOptions) updateBuildConfig(bc *buildv1.BuildConfig) { if o.Remove { bc.Spec.PostCommit.Args = nil bc.Spec.PostCommit.Command = nil diff --git a/pkg/oc/cli/cmd/set/buildsecret.go b/pkg/oc/cli/cmd/set/buildsecret.go index c790e5a67dae..28743ab96bf2 100644 --- a/pkg/oc/cli/cmd/set/buildsecret.go +++ b/pkg/oc/cli/cmd/set/buildsecret.go @@ -2,24 +2,24 @@ package set import ( "fmt" - "io" - "os" + "github.com/golang/glog" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/kubernetes/pkg/api/legacyscheme" + "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" buildv1 "github.com/openshift/api/build/v1" - "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -52,83 +52,74 @@ var ( ) type BuildSecretOptions struct { - Out io.Writer - Err io.Writer - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Filenames []string - Selector string - All bool - - Cmd *cobra.Command - - ShortOutput bool - Local bool - Mapper meta.RESTMapper - - Output string - - PrintObject func([]*resource.Info) error + PrintFlags *genericclioptions.PrintFlags + + Selector string + All bool + Local bool + Push bool + Pull bool + Source bool + Remove bool + + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Namespace string + ExplicitNamespace bool + Resources []string + SecretArg string + DryRun bool + + resource.FilenameOptions + genericclioptions.IOStreams +} - Secret string - Push bool - Pull bool - Source bool - Remove bool +func NewBuildSecretOptions(streams genericclioptions.IOStreams) *BuildSecretOptions { + return &BuildSecretOptions{ + PrintFlags: genericclioptions.NewPrintFlags("secret updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + } } // NewCmdBuildSecret implements the set build-secret command func NewCmdBuildSecret(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &BuildSecretOptions{ - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewBuildSecretOptions(streams) cmd := &cobra.Command{ Use: "build-secret BUILDCONFIG SECRETNAME", Short: "Update a build secret on a build config", Long: buildSecretLong, Example: fmt.Sprintf(buildSecretExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter build configs") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all build configs in the namespace") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.Push, "push", options.Push, "If true, set the push secret on a build config") - cmd.Flags().BoolVar(&options.Pull, "pull", options.Pull, "If true, set the pull secret on a build config") - cmd.Flags().BoolVar(&options.Source, "source", options.Source, "If true, set the source secret on a build config") - cmd.Flags().BoolVar(&options.Remove, "remove", options.Remove, "If true, remove the build secret.") - - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set build-secret will NOT contact api-server but run locally.") - - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter build configs") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all build configs in the namespace") + cmd.Flags().BoolVar(&o.Push, "push", o.Push, "If true, set the push secret on a build config") + cmd.Flags().BoolVar(&o.Pull, "pull", o.Pull, "If true, set the pull secret on a build config") + cmd.Flags().BoolVar(&o.Source, "source", o.Source, "If true, set the source secret on a build config") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove the build secret.") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set build-secret will NOT contact api-server but run locally.") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) + return cmd } var supportedBuildTypes = []string{"buildconfigs"} -func (o *BuildSecretOptions) secretFromArg(f kcmdutil.Factory, mapper meta.RESTMapper, typer runtime.ObjectTyper, namespace, arg string) (string, error) { - builder := f.NewBuilder(). +func (o *BuildSecretOptions) secretFromArg(arg string) (string, error) { + builder := o.Builder(). WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). - NamespaceParam(namespace).DefaultNamespace(). + NamespaceParam(o.Namespace).DefaultNamespace(). RequireObject(false). ContinueOnError(). ResourceNames("secrets", arg). @@ -152,64 +143,47 @@ func (o *BuildSecretOptions) secretFromArg(f kcmdutil.Factory, mapper meta.RESTM } func (o *BuildSecretOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - var secretArg string if !o.Remove { if len(args) < 1 { return kcmdutil.UsageErrorf(cmd, "a secret name must be specified") } - secretArg = args[len(args)-1] + o.SecretArg = args[len(args)-1] args = args[:len(args)-1] } - resources := args - if len(resources) == 0 && len(o.Selector) == 0 && len(o.Filenames) == 0 && !o.All { + o.Resources = args + if len(o.Resources) == 0 && len(o.Selector) == 0 && len(o.Filenames) == 0 && !o.All { return kcmdutil.UsageErrorf(cmd, "one or more build configs must be specified as or /") } - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - o.Cmd = cmd - - mapper, err := f.ToRESTMapper() + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } - typer := legacyscheme.Scheme - if len(secretArg) > 0 { - o.Secret, err = o.secretFromArg(f, mapper, typer, cmdNamespace, secretArg) - if err != nil { - return err - } - } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - Flatten() - - if !o.Local { - o.Builder = o.Builder. - ResourceNames("buildconfigs", resources...). - LabelSelectorParam(o.Selector). - Latest() + o.Builder = f.NewBuilder - if o.All { - o.Builder.ResourceTypes(supportedBuildTypes...).SelectAllParam(o.All) - } + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, o.Out) + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + o.Client, err = dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } return nil } @@ -218,85 +192,105 @@ func (o *BuildSecretOptions) Validate() error { if !o.Pull && !o.Push && !o.Source { return fmt.Errorf("specify the type of secret to set (--push, --pull, or --source)") } - if !o.Remove && len(o.Secret) == 0 { + if !o.Remove && len(o.SecretArg) == 0 { return fmt.Errorf("specify a secret to set") } - if o.Remove && len(o.Secret) > 0 { + if o.Remove && len(o.SecretArg) > 0 { return fmt.Errorf("a secret cannot be specified when using the --remove flag") } return nil } func (o *BuildSecretOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + var ( + secret string + err error + ) + if len(o.SecretArg) > 0 { + secret, err = o.secretFromArg(o.SecretArg) if err != nil { return err } - infos = loaded + } + + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + + if !o.Local { + b = b. + ResourceNames("buildconfigs", o.Resources...). + LabelSelectorParam(o.Selector). + Latest() + if o.All { + b = b.ResourceTypes(supportedBuildTypes...).SelectAllParam(o.All) + } + } + + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err } patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { - return o.setBuildSecret(info.Object) + bc, ok := info.Object.(*buildv1.BuildConfig) + if !ok { + return false, nil + } + o.updateBuildConfig(bc, secret) + return true, nil }) if singleItemImplied && len(patches) == 0 { return fmt.Errorf("cannot set a build secret on %s/%s", infos[0].Mapping.Resource, infos[0].Name) } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return o.PrintObject(infos) - } - - errs := []error{} + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - errs = append(errs, fmt.Errorf("%s/%s %v", info.Mapping.Resource.Resource, info.Name, patch.Err)) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) - if err != nil { - errs = append(errs, fmt.Errorf("%s/%s %v", info.Mapping.Resource.Resource, info.Name, err)) + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } continue } - info.Refresh(obj, true) - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, false, "updated") - } - if len(errs) > 0 { - return errors.NewAggregate(errs) - } - return nil -} + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) + if err != nil { + allErrs = append(allErrs, fmt.Errorf("failed to patch secret %v", err)) + continue + } -// setBuildSecret will set a secret on an object. For now the only supported -// object type is BuildConfig. -func (o *BuildSecretOptions) setBuildSecret(obj runtime.Object) (bool, error) { - switch buildObj := obj.(type) { - case *buildv1.BuildConfig: - o.updateBuildConfig(buildObj) - return true, nil - default: - return false, nil + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } + return errors.NewAggregate(allErrs) } -func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig) { +func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig, secret string) { if o.Push { if o.Remove { bc.Spec.Output.PushSecret = nil } else { bc.Spec.Output.PushSecret = &corev1.LocalObjectReference{ - Name: o.Secret, + Name: secret, } } } @@ -308,7 +302,7 @@ func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig) { bc.Spec.Strategy.DockerStrategy.PullSecret = nil } else { bc.Spec.Strategy.DockerStrategy.PullSecret = &corev1.LocalObjectReference{ - Name: o.Secret, + Name: secret, } } case bc.Spec.Strategy.SourceStrategy != nil: @@ -316,7 +310,7 @@ func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig) { bc.Spec.Strategy.SourceStrategy.PullSecret = nil } else { bc.Spec.Strategy.SourceStrategy.PullSecret = &corev1.LocalObjectReference{ - Name: o.Secret, + Name: secret, } } case bc.Spec.Strategy.CustomStrategy != nil: @@ -324,7 +318,7 @@ func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig) { bc.Spec.Strategy.CustomStrategy.PullSecret = nil } else { bc.Spec.Strategy.CustomStrategy.PullSecret = &corev1.LocalObjectReference{ - Name: o.Secret, + Name: secret, } } } @@ -335,7 +329,7 @@ func (o *BuildSecretOptions) updateBuildConfig(bc *buildv1.BuildConfig) { bc.Spec.Source.SourceSecret = nil } else { bc.Spec.Source.SourceSecret = &corev1.LocalObjectReference{ - Name: o.Secret, + Name: secret, } } } diff --git a/pkg/oc/cli/cmd/set/deploymenthook.go b/pkg/oc/cli/cmd/set/deploymenthook.go index f839b2473a32..e3341cd663f9 100644 --- a/pkg/oc/cli/cmd/set/deploymenthook.go +++ b/pkg/oc/cli/cmd/set/deploymenthook.go @@ -2,24 +2,27 @@ package set import ( "fmt" - "io" - "os" - "github.com/openshift/origin/pkg/oc/util/ocscheme" + "github.com/golang/glog" "github.com/spf13/cobra" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" appsv1 "github.com/openshift/api/apps/v1" cmdutil "github.com/openshift/origin/pkg/cmd/util" - "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" + "github.com/openshift/origin/pkg/oc/cli/cmd" utilenv "github.com/openshift/origin/pkg/oc/util/env" + "github.com/openshift/origin/pkg/oc/util/ocscheme" ) var ( @@ -59,137 +62,122 @@ var ( ) type DeploymentHookOptions struct { - Out io.Writer - Err io.Writer - - Builder *resource.Builder - Infos []*resource.Info - - Filenames []string - Container string - Selector string - All bool - - Output string - - ShortOutput bool - Local bool - Mapper meta.RESTMapper - - PrintObject func([]*resource.Info) error - - Pre bool - Mid bool - Post bool - Remove bool - - Cmd *cobra.Command - - Command []string - Environment []string - Volumes []string + PrintFlags *genericclioptions.PrintFlags + + Container string + Selector string + All bool + Local bool + Pre bool + Mid bool + Post bool + Remove bool + FailurePolicyStr string + + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Command []string + Resources []string + Environment []string + Volumes []string + Namespace string + ExplicitNamespace bool + DryRun bool + FailurePolicy appsv1.LifecycleHookFailurePolicy + + resource.FilenameOptions + genericclioptions.IOStreams +} - FailurePolicy appsv1.LifecycleHookFailurePolicy +func NewDeploymentHookOptions(streams genericclioptions.IOStreams) *DeploymentHookOptions { + return &DeploymentHookOptions{ + PrintFlags: genericclioptions.NewPrintFlags("hooks updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + FailurePolicyStr: "ignore", + } } // NewCmdDeploymentHook implements the set deployment-hook command func NewCmdDeploymentHook(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &DeploymentHookOptions{ - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewDeploymentHookOptions(streams) cmd := &cobra.Command{ Use: "deployment-hook DEPLOYMENTCONFIG --pre|--post|--mid -- CMD", Short: "Update a deployment hook on a deployment config", Long: deploymentHookLong, Example: fmt.Sprintf(deploymentHookExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Container, "container", "c", options.Container, "The name of the container in the selected deployment config to use for the deployment hook") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter deployment configs") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all deployment configs in the namespace") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.Remove, "remove", options.Remove, "If true, remove the specified deployment hook(s).") - cmd.Flags().BoolVar(&options.Pre, "pre", options.Pre, "Set or remove a pre deployment hook") - cmd.Flags().BoolVar(&options.Mid, "mid", options.Mid, "Set or remove a mid deployment hook") - cmd.Flags().BoolVar(&options.Post, "post", options.Post, "Set or remove a post deployment hook") - - cmd.Flags().StringArrayVarP(&options.Environment, "environment", "e", options.Environment, "Environment variable to use in the deployment hook pod") - cmd.Flags().StringSliceVar(&options.Volumes, "volumes", options.Volumes, "Volumes from the pod template to use in the deployment hook pod") - - cmd.Flags().String("failure-policy", "ignore", "The failure policy for the deployment hook. Valid values are: abort,retry,ignore") - - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set deployment hook will NOT contact api-server but run locally.") - - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Container, "container", "c", o.Container, "The name of the container in the selected deployment config to use for the deployment hook") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter deployment configs") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all deployment configs in the namespace") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove the specified deployment hook(s).") + cmd.Flags().BoolVar(&o.Pre, "pre", o.Pre, "Set or remove a pre deployment hook") + cmd.Flags().BoolVar(&o.Mid, "mid", o.Mid, "Set or remove a mid deployment hook") + cmd.Flags().BoolVar(&o.Post, "post", o.Post, "Set or remove a post deployment hook") + cmd.Flags().StringArrayVarP(&o.Environment, "environment", "e", o.Environment, "Environment variable to use in the deployment hook pod") + // FIXME: https://github.com/openshift/origin/issues/20097 + // cmd.Flags().StringSliceVarP(&o.Volumes, "volumes", "v", o.Volumes, "Volumes from the pod template to use in the deployment hook pod") + cmd.Flags().StringSliceVar(&o.Volumes, "volumes", o.Volumes, "Volumes from the pod template to use in the deployment hook pod") + cmd.Flags().MarkShorthandDeprecated("volumes", "Use --volumes instead.") + cmd.Flags().StringVar(&o.FailurePolicyStr, "failure-policy", o.FailurePolicyStr, "The failure policy for the deployment hook. Valid values are: abort,retry,ignore") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set deployment hook will NOT contact api-server but run locally.") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) return cmd } func (o *DeploymentHookOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - resources := args + o.Resources = args if i := cmd.ArgsLenAtDash(); i != -1 { - resources = args[:i] + o.Resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageErrorf(cmd, "one or more deployment configs must be specified as or dc/") } - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - o.Cmd = cmd - - mapper, err := f.ToRESTMapper() + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - Flatten() - if !o.Local { - o.Builder = o.Builder. - ResourceNames("deploymentconfigs", resources...). - LabelSelectorParam(o.Selector). - Latest() - if o.All { - o.Builder.ResourceTypes("deploymentconfigs").SelectAllParam(o.All) - } + o.Builder = f.NewBuilder + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, o.Out) + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + o.Client, err = dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } - failurePolicyString := kcmdutil.GetFlagString(cmd, "failure-policy") - if len(failurePolicyString) > 0 { - switch failurePolicyString { + if len(o.FailurePolicyStr) > 0 { + switch o.FailurePolicyStr { case "abort": o.FailurePolicy = appsv1.LifecycleHookFailurePolicyAbort case "ignore": @@ -205,7 +193,6 @@ func (o *DeploymentHookOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, } func (o *DeploymentHookOptions) Validate() error { - if o.Remove { if len(o.Command) > 0 || len(o.Volumes) > 0 || @@ -237,20 +224,35 @@ func (o *DeploymentHookOptions) Validate() error { return fmt.Errorf("you must specify a command for the deployment hook") } - cmdutil.WarnAboutCommaSeparation(o.Err, o.Environment, "--environment") + cmdutil.WarnAboutCommaSeparation(o.ErrOut, o.Environment, "--environment") return nil } func (o *DeploymentHookOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + + if !o.Local { + b = b. + ResourceNames("deploymentconfigs", o.Resources...). + LabelSelectorParam(o.Selector). + Latest() + if o.All { + b = b.ResourceTypes("deploymentconfigs").SelectAllParam(o.All) } - infos = loaded + + } + + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err } patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { @@ -258,45 +260,49 @@ func (o *DeploymentHookOptions) Run() error { if !ok { return false, nil } - updated, err := o.updateDeploymentConfig(dc) - return updated, err + return o.updateDeploymentConfig(dc) }) if singleItemImplied && len(patches) == 0 { - return fmt.Errorf("%s/%s is not a deployment config or does not have an applicable strategy", infos[0].Mapping.Resource, infos[0].Name) - } - - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return o.PrintObject(infos) + name := infos[0].Name + if infos[0].Mapping != nil { + name = fmt.Sprintf("%s/%s", infos[0].Mapping.Resource.Resource, infos[0].Name) + } + return fmt.Errorf("%s is not a deployment config or does not have an applicable strategy", name) } - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) + continue + } + + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } continue } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - fmt.Fprintf(o.Err, "error: %v\n", err) - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch deployment hook: %v\n", err)) continue } - info.Refresh(obj, true) - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) } func (o *DeploymentHookOptions) updateDeploymentConfig(dc *appsv1.DeploymentConfig) (bool, error) { @@ -395,7 +401,7 @@ func (o *DeploymentHookOptions) lifecycleHook(dc *appsv1.DeploymentConfig) (*app } } if !found { - fmt.Fprintf(o.Err, "warning: deployment config %q does not have a container named %q\n", dc.Name, o.Container) + fmt.Fprintf(o.ErrOut, "warning: deployment config %q does not have a container named %q\n", dc.Name, o.Container) } hook.ExecNewPod.ContainerName = o.Container } @@ -426,7 +432,7 @@ func (o *DeploymentHookOptions) lifecycleHook(dc *appsv1.DeploymentConfig) (*app } } if !found { - fmt.Fprintf(o.Err, "warning: deployment config %q does not have a volume named %q\n", dc.Name, v) + fmt.Fprintf(o.ErrOut, "warning: deployment config %q does not have a volume named %q\n", dc.Name, v) } } hook.ExecNewPod.Volumes = o.Volumes diff --git a/pkg/oc/cli/cmd/set/env.go b/pkg/oc/cli/cmd/set/env.go index 7b8f192b24ed..5c608a4f7d1c 100644 --- a/pkg/oc/cli/cmd/set/env.go +++ b/pkg/oc/cli/cmd/set/env.go @@ -4,31 +4,35 @@ import ( "encoding/json" "errors" "fmt" - "io" - "os" "regexp" "sort" "strings" - "github.com/openshift/origin/pkg/oc/util/ocscheme" "github.com/spf13/cobra" + + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/client-go/dynamic" + "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" kinternalclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" - buildapi "github.com/openshift/origin/pkg/build/apis/build" + buildv1 "github.com/openshift/api/build/v1" cmdutil "github.com/openshift/origin/pkg/cmd/util" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" utilenv "github.com/openshift/origin/pkg/oc/util/env" + "github.com/openshift/origin/pkg/oc/util/ocscheme" envresolve "github.com/openshift/origin/pkg/pod/envresolve" ) @@ -81,81 +85,78 @@ var ( ) type EnvOptions struct { - Out io.Writer - Err io.Writer - In io.Reader + PrintFlags *genericclioptions.PrintFlags - Filenames []string EnvParams []string EnvArgs []string Resources []string - All bool - Resolve bool - List bool - ShortOutput bool - Local bool - Overwrite bool + All bool + Resolve bool + List bool + Local bool + Overwrite bool + DryRun bool ResourceVersion string ContainerSelector string Selector string - Output string From string Prefix string - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Cmd *cobra.Command + UpdatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc + Builder func() *resource.Builder + Encoder runtime.Encoder + Mapper meta.RESTMapper + Client dynamic.Interface + KubeClient kinternalclientset.Interface + Printer printers.ResourcePrinter + Namespace string + ExplicitNamespace bool + + genericclioptions.IOStreams + resource.FilenameOptions +} - Mapper meta.RESTMapper - Client dynamic.Interface +func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions { + return &EnvOptions{ + PrintFlags: genericclioptions.NewPrintFlags("updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, - PrintObject func([]*resource.Info) error + ContainerSelector: "*", + Overwrite: true, + } } // NewCmdEnv implements the OpenShift cli env command func NewCmdEnv(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &EnvOptions{ - In: streams.In, - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewEnvOptions(streams) cmd := &cobra.Command{ Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N", Short: "Update environment variables on a pod template", Long: envLong, Example: fmt.Sprintf(envExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - err := options.RunEnv(f) - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.RunEnv()) }, } - - cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", "*", "The names of containers in the selected pod templates to change - may use wildcards") - cmd.Flags().StringP("from", "", "", "The name of a resource from which to inject environment variables") - cmd.Flags().StringP("prefix", "", "", "Prefix to append to variable names") - cmd.Flags().StringArrayVarP(&options.EnvParams, "env", "e", options.EnvParams, "Specify a key-value pair for an environment variable to set into each container.") - cmd.Flags().BoolVar(&options.List, "list", options.List, "If true, display the environment and any changes in the standard format") - cmd.Flags().BoolVar(&options.Resolve, "resolve", options.Resolve, "If true, show secret or configmap references when listing variables") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - cmd.Flags().BoolVar(&options.Overwrite, "overwrite", true, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.") - cmd.Flags().String("resource-version", "", "If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.ContainerSelector, "containers", "c", o.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards") + cmd.Flags().StringVar(&o.From, "from", o.From, "The name of a resource from which to inject environment variables") + cmd.Flags().StringVar(&o.Prefix, "prefix", o.Prefix, "Prefix to append to variable names") + cmd.Flags().StringArrayVarP(&o.EnvParams, "env", "e", o.EnvParams, "Specify a key-value pair for an environment variable to set into each container.") + cmd.Flags().BoolVar(&o.List, "list", o.List, "If true, display the environment and any changes in the standard format") + cmd.Flags().BoolVar(&o.Resolve, "resolve", o.Resolve, "If true, show secret or configmap references when listing variables") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Overwrite, "overwrite", o.Overwrite, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.") + cmd.Flags().StringVar(&o.ResourceVersion, "resource-version", o.ResourceVersion, "If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") kcmdutil.AddDryRunFlag(cmd) - kcmdutil.AddPrinterFlags(cmd) - - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") + o.PrintFlags.AddFlags(cmd) return cmd } @@ -175,96 +176,90 @@ func keyToEnvName(key string) string { } func (o *EnvOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - resources, envArgs, ok := utilenv.SplitEnvironmentFromResources(args) + var ok bool + o.Resources, o.EnvArgs, ok = utilenv.SplitEnvironmentFromResources(args) if !ok { return kcmdutil.UsageErrorf(cmd, "all resources must be specified before environment changes: %s", strings.Join(args, " ")) } - if len(o.Filenames) == 0 && len(resources) < 1 { + if len(o.Filenames) == 0 && len(o.Resources) < 1 { return kcmdutil.UsageErrorf(cmd, "one or more resources must be specified as or /") } - o.ContainerSelector = kcmdutil.GetFlagString(cmd, "containers") - o.List = kcmdutil.GetFlagBool(cmd, "list") - o.Resolve = kcmdutil.GetFlagBool(cmd, "resolve") - o.Selector = kcmdutil.GetFlagString(cmd, "selector") - o.All = kcmdutil.GetFlagBool(cmd, "all") - o.Overwrite = kcmdutil.GetFlagBool(cmd, "overwrite") - o.ResourceVersion = kcmdutil.GetFlagString(cmd, "resource-version") - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.From = kcmdutil.GetFlagString(cmd, "from") - o.Prefix = kcmdutil.GetFlagString(cmd, "prefix") - - o.EnvArgs = envArgs - o.Resources = resources - o.Cmd = cmd - - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - - clientConfig, err := f.ToRESTConfig() + var err error + o.KubeClient, err = f.ClientSet() if err != nil { return err } - o.Client, err = dynamic.NewForConfig(clientConfig) + + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - if o.List && len(o.Output) > 0 { - return kcmdutil.UsageErrorf(o.Cmd, "--list and --output may not be specified together") + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - return nil -} + o.Builder = f.NewBuilder + o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn -// RunEnv contains all the necessary functionality for the OpenShift cli env command -// TODO: refactor to share the common "patch resource" pattern of probe -func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { clientConfig, err := f.ToRESTConfig() if err != nil { return err } - - kubeClient, err := kinternalclientset.NewForConfig(clientConfig) + o.Client, err = dynamic.NewForConfig(clientConfig) if err != nil { return err } - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() - if err != nil { - return err + if o.List && o.PrintFlags.OutputFormat != nil && len(*o.PrintFlags.OutputFormat) > 0 { + return kcmdutil.UsageErrorf(cmd, "--list and --output may not be specified together") } - cmdutil.WarnAboutCommaSeparation(o.Err, o.EnvParams, "--env") + cmdutil.WarnAboutCommaSeparation(o.ErrOut, o.EnvParams, "--env") + + return nil +} +// RunEnv contains all the necessary functionality for the OpenShift cli env command +// TODO: refactor to share the common "patch resource" pattern of probe +// TODO: figure out how we can replace this with upstream counterpart +func (o *EnvOptions) RunEnv() error { env, remove, err := utilenv.ParseEnv(append(o.EnvParams, o.EnvArgs...), o.In) if err != nil { return err } if len(o.From) != 0 { - b := f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). Flatten() if !o.Local { b = b. LabelSelectorParam(o.Selector). - ResourceTypeOrNameArgs(o.All, o.From) + ResourceTypeOrNameArgs(o.All, o.From). + Latest() } - one := false - infos, err := b.Do().IntoSingleItemImplied(&one).Infos() + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { return err } for _, info := range infos { switch from := info.Object.(type) { - case *kapi.Secret: + case *corev1.Secret: for key := range from.Data { envVar := kapi.EnvVar{ Name: keyToEnvName(key), @@ -279,7 +274,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { } env = append(env, envVar) } - case *kapi.ConfigMap: + case *corev1.ConfigMap: for key := range from.Data { envVar := kapi.EnvVar{ Name: keyToEnvName(key), @@ -295,7 +290,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { env = append(env, envVar) } default: - return fmt.Errorf("unsupported resource specified in --from") + return fmt.Errorf("unsupported resource specified in --from: %T", from) } } } @@ -306,29 +301,30 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { } } - b := f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). Flatten() if !o.Local { b = b. LabelSelectorParam(o.Selector). - ResourceTypeOrNameArgs(o.All, o.Resources...) + ResourceTypeOrNameArgs(o.All, o.Resources...). + Latest() } - one := false - infos, err := b.Do().IntoSingleItemImplied(&one).Infos() + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { return err } // only apply resource version locking on a single resource - if !one && len(o.ResourceVersion) > 0 { - return kcmdutil.UsageErrorf(o.Cmd, "--resource-version may only be used with a single resource") + if !singleItemImplied && len(o.ResourceVersion) > 0 { + return fmt.Errorf("--resource-version may only be used with a single resource") } // Keep a copy of the original objects prior to updating their environment. // Used in constructing the patch(es) that will be applied in the server. @@ -346,11 +342,12 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { skipped := 0 errored := []*resource.Info{} for _, info := range infos { - ok, err := polymorphichelpers.UpdatePodSpecForObjectFn(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { + name := cmd.GetObjectName(info) + ok, err := o.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { resolutionErrorsEncountered := false containers, _ := selectContainers(spec.Containers, o.ContainerSelector) if len(containers) == 0 { - fmt.Fprintf(o.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) + fmt.Fprintf(o.ErrOut, "warning: %s does not have any containers matching %q\n", name, o.ContainerSelector) return nil } for _, c := range containers { @@ -367,7 +364,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { resolveErrors := map[string][]string{} store := envresolve.NewResourceStore() - fmt.Fprintf(o.Out, "# %s %s, container %s\n", info.Mapping.Resource.Resource, info.Name, c.Name) + fmt.Fprintf(o.Out, "# %s, container %s\n", name, c.Name) for _, env := range c.Env { // Print the simple value if env.ValueFrom == nil { @@ -381,7 +378,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { continue } - value, err := envresolve.GetEnvVarRefValue(kubeClient, cmdNamespace, store, env.ValueFrom, info.Object, c) + value, err := envresolve.GetEnvVarRefValue(o.KubeClient, o.Namespace, store, env.ValueFrom, info.Object, c) // Print the resolved value if err == nil { fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value) @@ -403,7 +400,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { } sort.Strings(errs) for _, err := range errs { - fmt.Fprintln(o.Err, err) + fmt.Fprintln(o.ErrOut, err) } } } @@ -427,7 +424,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { } *vars = updateEnv(*vars, env, remove) if o.List { - fmt.Fprintf(o.Out, "# %s %s\n", info.Mapping.Resource.Resource, info.Name) + fmt.Fprintf(o.Out, "# %s\n", name) for _, env := range *vars { fmt.Fprintf(o.Out, "%s=%s\n", env.Name, env.Value) } @@ -440,12 +437,13 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { } } if err != nil { - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, err) + fmt.Fprintf(o.ErrOut, "error: %s %v\n", name, err) continue } } - if one && skipped == len(infos) { - return fmt.Errorf("%s/%s is not a pod or does not have a pod template", infos[0].Mapping.Resource.Resource, infos[0].Name) + if singleItemImplied && skipped == len(infos) { + name := cmd.GetObjectName(infos[0]) + return fmt.Errorf("%s is not a pod or does not have a pod template", name) } if len(errored) == len(infos) { return kcmdutil.ErrExit @@ -455,11 +453,7 @@ func (o *EnvOptions) RunEnv(f kcmdutil.Factory) error { return nil } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return clientcmd.PrintResourceInfos(o.Cmd, infos, o.Out) - } - - failed := false + allErrs := []error{} updates: for i, info := range infos { for _, erroredInfo := range errored { @@ -467,19 +461,28 @@ updates: continue updates } } + + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } + continue + } + newData, err := json.Marshal(kcmdutil.AsDefaultVersionedOrOriginal(infos[i].Object, nil)) if err != nil { - return err + allErrs = append(allErrs, err) + continue } patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData[i], newData, kcmdutil.AsDefaultVersionedOrOriginal(infos[i].Object, nil)) if err != nil { - return err + allErrs = append(allErrs, err) + continue } - actualObj, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patchBytes) + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patchBytes) if err != nil { - handlePodUpdateError(o.Err, err, "environment variables") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to set env: %v\n", err)) continue } @@ -489,30 +492,48 @@ updates: return fmt.Errorf("at least one environment variable must be provided") } - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, actualObj, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) } // UpdateObjectEnvironment update the environment variables in object specification. func updateObjectEnvironment(obj runtime.Object, fn func(*[]kapi.EnvVar) error) (bool, error) { switch t := obj.(type) { - case *buildapi.BuildConfig: + case *buildv1.BuildConfig: if t.Spec.Strategy.CustomStrategy != nil { - return true, fn(&t.Spec.Strategy.CustomStrategy.Env) + return true, convertInternalEnvVarToExternal(fn)(&t.Spec.Strategy.CustomStrategy.Env) } if t.Spec.Strategy.SourceStrategy != nil { - return true, fn(&t.Spec.Strategy.SourceStrategy.Env) + return true, convertInternalEnvVarToExternal(fn)(&t.Spec.Strategy.SourceStrategy.Env) } if t.Spec.Strategy.DockerStrategy != nil { - return true, fn(&t.Spec.Strategy.DockerStrategy.Env) + return true, convertInternalEnvVarToExternal(fn)(&t.Spec.Strategy.DockerStrategy.Env) } if t.Spec.Strategy.JenkinsPipelineStrategy != nil { - return true, fn(&t.Spec.Strategy.JenkinsPipelineStrategy.Env) + return true, convertInternalEnvVarToExternal(fn)(&t.Spec.Strategy.JenkinsPipelineStrategy.Env) + } + } + return false, fmt.Errorf("object does not contain any environment variables %T", obj) +} + +// TODO: this needs to die when switching to external versions +func convertInternalEnvVarToExternal(inFn func(*[]kapi.EnvVar) error) func(*[]corev1.EnvVar) error { + return func(specToMutate *[]corev1.EnvVar) error { + externalEnvVar := &[]kapi.EnvVar{} + if err := legacyscheme.Scheme.Convert(specToMutate, externalEnvVar, nil); err != nil { + return err + } + if err := inFn(externalEnvVar); err != nil { + return err } + internalEnvVar := &[]corev1.EnvVar{} + if err := legacyscheme.Scheme.Convert(externalEnvVar, internalEnvVar, nil); err != nil { + return err + } + *specToMutate = *internalEnvVar + return nil } - return false, fmt.Errorf("object does not contain any environment variables") } diff --git a/pkg/oc/cli/cmd/set/imagelookup.go b/pkg/oc/cli/cmd/set/imagelookup.go index 1af9de70714c..c5ee75244812 100644 --- a/pkg/oc/cli/cmd/set/imagelookup.go +++ b/pkg/oc/cli/cmd/set/imagelookup.go @@ -2,24 +2,24 @@ package set import ( "fmt" - "io" "text/tabwriter" "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + imagev1 "github.com/openshift/api/image/v1" ometa "github.com/openshift/origin/pkg/api/meta" - imageapi "github.com/openshift/origin/pkg/image/apis/image" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -81,166 +81,161 @@ var ( const alphaResolveNamesAnnotation = "alpha.image.policy.openshift.io/resolve-names" type ImageLookupOptions struct { - Out io.Writer - Err io.Writer - - Filenames []string - Selector string - All bool - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - ShortOutput bool - Mapper meta.RESTMapper - OutputVersion schema.GroupVersion - - PrintTable bool - PrintObject func(runtime.Object) error - - List bool - Local bool + PrintFlags *genericclioptions.PrintFlags + + Selector string + All bool + List bool + Local bool + Enabled bool + PrintTable bool + + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Namespace string + ExplicitNamespace bool + DryRun bool + Args []string + + resource.FilenameOptions + genericclioptions.IOStreams +} - Enabled bool +func NewImageLookupOptions(streams genericclioptions.IOStreams) *ImageLookupOptions { + return &ImageLookupOptions{ + PrintFlags: genericclioptions.NewPrintFlags("image lookup updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + Enabled: true, + } } // NewCmdImageLookup implements the set image-lookup command func NewCmdImageLookup(fullName, parentName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &ImageLookupOptions{ - Out: streams.Out, - Err: streams.ErrOut, - Enabled: true, - } + o := NewImageLookupOptions(streams) cmd := &cobra.Command{ Use: "image-lookup STREAMNAME [...]", Short: "Change how images are resolved when deploying applications", Long: fmt.Sprintf(imageLookupLong, fullName, parentName), Example: fmt.Sprintf(imageLookupExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - kcmdutil.CheckErr(options.Run()) + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on.") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types.") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.List, "list", false, "Display the current states of the requested resources.") - cmd.Flags().BoolVar(&options.Enabled, "enabled", options.Enabled, "Mark the image stream as resolving tagged images in this namespace.") - - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, operations will be performed locally.") + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on.") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types.") + cmd.Flags().BoolVar(&o.List, "list", o.List, "Display the current states of the requested resources.") + cmd.Flags().BoolVar(&o.Enabled, "enabled", o.Enabled, "Mark the image stream as resolving tagged images in this namespace.") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, operations will be performed locally.") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") return cmd } // Complete takes command line information to fill out ImageLookupOptions or returns an error. func (o *ImageLookupOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - clientConfig, err := f.ToRESTConfig() + o.PrintTable = (o.PrintFlags.OutputFormat == nil && len(args) == 0 && !o.All) || o.List + + o.Args = args + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } + o.Builder = f.NewBuilder - outputVersionString := kcmdutil.GetFlagString(cmd, "output-version") - if len(outputVersionString) == 0 { - o.OutputVersion = *clientConfig.GroupVersion - } else { - o.OutputVersion, err = schema.ParseGroupVersion(outputVersionString) - if err != nil { - return err - } + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.PrintTable = (len(args) == 0 && !o.All) || o.List - - mapper, err := f.ToRESTMapper() + clientConfig, err := f.ToRESTConfig() if err != nil { return err } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). + o.Client, err = dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } + + return nil +} + +func (o *ImageLookupOptions) Validate() error { + if o.Local && len(o.Args) > 0 { + return fmt.Errorf("pass files with -f when using --local") + } + + return nil +} + +// Run executes the ImageLookupOptions or returns an error. +func (o *ImageLookupOptions) Run() error { + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). LocalParam(o.Local). ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). Flatten() switch { - case o.Local && len(args) > 0: - return kcmdutil.UsageErrorf(cmd, "Pass files with -f when using --local") case o.Local: // perform no lookups on the server // TODO: discovery still requires a running server, doesn't fall back correctly - case len(args) == 0 && len(o.Filenames) == 0: - o.Builder = o.Builder. + case len(o.Args) == 0 && len(o.Filenames) == 0: + b = b. LabelSelectorParam(o.Selector). SelectAllParam(true). ResourceTypes("imagestreams") case o.List: - o.Builder = o.Builder. + b = b. LabelSelectorParam(o.Selector). SelectAllParam(o.All). - ResourceTypeOrNameArgs(true, args...) + ResourceTypeOrNameArgs(true, o.Args...) default: - o.Builder = o.Builder. + b = b. LabelSelectorParam(o.Selector). SelectAllParam(o.All). - ResourceNames("imagestreams", args...) - } - - output := kcmdutil.GetFlagString(cmd, "output") - if len(output) != 0 || o.Local || kcmdutil.GetDryRunFlag(cmd) { - o.PrintObject = func(obj runtime.Object) error { return kcmdutil.PrintObject(cmd, obj, o.Out) } + ResourceNames("imagestreams", o.Args...). + Latest() } - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper - - return nil -} - -// Validate verifies the provided options are valid or returns an error. -func (o *ImageLookupOptions) Validate() error { - return nil -} - -// Run executes the ImageLookupOptions or returns an error. -func (o *ImageLookupOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err - } - infos = loaded + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err } - if o.PrintTable && o.PrintObject == nil { + if o.PrintTable { return o.printImageLookup(infos) } - patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { + patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { switch t := info.Object.(type) { - case *imageapi.ImageStream: + case *imagev1.ImageStream: t.Spec.LookupPolicy.Local = o.Enabled return true, nil default: accessor, ok := ometa.GetAnnotationAccessor(info.Object) if !ok { - return true, fmt.Errorf("the resource %s/%s does not support altering image lookup", info.Mapping.Resource, info.Name) + return true, fmt.Errorf("the resource %s does not support altering image lookup", cmd.GetObjectName(info)) } templateAnnotations, ok := accessor.TemplateAnnotations() if ok { @@ -268,50 +263,40 @@ func (o *ImageLookupOptions) Run() error { return true, nil } }) - if singleItemImplied && len(patches) == 0 { - return fmt.Errorf("%s/%s no changes", infos[0].Mapping.Resource, infos[0].Name) - } - if o.PrintObject != nil { - allErrs := []error{} - for i := range infos { - if err := o.PrintObject(kcmdutil.AsDefaultVersionedOrOriginal(infos[i].Object, infos[i].Mapping)); err != nil { - allErrs = append(allErrs, err) - } - } - - return utilerrors.NewAggregate(allErrs) - } - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - failed = true - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - glog.V(4).Infof("Calculated patch %s", patch.Patch) + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } + continue + } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - handlePodUpdateError(o.Err, err, "altered") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch image lookup: %v\n", err)) continue } - info.Refresh(obj, true) - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) + } // printImageLookup displays a tabular output of the imageLookup for each object. @@ -321,13 +306,14 @@ func (o *ImageLookupOptions) printImageLookup(infos []*resource.Info) error { fmt.Fprintf(w, "NAME\tLOCAL\n") for _, info := range infos { switch t := info.Object.(type) { - case *imageapi.ImageStream: + case *imagev1.ImageStream: fmt.Fprintf(w, "%s\t%t\n", info.Name, t.Spec.LookupPolicy.Local) default: + name := cmd.GetObjectName(info) accessor, ok := ometa.GetAnnotationAccessor(info.Object) if !ok { // has no annotations - fmt.Fprintf(w, "%s/%s\tUNKNOWN\n", info.Mapping.Resource, info.Name) + fmt.Fprintf(w, "%s\tUNKNOWN\n", name) break } var enabled bool @@ -337,7 +323,7 @@ func (o *ImageLookupOptions) printImageLookup(infos []*resource.Info) error { if !enabled { enabled = accessor.Annotations()[alphaResolveNamesAnnotation] == "*" } - fmt.Fprintf(w, "%s/%s\t%t\n", info.Mapping.Resource, info.Name, enabled) + fmt.Fprintf(w, "%s\t%t\n", name, enabled) } } return nil diff --git a/pkg/oc/cli/cmd/set/probe.go b/pkg/oc/cli/cmd/set/probe.go index ff836550417b..2900132f7135 100644 --- a/pkg/oc/cli/cmd/set/probe.go +++ b/pkg/oc/cli/cmd/set/probe.go @@ -2,27 +2,29 @@ package set import ( "fmt" - "io" "net" "net/url" - "os" "strconv" "strings" + "github.com/golang/glog" "github.com/spf13/cobra" - "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/dynamic" kapi "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -70,40 +72,32 @@ var ( ) type ProbeOptions struct { - Out io.Writer - Err io.Writer + PrintFlags *genericclioptions.PrintFlags - Filenames []string ContainerSelector string Selector string All bool - Output string - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Cmd *cobra.Command - - ShortOutput bool - Mapper meta.RESTMapper - - PrintObject func([]*resource.Info) error - UpdatePodSpecForObject func(runtime.Object, func(spec *v1.PodSpec) error) (bool, error) - - Readiness bool - Liveness bool - Remove bool - Local bool - - OpenTCPSocket string - HTTPGet string - Command []string + Readiness bool + Liveness bool + Remove bool + Local bool + OpenTCPSocket string + HTTPGet string + + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Encoder runtime.Encoder + Namespace string + ExplicitNamespace bool + UpdatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc + Command []string + Resources []string + DryRun bool FlagSet func(string) bool HTTPGetAction *kapi.HTTPGetAction - Client dynamic.Interface // Length of time before health checking is activated. In seconds. InitialDelaySeconds *int @@ -116,104 +110,90 @@ type ProbeOptions struct { SuccessThreshold *int // Minimum consecutive failures for the probe to be considered failed after having succeeded. FailureThreshold *int + + resource.FilenameOptions + genericclioptions.IOStreams } -// NewCmdProbe implements the set probe command -func NewCmdProbe(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &ProbeOptions{ - Out: streams.Out, - Err: streams.ErrOut, +func NewProbeOptions(streams genericclioptions.IOStreams) *ProbeOptions { + return &ProbeOptions{ + PrintFlags: genericclioptions.NewPrintFlags("probes updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, ContainerSelector: "*", } +} + +// NewCmdProbe implements the set probe command +func NewCmdProbe(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewProbeOptions(streams) cmd := &cobra.Command{ Use: "probe RESOURCE/NAME --readiness|--liveness [flags] (--get-url=URL|--open-tcp=PORT|-- CMD)", Short: "Update a probe on a pod template", Long: probeLong, Example: fmt.Sprintf(probeExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", options.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards") - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.Remove, "remove", options.Remove, "If true, remove the specified probe(s).") - cmd.Flags().BoolVar(&options.Readiness, "readiness", options.Readiness, "Set or remove a readiness probe to indicate when this container should receive traffic") - cmd.Flags().BoolVar(&options.Liveness, "liveness", options.Liveness, "Set or remove a liveness probe to verify this container is running") - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - - cmd.Flags().StringVar(&options.OpenTCPSocket, "open-tcp", options.OpenTCPSocket, "A port number or port name to attempt to open via TCP.") - cmd.Flags().StringVar(&options.HTTPGet, "get-url", options.HTTPGet, "A URL to perform an HTTP GET on (you can omit the host, have a string port, or omit the scheme.") - options.InitialDelaySeconds = cmd.Flags().Int("initial-delay-seconds", 0, "The time in seconds to wait before the probe begins checking") - options.SuccessThreshold = cmd.Flags().Int("success-threshold", 0, "The number of successes required before the probe is considered successful") - options.FailureThreshold = cmd.Flags().Int("failure-threshold", 0, "The number of failures before the probe is considered to have failed") - options.PeriodSeconds = cmd.Flags().Int("period-seconds", 0, "The time in seconds between attempts") - options.TimeoutSeconds = cmd.Flags().Int("timeout-seconds", 0, "The time in seconds to wait before considering the probe to have failed") - + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.ContainerSelector, "containers", "c", o.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards") + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove the specified probe(s).") + cmd.Flags().BoolVar(&o.Readiness, "readiness", o.Readiness, "Set or remove a readiness probe to indicate when this container should receive traffic") + cmd.Flags().BoolVar(&o.Liveness, "liveness", o.Liveness, "Set or remove a liveness probe to verify this container is running") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + cmd.Flags().StringVar(&o.OpenTCPSocket, "open-tcp", o.OpenTCPSocket, "A port number or port name to attempt to open via TCP.") + cmd.Flags().StringVar(&o.HTTPGet, "get-url", o.HTTPGet, "A URL to perform an HTTP GET on (you can omit the host, have a string port, or omit the scheme.") + + o.InitialDelaySeconds = cmd.Flags().Int("initial-delay-seconds", 0, "The time in seconds to wait before the probe begins checking") + o.SuccessThreshold = cmd.Flags().Int("success-threshold", 0, "The number of successes required before the probe is considered successful") + o.FailureThreshold = cmd.Flags().Int("failure-threshold", 0, "The number of failures before the probe is considered to have failed") + o.PeriodSeconds = cmd.Flags().Int("period-seconds", 0, "The time in seconds between attempts") + o.TimeoutSeconds = cmd.Flags().Int("timeout-seconds", 0, "The time in seconds to wait before considering the probe to have failed") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") return cmd } func (o *ProbeOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - resources := args + o.Resources = args if i := cmd.ArgsLenAtDash(); i != -1 { - resources = args[:i] + o.Resources = args[:i] o.Command = args[i:] } if len(o.Filenames) == 0 && len(args) < 1 { return kcmdutil.UsageErrorf(cmd, "one or more resources must be specified as or /") } - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - o.Cmd = cmd - - mapper, err := f.ToRESTMapper() + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - Flatten() + o.Builder = f.NewBuilder + o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn - if !o.Local { - o.Builder = o.Builder. - LabelSelectorParam(o.Selector). - ResourceTypeOrNameArgs(o.All, resources...) + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, o.Out) + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper - if !cmd.Flags().Lookup("initial-delay-seconds").Changed { o.InitialDelaySeconds = nil } @@ -266,7 +246,7 @@ func (o *ProbeOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []s func (o *ProbeOptions) Validate() error { if !o.Readiness && !o.Liveness { - return fmt.Errorf("you must specify one of --readiness or --liveness or both") + return fmt.Errorf("you must specify one of --readiness, --liveness or both") } count := 0 if o.Command != nil { @@ -302,26 +282,42 @@ func (o *ProbeOptions) Validate() error { if o.PeriodSeconds != nil && *o.PeriodSeconds < 0 { return fmt.Errorf("--period-seconds may not be negative") } + if len(o.HTTPGet) > 0 && len(o.HTTPGetAction.Port.String()) == 0 { + return fmt.Errorf("port must be specified as part of a url") + } + return nil } func (o *ProbeOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err - } - infos = loaded + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + + if !o.Local { + b = b. + LabelSelectorParam(o.Selector). + ResourceTypeOrNameArgs(o.All, o.Resources...). + Latest() } - patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err + } + + patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { transformed := false + name := cmd.GetObjectName(info) _, err := o.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { containers, _ := selectContainers(spec.Containers, o.ContainerSelector) if len(containers) == 0 { - fmt.Fprintf(o.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) + fmt.Fprintf(o.ErrOut, "warning: %s does not have any containers matching %q\n", name, o.ContainerSelector) return nil } // perform updates @@ -337,41 +333,39 @@ func (o *ProbeOptions) Run() error { return fmt.Errorf("%s/%s is not a pod or does not have a pod template", infos[0].Mapping.Resource, infos[0].Name) } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return o.PrintObject(infos) - } - - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - actualObj, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) - if err != nil { - // if no port was specified, inform that one must be provided - if len(o.HTTPGet) > 0 && len(o.HTTPGetAction.Port.String()) == 0 { - fmt.Fprintf(o.Err, "A port must be specified as part of a url (http://127.0.0.1:3306).\n\nSee 'oc set probe -h' for help and examples.\n") + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) } - handlePodUpdateError(o.Err, err, "probes") + continue + } - failed = true + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) + if err != nil { + allErrs = append(allErrs, err) continue } - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, actualObj, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) + } func (o *ProbeOptions) updateContainer(container *kapi.Container) { diff --git a/pkg/oc/cli/cmd/set/routebackends.go b/pkg/oc/cli/cmd/set/routebackends.go index 5244cfc07a5b..930dd1828367 100644 --- a/pkg/oc/cli/cmd/set/routebackends.go +++ b/pkg/oc/cli/cmd/set/routebackends.go @@ -2,8 +2,6 @@ package set import ( "fmt" - "io" - "os" "strconv" "strings" "text/tabwriter" @@ -13,17 +11,19 @@ import ( "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" - kapi "k8s.io/kubernetes/pkg/apis/core" + "k8s.io/client-go/dynamic" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + routev1 "github.com/openshift/api/route/v1" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" - routeapi "github.com/openshift/origin/pkg/route/apis/route" ) var ( @@ -72,82 +72,74 @@ var ( ) type BackendsOptions struct { - Out io.Writer - Err io.Writer - - Filenames []string - Selector string - All bool - Output string - - Cmd *cobra.Command - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Local bool - ShortOutput bool - Mapper meta.RESTMapper - OutputVersion schema.GroupVersion - - PrintTable bool - PrintObject func(runtime.Object) error + PrintFlags *genericclioptions.PrintFlags + + Selector string + All bool + Local bool + PrintTable bool + Transform BackendTransform + + Mapper meta.RESTMapper + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Namespace string + ExplicitNamespace bool + DryRun bool + Resources []string + + resource.FilenameOptions + genericclioptions.IOStreams +} - Transform BackendTransform +func NewBackendsOptions(streams genericclioptions.IOStreams) *BackendsOptions { + return &BackendsOptions{ + PrintFlags: genericclioptions.NewPrintFlags("backends updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + } } // NewCmdRouteBackends implements the set route-backends command func NewCmdRouteBackends(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &BackendsOptions{ - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewBackendsOptions(streams) cmd := &cobra.Command{ Use: "route-backends ROUTENAME [--zero|--equal] [--adjust] SERVICE=WEIGHT[%] [...]", Short: "Update the backends for a route", Long: fmt.Sprintf(backendsLong, fullName), Example: fmt.Sprintf(backendsExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - err := options.Run() - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - - cmd.Flags().BoolVar(&options.Transform.Adjust, "adjust", options.Transform.Adjust, "Adjust a single backend using an absolute or relative weight. If the primary backend is selected and there is more than one alternate an error will be returned.") - cmd.Flags().BoolVar(&options.Transform.Zero, "zero", options.Transform.Zero, "If true, set the weight of all backends to zero.") - cmd.Flags().BoolVar(&options.Transform.Equal, "equal", options.Transform.Equal, "If true, set the weight of all backends to 100.") - + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + cmd.Flags().BoolVar(&o.Transform.Adjust, "adjust", o.Transform.Adjust, "Adjust a single backend using an absolute or relative weight. If the primary backend is selected and there is more than one alternate an error will be returned.") + cmd.Flags().BoolVar(&o.Transform.Zero, "zero", o.Transform.Zero, "If true, set the weight of all backends to zero.") + cmd.Flags().BoolVar(&o.Transform.Equal, "equal", o.Transform.Equal, "If true, set the weight of all backends to 100.") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") return cmd } // Complete takes command line information to fill out BackendOptions or returns an error. func (o *BackendsOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - var resources []string for _, arg := range args { if !strings.Contains(arg, "=") { - resources = append(resources, arg) + o.Resources = append(o.Resources, arg) continue } input, err := ParseBackendInput(arg) @@ -159,36 +151,29 @@ func (o *BackendsOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args o.PrintTable = o.Transform.Empty() - o.Cmd = cmd - - mapper, err := f.ToRESTMapper() + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - Flatten() - if !o.Local { - o.Builder = o.Builder. - LabelSelectorParam(o.Selector). - SelectAllParam(o.All). - ResourceNames("route", resources...) + o.Builder = f.NewBuilder - if len(resources) == 0 { - o.Builder.ResourceTypes("routes") - } + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(obj runtime.Object) error { return kcmdutil.PrintObject(cmd, obj, o.Out) } - - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper + clientConfig, err := f.ToRESTConfig() + if err != nil { + return err + } + o.Client, err = dynamic.NewForConfig(clientConfig) + if err != nil { + return err + } return nil } @@ -200,71 +185,77 @@ func (o *BackendsOptions) Validate() error { // Run executes the BackendOptions or returns an error. func (o *BackendsOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + if !o.Local { + b = b. + LabelSelectorParam(o.Selector). + SelectAllParam(o.All). + ResourceNames("route", o.Resources...). + Latest() + if len(o.Resources) == 0 { + b = b.ResourceTypes("routes") } - infos = loaded } - if o.PrintTable && len(o.Output) == 0 { + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err + } + + if o.PrintTable { return o.printBackends(infos) } - patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { + patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { return UpdateBackendsForObject(info.Object, o.Transform.Apply) }) if singleItemImplied && len(patches) == 0 { - return fmt.Errorf("%s/%s is not a deployment config or build config", infos[0].Mapping.Resource.Resource, infos[0].Name) - } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - var object runtime.Object - if len(infos) == 1 && singleItemImplied { - object = infos[0].Object - } else { - var items []runtime.Object - for i := range infos { - items = append(items, infos[i].Object) - } - object = &kapi.List{Items: items} + name := infos[0].Name + if infos[0].Mapping != nil { + name = fmt.Sprintf("%s/%s", infos[0].Mapping.Resource.Resource, infos[0].Name) } - - return o.PrintObject(object) + return fmt.Errorf("%s is not a deployment config or build config", name) } - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - failed = true - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - glog.V(4).Infof("Calculated patch %s", patch.Patch) + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } + continue + } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - handlePodUpdateError(o.Err, err, "altered") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch route backends: %v\n", err)) continue } - info.Refresh(obj, true) - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) } // printBackends displays a tabular output of the backends for each object. @@ -415,7 +406,7 @@ func (t BackendTransform) Apply(b *Backends) error { b.Backends = nil for _, input := range t.Inputs { weight := input.Value - b.Backends = append(b.Backends, routeapi.RouteTargetReference{ + b.Backends = append(b.Backends, routev1.RouteTargetReference{ Kind: "Service", Name: input.Name, Weight: &weight, @@ -438,7 +429,7 @@ type BackendInput struct { } // Apply alters the weights of two services. -func (input *BackendInput) Apply(ref, to *routeapi.RouteTargetReference, backends []routeapi.RouteTargetReference) { +func (input *BackendInput) Apply(ref, to *routev1.RouteTargetReference, backends []routev1.RouteTargetReference) { weight := int32(100) if ref.Weight != nil { weight = *ref.Weight @@ -556,7 +547,7 @@ func ParseBackendInput(s string) (*BackendInput, error) { // Backends is a struct that represents the backends to be transformed. type Backends struct { - Backends []routeapi.RouteTargetReference + Backends []routev1.RouteTargetReference } // Names returns the referenced backend service names, in the order they appear. @@ -574,9 +565,9 @@ func (b *Backends) Names() []string { func UpdateBackendsForObject(obj runtime.Object, fn func(*Backends) error) (bool, error) { // TODO: replace with a swagger schema based approach (identify pod template via schema introspection) switch t := obj.(type) { - case *routeapi.Route: + case *routev1.Route: b := &Backends{ - Backends: []routeapi.RouteTargetReference{t.Spec.To}, + Backends: []routev1.RouteTargetReference{t.Spec.To}, } for _, backend := range t.Spec.AlternateBackends { b.Backends = append(b.Backends, backend) @@ -585,7 +576,7 @@ func UpdateBackendsForObject(obj runtime.Object, fn func(*Backends) error) (bool return true, err } if len(b.Backends) == 0 { - t.Spec.To = routeapi.RouteTargetReference{} + t.Spec.To = routev1.RouteTargetReference{} } else { t.Spec.To = b.Backends[0] } diff --git a/pkg/oc/cli/cmd/set/set.go b/pkg/oc/cli/cmd/set/set.go index 69420e42b02e..7af988a43336 100644 --- a/pkg/oc/cli/cmd/set/set.go +++ b/pkg/oc/cli/cmd/set/set.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "k8s.io/kubernetes/pkg/kubectl/cmd/set" ktemplates "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -37,6 +38,7 @@ func NewCmdSet(fullName string, f kcmdutil.Factory, streams genericclioptions.IO NewCmdEnv(name, f, streams), NewCmdResources(name, f, streams), NewCmdVolume(name, f, streams), + // TODO: this seems reasonable to upstream NewCmdProbe(name, f, streams), NewCmdDeploymentHook(name, f, streams), NewCmdImage(name, f, streams), diff --git a/pkg/oc/cli/cmd/set/set_test.go b/pkg/oc/cli/cmd/set/set_test.go index 151634f0e8aa..0d4edb14007a 100644 --- a/pkg/oc/cli/cmd/set/set_test.go +++ b/pkg/oc/cli/cmd/set/set_test.go @@ -4,9 +4,9 @@ import ( "testing" "github.com/spf13/cobra" - "k8s.io/kubernetes/pkg/kubectl/genericclioptions" kcmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions" ) func TestLocalAndDryRunFlags(t *testing.T) { diff --git a/pkg/oc/cli/cmd/set/triggers.go b/pkg/oc/cli/cmd/set/triggers.go index dbd17cecf0f8..4095361a3ada 100644 --- a/pkg/oc/cli/cmd/set/triggers.go +++ b/pkg/oc/cli/cmd/set/triggers.go @@ -3,8 +3,6 @@ package set import ( "encoding/json" "fmt" - "io" - "os" "reflect" "strings" "text/tabwriter" @@ -12,27 +10,32 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" + kappsv1 "k8s.io/api/apps/v1" + kappsv1beta1 "k8s.io/api/apps/v1beta1" + kappsv1beta2 "k8s.io/api/apps/v1beta2" + batchv1beta1 "k8s.io/api/batch/v1beta1" + batchv2alpha1 "k8s.io/api/batch/v2alpha1" + corev1 "k8s.io/api/core/v1" + extensionsv1beta1 "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/dynamic" - kapps "k8s.io/kubernetes/pkg/apis/apps" - kbatch "k8s.io/kubernetes/pkg/apis/batch" - kapi "k8s.io/kubernetes/pkg/apis/core" - kextensions "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" + appsv1 "github.com/openshift/api/apps/v1" + buildv1 "github.com/openshift/api/build/v1" ometa "github.com/openshift/origin/pkg/api/meta" - appsapi "github.com/openshift/origin/pkg/apps/apis/apps" - buildapi "github.com/openshift/origin/pkg/build/apis/build" imageapi "github.com/openshift/origin/pkg/image/apis/image" triggerapi "github.com/openshift/origin/pkg/image/apis/image/v1/trigger" "github.com/openshift/origin/pkg/image/trigger/annotations" - "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/generate/app" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -84,99 +87,88 @@ var ( ) type TriggersOptions struct { - Out io.Writer - Err io.Writer - - Filenames []string - Selector string - All bool - Output string - - Builder *resource.Builder - Infos []*resource.Info - - Encoder runtime.Encoder - - Cmd *cobra.Command - - Local bool - ShortOutput bool - Mapper meta.RESTMapper - Client dynamic.Interface - - PrintTable bool - PrintObject func([]*resource.Info) error - - Remove bool - RemoveAll bool - Auto bool - Manual bool - Reset bool - + PrintFlags *genericclioptions.PrintFlags + + Selector string + All bool + Local bool + Remove bool + RemoveAll bool + Auto bool + Manual bool + Reset bool ContainerNames string FromConfig bool + FromImage string FromGitHub *bool FromWebHook *bool FromWebHookAllowEnv *bool FromGitLab *bool FromBitbucket *bool - FromImage string // FromImageNamespace is the namespace for the FromImage FromImageNamespace string + + PrintTable bool + Client dynamic.Interface + Printer printers.ResourcePrinter + Builder func() *resource.Builder + Namespace string + ExplicitNamespace bool + DryRun bool + Args []string + + resource.FilenameOptions + genericclioptions.IOStreams +} + +func NewTriggersOptions(streams genericclioptions.IOStreams) *TriggersOptions { + return &TriggersOptions{ + PrintFlags: genericclioptions.NewPrintFlags("triggers updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + IOStreams: streams, + } } // NewCmdTriggers implements the set triggers command func NewCmdTriggers(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - options := &TriggersOptions{ - Out: streams.Out, - Err: streams.ErrOut, - } + o := NewTriggersOptions(streams) cmd := &cobra.Command{ Use: "triggers RESOURCE/NAME [--from-config|--from-image|--from-github|--from-webhook] [--auto|--manual]", Short: "Update the triggers on one or more objects", Long: triggersLong, Example: fmt.Sprintf(triggersExample, fullName), Run: func(cmd *cobra.Command, args []string) { - kcmdutil.CheckErr(options.Complete(f, cmd, args)) - kcmdutil.CheckErr(options.Validate()) - if err := options.Run(); err != nil { - // TODO: move me to kcmdutil - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) - } + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.Run()) }, } - - kcmdutil.AddPrinterFlags(cmd) - cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on") - cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().StringSliceVarP(&options.Filenames, "filename", "f", options.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - - cmd.Flags().BoolVar(&options.Remove, "remove", options.Remove, "If true, remove the specified trigger(s).") - cmd.Flags().BoolVar(&options.RemoveAll, "remove-all", options.RemoveAll, "If true, remove all triggers.") - cmd.Flags().BoolVar(&options.Auto, "auto", options.Auto, "If true, enable all triggers, or just the specified trigger") - cmd.Flags().BoolVar(&options.Manual, "manual", options.Manual, "If true, set all triggers to manual, or just the specified trigger") - cmd.Flags().BoolVar(&options.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - - cmd.Flags().BoolVar(&options.FromConfig, "from-config", options.FromConfig, "If set, configuration changes will result in a change") - cmd.Flags().StringVarP(&options.ContainerNames, "containers", "c", options.ContainerNames, "Comma delimited list of container names this trigger applies to on deployments; defaults to the name of the only container") - cmd.Flags().StringVar(&options.FromImage, "from-image", options.FromImage, "An image stream tag to trigger off of") - options.FromGitHub = cmd.Flags().Bool("from-github", false, "If true, a GitHub webhook - a secret value will be generated automatically") - options.FromWebHook = cmd.Flags().Bool("from-webhook", false, "If true, a generic webhook - a secret value will be generated automatically") - options.FromWebHookAllowEnv = cmd.Flags().Bool("from-webhook-allow-env", false, "If true, a generic webhook which can provide environment variables - a secret value will be generated automatically") - options.FromGitLab = cmd.Flags().Bool("from-gitlab", false, "If true, a GitLab webhook - a secret value will be generated automatically") - options.FromBitbucket = cmd.Flags().Bool("from-bitbucket", false, "If true, a Bitbucket webhook - a secret value will be generated automatically") - + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove the specified trigger(s).") + cmd.Flags().BoolVar(&o.RemoveAll, "remove-all", o.RemoveAll, "If true, remove all triggers.") + cmd.Flags().BoolVar(&o.Auto, "auto", o.Auto, "If true, enable all triggers, or just the specified trigger") + cmd.Flags().BoolVar(&o.Manual, "manual", o.Manual, "If true, set all triggers to manual, or just the specified trigger") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + cmd.Flags().BoolVar(&o.FromConfig, "from-config", o.FromConfig, "If set, configuration changes will result in a change") + cmd.Flags().StringVarP(&o.ContainerNames, "containers", "c", o.ContainerNames, "Comma delimited list of container names this trigger applies to on deployments; defaults to the name of the only container") + cmd.Flags().StringVar(&o.FromImage, "from-image", o.FromImage, "An image stream tag to trigger off of") + o.FromGitHub = cmd.Flags().Bool("from-github", false, "If true, a GitHub webhook - a secret value will be generated automatically") + o.FromWebHook = cmd.Flags().Bool("from-webhook", false, "If true, a generic webhook - a secret value will be generated automatically") + o.FromWebHookAllowEnv = cmd.Flags().Bool("from-webhook-allow-env", false, "If true, a generic webhook which can provide environment variables - a secret value will be generated automatically") + o.FromGitLab = cmd.Flags().Bool("from-gitlab", false, "If true, a GitLab webhook - a secret value will be generated automatically") + o.FromBitbucket = cmd.Flags().Bool("from-bitbucket", false, "If true, a Bitbucket webhook - a secret value will be generated automatically") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") return cmd } func (o *TriggersOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + var err error + o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } @@ -197,8 +189,6 @@ func (o *TriggersOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args o.FromBitbucket = nil } - o.Cmd = cmd - if len(o.FromImage) > 0 { ref, err := imageapi.ParseDockerImageReference(o.FromImage) if err != nil { @@ -211,7 +201,7 @@ func (o *TriggersOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args return fmt.Errorf("the value of --from-image must include the tag you wish to pull from") } o.FromImage = ref.NameString() - o.FromImageNamespace = defaultNamespace(ref.Namespace, cmdNamespace) + o.FromImageNamespace = defaultNamespace(ref.Namespace, o.Namespace) } count := o.count() @@ -223,33 +213,18 @@ func (o *TriggersOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args o.Auto = true } - mapper, err := f.ToRESTMapper() - if err != nil { - return err - } - o.Builder = f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - LocalParam(o.Local). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - FilenameParam(explicit, &resource.FilenameOptions{Recursive: false, Filenames: o.Filenames}). - Flatten() + o.Args = args + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + o.Builder = f.NewBuilder - if !o.Local { - o.Builder = o.Builder. - LabelSelectorParam(o.Selector). - ResourceTypeOrNameArgs(o.All, args...) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") } - - o.Output = kcmdutil.GetFlagString(cmd, "output") - o.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, o.Out) + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err } - o.Encoder = kcmdutil.InternalVersionJSONEncoder() - o.ShortOutput = kcmdutil.GetFlagString(cmd, "output") == "name" - o.Mapper = mapper - clientConfig, err := f.ToRESTConfig() if err != nil { return err @@ -308,17 +283,28 @@ func (o *TriggersOptions) Validate() error { } func (o *TriggersOptions) Run() error { - infos := o.Infos - singleItemImplied := len(o.Infos) <= 1 - if o.Builder != nil { - loaded, err := o.Builder.Do().IntoSingleItemImplied(&singleItemImplied).Infos() - if err != nil { - return err - } - infos = loaded + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). + ContinueOnError(). + NamespaceParam(o.Namespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). + Flatten() + + if !o.Local { + b = b. + LabelSelectorParam(o.Selector). + ResourceTypeOrNameArgs(o.All, o.Args...). + Latest() } - if o.PrintTable && len(o.Output) == 0 { + singleItemImplied := false + infos, err := b.Do().IntoSingleItemImplied(&singleItemImplied).Infos() + if err != nil { + return err + } + + if o.PrintTable { return o.printTriggers(infos) } @@ -326,45 +312,46 @@ func (o *TriggersOptions) Run() error { o.updateTriggers(triggers) return nil } - patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { + patches := CalculatePatchesExternal(infos, func(info *resource.Info) (bool, error) { return UpdateTriggersForObject(info.Object, updateTriggerFn) }) if singleItemImplied && len(patches) == 0 { return fmt.Errorf("%s/%s does not support triggers", infos[0].Mapping.Resource.Resource, infos[0].Name) } - if len(o.Output) > 0 || o.Local || kcmdutil.GetDryRunFlag(o.Cmd) { - return o.PrintObject(infos) - } - failed := false + allErrs := []error{} for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - failed = true - fmt.Fprintf(o.Err, "error: %s/%s %v\n", info.Mapping.Resource.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(o.Err, "info: %s %q was not changed\n", info.Mapping.Resource.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - glog.V(4).Infof("Calculated patch %s", patch.Patch) + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } + continue + } actual, err := o.Client.Resource(info.Mapping.Resource).Namespace(info.Namespace).Patch(info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - handlePodUpdateError(o.Err, err, "triggered") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch build hook: %v\n", err)) continue } - kcmdutil.PrintSuccess(o.ShortOutput, o.Out, actual, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) + } // printTriggers displays a tabular output of the triggers for each object. @@ -496,7 +483,7 @@ func (o *TriggersOptions) updateTriggers(triggers *TriggerDefinition) { if o.FromWebHook != nil && *o.FromWebHook { secret := app.GenerateSecret(20) triggers.GenericWebHooks = append(triggers.GenericWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: secret, AllowEnv: false, }, @@ -505,7 +492,7 @@ func (o *TriggersOptions) updateTriggers(triggers *TriggerDefinition) { if o.FromWebHookAllowEnv != nil && *o.FromWebHookAllowEnv { secret := app.GenerateSecret(20) triggers.GenericWebHooks = append(triggers.GenericWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: secret, AllowEnv: true, }, @@ -514,7 +501,7 @@ func (o *TriggersOptions) updateTriggers(triggers *TriggerDefinition) { if o.FromGitHub != nil && *o.FromGitHub { secret := app.GenerateSecret(20) triggers.GitHubWebHooks = append(triggers.GitHubWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: secret, }, ) @@ -522,7 +509,7 @@ func (o *TriggersOptions) updateTriggers(triggers *TriggerDefinition) { if o.FromGitLab != nil && *o.FromGitLab { secret := app.GenerateSecret(20) triggers.GitLabWebHooks = append(triggers.GitLabWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: secret, }, ) @@ -530,7 +517,7 @@ func (o *TriggersOptions) updateTriggers(triggers *TriggerDefinition) { if o.FromBitbucket != nil && *o.FromBitbucket { secret := app.GenerateSecret(20) triggers.BitbucketWebHooks = append(triggers.BitbucketWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: secret, }, ) @@ -554,10 +541,10 @@ type ImageChangeTrigger struct { type TriggerDefinition struct { ConfigChange bool ImageChange []ImageChangeTrigger - GenericWebHooks []buildapi.WebHookTrigger - GitHubWebHooks []buildapi.WebHookTrigger - GitLabWebHooks []buildapi.WebHookTrigger - BitbucketWebHooks []buildapi.WebHookTrigger + GenericWebHooks []buildv1.WebHookTrigger + GitHubWebHooks []buildv1.WebHookTrigger + GitLabWebHooks []buildv1.WebHookTrigger + BitbucketWebHooks []buildv1.WebHookTrigger } // defaultNamespace returns an empty string if the provided namespace matches the default namespace, or @@ -579,7 +566,13 @@ func NewAnnotationTriggers(obj runtime.Object) (*TriggerDefinition, error) { t := &TriggerDefinition{ConfigChange: true} switch typed := obj.(type) { - case *kextensions.Deployment: + case *extensionsv1beta1.Deployment: + t.ConfigChange = !typed.Spec.Paused + case *kappsv1beta1.Deployment: + t.ConfigChange = !typed.Spec.Paused + case *kappsv1beta2.Deployment: + t.ConfigChange = !typed.Spec.Paused + case *kappsv1.Deployment: t.ConfigChange = !typed.Spec.Paused } @@ -608,13 +601,13 @@ func NewAnnotationTriggers(obj runtime.Object) (*TriggerDefinition, error) { } // NewDeploymentConfigTriggers creates a trigger definition from a deployment config. -func NewDeploymentConfigTriggers(config *appsapi.DeploymentConfig) *TriggerDefinition { +func NewDeploymentConfigTriggers(config *appsv1.DeploymentConfig) *TriggerDefinition { t := &TriggerDefinition{} for _, trigger := range config.Spec.Triggers { switch trigger.Type { - case appsapi.DeploymentTriggerOnConfigChange: + case appsv1.DeploymentTriggerOnConfigChange: t.ConfigChange = true - case appsapi.DeploymentTriggerOnImageChange: + case appsv1.DeploymentTriggerOnImageChange: t.ImageChange = append(t.ImageChange, ImageChangeTrigger{ Auto: trigger.ImageChangeParams.Automatic, Names: trigger.ImageChangeParams.ContainerNames, @@ -627,43 +620,43 @@ func NewDeploymentConfigTriggers(config *appsapi.DeploymentConfig) *TriggerDefin } // NewBuildConfigTriggers creates a trigger definition from a build config. -func NewBuildConfigTriggers(config *buildapi.BuildConfig) *TriggerDefinition { +func NewBuildConfigTriggers(config *buildv1.BuildConfig) *TriggerDefinition { t := &TriggerDefinition{} setStrategy := false for _, trigger := range config.Spec.Triggers { switch trigger.Type { - case buildapi.ConfigChangeBuildTriggerType: + case buildv1.ConfigChangeBuildTriggerType: t.ConfigChange = true - case buildapi.GenericWebHookBuildTriggerType: + case buildv1.GenericWebHookBuildTriggerType: t.GenericWebHooks = append(t.GenericWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: trigger.GenericWebHook.Secret, SecretReference: trigger.GenericWebHook.SecretReference, AllowEnv: trigger.GenericWebHook.AllowEnv, }, ) - case buildapi.GitHubWebHookBuildTriggerType: + case buildv1.GitHubWebHookBuildTriggerType: t.GitHubWebHooks = append(t.GitHubWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: trigger.GitHubWebHook.Secret, SecretReference: trigger.GitHubWebHook.SecretReference, }, ) - case buildapi.GitLabWebHookBuildTriggerType: + case buildv1.GitLabWebHookBuildTriggerType: t.GitLabWebHooks = append(t.GitLabWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: trigger.GitLabWebHook.Secret, SecretReference: trigger.GitLabWebHook.SecretReference, }, ) - case buildapi.BitbucketWebHookBuildTriggerType: + case buildv1.BitbucketWebHookBuildTriggerType: t.BitbucketWebHooks = append(t.BitbucketWebHooks, - buildapi.WebHookTrigger{ + buildv1.WebHookTrigger{ Secret: trigger.BitbucketWebHook.Secret, SecretReference: trigger.BitbucketWebHook.SecretReference, }, ) - case buildapi.ImageChangeBuildTriggerType: + case buildv1.ImageChangeBuildTriggerType: if trigger.ImageChange.From == nil { if strategyTrigger := strategyTrigger(config); strategyTrigger != nil { setStrategy = true @@ -692,7 +685,7 @@ func NewBuildConfigTriggers(config *buildapi.BuildConfig) *TriggerDefinition { // Apply writes a trigger definition back to an object. func (t *TriggerDefinition) Apply(obj runtime.Object) error { switch c := obj.(type) { - case *appsapi.DeploymentConfig: + case *appsv1.DeploymentConfig: if len(t.GitHubWebHooks) > 0 { return fmt.Errorf("deployment configs do not support GitHub web hooks") } @@ -706,10 +699,10 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { return fmt.Errorf("deployment configs do not support Bitbucket web hooks") } - existingTriggers := filterDeploymentTriggers(c.Spec.Triggers, appsapi.DeploymentTriggerOnConfigChange) - var triggers []appsapi.DeploymentTriggerPolicy + existingTriggers := filterDeploymentTriggers(c.Spec.Triggers, appsv1.DeploymentTriggerOnConfigChange) + var triggers []appsv1.DeploymentTriggerPolicy if t.ConfigChange { - triggers = append(triggers, appsapi.DeploymentTriggerPolicy{Type: appsapi.DeploymentTriggerOnConfigChange}) + triggers = append(triggers, appsv1.DeploymentTriggerPolicy{Type: appsv1.DeploymentTriggerOnConfigChange}) } allNames := sets.NewString() for _, container := range c.Spec.Template.Spec.Containers { @@ -729,11 +722,11 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { strings.Join(allNames.List(), ", "), ) } - triggers = append(triggers, appsapi.DeploymentTriggerPolicy{ - Type: appsapi.DeploymentTriggerOnImageChange, - ImageChangeParams: &appsapi.DeploymentTriggerImageChangeParams{ + triggers = append(triggers, appsv1.DeploymentTriggerPolicy{ + Type: appsv1.DeploymentTriggerOnImageChange, + ImageChangeParams: &appsv1.DeploymentTriggerImageChangeParams{ Automatic: trigger.Auto, - From: kapi.ObjectReference{ + From: corev1.ObjectReference{ Kind: "ImageStreamTag", Name: trigger.From, Namespace: trigger.Namespace, @@ -745,32 +738,32 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { c.Spec.Triggers = mergeDeployTriggers(existingTriggers, triggers) return nil - case *buildapi.BuildConfig: - var triggers []buildapi.BuildTriggerPolicy + case *buildv1.BuildConfig: + var triggers []buildv1.BuildTriggerPolicy if t.ConfigChange { - triggers = append(triggers, buildapi.BuildTriggerPolicy{Type: buildapi.ConfigChangeBuildTriggerType}) + triggers = append(triggers, buildv1.BuildTriggerPolicy{Type: buildv1.ConfigChangeBuildTriggerType}) } for i := range t.GenericWebHooks { - triggers = append(triggers, buildapi.BuildTriggerPolicy{ - Type: buildapi.GenericWebHookBuildTriggerType, + triggers = append(triggers, buildv1.BuildTriggerPolicy{ + Type: buildv1.GenericWebHookBuildTriggerType, GenericWebHook: &t.GenericWebHooks[i], }) } for i := range t.GitHubWebHooks { - triggers = append(triggers, buildapi.BuildTriggerPolicy{ - Type: buildapi.GitHubWebHookBuildTriggerType, + triggers = append(triggers, buildv1.BuildTriggerPolicy{ + Type: buildv1.GitHubWebHookBuildTriggerType, GitHubWebHook: &t.GitHubWebHooks[i], }) } for i := range t.GitLabWebHooks { - triggers = append(triggers, buildapi.BuildTriggerPolicy{ - Type: buildapi.GitLabWebHookBuildTriggerType, + triggers = append(triggers, buildv1.BuildTriggerPolicy{ + Type: buildv1.GitLabWebHookBuildTriggerType, GitLabWebHook: &t.GitLabWebHooks[i], }) } for i := range t.BitbucketWebHooks { - triggers = append(triggers, buildapi.BuildTriggerPolicy{ - Type: buildapi.BitbucketWebHookBuildTriggerType, + triggers = append(triggers, buildv1.BuildTriggerPolicy{ + Type: buildv1.BitbucketWebHookBuildTriggerType, BitbucketWebHook: &t.BitbucketWebHooks[i], }) } @@ -780,8 +773,8 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { existingTriggers := c.Spec.Triggers strategyTrigger := strategyTrigger(c) for _, trigger := range t.ImageChange { - change := &buildapi.ImageChangeTrigger{ - From: &kapi.ObjectReference{ + change := &buildv1.ImageChangeTrigger{ + From: &corev1.ObjectReference{ Kind: "ImageStreamTag", Name: trigger.From, Namespace: trigger.Namespace, @@ -802,15 +795,19 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { continue } - triggers = append(triggers, buildapi.BuildTriggerPolicy{ - Type: buildapi.ImageChangeBuildTriggerType, + triggers = append(triggers, buildv1.BuildTriggerPolicy{ + Type: buildv1.ImageChangeBuildTriggerType, ImageChange: change, }) } c.Spec.Triggers = mergeBuildTriggers(existingTriggers, triggers) return nil - case *kextensions.DaemonSet, *kapps.StatefulSet, *kbatch.CronJob, *kextensions.Deployment: + case *extensionsv1beta1.DaemonSet, *kappsv1beta2.DaemonSet, *kappsv1.DaemonSet, + *extensionsv1beta1.Deployment, *kappsv1beta1.Deployment, *kappsv1beta2.Deployment, *kappsv1.Deployment, + *kappsv1beta1.StatefulSet, *kappsv1beta2.StatefulSet, *kappsv1.StatefulSet, + *batchv1beta1.CronJob, *batchv2alpha1.CronJob: + if len(t.GitHubWebHooks) > 0 { return fmt.Errorf("does not support GitHub web hooks") } @@ -827,7 +824,7 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { if err != nil { return err } - spec, path, err := ometa.GetPodSpec(obj) + spec, path, err := ometa.GetPodSpecV1(obj) if err != nil { return err } @@ -885,7 +882,13 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { m.SetAnnotations(a) switch typed := obj.(type) { - case *kextensions.Deployment: + case *extensionsv1beta1.Deployment: + typed.Spec.Paused = !t.ConfigChange + case *kappsv1beta1.Deployment: + typed.Spec.Paused = !t.ConfigChange + case *kappsv1beta2.Deployment: + typed.Spec.Paused = !t.ConfigChange + case *kappsv1.Deployment: typed.Spec.Paused = !t.ConfigChange } glog.V(4).Infof("Updated annotated object: %#v", obj) @@ -897,7 +900,7 @@ func (t *TriggerDefinition) Apply(obj runtime.Object) error { } // triggerMatchesBuildImageChange identifies whether the image change is equivalent to the trigger -func triggerMatchesBuildImageChange(trigger ImageChangeTrigger, strategyTrigger *ImageChangeTrigger, imageChange *buildapi.ImageChangeTrigger) bool { +func triggerMatchesBuildImageChange(trigger ImageChangeTrigger, strategyTrigger *ImageChangeTrigger, imageChange *buildv1.ImageChangeTrigger) bool { if imageChange == nil { return false } @@ -913,8 +916,8 @@ func triggerMatchesBuildImageChange(trigger ImageChangeTrigger, strategyTrigger // filterBuildImageTriggers return only triggers that do not match the provided ImageChangeTrigger. strategyTrigger may be provided // if set to remove a BuildTriggerPolicy without a From (which points to the strategy) -func filterBuildImageTriggers(src []buildapi.BuildTriggerPolicy, trigger ImageChangeTrigger, strategyTrigger *ImageChangeTrigger) []buildapi.BuildTriggerPolicy { - var dst []buildapi.BuildTriggerPolicy +func filterBuildImageTriggers(src []buildv1.BuildTriggerPolicy, trigger ImageChangeTrigger, strategyTrigger *ImageChangeTrigger) []buildv1.BuildTriggerPolicy { + var dst []buildv1.BuildTriggerPolicy for i := range src { if triggerMatchesBuildImageChange(trigger, strategyTrigger, src[i].ImageChange) { continue @@ -925,8 +928,8 @@ func filterBuildImageTriggers(src []buildapi.BuildTriggerPolicy, trigger ImageCh } // filterDeploymentTriggers returns only triggers that do not have one of the provided types. -func filterDeploymentTriggers(src []appsapi.DeploymentTriggerPolicy, types ...appsapi.DeploymentTriggerType) []appsapi.DeploymentTriggerPolicy { - var dst []appsapi.DeploymentTriggerPolicy +func filterDeploymentTriggers(src []appsv1.DeploymentTriggerPolicy, types ...appsv1.DeploymentTriggerType) []appsv1.DeploymentTriggerPolicy { + var dst []appsv1.DeploymentTriggerPolicy Outer: for i := range src { for _, t := range types { @@ -941,8 +944,8 @@ Outer: // strategyTrigger returns a synthetic ImageChangeTrigger that represents the image stream tag the build strategy // points to, or nil if no such strategy trigger is possible (if the build doesn't point to an ImageStreamTag). -func strategyTrigger(config *buildapi.BuildConfig) *ImageChangeTrigger { - if from := buildapi.GetInputReference(config.Spec.Strategy); from != nil { +func strategyTrigger(config *buildv1.BuildConfig) *ImageChangeTrigger { + if from := getInputReference(config.Spec.Strategy); from != nil { if from.Kind == "ImageStreamTag" { // normalize the strategy object reference from.Namespace = defaultNamespace(from.Namespace, config.Namespace) @@ -953,9 +956,9 @@ func strategyTrigger(config *buildapi.BuildConfig) *ImageChangeTrigger { } // mergeDeployTriggers returns an array of DeploymentTriggerPolicies that have no duplicates. -func mergeDeployTriggers(dst, src []appsapi.DeploymentTriggerPolicy) []appsapi.DeploymentTriggerPolicy { +func mergeDeployTriggers(dst, src []appsv1.DeploymentTriggerPolicy) []appsv1.DeploymentTriggerPolicy { // never return an empty map, because the triggers on a deployment config default when the map is empty - result := []appsapi.DeploymentTriggerPolicy{} + result := []appsv1.DeploymentTriggerPolicy{} for _, current := range dst { if findDeployTrigger(src, current) != -1 { result = append(result, current) @@ -971,7 +974,7 @@ func mergeDeployTriggers(dst, src []appsapi.DeploymentTriggerPolicy) []appsapi.D // findDeployTrigger finds the position of a deployment trigger in the provided array, or -1 if no such // matching trigger is found. -func findDeployTrigger(dst []appsapi.DeploymentTriggerPolicy, trigger appsapi.DeploymentTriggerPolicy) int { +func findDeployTrigger(dst []appsv1.DeploymentTriggerPolicy, trigger appsv1.DeploymentTriggerPolicy) int { for i := range dst { if reflect.DeepEqual(dst[i], trigger) { return i @@ -982,8 +985,8 @@ func findDeployTrigger(dst []appsapi.DeploymentTriggerPolicy, trigger appsapi.De // mergeBuildTriggers returns an array of BuildTriggerPolicies that have no duplicates, in the same order // as they exist in their original arrays (a zip-merge). -func mergeBuildTriggers(dst, src []buildapi.BuildTriggerPolicy) []buildapi.BuildTriggerPolicy { - var result []buildapi.BuildTriggerPolicy +func mergeBuildTriggers(dst, src []buildv1.BuildTriggerPolicy) []buildv1.BuildTriggerPolicy { + var result []buildv1.BuildTriggerPolicy for _, current := range dst { if findBuildTrigger(src, current) != -1 { result = append(result, current) @@ -999,15 +1002,15 @@ func mergeBuildTriggers(dst, src []buildapi.BuildTriggerPolicy) []buildapi.Build // findBuildTrigger finds the equivalent build trigger position in the provided array, or -1 if // no such build trigger exists. Equality only cares about the value of the From field. -func findBuildTrigger(dst []buildapi.BuildTriggerPolicy, trigger buildapi.BuildTriggerPolicy) int { +func findBuildTrigger(dst []buildv1.BuildTriggerPolicy, trigger buildv1.BuildTriggerPolicy) int { // make a copy for semantic equality if trigger.ImageChange != nil { - trigger.ImageChange = &buildapi.ImageChangeTrigger{From: trigger.ImageChange.From} + trigger.ImageChange = &buildv1.ImageChangeTrigger{From: trigger.ImageChange.From} } for i, copied := range dst { // make a copy for semantic equality if copied.ImageChange != nil { - copied.ImageChange = &buildapi.ImageChangeTrigger{From: copied.ImageChange.From} + copied.ImageChange = &buildv1.ImageChangeTrigger{From: copied.ImageChange.From} } if reflect.DeepEqual(copied, trigger) { return i @@ -1022,19 +1025,22 @@ func findBuildTrigger(dst []buildapi.BuildTriggerPolicy, trigger buildapi.BuildT func UpdateTriggersForObject(obj runtime.Object, fn func(*TriggerDefinition) error) (bool, error) { // TODO: replace with a swagger schema based approach (identify pod template via schema introspection) switch t := obj.(type) { - case *appsapi.DeploymentConfig: + case *appsv1.DeploymentConfig: triggers := NewDeploymentConfigTriggers(t) if err := fn(triggers); err != nil { return true, err } return true, triggers.Apply(t) - case *buildapi.BuildConfig: + case *buildv1.BuildConfig: triggers := NewBuildConfigTriggers(t) if err := fn(triggers); err != nil { return true, err } return true, triggers.Apply(t) - case *kextensions.DaemonSet, *kextensions.Deployment, *kapps.StatefulSet, *kbatch.CronJob: + case *extensionsv1beta1.DaemonSet, *kappsv1beta2.DaemonSet, *kappsv1.DaemonSet, + *extensionsv1beta1.Deployment, *kappsv1beta1.Deployment, *kappsv1beta2.Deployment, *kappsv1.Deployment, + *kappsv1beta1.StatefulSet, *kappsv1beta2.StatefulSet, *kappsv1.StatefulSet, + *batchv1beta1.CronJob, *batchv2alpha1.CronJob: triggers, err := NewAnnotationTriggers(obj) if err != nil { return false, err @@ -1044,6 +1050,19 @@ func UpdateTriggersForObject(obj runtime.Object, fn func(*TriggerDefinition) err } return true, triggers.Apply(obj) default: - return false, fmt.Errorf("the object does not support triggers") + return false, fmt.Errorf("the object does not support triggers: %T", t) + } +} + +func getInputReference(strategy buildv1.BuildStrategy) *corev1.ObjectReference { + switch { + case strategy.SourceStrategy != nil: + return &strategy.SourceStrategy.From + case strategy.DockerStrategy != nil: + return strategy.DockerStrategy.From + case strategy.CustomStrategy != nil: + return &strategy.CustomStrategy.From + default: + return nil } } diff --git a/pkg/oc/cli/cmd/set/volume.go b/pkg/oc/cli/cmd/set/volume.go index de0296efda55..5599e1f0f585 100644 --- a/pkg/oc/cli/cmd/set/volume.go +++ b/pkg/oc/cli/cmd/set/volume.go @@ -4,8 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "io" - "os" "path" "regexp" "strconv" @@ -14,7 +12,6 @@ import ( "github.com/golang/glog" "github.com/spf13/cobra" - "k8s.io/api/core/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" kresource "k8s.io/apimachinery/pkg/api/resource" @@ -22,16 +19,18 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apiserver/pkg/storage/names" - "k8s.io/kubernetes/pkg/api/legacyscheme" kapi "k8s.io/kubernetes/pkg/apis/core" kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/genericclioptions" + "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" + "github.com/openshift/origin/pkg/oc/cli/cmd" "github.com/openshift/origin/pkg/oc/cli/util/clientcmd" "github.com/openshift/origin/pkg/oc/util/ocscheme" ) @@ -101,21 +100,19 @@ var ( ) type VolumeOptions struct { + PrintFlags *genericclioptions.PrintFlags + DefaultNamespace string ExplicitNamespace bool - Out io.Writer - Err io.Writer Mapper meta.RESTMapper - Typer runtime.ObjectTyper - UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) - Client kcoreclient.PersistentVolumeClaimsGetter + Client kcoreclient.CoreInterface + UpdatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc Encoder runtime.Encoder - Cmd *cobra.Command + Builder func() *resource.Builder // Resource selection - Selector string - All bool - Filenames []string + Selector string + All bool // Operations Add bool @@ -123,15 +120,19 @@ type VolumeOptions struct { List bool // Common optional params - Name string - Containers string - Confirm bool - Local bool - Output string - PrintObject func([]*resource.Info) error + Name string + Containers string + Confirm bool + Local bool + Args []string + Printer printers.ResourcePrinter + DryRun bool // Add op params AddOpts *AddVolumeOptions + + resource.FilenameOptions + genericclioptions.IOStreams } type AddVolumeOptions struct { @@ -145,6 +146,7 @@ type AddVolumeOptions struct { SecretName string Source string + ReadOnly bool CreateClaim bool ClaimName string ClaimSize string @@ -154,13 +156,20 @@ type AddVolumeOptions struct { TypeChanged bool } -func NewCmdVolume(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - addOpts := &AddVolumeOptions{} - opts := &VolumeOptions{ - AddOpts: addOpts, - Out: streams.Out, - Err: streams.ErrOut, +func NewVolumeOptions(streams genericclioptions.IOStreams) *VolumeOptions { + return &VolumeOptions{ + PrintFlags: genericclioptions.NewPrintFlags("volume updated").WithTypeSetter(ocscheme.PrintingInternalScheme), + + Containers: "*", + AddOpts: &AddVolumeOptions{ + ClaimMode: "ReadWriteOnce", + }, + IOStreams: streams, } +} + +func NewCmdVolume(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { + o := NewVolumeOptions(streams) cmd := &cobra.Command{ Use: "volumes RESOURCE/NAME --add|--remove|--list", Short: "Update volumes on a pod template", @@ -168,51 +177,40 @@ func NewCmdVolume(fullName string, f kcmdutil.Factory, streams genericclioptions Example: fmt.Sprintf(volumeExample, fullName), Aliases: []string{"volume"}, Run: func(cmd *cobra.Command, args []string) { - addOpts.TypeChanged = cmd.Flag("type").Changed - - kcmdutil.CheckErr(opts.Complete(f, cmd)) - - err := opts.Validate(cmd, args) - if err != nil { - kcmdutil.CheckErr(kcmdutil.UsageErrorf(cmd, err.Error())) - } - - err = opts.RunVolume(args, f) - if err == kcmdutil.ErrExit { - os.Exit(1) - } - kcmdutil.CheckErr(err) + kcmdutil.CheckErr(o.Complete(f, cmd, args)) + kcmdutil.CheckErr(o.Validate()) + kcmdutil.CheckErr(o.RunVolume()) }, } - cmd.Flags().StringVarP(&opts.Selector, "selector", "l", "", "Selector (label query) to filter on") - cmd.Flags().BoolVar(&opts.All, "all", false, "If true, select all resources in the namespace of the specified resource types") - cmd.Flags().StringSliceVarP(&opts.Filenames, "filename", "f", opts.Filenames, "Filename, directory, or URL to file to use to edit the resource.") - cmd.Flags().BoolVar(&opts.Add, "add", false, "If true, add volume and/or volume mounts for containers") - cmd.Flags().BoolVar(&opts.Remove, "remove", false, "If true, remove volume and/or volume mounts for containers") - cmd.Flags().BoolVar(&opts.List, "list", false, "If true, list volumes and volume mounts for containers") - cmd.Flags().BoolVar(&opts.Local, "local", false, "If true, set image will NOT contact api-server but run locally.") - - cmd.Flags().StringVar(&opts.Name, "name", "", "Name of the volume. If empty, auto generated for add operation") - cmd.Flags().StringVarP(&opts.Containers, "containers", "c", "*", "The names of containers in the selected pod templates to change - may use wildcards") - cmd.Flags().BoolVar(&opts.Confirm, "confirm", false, "If true, confirm that you really want to remove multiple volumes") - - cmd.Flags().StringVarP(&addOpts.Type, "type", "t", "", "Type of the volume source for add operation. Supported options: emptyDir, hostPath, secret, configmap, persistentVolumeClaim") - cmd.Flags().StringVarP(&addOpts.MountPath, "mount-path", "m", "", "Mount path inside the container. Optional param for --add or --remove") - cmd.Flags().StringVar(&addOpts.SubPath, "sub-path", "", "Path within the local volume from which the container's volume should be mounted. Optional param for --add or --remove") - cmd.Flags().StringVarP(&addOpts.DefaultMode, "default-mode", "", "", "The default mode bits to create files with. Can be between 0000 and 0777. Defaults to 0644.") - cmd.Flags().BoolVar(&addOpts.Overwrite, "overwrite", false, "If true, replace existing volume source with the provided name and/or volume mount for the given resource") - cmd.Flags().StringVar(&addOpts.Path, "path", "", "Host path. Must be provided for hostPath volume type") - cmd.Flags().StringVar(&addOpts.ConfigMapName, "configmap-name", "", "Name of the persisted config map. Must be provided for configmap volume type") - cmd.Flags().StringVar(&addOpts.SecretName, "secret-name", "", "Name of the persisted secret. Must be provided for secret volume type") - cmd.Flags().StringVar(&addOpts.ClaimName, "claim-name", "", "Persistent volume claim name. Must be provided for persistentVolumeClaim volume type") - cmd.Flags().StringVar(&addOpts.ClaimClass, "claim-class", "", "StorageClass to use for the persistent volume claim") - cmd.Flags().StringVar(&addOpts.ClaimSize, "claim-size", "", "If specified along with a persistent volume type, create a new claim with the given size in bytes. Accepts SI notation: 10, 10G, 10Gi") - cmd.Flags().StringVar(&addOpts.ClaimMode, "claim-mode", "ReadWriteOnce", "Set the access mode of the claim to be created. Valid values are ReadWriteOnce (rwo), ReadWriteMany (rwm), or ReadOnlyMany (rom)") - cmd.Flags().StringVar(&addOpts.Source, "source", "", "Details of volume source as json string. This can be used if the required volume type is not supported by --type option. (e.g.: '{\"gitRepo\": {\"repository\": , \"revision\": }}')") - + usage := "to use to edit the resource" + kcmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage) + cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on") + cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types") + cmd.Flags().BoolVar(&o.Add, "add", o.Add, "If true, add volume and/or volume mounts for containers") + cmd.Flags().BoolVar(&o.Remove, "remove", o.Remove, "If true, remove volume and/or volume mounts for containers") + cmd.Flags().BoolVar(&o.List, "list", o.List, "If true, list volumes and volume mounts for containers") + cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set image will NOT contact api-server but run locally.") + cmd.Flags().StringVar(&o.Name, "name", o.Name, "Name of the volume. If empty, auto generated for add operation") + cmd.Flags().StringVarP(&o.Containers, "containers", "c", o.Containers, "The names of containers in the selected pod templates to change - may use wildcards") + cmd.Flags().BoolVar(&o.Confirm, "confirm", o.Confirm, "If true, confirm that you really want to remove multiple volumes") + + cmd.Flags().StringVarP(&o.AddOpts.Type, "type", "t", o.AddOpts.Type, "Type of the volume source for add operation. Supported options: emptyDir, hostPath, secret, configmap, persistentVolumeClaim") + cmd.Flags().StringVarP(&o.AddOpts.MountPath, "mount-path", "m", o.AddOpts.MountPath, "Mount path inside the container. Optional param for --add or --remove") + cmd.Flags().StringVar(&o.AddOpts.SubPath, "sub-path", o.AddOpts.SubPath, "Path within the local volume from which the container's volume should be mounted. Optional param for --add or --remove") + cmd.Flags().StringVar(&o.AddOpts.DefaultMode, "default-mode", o.AddOpts.DefaultMode, "The default mode bits to create files with. Can be between 0000 and 0777. Defaults to 0644.") + cmd.Flags().BoolVar(&o.AddOpts.ReadOnly, "read-only", o.AddOpts.ReadOnly, "Mount volume as ReadOnly. Optional param for --add or --remove") + cmd.Flags().BoolVar(&o.AddOpts.Overwrite, "overwrite", o.AddOpts.Overwrite, "If true, replace existing volume source with the provided name and/or volume mount for the given resource") + cmd.Flags().StringVar(&o.AddOpts.Path, "path", o.AddOpts.Path, "Host path. Must be provided for hostPath volume type") + cmd.Flags().StringVar(&o.AddOpts.ConfigMapName, "configmap-name", o.AddOpts.ConfigMapName, "Name of the persisted config map. Must be provided for configmap volume type") + cmd.Flags().StringVar(&o.AddOpts.SecretName, "secret-name", o.AddOpts.SecretName, "Name of the persisted secret. Must be provided for secret volume type") + cmd.Flags().StringVar(&o.AddOpts.ClaimName, "claim-name", o.AddOpts.ClaimName, "Persistent volume claim name. Must be provided for persistentVolumeClaim volume type") + cmd.Flags().StringVar(&o.AddOpts.ClaimClass, "claim-class", o.AddOpts.ClaimClass, "StorageClass to use for the persistent volume claim") + cmd.Flags().StringVar(&o.AddOpts.ClaimSize, "claim-size", o.AddOpts.ClaimSize, "If specified along with a persistent volume type, create a new claim with the given size in bytes. Accepts SI notation: 10, 10G, 10Gi") + cmd.Flags().StringVar(&o.AddOpts.ClaimMode, "claim-mode", o.AddOpts.ClaimMode, "Set the access mode of the claim to be created. Valid values are ReadWriteOnce (rwo), ReadWriteMany (rwm), or ReadOnlyMany (rom)") + cmd.Flags().StringVar(&o.AddOpts.Source, "source", o.AddOpts.Source, "Details of volume source as json string. This can be used if the required volume type is not supported by --type option. (e.g.: '{\"gitRepo\": {\"repository\": , \"revision\": }}')") + + o.PrintFlags.AddFlags(cmd) kcmdutil.AddDryRunFlag(cmd) - kcmdutil.AddPrinterFlags(cmd) - cmd.MarkFlagFilename("filename", "yaml", "yml", "json") // deprecate --list option cmd.Flags().MarkDeprecated("list", "Volumes and volume mounts can be listed by providing a resource with no additional options.") @@ -220,35 +218,35 @@ func NewCmdVolume(fullName string, f kcmdutil.Factory, streams genericclioptions return cmd } -func (v *VolumeOptions) Validate(cmd *cobra.Command, args []string) error { - if len(v.Selector) > 0 { - if _, err := labels.Parse(v.Selector); err != nil { +func (o *VolumeOptions) Validate() error { + if len(o.Selector) > 0 { + if _, err := labels.Parse(o.Selector); err != nil { return errors.New("--selector= must be a valid label selector") } - if v.All { + if o.All { return errors.New("you may specify either --selector or --all but not both") } } - if len(v.Filenames) == 0 && len(args) < 1 { + if len(o.Filenames) == 0 && len(o.Args) < 1 { return errors.New("provide one or more resources to add, list, or delete volumes on as TYPE/NAME") } - if v.List && len(v.Output) > 0 { + if o.List && o.PrintFlags.OutputFormat != nil && len(*o.PrintFlags.OutputFormat) > 0 { return errors.New("--list and --output may not be specified together") } - if v.Add { - err := v.AddOpts.Validate() + if o.Add { + err := o.AddOpts.Validate() if err != nil { return err } - } else if len(v.AddOpts.Source) > 0 || len(v.AddOpts.Path) > 0 || len(v.AddOpts.SecretName) > 0 || - len(v.AddOpts.ConfigMapName) > 0 || len(v.AddOpts.ClaimName) > 0 || len(v.AddOpts.DefaultMode) > 0 || - v.AddOpts.Overwrite { + } else if len(o.AddOpts.Source) > 0 || len(o.AddOpts.Path) > 0 || len(o.AddOpts.SecretName) > 0 || + len(o.AddOpts.ConfigMapName) > 0 || len(o.AddOpts.ClaimName) > 0 || len(o.AddOpts.DefaultMode) > 0 || + o.AddOpts.Overwrite { return errors.New("--type|--path|--configmap-name|--secret-name|--claim-name|--source|--default-mode|--overwrite are only valid for --add operation") } // Removing all volumes for the resource type needs confirmation - if v.Remove && len(v.Name) == 0 && !v.Confirm { + if o.Remove && len(o.Name) == 0 && !o.Confirm { return errors.New("must provide --confirm for removing more than one volume") } return nil @@ -321,57 +319,59 @@ func (a *AddVolumeOptions) Validate() error { return nil } -func (v *VolumeOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command) error { +func (o *VolumeOptions) Complete(f kcmdutil.Factory, cmd *cobra.Command, args []string) error { kc, err := f.ClientSet() if err != nil { return err } - v.Client = kc.Core() + o.Client = kc.Core() - cmdNamespace, explicit, err := f.ToRawKubeConfigLoader().Namespace() + o.DefaultNamespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace() if err != nil { return err } - mapper, err := f.ToRESTMapper() + o.Mapper, err = f.ToRESTMapper() if err != nil { return err } numOps := 0 - if v.Add { + if o.Add { numOps++ } - if v.Remove { + if o.Remove { numOps++ } - if v.List { + if o.List { numOps++ } switch { case numOps == 0: - v.List = true + o.List = true case numOps > 1: return errors.New("you may only specify one operation at a time") } - v.Output = kcmdutil.GetFlagString(cmd, "output") - v.PrintObject = func(infos []*resource.Info) error { - return clientcmd.PrintResourceInfos(cmd, infos, v.Out) - } + o.Args = args + o.Builder = f.NewBuilder + o.Encoder = kcmdutil.InternalVersionJSONEncoder() + o.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn - v.Cmd = cmd - v.DefaultNamespace = cmdNamespace - v.ExplicitNamespace = explicit - v.Mapper = mapper - v.Typer = legacyscheme.Scheme - v.UpdatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn - v.Encoder = kcmdutil.InternalVersionJSONEncoder() + o.AddOpts.TypeChanged = cmd.Flag("type").Changed + + o.DryRun = kcmdutil.GetDryRunFlag(cmd) + if o.DryRun { + o.PrintFlags.Complete("%s (dry run)") + } + o.Printer, err = o.PrintFlags.ToPrinter() + if err != nil { + return err + } // Complete AddOpts - if v.Add { - err := v.AddOpts.Complete() - if err != nil { + if o.Add { + if err := o.AddOpts.Complete(); err != nil { return err } } @@ -437,19 +437,20 @@ func (a *AddVolumeOptions) Complete() error { return nil } -func (v *VolumeOptions) RunVolume(args []string, f kcmdutil.Factory) error { - b := f.NewBuilder(). - WithScheme(ocscheme.ReadingInternalScheme). - LocalParam(v.Local). +func (o *VolumeOptions) RunVolume() error { + b := o.Builder(). + WithScheme(ocscheme.ReadingInternalScheme, ocscheme.ReadingInternalScheme.PrioritizedVersionsAllGroups()...). + LocalParam(o.Local). ContinueOnError(). - NamespaceParam(v.DefaultNamespace).DefaultNamespace(). - FilenameParam(v.ExplicitNamespace, &resource.FilenameOptions{Recursive: false, Filenames: v.Filenames}). + NamespaceParam(o.DefaultNamespace).DefaultNamespace(). + FilenameParam(o.ExplicitNamespace, &o.FilenameOptions). Flatten() - if !v.Local { + if !o.Local { b = b. - LabelSelectorParam(v.Selector). - ResourceTypeOrNameArgs(v.All, args...) + LabelSelectorParam(o.Selector). + ResourceTypeOrNameArgs(o.All, o.Args...). + Latest() } singleItemImplied := false @@ -457,10 +458,8 @@ func (v *VolumeOptions) RunVolume(args []string, f kcmdutil.Factory) error { if err != nil { return err } - - if v.List { - listingErrors := v.printVolumes(infos) - if len(listingErrors) > 0 { + if o.List { + if listingErrors := o.printVolumes(infos); len(listingErrors) > 0 { return kcmdutil.ErrExit } return nil @@ -468,40 +467,36 @@ func (v *VolumeOptions) RunVolume(args []string, f kcmdutil.Factory) error { updateInfos := []*resource.Info{} // if a claim should be created, generate the info we'll add to the flow - if v.Add && v.AddOpts.CreateClaim { - claim := v.AddOpts.createClaim() - m, err := v.Mapper.RESTMapping(kapi.Kind("PersistentVolumeClaim")) - if err != nil { - return err - } - clientConfig, err := f.ToRESTConfig() - if err != nil { - return err - } - kubeclient, err := kcoreclient.NewForConfig(clientConfig) + if o.Add && o.AddOpts.CreateClaim { + claim := o.AddOpts.createClaim() + m, err := o.Mapper.RESTMapping(kapi.Kind("PersistentVolumeClaim")) if err != nil { return err } info := &resource.Info{ Mapping: m, - Client: kubeclient.RESTClient(), - Namespace: v.DefaultNamespace, + Client: o.Client.RESTClient(), + Namespace: o.DefaultNamespace, Object: claim, } infos = append(infos, info) updateInfos = append(updateInfos, info) } - patches, patchError := v.getVolumeUpdatePatches(infos, singleItemImplied) + patches, patchError := o.getVolumeUpdatePatches(infos, singleItemImplied) if patchError != nil { return patchError } - if len(v.Output) > 0 || v.Local || kcmdutil.GetDryRunFlag(v.Cmd) { - return v.PrintObject(infos) + if o.Local || o.DryRun { + for _, info := range infos { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + return err + } + } } - failed := false + allErrs := []error{} for _, info := range updateInfos { var obj runtime.Object if len(info.ResourceVersion) == 0 { @@ -510,56 +505,56 @@ func (v *VolumeOptions) RunVolume(args []string, f kcmdutil.Factory) error { obj, err = resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, info.Object) } if err != nil { - handlePodUpdateError(v.Err, err, "volume") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch volume update to pod template: %v\n", err)) continue } info.Refresh(obj, true) - fmt.Fprintf(v.Out, "%s/%s\n", info.Mapping.Resource, info.Name) } for _, patch := range patches { info := patch.Info + name := cmd.GetObjectName(info) if patch.Err != nil { - failed = true - fmt.Fprintf(v.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, patch.Err) + allErrs = append(allErrs, fmt.Errorf("error: %s %v\n", name, patch.Err)) continue } if string(patch.Patch) == "{}" || len(patch.Patch) == 0 { - fmt.Fprintf(v.Err, "info: %s %q was not changed\n", info.Mapping.Resource, info.Name) + glog.V(1).Infof("info: %s was not changed\n", name) continue } - glog.V(4).Infof("Calculated patch %s", patch.Patch) + if o.Local || o.DryRun { + if err := o.Printer.PrintObj(info.Object, o.Out); err != nil { + allErrs = append(allErrs, err) + } + continue + } - obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) + actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) if err != nil { - handlePodUpdateError(v.Err, err, "volume") - failed = true + allErrs = append(allErrs, fmt.Errorf("failed to patch volume update to pod template: %v\n", err)) continue } - info.Refresh(obj, true) - kcmdutil.PrintSuccess(false, v.Out, info.Object, false, "updated") - } - if failed { - return kcmdutil.ErrExit + if err := o.Printer.PrintObj(actual, o.Out); err != nil { + allErrs = append(allErrs, err) + } } - return nil + return utilerrors.NewAggregate(allErrs) } -func (v *VolumeOptions) getVolumeUpdatePatches(infos []*resource.Info, singleItemImplied bool) ([]*Patch, error) { +func (o *VolumeOptions) getVolumeUpdatePatches(infos []*resource.Info, singleItemImplied bool) ([]*Patch, error) { skipped := 0 - patches := CalculatePatches(infos, v.Encoder, func(info *resource.Info) (bool, error) { + patches := CalculatePatches(infos, o.Encoder, func(info *resource.Info) (bool, error) { transformed := false - ok, err := v.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { + ok, err := o.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { var e error switch { - case v.Add: - e = v.addVolumeToSpec(spec, info, singleItemImplied) + case o.Add: + e = o.addVolumeToSpec(spec, info, singleItemImplied) transformed = true - case v.Remove: - e = v.removeVolumeFromSpec(spec, info) + case o.Remove: + e = o.removeVolumeFromSpec(spec, info) transformed = true } return e @@ -616,45 +611,45 @@ func setVolumeSourceByType(kv *kapi.Volume, opts *AddVolumeOptions) error { return nil } -func (v *VolumeOptions) printVolumes(infos []*resource.Info) []error { +func (o *VolumeOptions) printVolumes(infos []*resource.Info) []error { listingErrors := []error{} for _, info := range infos { - _, err := v.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { - return v.listVolumeForSpec(spec, info) + _, err := o.UpdatePodSpecForObject(info.Object, clientcmd.ConvertInteralPodSpecToExternal(func(spec *kapi.PodSpec) error { + return o.listVolumeForSpec(spec, info) })) if err != nil { listingErrors = append(listingErrors, err) - fmt.Fprintf(v.Err, "error: %s/%s %v\n", info.Mapping.Resource, info.Name, err) + fmt.Fprintf(o.ErrOut, "error: %s %v\n", cmd.GetObjectName(info), err) } } return listingErrors } -func (v *AddVolumeOptions) createClaim() *kapi.PersistentVolumeClaim { +func (a *AddVolumeOptions) createClaim() *kapi.PersistentVolumeClaim { pvc := &kapi.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ - Name: v.ClaimName, + Name: a.ClaimName, }, Spec: kapi.PersistentVolumeClaimSpec{ - AccessModes: []kapi.PersistentVolumeAccessMode{kapi.PersistentVolumeAccessMode(v.ClaimMode)}, + AccessModes: []kapi.PersistentVolumeAccessMode{kapi.PersistentVolumeAccessMode(a.ClaimMode)}, Resources: kapi.ResourceRequirements{ Requests: kapi.ResourceList{ - kapi.ResourceName(kapi.ResourceStorage): kresource.MustParse(v.ClaimSize), + kapi.ResourceName(kapi.ResourceStorage): kresource.MustParse(a.ClaimSize), }, }, }, } - if len(v.ClaimClass) > 0 { + if len(a.ClaimClass) > 0 { pvc.Annotations = map[string]string{ - storageAnnClass: v.ClaimClass, + storageAnnClass: a.ClaimClass, } } return pvc } -func (v *VolumeOptions) setVolumeSource(kv *kapi.Volume) error { +func (o *VolumeOptions) setVolumeSource(kv *kapi.Volume) error { var err error - opts := v.AddOpts + opts := o.AddOpts if len(opts.Type) > 0 { err = setVolumeSourceByType(kv, opts) } else if len(opts.Source) > 0 { @@ -663,29 +658,30 @@ func (v *VolumeOptions) setVolumeSource(kv *kapi.Volume) error { return err } -func (v *VolumeOptions) setVolumeMount(spec *kapi.PodSpec, info *resource.Info) error { - opts := v.AddOpts - containers, _ := selectContainers(spec.Containers, v.Containers) - if len(containers) == 0 && v.Containers != "*" { - fmt.Fprintf(v.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, v.Containers) +func (o *VolumeOptions) setVolumeMount(spec *kapi.PodSpec, info *resource.Info) error { + opts := o.AddOpts + containers, _ := selectContainers(spec.Containers, o.Containers) + if len(containers) == 0 && o.Containers != "*" { + fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource.Resource, info.Name, o.Containers) return nil } for _, c := range containers { for _, m := range c.VolumeMounts { - if path.Clean(m.MountPath) == path.Clean(opts.MountPath) && m.Name != v.Name { + if path.Clean(m.MountPath) == path.Clean(opts.MountPath) && m.Name != o.Name { return fmt.Errorf("volume mount '%s' already exists for container '%s'", opts.MountPath, c.Name) } } for i, m := range c.VolumeMounts { - if m.Name == v.Name && opts.Overwrite { + if m.Name == o.Name && opts.Overwrite { c.VolumeMounts = append(c.VolumeMounts[:i], c.VolumeMounts[i+1:]...) break } } volumeMount := &kapi.VolumeMount{ - Name: v.Name, + Name: o.Name, MountPath: path.Clean(opts.MountPath), + ReadOnly: opts.ReadOnly, } if len(opts.SubPath) > 0 { volumeMount.SubPath = path.Clean(opts.SubPath) @@ -695,8 +691,8 @@ func (v *VolumeOptions) setVolumeMount(spec *kapi.PodSpec, info *resource.Info) return nil } -func (v *VolumeOptions) getVolumeName(spec *kapi.PodSpec, singleResource bool) (string, bool, error) { - opts := v.AddOpts +func (o *VolumeOptions) getVolumeName(spec *kapi.PodSpec, singleResource bool) (string, bool, error) { + opts := o.AddOpts if opts.Overwrite { // Multiple resources can have same mount-path for different volumes, // so restrict it for single resource to uniquely find the volume @@ -704,7 +700,7 @@ func (v *VolumeOptions) getVolumeName(spec *kapi.PodSpec, singleResource bool) ( return "", false, fmt.Errorf("you must specify --name for the volume name when dealing with multiple resources") } if len(opts.MountPath) > 0 { - containers, _ := selectContainers(spec.Containers, v.Containers) + containers, _ := selectContainers(spec.Containers, o.Containers) var name string matchCount := 0 for _, c := range containers { @@ -729,52 +725,52 @@ func (v *VolumeOptions) getVolumeName(spec *kapi.PodSpec, singleResource bool) ( return "", false, fmt.Errorf("ambiguous --overwrite, specify --name or --mount-path") } - oldName, claimFound := v.checkForExistingClaim(spec) + oldName, claimFound := o.checkForExistingClaim(spec) if claimFound { return oldName, true, nil } // Generate volume name name := names.SimpleNameGenerator.GenerateName(volumePrefix) - if len(v.Output) == 0 { - fmt.Fprintf(v.Err, "info: Generated volume name: %s\n", name) + if o.PrintFlags.OutputFormat == nil || len(*o.PrintFlags.OutputFormat) == 0 { + fmt.Fprintf(o.ErrOut, "info: Generated volume name: %s\n", name) } return name, false, nil } -func (v *VolumeOptions) checkForExistingClaim(spec *kapi.PodSpec) (string, bool) { +func (o *VolumeOptions) checkForExistingClaim(spec *kapi.PodSpec) (string, bool) { for _, vol := range spec.Volumes { oldSource := vol.VolumeSource.PersistentVolumeClaim - if oldSource != nil && v.AddOpts.ClaimName == oldSource.ClaimName { + if oldSource != nil && o.AddOpts.ClaimName == oldSource.ClaimName { return vol.Name, true } } return "", false } -func (v *VolumeOptions) addVolumeToSpec(spec *kapi.PodSpec, info *resource.Info, singleResource bool) error { - opts := v.AddOpts +func (o *VolumeOptions) addVolumeToSpec(spec *kapi.PodSpec, info *resource.Info, singleResource bool) error { + opts := o.AddOpts claimFound := false - if len(v.Name) == 0 { + if len(o.Name) == 0 { var err error - v.Name, claimFound, err = v.getVolumeName(spec, singleResource) + o.Name, claimFound, err = o.getVolumeName(spec, singleResource) if err != nil { return err } } else { - _, claimFound = v.checkForExistingClaim(spec) + _, claimFound = o.checkForExistingClaim(spec) } newVolume := &kapi.Volume{ - Name: v.Name, + Name: o.Name, } setSource := true vNameFound := false for i, vol := range spec.Volumes { - if v.Name == vol.Name { + if o.Name == vol.Name { vNameFound = true if !opts.Overwrite && !claimFound { - return fmt.Errorf("volume '%s' already exists. Use --overwrite to replace", v.Name) + return fmt.Errorf("volume '%s' already exists. Use --overwrite to replace", o.Name) } if !opts.TypeChanged && len(opts.Source) == 0 { newVolume.VolumeSource = vol.VolumeSource @@ -786,12 +782,12 @@ func (v *VolumeOptions) addVolumeToSpec(spec *kapi.PodSpec, info *resource.Info, } // if --overwrite was passed, but volume did not previously // exist, log a warning that no volumes were overwritten - if !vNameFound && opts.Overwrite && len(v.Output) == 0 { - fmt.Fprintf(v.Err, "warning: volume %q did not previously exist and was not overriden. A new volume with this name has been created instead.", v.Name) + if !vNameFound && opts.Overwrite && (o.PrintFlags.OutputFormat == nil || len(*o.PrintFlags.OutputFormat) == 0) { + fmt.Fprintf(o.ErrOut, "warning: volume %q did not previously exist and was not overriden. A new volume with this name has been created instead.", o.Name) } if setSource { - err := v.setVolumeSource(newVolume) + err := o.setVolumeSource(newVolume) if err != nil { return err } @@ -799,7 +795,7 @@ func (v *VolumeOptions) addVolumeToSpec(spec *kapi.PodSpec, info *resource.Info, spec.Volumes = append(spec.Volumes, *newVolume) if len(opts.MountPath) > 0 { - err := v.setVolumeMount(spec, info) + err := o.setVolumeMount(spec, info) if err != nil { return err } @@ -807,12 +803,12 @@ func (v *VolumeOptions) addVolumeToSpec(spec *kapi.PodSpec, info *resource.Info, return nil } -func (v *VolumeOptions) removeSpecificVolume(spec *kapi.PodSpec, containers, skippedContainers []*kapi.Container) error { +func (o *VolumeOptions) removeSpecificVolume(spec *kapi.PodSpec, containers, skippedContainers []*kapi.Container) error { for _, c := range containers { newMounts := c.VolumeMounts[:0] for _, m := range c.VolumeMounts { // Remove all volume mounts that match specified name - if v.Name != m.Name { + if o.Name != m.Name { newMounts = append(newMounts, m) } } @@ -823,7 +819,7 @@ func (v *VolumeOptions) removeSpecificVolume(spec *kapi.PodSpec, containers, ski found := false for _, c := range skippedContainers { for _, m := range c.VolumeMounts { - if v.Name == m.Name { + if o.Name == m.Name { found = true break } @@ -835,33 +831,33 @@ func (v *VolumeOptions) removeSpecificVolume(spec *kapi.PodSpec, containers, ski if !found { foundVolume := false for i, vol := range spec.Volumes { - if v.Name == vol.Name { + if o.Name == vol.Name { spec.Volumes = append(spec.Volumes[:i], spec.Volumes[i+1:]...) foundVolume = true break } } if !foundVolume { - return fmt.Errorf("volume '%s' not found", v.Name) + return fmt.Errorf("volume '%s' not found", o.Name) } } return nil } -func (v *VolumeOptions) removeVolumeFromSpec(spec *kapi.PodSpec, info *resource.Info) error { - containers, skippedContainers := selectContainers(spec.Containers, v.Containers) - if len(containers) == 0 && v.Containers != "*" { - fmt.Fprintf(v.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, v.Containers) +func (o *VolumeOptions) removeVolumeFromSpec(spec *kapi.PodSpec, info *resource.Info) error { + containers, skippedContainers := selectContainers(spec.Containers, o.Containers) + if len(containers) == 0 && o.Containers != "*" { + fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource.Resource, info.Name, o.Containers) return nil } - if len(v.Name) == 0 { + if len(o.Name) == 0 { for _, c := range containers { c.VolumeMounts = []kapi.VolumeMount{} } spec.Volumes = []kapi.Volume{} } else { - err := v.removeSpecificVolume(spec, containers, skippedContainers) + err := o.removeSpecificVolume(spec, containers, skippedContainers) if err != nil { return err } @@ -925,18 +921,18 @@ func describeVolumeSource(source *kapi.VolumeSource) string { } } -func (v *VolumeOptions) listVolumeForSpec(spec *kapi.PodSpec, info *resource.Info) error { - containers, _ := selectContainers(spec.Containers, v.Containers) - if len(containers) == 0 && v.Containers != "*" { - fmt.Fprintf(v.Err, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, v.Containers) +func (o *VolumeOptions) listVolumeForSpec(spec *kapi.PodSpec, info *resource.Info) error { + containers, _ := selectContainers(spec.Containers, o.Containers) + if len(containers) == 0 && o.Containers != "*" { + fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource.Resource, info.Name, o.Containers) return nil } - fmt.Fprintf(v.Out, "%s/%s\n", info.Mapping.Resource, info.Name) - checkName := (len(v.Name) > 0) + fmt.Fprintf(o.Out, "%s/%s\n", info.Mapping.Resource.Resource, info.Name) + checkName := (len(o.Name) > 0) found := false for _, vol := range spec.Volumes { - if checkName && v.Name != vol.Name { + if checkName && o.Name != vol.Name { continue } found = true @@ -944,36 +940,36 @@ func (v *VolumeOptions) listVolumeForSpec(spec *kapi.PodSpec, info *resource.Inf refInfo := "" if vol.VolumeSource.PersistentVolumeClaim != nil { claimName := vol.VolumeSource.PersistentVolumeClaim.ClaimName - claim, err := v.Client.PersistentVolumeClaims(info.Namespace).Get(claimName, metav1.GetOptions{}) + claim, err := o.Client.PersistentVolumeClaims(info.Namespace).Get(claimName, metav1.GetOptions{}) switch { case err == nil: refInfo = fmt.Sprintf("(%s)", describePersistentVolumeClaim(claim)) case apierrs.IsNotFound(err): refInfo = "(does not exist)" default: - fmt.Fprintf(v.Err, "error: unable to retrieve persistent volume claim %s referenced in %s/%s: %v", claimName, info.Mapping.Resource, info.Name, err) + fmt.Fprintf(o.ErrOut, "error: unable to retrieve persistent volume claim %s referenced in %s/%s: %v", claimName, info.Mapping.Resource.Resource, info.Name, err) } } if len(refInfo) > 0 { refInfo = " " + refInfo } - fmt.Fprintf(v.Out, " %s%s as %s\n", describeVolumeSource(&vol.VolumeSource), refInfo, vol.Name) + fmt.Fprintf(o.Out, " %s%s as %s\n", describeVolumeSource(&vol.VolumeSource), refInfo, vol.Name) for _, c := range containers { for _, m := range c.VolumeMounts { if vol.Name != m.Name { continue } if len(spec.Containers) == 1 { - fmt.Fprintf(v.Out, " mounted at %s\n", m.MountPath) + fmt.Fprintf(o.Out, " mounted at %s\n", m.MountPath) } else { - fmt.Fprintf(v.Out, " mounted at %s in container %s\n", m.MountPath, c.Name) + fmt.Fprintf(o.Out, " mounted at %s in container %s\n", m.MountPath, c.Name) } } } } if checkName && !found { - return fmt.Errorf("volume %q not found", v.Name) + return fmt.Errorf("volume %q not found", o.Name) } return nil diff --git a/pkg/oc/cli/cmd/wrappers.go b/pkg/oc/cli/cmd/wrappers.go index 96a19f2e50e6..feb81e23b463 100644 --- a/pkg/oc/cli/cmd/wrappers.go +++ b/pkg/oc/cli/cmd/wrappers.go @@ -474,8 +474,6 @@ var ( // NewCmdRun is a wrapper for the Kubernetes cli run command func NewCmdRun(fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command { - // FIXME-REBASE - // opts := &kcmd.RunOptions{DefaultRestartAlwaysGenerator: "deploymentconfig/v1"} cmd := kcmd.NewCmdRun(f, streams) cmd.Long = runLong cmd.Example = fmt.Sprintf(runExample, fullName) diff --git a/pkg/oc/originpolymorphichelpers/updatepodspec.go b/pkg/oc/originpolymorphichelpers/updatepodspec.go index aaa29ae13be7..7e3f793e3ac8 100644 --- a/pkg/oc/originpolymorphichelpers/updatepodspec.go +++ b/pkg/oc/originpolymorphichelpers/updatepodspec.go @@ -36,7 +36,7 @@ func NewUpdatePodSpecForObjectFn(delegate polymorphichelpers.UpdatePodSpecForObj } return true, fn(&template.Spec) - // FIXME-REBASE: we should probably get rid of these: + // TODO: we need to get rid of these: // k8s internals case *kapi.Pod: return true, convertExteralPodSpecToInternal(fn)(&t.Spec) diff --git a/test/cmd/admin.sh b/test/cmd/admin.sh index efb702e900b2..283fdb09b869 100755 --- a/test/cmd/admin.sh +++ b/test/cmd/admin.sh @@ -368,7 +368,7 @@ os::cmd::expect_success "oc adm registry --images='${USE_IMAGES}'" os::cmd::expect_success_and_text 'oc adm registry' 'service exists' os::cmd::expect_success_and_text 'oc describe svc/docker-registry' 'Session Affinity:\s*ClientIP' os::cmd::expect_success_and_text 'oc get dc/docker-registry -o yaml' 'readinessProbe' -os::cmd::expect_success_and_text 'oc env --list dc/docker-registry' 'REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ENFORCEQUOTA=false' +os::cmd::expect_success_and_text 'oc set env --list dc/docker-registry' 'REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ENFORCEQUOTA=false' echo "registry: ok" os::test::junit::declare_suite_end diff --git a/test/cmd/basicresources.sh b/test/cmd/basicresources.sh index d97079d8903c..52f611937045 100755 --- a/test/cmd/basicresources.sh +++ b/test/cmd/basicresources.sh @@ -162,30 +162,30 @@ os::test::junit::declare_suite_start "cmd/basicresources/setprobe" # Validate the probe command arg="-f examples/hello-openshift/hello-pod.json" os::cmd::expect_failure_and_text "oc set probe" "error: one or more resources" -os::cmd::expect_failure_and_text "oc set probe ${arg}" "error: you must specify one of --readiness or --liveness" -os::cmd::expect_success_and_text "oc set probe ${arg} --liveness -o yaml" 'livenessProbe: \{\}' -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --initial-delay-seconds=10 -o yaml" "livenessProbe:" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --initial-delay-seconds=10 -o yaml" "initialDelaySeconds: 10" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness -- echo test" "livenessProbe:" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --readiness -- echo test" "readinessProbe:" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness -- echo test" "exec:" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness -- echo test" "\- echo" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness -- echo test" "\- test" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --open-tcp=3306" "tcpSocket:" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --open-tcp=3306" "port: 3306" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --open-tcp=port" "port: port" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:port/path" "port: port" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:8080/path" "port: 8080" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1/path" 'port: ""' -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:port/path" "path: /path" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:port/path" "scheme: HTTPS" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=http://127.0.0.1:port/path" "scheme: HTTP" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:port/path" "host: 127.0.0.1" -os::cmd::expect_success_and_text "oc set probe ${arg} -o yaml --liveness --get-url=https://127.0.0.1:port/path" "port: port" +os::cmd::expect_failure_and_text "oc set probe ${arg}" "error: you must specify one of --readiness, --liveness or both" +os::cmd::expect_failure_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1/path" "port must be specified as part of a url" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness" 'livenessProbe: \{\}' +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --initial-delay-seconds=10" "livenessProbe:" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --initial-delay-seconds=10" "initialDelaySeconds: 10" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness -- echo test" "livenessProbe:" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --readiness -- echo test" "readinessProbe:" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness -- echo test" "exec:" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness -- echo test" "\- echo" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness -- echo test" "\- test" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --open-tcp=3306" "tcpSocket:" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --open-tcp=3306" "port: 3306" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --open-tcp=port" "port: port" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:port/path" "port: port" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:8080/path" "port: 8080" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:port/path" "path: /path" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:port/path" "scheme: HTTPS" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=http://127.0.0.1:port/path" "scheme: HTTP" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:port/path" "host: 127.0.0.1" +os::cmd::expect_success_and_text "oc set probe ${arg} --local -o yaml --liveness --get-url=https://127.0.0.1:port/path" "port: port" os::cmd::expect_success "oc create -f test/integration/testdata/test-deployment-config.yaml" os::cmd::expect_failure_and_text "oc set probe dc/test-deployment-config --liveness" "Required value: must specify a handler type" os::cmd::expect_success_and_text "oc set probe dc test-deployment-config --liveness --open-tcp=8080" "updated" -os::cmd::expect_success_and_text "oc set probe dc/test-deployment-config --liveness --open-tcp=8080" "was not changed" +os::cmd::expect_success_and_text "oc set probe dc/test-deployment-config --liveness --open-tcp=8080 --v=1" "was not changed" os::cmd::expect_success_and_text "oc get dc/test-deployment-config -o yaml" "livenessProbe:" os::cmd::expect_success_and_text "oc set probe dc/test-deployment-config --liveness --initial-delay-seconds=10" "updated" os::cmd::expect_success_and_text "oc get dc/test-deployment-config -o yaml" "initialDelaySeconds: 10" diff --git a/test/cmd/deployments.sh b/test/cmd/deployments.sh index 10002ab475cc..cbe49f9a5ce7 100755 --- a/test/cmd/deployments.sh +++ b/test/cmd/deployments.sh @@ -26,43 +26,43 @@ os::cmd::try_until_text 'oc status' 'pod/hello-openshift runs openshift/hello-op os::test::junit::declare_suite_start "cmd/deployments/env" # Patch a nil list -os::cmd::expect_success 'oc env dc/test-deployment-config TEST=value' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'TEST=value' +os::cmd::expect_success 'oc set env dc/test-deployment-config TEST=value' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'TEST=value' # Remove only env in the list -os::cmd::expect_success 'oc env dc/test-deployment-config TEST-' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config --list' 'TEST=value' +os::cmd::expect_success 'oc set env dc/test-deployment-config TEST-' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config --list' 'TEST=value' # Add back to empty list -os::cmd::expect_success 'oc env dc/test-deployment-config TEST=value' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config TEST=foo --list' 'TEST=value' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config TEST=foo --list' 'TEST=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo --list' 'TEST=value' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config OTHER=foo -c ruby --list' 'OTHER=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo -c ruby* --list' 'OTHER=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo -c *hello* --list' 'OTHER=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo -c *world --list' 'OTHER=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo --list' 'OTHER=foo' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config OTHER=foo -o yaml' 'name: OTHER' -os::cmd::expect_success_and_text 'echo OTHER=foo | oc env dc/test-deployment-config -e - --list' 'OTHER=foo' -os::cmd::expect_success_and_not_text 'echo #OTHER=foo | oc env dc/test-deployment-config -e - --list' 'OTHER=foo' -os::cmd::expect_success 'oc env dc/test-deployment-config TEST=bar OTHER=baz BAR-' -os::cmd::expect_success_and_text 'oc env -f test/integration/testdata/test-deployment-config.yaml TEST=VERSION -o yaml' 'v1' -os::cmd::expect_success 'oc env dc/test-deployment-config A=a B=b C=c D=d E=e F=f G=g' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'A=a' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'B=b' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'C=c' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'D=d' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'E=e' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'F=f' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'G=g' -os::cmd::expect_success 'oc env dc/test-deployment-config H=h G- E=updated C- A-' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'B=b' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'D=d' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'E=updated' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'F=f' -os::cmd::expect_success_and_text 'oc env dc/test-deployment-config --list' 'H=h' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config --list' 'A=a' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config --list' 'C=c' -os::cmd::expect_success_and_not_text 'oc env dc/test-deployment-config --list' 'G=g' +os::cmd::expect_success 'oc set env dc/test-deployment-config TEST=value' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config TEST=foo --list' 'TEST=value' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config TEST=foo --list' 'TEST=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo --list' 'TEST=value' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config OTHER=foo -c ruby --list' 'OTHER=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo -c ruby* --list' 'OTHER=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo -c *hello* --list' 'OTHER=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo -c *world --list' 'OTHER=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo --list' 'OTHER=foo' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config OTHER=foo -o yaml' 'name: OTHER' +os::cmd::expect_success_and_text 'echo OTHER=foo | oc set env dc/test-deployment-config -e - --list' 'OTHER=foo' +os::cmd::expect_success_and_not_text 'echo #OTHER=foo | oc set env dc/test-deployment-config -e - --list' 'OTHER=foo' +os::cmd::expect_success 'oc set env dc/test-deployment-config TEST=bar OTHER=baz BAR-' +os::cmd::expect_success_and_text 'oc set env -f test/integration/testdata/test-deployment-config.yaml TEST=VERSION -o yaml' 'v1' +os::cmd::expect_success 'oc set env dc/test-deployment-config A=a B=b C=c D=d E=e F=f G=g' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'A=a' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'B=b' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'C=c' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'D=d' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'E=e' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'F=f' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'G=g' +os::cmd::expect_success 'oc set env dc/test-deployment-config H=h G- E=updated C- A-' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'B=b' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'D=d' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'E=updated' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'F=f' +os::cmd::expect_success_and_text 'oc set env dc/test-deployment-config --list' 'H=h' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config --list' 'A=a' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config --list' 'C=c' +os::cmd::expect_success_and_not_text 'oc set env dc/test-deployment-config --list' 'G=g' echo "env: ok" os::test::junit::declare_suite_end @@ -162,32 +162,30 @@ os::cmd::expect_failure_and_text "oc set deployment-hook ${arg}" "error: you mus os::cmd::expect_failure_and_text "oc set deployment-hook ${arg} -o yaml --pre -- mycmd" 'deploymentconfigs.apps.openshift.io "test-deployment-config" not found' os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local -o yaml --post -- mycmd" 'mycmd' os::cmd::expect_success_and_not_text "oc set deployment-hook ${arg} --local -o yaml --post -- mycmd | oc set deployment-hook -f - --local -o yaml --post --remove" 'mycmd' -os::cmd::expect_success "oc create ${arg}" -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre -o yaml -- echo 'hello world'" 'pre:' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre -o yaml -- echo 'hello world'" 'execNewPod:' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre -o yaml -- echo 'hello world'" '\- echo' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre -o yaml -- echo 'hello world'" '\- hello world' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --post -o yaml -- echo 'hello world'" 'post:' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --mid -o yaml -- echo 'hello world'" 'mid:' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --failure-policy=ignore -o yaml -- echo 'hello world'" 'failurePolicy: Ignore' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --failure-policy=retry -o yaml -- echo 'hello world'" 'failurePolicy: Retry' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --failure-policy=abort -o yaml -- echo 'hello world'" 'failurePolicy: Abort' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre -o yaml -- echo 'hello world'" 'pre:' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre -o yaml -- echo 'hello world'" 'execNewPod:' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre -o yaml -- echo 'hello world'" '\- echo' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre -o yaml -- echo 'hello world'" '\- hello world' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --post -o yaml -- echo 'hello world'" 'post:' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --mid -o yaml -- echo 'hello world'" 'mid:' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --failure-policy=ignore -o yaml -- echo 'hello world'" 'failurePolicy: Ignore' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --failure-policy=retry -o yaml -- echo 'hello world'" 'failurePolicy: Retry' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --failure-policy=abort -o yaml -- echo 'hello world'" 'failurePolicy: Abort' # Non-existent container -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --container=blah -o yaml -- echo 'hello world'" 'does not have a container named' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --container=blah -o yaml -- echo 'hello world'" 'does not have a container named' # Non-existent volume -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --volumes=blah -o yaml -- echo 'hello world'" 'does not have a volume named' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --volumes=blah -o yaml -- echo 'hello world'" 'does not have a volume named' # Existing container -os::cmd::expect_success_and_not_text "oc set deployment-hook ${arg} --pre --container=ruby-helloworld -o yaml -- echo 'hello world'" 'does not have a container named' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --container=ruby-helloworld -o yaml -- echo 'hello world'" 'containerName: ruby-helloworld' +os::cmd::expect_success_and_not_text "oc set deployment-hook ${arg} --local --pre --container=ruby-helloworld -o yaml -- echo 'hello world'" 'does not have a container named' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --container=ruby-helloworld -o yaml -- echo 'hello world'" 'containerName: ruby-helloworld' # Existing volume -os::cmd::expect_success_and_not_text "oc set deployment-hook ${arg} --pre --volumes=vol1 -o yaml -- echo 'hello world'" 'does not have a volume named' -os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --pre --volumes=vol1 -o yaml -- echo 'hello world'" '\- vol1' -os::cmd::expect_success 'oc delete dc/test-deployment-config' +os::cmd::expect_success_and_not_text "oc set deployment-hook ${arg} --local --pre --volumes=vol1 -o yaml -- echo 'hello world'" 'does not have a volume named' +os::cmd::expect_success_and_text "oc set deployment-hook ${arg} --local --pre --volumes=vol1 -o yaml -- echo 'hello world'" '\- vol1' # Server object tests os::cmd::expect_success "oc create -f test/integration/testdata/test-deployment-config.yaml" os::cmd::expect_failure_and_text "oc set deployment-hook dc/test-deployment-config --pre" "you must specify a command" os::cmd::expect_success_and_text "oc set deployment-hook test-deployment-config --pre -- echo 'hello world'" "updated" -os::cmd::expect_success_and_text "oc set deployment-hook dc/test-deployment-config --pre -- echo 'hello world'" "was not changed" +os::cmd::expect_success_and_text "oc set deployment-hook dc/test-deployment-config --v=1 --pre -- echo 'hello world'" "was not changed" os::cmd::expect_success_and_text "oc get dc/test-deployment-config -o yaml" "pre:" os::cmd::expect_success_and_text "oc set deployment-hook dc/test-deployment-config --pre --failure-policy=abort -- echo 'test'" "updated" os::cmd::expect_success_and_text "oc get dc/test-deployment-config -o yaml" "failurePolicy: Abort" diff --git a/test/cmd/env.sh b/test/cmd/env.sh index f80a47ae6777..f767cc9f47d8 100755 --- a/test/cmd/env.sh +++ b/test/cmd/env.sh @@ -6,21 +6,21 @@ os::test::junit::declare_suite_start "cmd/set-env" # This test validates the value of --image for oc run os::cmd::expect_success 'oc new-app node' os::cmd::expect_failure_and_text 'oc set env dc/node' 'error: at least one environment variable must be provided' -os::cmd::expect_success_and_text 'oc set env dc/node key=value' 'deploymentconfig.apps.openshift.io "node" updated' -os::cmd::expect_success_and_text 'oc set env dc/node --list' 'deploymentconfigs node, container node' -os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" key-' 'deploymentconfig.apps.openshift.io "node" updated' +os::cmd::expect_success_and_text 'oc set env dc/node key=value' 'deploymentconfig.apps.openshift.io/node updated' +os::cmd::expect_success_and_text 'oc set env dc/node --list' 'deploymentconfigs/node, container node' +os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" key-' 'deploymentconfig.apps.openshift.io/node updated' os::cmd::expect_failure_and_text 'oc set env dc --all --containers="node"' 'error: at least one environment variable must be provided' os::cmd::expect_failure_and_not_text 'oc set env --from=secret/mysecret dc/node' 'error: at least one environment variable must be provided' os::cmd::expect_failure_and_text 'oc set env dc/node test#abc=1234' 'environment variables must be of the form key=value, but is "test#abc=1234"' # ensure deleting a var through --env does not result in an error message -os::cmd::expect_success_and_text 'oc set env dc/node key=value' 'deploymentconfig.apps.openshift.io "node" updated' -os::cmd::expect_success_and_text 'oc set env dc/node dots.in.a.key=dots.in.a.value' 'deploymentconfig.apps.openshift.io "node" updated' -os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" --env=key-' 'deploymentconfig.apps.openshift.io "node" updated' +os::cmd::expect_success_and_text 'oc set env dc/node key=value' 'deploymentconfig.apps.openshift.io/node updated' +os::cmd::expect_success_and_text 'oc set env dc/node dots.in.a.key=dots.in.a.value' 'deploymentconfig.apps.openshift.io/node updated' +os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" --env=key-' 'deploymentconfig.apps.openshift.io/node updated' # ensure deleting a var through --env actually deletes the env var os::cmd::expect_success_and_not_text "oc get dc/node -o jsonpath='{ .spec.template.spec.containers[?(@.name==\"node\")].env }'" 'name\:key' os::cmd::expect_success_and_text "oc get dc/node -o jsonpath='{ .spec.template.spec.containers[?(@.name==\"node\")].env }'" 'name\:dots.in.a.key' -os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" --env=dots.in.a.key-' 'deploymentconfig.apps.openshift.io "node" updated' +os::cmd::expect_success_and_text 'oc set env dc --all --containers="node" --env=dots.in.a.key-' 'deploymentconfig.apps.openshift.io/node updated' os::cmd::expect_success_and_not_text "oc get dc/node -o jsonpath='{ .spec.template.spec.containers[?(@.name==\"node\")].env }'" 'name\:dots.in.a.key' # check that env vars are not split at commas @@ -48,7 +48,7 @@ spec: # ensure build-config has been created and that its type is "JenkinsPipeline" os::cmd::expect_success_and_text "oc get bc fake-pipeline -o jsonpath='{ .spec.strategy.type }'" 'JenkinsPipeline' # attempt to set an environment variable -os::cmd::expect_success_and_text 'oc set env bc/fake-pipeline FOO=BAR' 'buildconfig.build.openshift.io "fake\-pipeline" updated' +os::cmd::expect_success_and_text 'oc set env bc/fake-pipeline FOO=BAR' 'buildconfig.build.openshift.io/fake\-pipeline updated' # ensure environment variable was set os::cmd::expect_success_and_text "oc get bc fake-pipeline -o jsonpath='{ .spec.strategy.jenkinsPipelineStrategy.env }'" 'name\:FOO' os::cmd::expect_success 'oc delete bc fake-pipeline' diff --git a/test/cmd/image-lookup.sh b/test/cmd/image-lookup.sh index 8ed6f40c1465..82e770900e0f 100755 --- a/test/cmd/image-lookup.sh +++ b/test/cmd/image-lookup.sh @@ -16,7 +16,7 @@ os::test::junit::declare_suite_start "cmd/image-lookup" # This test validates image lookup resolution # Verify image resolution on default resource types -os::cmd::expect_success "oc import-image --confirm --from=nginx:latest nginx:latest" +os::cmd::expect_success_and_text "oc import-image --confirm --from=nginx:latest nginx:latest" "sha256:" os::cmd::expect_success_and_text "oc set image-lookup is/nginx" "updated" # Image lookup works for pods os::cmd::expect_success "oc run --generator=run-pod/v1 --restart=Never --image=nginx:latest nginx" @@ -33,8 +33,8 @@ os::cmd::expect_success "echo '${rc}' | oc create -f -" os::cmd::expect_success_and_text "oc get rc/nginx -o jsonpath='{.spec.template.spec.containers[0].image}'" "nginx@sha256:" # Verify swapping settings on image stream -os::cmd::expect_success_and_text "oc set image-lookup is/nginx" "was not changed" -os::cmd::expect_success_and_text "oc set image-lookup nginx" "was not changed" +os::cmd::expect_success_and_text "oc set image-lookup is/nginx --v=1" "was not changed" +os::cmd::expect_success_and_text "oc set image-lookup nginx --v=1" "was not changed" os::cmd::expect_success_and_text "oc set image-lookup is --list" "nginx.*true" os::cmd::expect_success_and_text "oc set image-lookup nginx --enabled=false" "updated" os::cmd::expect_success_and_text "oc set image-lookup is --list" "nginx.*false" @@ -47,7 +47,7 @@ os::cmd::expect_success "oc delete deploy,dc,rs,rc,pods --all" # Resource annotated with image lookup will create pods that resolve os::cmd::expect_success "oc tag nginx:latest alternate:latest" rc='{"kind":"Deployment","apiVersion":"apps/v1beta1","metadata":{"name":"alternate"},"spec":{"template":{"metadata":{"labels":{"app":"test"}},"spec":{"containers":[{"name":"main","image":"alternate:latest"}]}}}}' -os::cmd::expect_success "echo '${rc}' | oc set image-lookup -f - -o json | oc create -f -" +os::cmd::expect_success "echo '${rc}' | oc set image-lookup --local -f - -o json | oc create -f -" os::cmd::expect_success "oc run --generator=run-pod/v1 --restart=Never --image=alternate:latest alternate" os::cmd::expect_success_and_text "oc get pod/alternate -o jsonpath='{.spec.containers[0].image}'" "alternate:latest" os::cmd::expect_success_and_text "oc get rs -o jsonpath='{..spec.template.spec.containers[0].image}'" "nginx@sha256:" diff --git a/test/cmd/printer.sh b/test/cmd/printer.sh index d9dd51333276..4c684c435377 100755 --- a/test/cmd/printer.sh +++ b/test/cmd/printer.sh @@ -15,11 +15,10 @@ os::cmd::expect_success_and_text 'oc new-app ruby-helloworld-sample' 'deployment os::cmd::expect_success_and_text 'oc get all --all-namespaces' 'cmd-printer[\ ]+buildconfig.build.openshift.io\/ruby\-sample\-build' # Test that infos printer supports all outputFormat options -os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value' 'deploymentconfig.apps.openshift.io "node" updated' -os::cmd::expect_success 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o custom-colums="NAME:.metadata.name"' +os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value' 'deploymentconfig.apps.openshift.io/node updated' +# FIXME: what to do with this? +# os::cmd::expect_success 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o custom-colums="NAME:.metadata.name"' os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o yaml' 'apiVersion: apps.openshift.io/v1' os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o json' '"apiVersion": "apps.openshift.io/v1"' -os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o wide' 'node' -os::cmd::expect_success_and_text 'oc new-app node -o yaml | oc set env -f - MYVAR=value -o name' 'deploymentconfig.apps.openshift.io/node' echo "resource printer: ok" -os::test::junit::declare_suite_end \ No newline at end of file +os::test::junit::declare_suite_end diff --git a/test/cmd/set-liveness-probe.sh b/test/cmd/set-liveness-probe.sh index 068c761112fe..c8bb4d8a79d2 100755 --- a/test/cmd/set-liveness-probe.sh +++ b/test/cmd/set-liveness-probe.sh @@ -24,7 +24,7 @@ os::cmd::expect_success_and_text 'oc set probe dc/simple-deployment --liveness - os::cmd::expect_success_and_text 'oc set probe dc/simple-deployment --liveness --get-url=http://google.com:80 -o yaml' 'name: simple-deployment' os::cmd::expect_success_and_not_text 'oc status --suggest' 'rc/simple-deployment-1 has no liveness probe' -os::cmd::expect_success_and_text 'oc set probe dc/simple-deployment --liveness --get-url=http://google.com:80' 'deploymentconfig.apps.openshift.io "simple-deployment" updated' +os::cmd::expect_success_and_text 'oc set probe dc/simple-deployment --liveness --get-url=http://google.com:80' 'deploymentconfig.apps.openshift.io/simple-deployment probes updated' os::cmd::expect_success_and_not_text 'oc status --suggest' 'dc/simple-deployment has no liveness probe' echo "set-probe-liveness: ok" os::test::junit::declare_suite_end diff --git a/test/cmd/setbuildhook.sh b/test/cmd/setbuildhook.sh index 0f5015fecef0..60e1a5ec287d 100755 --- a/test/cmd/setbuildhook.sh +++ b/test/cmd/setbuildhook.sh @@ -15,18 +15,18 @@ os::test::junit::declare_suite_start "cmd/builds/setbuildhook" arg="-f test/testdata/test-bc.yaml" os::cmd::expect_failure_and_text "oc set build-hook" "error: one or more build configs" os::cmd::expect_failure_and_text "oc set build-hook ${arg}" "error: you must specify a type of hook" -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit -o yaml -- echo 'hello world'" 'postCommit:' -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit -o yaml -- echo 'hello world'" 'args:' -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit -o yaml -- echo 'hello world'" '\- echo' -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit -o yaml -- echo 'hello world'" '\- hello world' -os::cmd::expect_success_and_not_text "oc set build-hook ${arg} --post-commit -o yaml -- echo 'hello world'" 'command:' -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit --command -o yaml -- echo 'hello world'" 'command:' -os::cmd::expect_success_and_text "oc set build-hook ${arg} --post-commit -o yaml --script='echo \"hello world\"'" 'script: echo \"hello world\"' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit -o yaml -- echo 'hello world'" 'postCommit:' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit -o yaml -- echo 'hello world'" 'args:' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit -o yaml -- echo 'hello world'" '\- echo' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit -o yaml -- echo 'hello world'" '\- hello world' +os::cmd::expect_success_and_not_text "oc set build-hook ${arg} --local --post-commit -o yaml -- echo 'hello world'" 'command:' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit --command -o yaml -- echo 'hello world'" 'command:' +os::cmd::expect_success_and_text "oc set build-hook ${arg} --local --post-commit -o yaml --script='echo \"hello world\"'" 'script: echo \"hello world\"' # Server object tests os::cmd::expect_success "oc create -f test/testdata/test-bc.yaml" os::cmd::expect_failure_and_text "oc set build-hook bc/test-buildconfig --post-commit" "you must specify either a script or command" os::cmd::expect_success_and_text "oc set build-hook test-buildconfig --post-commit -- echo 'hello world'" "updated" -os::cmd::expect_success_and_text "oc set build-hook bc/test-buildconfig --post-commit -- echo 'hello world'" "was not changed" +os::cmd::expect_success_and_text "oc set build-hook bc/test-buildconfig --v=1 --post-commit -- echo 'hello world'" "was not changed" os::cmd::expect_success_and_text "oc get bc/test-buildconfig -o yaml" "args:" os::cmd::expect_success_and_text "oc set build-hook bc/test-buildconfig --post-commit --command -- /bin/bash -c \"echo 'test'\"" "updated" os::cmd::expect_success_and_text "oc get bc/test-buildconfig -o yaml" "command:" diff --git a/test/cmd/setbuildsecret.sh b/test/cmd/setbuildsecret.sh index bf40b6ecf041..f00c99843388 100755 --- a/test/cmd/setbuildsecret.sh +++ b/test/cmd/setbuildsecret.sh @@ -27,7 +27,7 @@ os::cmd::expect_success_and_not_text "oc set build-secret ${arg} mysecret --push # Server object tests os::cmd::expect_success "oc create -f test/testdata/test-bc.yaml" os::cmd::expect_success_and_text "oc set build-secret test-buildconfig mysecret --push" "updated" -os::cmd::expect_success_and_text "oc set build-secret bc/test-buildconfig mysecret --push" "was not changed" +os::cmd::expect_success_and_text "oc set build-secret bc/test-buildconfig mysecret --push --v=1" "was not changed" os::cmd::expect_success_and_text "oc get bc/test-buildconfig -o yaml" "pushSecret:" os::cmd::expect_success_and_text "oc set build-secret bc/test-buildconfig --push --remove" "updated" os::cmd::expect_success_and_not_text "oc get bc/test-buildconfig -o yaml" "pushSecret:" diff --git a/test/cmd/volumes.sh b/test/cmd/volumes.sh index c1ab4766de91..e0adb51c505b 100755 --- a/test/cmd/volumes.sh +++ b/test/cmd/volumes.sh @@ -16,8 +16,8 @@ os::test::junit::declare_suite_start "cmd/volumes" os::cmd::expect_success 'oc create -f test/integration/testdata/test-deployment-config.yaml' os::cmd::expect_success 'oc create -f test/testdata/rollingupdate-daemonset.yaml' -os::cmd::expect_success_and_text 'oc volume dc/test-deployment-config --list' 'vol1' -os::cmd::expect_success 'oc volume dc/test-deployment-config --add --name=vol0 -m /opt5' +os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --list' 'vol1' +os::cmd::expect_success 'oc set volume dc/test-deployment-config --add --name=vol0 -m /opt5' os::cmd::expect_success 'oc set volume dc/test-deployment-config --add --name=vol2 --type=emptydir -m /opt' os::cmd::expect_failure_and_text "oc set volume dc/test-deployment-config --add --name=vol1 --type=secret --secret-name='\$ecret' -m /data" 'overwrite to replace' os::cmd::expect_success "oc set volume dc/test-deployment-config --add --name=vol10 --secret-name='my-secret' -m /data-2" @@ -29,7 +29,7 @@ os::cmd::expect_failure_and_text 'oc set volume dc/test-deployment-config --add os::cmd::expect_success_and_text "oc set volume dc/test-deployment-config --add --name=vol2 -m /etc -c 'ruby' --overwrite" 'does not have any containers' os::cmd::expect_success "oc set volume dc/test-deployment-config --add --name=vol2 -m /etc -c 'ruby*' --overwrite" os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --list --name=vol2' 'mounted at /etc' -os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --add --name=vol3 -o yaml' 'name: vol3' +os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --dry-run --add --name=vol3 -o yaml' 'name: vol3' os::cmd::expect_failure_and_text 'oc set volume dc/test-deployment-config --list --name=vol3' 'volume "vol3" not found' os::cmd::expect_failure_and_text 'oc set volume dc/test-deployment-config --remove' 'confirm for removing more than one volume' os::cmd::expect_success 'oc set volume dc/test-deployment-config --remove --name=vol2' @@ -42,25 +42,25 @@ os::cmd::expect_success_and_not_text 'oc set volume dc/test-deployment-config -- os::cmd::expect_success 'oc set volume ds/bind --add --name=vol2 --type=emptydir -m /opt' os::cmd::expect_success 'oc set volume ds/bind --remove --name=vol2' -os::cmd::expect_success "oc volume dc/test-deployment-config --add -t 'secret' --secret-name='asdf' --default-mode '765'" +os::cmd::expect_success "oc set volume dc/test-deployment-config --add -t 'secret' --secret-name='asdf' --default-mode '765'" os::cmd::expect_success_and_text 'oc get dc/test-deployment-config -o jsonpath={.spec.template.spec.volumes[0]}' '501' os::cmd::expect_success 'oc set volume dc/test-deployment-config --remove --confirm' -os::cmd::expect_failure "oc volume dc/test-deployment-config --add -t 'secret' --secret-name='asdf' --default-mode '888'" +os::cmd::expect_failure "oc set volume dc/test-deployment-config --add -t 'secret' --secret-name='asdf' --default-mode '888'" -os::cmd::expect_success "oc volume dc/test-deployment-config --add -t 'configmap' --configmap-name='asdf' --default-mode '123'" +os::cmd::expect_success "oc set volume dc/test-deployment-config --add -t 'configmap' --configmap-name='asdf' --default-mode '123'" os::cmd::expect_success_and_text 'oc get dc/test-deployment-config -o jsonpath={.spec.template.spec.volumes[0]}' '83' os::cmd::expect_success 'oc set volume dc/test-deployment-config --remove --confirm' os::cmd::expect_success_and_text 'oc get pvc --no-headers | wc -l' '0' -os::cmd::expect_success 'oc volume dc/test-deployment-config --add --mount-path=/other --claim-size=1G' +os::cmd::expect_success 'oc set volume dc/test-deployment-config --add --mount-path=/other --claim-size=1G' os::cmd::expect_success 'oc set volume dc/test-deployment-config --add --mount-path=/second --type=pvc --claim-size=1G --claim-mode=rwo' os::cmd::expect_success_and_text 'oc get pvc --no-headers | wc -l' '2' # attempt to add the same volume mounted in /other, but with a subpath # we are not using --overwrite, so expect a failure os::cmd::expect_failure_and_text 'oc set volume dc/test-deployment-config --add --mount-path=/second --sub-path=foo' "'/second' already exists" # add --sub-path and expect success and --sub-path added when using --overwrite -os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --add --mount-path=/second --sub-path=foo --overwrite' 'deploymentconfig.apps.openshift.io "test-deployment-config" updated' +os::cmd::expect_success_and_text 'oc set volume dc/test-deployment-config --add --mount-path=/second --sub-path=foo --overwrite' 'deploymentconfig.apps.openshift.io/test-deployment-config volume updated' os::cmd::expect_success_and_text "oc get dc/test-deployment-config -o jsonpath='{.spec.template.spec.containers[0].volumeMounts[*].subPath}'" 'foo' # ensure that we can describe volumes of type ConfigMap @@ -88,10 +88,10 @@ spec: os::cmd::expect_success_and_text 'oc get dc simple-dc' 'simple-dc' os::cmd::expect_success 'oc create cm cmvol' os::cmd::expect_success 'oc set volume dc/simple-dc --add --name=cmvolume --type=configmap --configmap-name=cmvol' -os::cmd::expect_success_and_text 'oc volume dc/simple-dc' 'configMap/cmvol as cmvolume' +os::cmd::expect_success_and_text 'oc set volume dc/simple-dc' 'configMap/cmvol as cmvolume' # command alias -os::cmd::expect_success 'oc volumes --help' +os::cmd::expect_success 'oc set volumes --help' os::cmd::expect_success 'oc set volumes --help' os::cmd::expect_success 'oc set volumes dc/test-deployment-config --list' diff --git a/test/end-to-end/core.sh b/test/end-to-end/core.sh index 5cee99dffc42..0070fa47c15a 100755 --- a/test/end-to-end/core.sh +++ b/test/end-to-end/core.sh @@ -110,7 +110,7 @@ os::cmd::expect_success "dig @${DNS_SERVICE_IP} docker-registry.default.local. A os::log::info "Configure registry to disable mirroring" os::cmd::expect_success "oc project '${CLUSTER_ADMIN_CONTEXT}'" -os::cmd::expect_success 'oc env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_MIRRORPULLTHROUGH=false' +os::cmd::expect_success 'oc set env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_MIRRORPULLTHROUGH=false' os::cmd::expect_success 'oc rollout status dc/docker-registry' os::log::info "Registry configured to disable mirroring" @@ -127,7 +127,7 @@ os::cmd::expect_success "oc get istag/busybox:latest" os::log::info "Restore registry mirroring" os::cmd::expect_success "oc project '${CLUSTER_ADMIN_CONTEXT}'" -os::cmd::expect_success 'oc env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_MIRRORPULLTHROUGH=true' +os::cmd::expect_success 'oc set env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_MIRRORPULLTHROUGH=true' os::cmd::expect_success 'oc rollout status dc/docker-registry' os::log::info "Restore configured to enable mirroring" @@ -625,7 +625,7 @@ os::log::info "Validated image pruning" # with registry's re-deployment we loose all the blobs stored in its storage until now os::log::info "Configure registry to accept manifest V2 schema 2" os::cmd::expect_success "oc project '${CLUSTER_ADMIN_CONTEXT}'" -os::cmd::expect_success 'oc env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ACCEPTSCHEMA2=true' +os::cmd::expect_success 'oc set env -n default dc/docker-registry REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_ACCEPTSCHEMA2=true' os::cmd::expect_success 'oc rollout status dc/docker-registry' os::log::info "Registry configured to accept manifest V2 schema 2" diff --git a/test/extended/cmd.sh b/test/extended/cmd.sh index 7b18013d1c0e..381971685ca6 100755 --- a/test/extended/cmd.sh +++ b/test/extended/cmd.sh @@ -155,7 +155,7 @@ VERBOSE=true os::cmd::expect_success "oc new-project service-serving-cert-genera os::cmd::expect_success 'oc create dc nginx --image=nginx -- sh -c "nginx -c /etc/nginx/nginx.conf && sleep 86400"' os::cmd::expect_success "oc expose dc/nginx --port=443" os::cmd::expect_success "oc annotate svc/nginx service.alpha.openshift.io/serving-cert-secret-name=nginx-ssl-key" -os::cmd::expect_success "oc volumes dc/nginx --add --secret-name=nginx-ssl-key --mount-path=/etc/serving-cert" +os::cmd::expect_success "oc set volumes dc/nginx --add --secret-name=nginx-ssl-key --mount-path=/etc/serving-cert" os::cmd::expect_success "oc create configmap default-conf --from-file=test/extended/testdata/service-serving-cert/nginx-serving-cert.conf" os::cmd::expect_success "oc set volumes dc/nginx --add --configmap-name=default-conf --mount-path=/etc/nginx/conf.d" os::cmd::try_until_text "oc get pods -l deployment-config.name=nginx" 'Running' diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go index 453b913e78b6..44b76c313c4f 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/genericclioptions/print_flags.go @@ -97,7 +97,7 @@ func (f *PrintFlags) AddFlags(cmd *cobra.Command) { f.NamePrintFlags.AddFlags(cmd) if f.OutputFormat != nil { - cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].") + cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, fmt.Sprintf("Output format. One of: %s.", strings.Join(f.AllowedFormats(), "|"))) } }