From a090086ff690cd230b10a55cfd6d3eb4682249d3 Mon Sep 17 00:00:00 2001 From: Boaz Shuster Date: Mon, 10 Jul 2017 12:43:57 +0300 Subject: [PATCH 01/18] Sort swarm stacks and nodes using natural sorting This commit changes the order stacks and nodes are displayed. For example, running "docker stack ls" is expected to display the following list: NAME SERVICES service-1 1 service-2 1 service-10 1 However, currently this is what is printed: NAME SERVICES service-1 1 service-10 1 service-2 1 To fix this, "docker stack ls" and "docker node ls" are using natural sorting to make it more human readable. Signed-off-by: Boaz Shuster Upstream-commit: 1333b49194c7bd6934a041b6ef491fa95a8bf2af Component: cli --- components/cli/cli/command/node/list.go | 13 ++++ components/cli/cli/command/node/list_test.go | 21 +++++ .../node/testdata/node-list-sort.golden | 3 + components/cli/cli/command/stack/list.go | 3 +- components/cli/cli/command/stack/list_test.go | 52 ++++++++++--- .../testdata/stack-list-sort-natural.golden | 4 + components/cli/vendor.conf | 1 + components/cli/vendor/vbom.ml/util/LICENSE | 17 +++++ components/cli/vendor/vbom.ml/util/README.md | 5 ++ .../vendor/vbom.ml/util/sortorder/README.md | 5 ++ .../cli/vendor/vbom.ml/util/sortorder/doc.go | 5 ++ .../vendor/vbom.ml/util/sortorder/natsort.go | 76 +++++++++++++++++++ 12 files changed, 194 insertions(+), 11 deletions(-) create mode 100644 components/cli/cli/command/node/testdata/node-list-sort.golden create mode 100644 components/cli/cli/command/stack/testdata/stack-list-sort-natural.golden create mode 100644 components/cli/vendor/vbom.ml/util/LICENSE create mode 100644 components/cli/vendor/vbom.ml/util/README.md create mode 100644 components/cli/vendor/vbom.ml/util/sortorder/README.md create mode 100644 components/cli/vendor/vbom.ml/util/sortorder/doc.go create mode 100644 components/cli/vendor/vbom.ml/util/sortorder/natsort.go diff --git a/components/cli/cli/command/node/list.go b/components/cli/cli/command/node/list.go index 0c3d7e1abc..7dac795663 100644 --- a/components/cli/cli/command/node/list.go +++ b/components/cli/cli/command/node/list.go @@ -1,15 +1,27 @@ package node import ( + "sort" + "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/opts" "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" "github.com/spf13/cobra" "golang.org/x/net/context" + "vbom.ml/util/sortorder" ) +type byHostname []swarm.Node + +func (n byHostname) Len() int { return len(n) } +func (n byHostname) Swap(i, j int) { n[i], n[j] = n[j], n[i] } +func (n byHostname) Less(i, j int) bool { + return sortorder.NaturalLess(n[i].Description.Hostname, n[j].Description.Hostname) +} + type listOptions struct { quiet bool format string @@ -68,5 +80,6 @@ func runList(dockerCli command.Cli, options listOptions) error { Output: dockerCli.Out(), Format: formatter.NewNodeFormat(format, options.quiet), } + sort.Sort(byHostname(nodes)) return formatter.NodeWrite(nodesCtx, nodes, info) } diff --git a/components/cli/cli/command/node/list_test.go b/components/cli/cli/command/node/list_test.go index eb58d7709e..f579ebc88a 100644 --- a/components/cli/cli/command/node/list_test.go +++ b/components/cli/cli/command/node/list_test.go @@ -9,6 +9,8 @@ import ( "github.com/docker/cli/cli/internal/test" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/pkg/testutil" + "github.com/docker/docker/pkg/testutil/golden" "github.com/pkg/errors" // Import builders to get the builder function as package function . "github.com/docker/cli/cli/internal/test/builders" @@ -156,3 +158,22 @@ func TestNodeListFormat(t *testing.T) { assert.Contains(t, buf.String(), `nodeHostname1: Leader`) assert.Contains(t, buf.String(), `nodeHostname2: Reachable`) } + +func TestNodeListOrder(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{ + nodeListFunc: func() ([]swarm.Node, error) { + return []swarm.Node{ + *Node(Hostname("node-2-foo"), Manager(Leader())), + *Node(Hostname("node-10-foo"), Manager()), + *Node(Hostname("node-1-foo")), + }, nil + + }, + }) + cmd := newListCommand(cli) + cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}") + assert.NoError(t, cmd.Execute()) + actual := cli.OutBuffer().String() + expected := golden.Get(t, []byte(actual), "node-list-sort.golden") + testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected)) +} diff --git a/components/cli/cli/command/node/testdata/node-list-sort.golden b/components/cli/cli/command/node/testdata/node-list-sort.golden new file mode 100644 index 0000000000..e2f2811994 --- /dev/null +++ b/components/cli/cli/command/node/testdata/node-list-sort.golden @@ -0,0 +1,3 @@ +node-1-foo: +node-2-foo: Leader +node-10-foo: Reachable diff --git a/components/cli/cli/command/stack/list.go b/components/cli/cli/command/stack/list.go index f3781d260c..24da30512f 100644 --- a/components/cli/cli/command/stack/list.go +++ b/components/cli/cli/command/stack/list.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/net/context" + "vbom.ml/util/sortorder" ) type listOptions struct { @@ -60,7 +61,7 @@ type byName []*formatter.Stack func (n byName) Len() int { return len(n) } func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byName) Less(i, j int) bool { return n[i].Name < n[j].Name } +func (n byName) Less(i, j int) bool { return sortorder.NaturalLess(n[i].Name, n[j].Name) } func getStacks(ctx context.Context, apiclient client.APIClient) ([]*formatter.Stack, error) { services, err := apiclient.ServiceList( diff --git a/components/cli/cli/command/stack/list_test.go b/components/cli/cli/command/stack/list_test.go index de1aa02365..48b141653f 100644 --- a/components/cli/cli/command/stack/list_test.go +++ b/components/cli/cli/command/stack/list_test.go @@ -98,10 +98,13 @@ func TestListWithoutFormat(t *testing.T) { } func TestListOrder(t *testing.T) { - buf := new(bytes.Buffer) - cmd := newListCommand(test.NewFakeCliWithOutput(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ + usecases := []struct { + golden string + swarmServices []swarm.Service + }{ + { + golden: "stack-list-sort.golden", + swarmServices: []swarm.Service{ *Service( ServiceLabels(map[string]string{ "com.docker.stack.namespace": "service-name-foo", @@ -112,11 +115,40 @@ func TestListOrder(t *testing.T) { "com.docker.stack.namespace": "service-name-bar", }), ), - }, nil + }, }, - }, buf)) - assert.NoError(t, cmd.Execute()) - actual := buf.String() - expected := golden.Get(t, []byte(actual), "stack-list-sort.golden") - testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected)) + { + golden: "stack-list-sort-natural.golden", + swarmServices: []swarm.Service{ + *Service( + ServiceLabels(map[string]string{ + "com.docker.stack.namespace": "service-name-1-foo", + }), + ), + *Service( + ServiceLabels(map[string]string{ + "com.docker.stack.namespace": "service-name-10-foo", + }), + ), + *Service( + ServiceLabels(map[string]string{ + "com.docker.stack.namespace": "service-name-2-foo", + }), + ), + }, + }, + } + + for _, uc := range usecases { + buf := new(bytes.Buffer) + cmd := newListCommand(test.NewFakeCliWithOutput(&fakeClient{ + serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { + return uc.swarmServices, nil + }, + }, buf)) + assert.NoError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), uc.golden) + testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected)) + } } diff --git a/components/cli/cli/command/stack/testdata/stack-list-sort-natural.golden b/components/cli/cli/command/stack/testdata/stack-list-sort-natural.golden new file mode 100644 index 0000000000..09507fbf40 --- /dev/null +++ b/components/cli/cli/command/stack/testdata/stack-list-sort-natural.golden @@ -0,0 +1,4 @@ +NAME SERVICES +service-name-1-foo 1 +service-name-2-foo 1 +service-name-10-foo 1 diff --git a/components/cli/vendor.conf b/components/cli/vendor.conf index a212dd0a3a..a71e77c0c0 100755 --- a/components/cli/vendor.conf +++ b/components/cli/vendor.conf @@ -52,3 +52,4 @@ gopkg.in/yaml.v2 4c78c975fe7c825c6d1466c42be594d1d6f3aba6 github.com/tonistiigi/fsutil 0ac4c11b053b9c5c7c47558f81f96c7100ce50fb github.com/stevvooe/continuity cd7a8e21e2b6f84799f5dd4b65faf49c8d3ee02d golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 +vbom.ml/util 928aaa586d7718c70f4090ddf83f2b34c16fdc8d diff --git a/components/cli/vendor/vbom.ml/util/LICENSE b/components/cli/vendor/vbom.ml/util/LICENSE new file mode 100644 index 0000000000..5c695fb590 --- /dev/null +++ b/components/cli/vendor/vbom.ml/util/LICENSE @@ -0,0 +1,17 @@ +The MIT License (MIT) +Copyright (c) 2015 Frits van Bommel +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/components/cli/vendor/vbom.ml/util/README.md b/components/cli/vendor/vbom.ml/util/README.md new file mode 100644 index 0000000000..72de507980 --- /dev/null +++ b/components/cli/vendor/vbom.ml/util/README.md @@ -0,0 +1,5 @@ +## util [![GoDoc](https://godoc.org/vbom.ml/util?status.svg)](https://godoc.org/vbom.ml/util) + + import "vbom.ml/util" + +Go utility packages. diff --git a/components/cli/vendor/vbom.ml/util/sortorder/README.md b/components/cli/vendor/vbom.ml/util/sortorder/README.md new file mode 100644 index 0000000000..ed8da0e29b --- /dev/null +++ b/components/cli/vendor/vbom.ml/util/sortorder/README.md @@ -0,0 +1,5 @@ +## sortorder [![GoDoc](https://godoc.org/vbom.ml/util/sortorder?status.svg)](https://godoc.org/vbom.ml/util/sortorder) + + import "vbom.ml/util/sortorder" + +Sort orders and comparison functions. diff --git a/components/cli/vendor/vbom.ml/util/sortorder/doc.go b/components/cli/vendor/vbom.ml/util/sortorder/doc.go new file mode 100644 index 0000000000..61b37a9374 --- /dev/null +++ b/components/cli/vendor/vbom.ml/util/sortorder/doc.go @@ -0,0 +1,5 @@ +// Package sortorder implements sort orders and comparison functions. +// +// Currently, it only implements so-called "natural order", where integers +// embedded in strings are compared by value. +package sortorder // import "vbom.ml/util/sortorder" diff --git a/components/cli/vendor/vbom.ml/util/sortorder/natsort.go b/components/cli/vendor/vbom.ml/util/sortorder/natsort.go new file mode 100644 index 0000000000..1af08c1bd1 --- /dev/null +++ b/components/cli/vendor/vbom.ml/util/sortorder/natsort.go @@ -0,0 +1,76 @@ +package sortorder + +// Natural implements sort.Interface to sort strings in natural order. This +// means that e.g. "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +type Natural []string + +func (n Natural) Len() int { return len(n) } +func (n Natural) Swap(i, j int) { n[i], n[j] = n[j], n[i] } +func (n Natural) Less(i, j int) bool { return NaturalLess(n[i], n[j]) } + +func isdigit(b byte) bool { return '0' <= b && b <= '9' } + +// NaturalLess compares two strings using natural ordering. This means that e.g. +// "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +func NaturalLess(str1, str2 string) bool { + idx1, idx2 := 0, 0 + for idx1 < len(str1) && idx2 < len(str2) { + c1, c2 := str1[idx1], str2[idx2] + dig1, dig2 := isdigit(c1), isdigit(c2) + switch { + case dig1 != dig2: // Digits before other characters. + return dig1 // True if LHS is a digit, false if the RHS is one. + case !dig1: // && !dig2, because dig1 == dig2 + // UTF-8 compares bytewise-lexicographically, no need to decode + // codepoints. + if c1 != c2 { + return c1 < c2 + } + idx1++ + idx2++ + default: // Digits + // Eat zeros. + for ; idx1 < len(str1) && str1[idx1] == '0'; idx1++ { + } + for ; idx2 < len(str2) && str2[idx2] == '0'; idx2++ { + } + // Eat all digits. + nonZero1, nonZero2 := idx1, idx2 + for ; idx1 < len(str1) && isdigit(str1[idx1]); idx1++ { + } + for ; idx2 < len(str2) && isdigit(str2[idx2]); idx2++ { + } + // If lengths of numbers with non-zero prefix differ, the shorter + // one is less. + if len1, len2 := idx1-nonZero1, idx2-nonZero2; len1 != len2 { + return len1 < len2 + } + // If they're not equal, string comparison is correct. + if nr1, nr2 := str1[nonZero1:idx1], str2[nonZero2:idx2]; nr1 != nr2 { + return nr1 < nr2 + } + // Otherwise, the one with less zeros is less. + // Because everything up to the number is equal, comparing the index + // after the zeros is sufficient. + if nonZero1 != nonZero2 { + return nonZero1 < nonZero2 + } + } + // They're identical so far, so continue comparing. + } + // So far they are identical. At least one is ended. If the other continues, + // it sorts last. + return len(str1) < len(str2) +} From a61c7f009eca8003ca22b687426b55f98a080e31 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Huynh Date: Thu, 29 Jun 2017 14:10:04 +0100 Subject: [PATCH 02/18] Add shellcheck for bash completion Signed-off-by: Jean-Pierre Huynh Upstream-commit: b2fc35aefaf1412c9ef4963bed8de248038243df Component: cli --- components/cli/Makefile | 5 + components/cli/circle.yml | 16 +- components/cli/contrib/completion/bash/docker | 157 ++++++++++-------- components/cli/docker.Makefile | 8 + .../cli/dockerfiles/Dockerfile.validate | 9 + components/cli/scripts/validate/shellcheck | 11 ++ 6 files changed, 133 insertions(+), 73 deletions(-) create mode 100644 components/cli/dockerfiles/Dockerfile.validate create mode 100755 components/cli/scripts/validate/shellcheck diff --git a/components/cli/Makefile b/components/cli/Makefile index dbb3d3bfef..926b39b25b 100644 --- a/components/cli/Makefile +++ b/components/cli/Makefile @@ -54,6 +54,11 @@ manpages: yamldocs: scripts/docs/generate-yaml.sh +## Shellcheck validation +.PHONY: shellcheck +shellcheck: + scripts/validate/shellcheck + cli/compose/schema/bindata.go: cli/compose/schema/data/*.json go generate github.com/docker/cli/cli/compose/schema diff --git a/components/cli/circle.yml b/components/cli/circle.yml index 4552ee6dd9..de056d40e4 100644 --- a/components/cli/circle.yml +++ b/components/cli/circle.yml @@ -91,7 +91,20 @@ jobs: docker build -f $dockerfile --tag cli-builder-with-git:$CIRCLE_BUILD_NUM . docker run --rm cli-builder-with-git:$CIRCLE_BUILD_NUM \ make -B vendor compose-jsonschema manpages yamldocs - + shellcheck: + working_directory: /work + docker: [{image: 'docker:17.05-git'}] + steps: + - checkout + - setup_remote_docker + - run: + name: "Run shellcheck" + command: | + dockerfile=dockerfiles/Dockerfile.validate + echo "COPY . ." >> $dockerfile + docker build -f $dockerfile --tag cli-validator:$CIRCLE_BUILD_NUM . + docker run --rm cli-validator:$CIRCLE_BUILD_NUM \ + make -B shellcheck workflows: version: 2 ci: @@ -100,3 +113,4 @@ workflows: - cross - test - validate + - shellcheck diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker index 95cc588ca0..40c2abc218 100644 --- a/components/cli/contrib/completion/bash/docker +++ b/components/cli/contrib/completion/bash/docker @@ -1,4 +1,8 @@ #!/usr/bin/env bash +# shellcheck disable=SC2155 +# +# Shellcheck ignore list: +# - SC2155: Declare and assign separately to avoid masking return values. # # bash completion file for core docker commands # @@ -142,6 +146,7 @@ __docker_images() { esac local repo_print_command + # shellcheck disable=SC2016 if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then repo_print_command='print $1; print $1":"$2' else @@ -149,6 +154,7 @@ __docker_images() { fi local awk_script + # shellcheck disable=SC2016 case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in all|non-intermediate) awk_script='NR>1 { print $3; if ($1 != "") { '"$repo_print_command"' } }' @@ -213,6 +219,7 @@ __docker_complete_networks() { COMPREPLY=( $(compgen -W "$(__docker_networks "$@")" -- "$current") ) } +# shellcheck disable=SC2016,SC2128,SC2178 __docker_complete_containers_in_network() { local containers=$(__docker_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1") COMPREPLY=( $(compgen -W "$containers" -- "$cur") ) @@ -271,6 +278,7 @@ __docker_plugins_bundled() { for del in "${remove[@]}" ; do plugins=(${plugins[@]/$del/}) done + # shellcheck disable=SC2145 echo "${plugins[@]} ${add[@]}" } @@ -389,6 +397,7 @@ __docker_complete_stacks() { # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. # Completions may be added with `--add`, e.g. `--add self`. +# shellcheck disable=SC2016 __docker_nodes() { local add=() local fields='$2' # default: node name only @@ -414,7 +423,7 @@ __docker_nodes() { esac done - echo $(__docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}") "${add[@]}" + echo "$(__docker_q node ls "$@" | tr -d '*' | awk "NR>1 {print $fields}")" "${add[@]}" } # __docker_complete_nodes applies completion of nodes based on the current @@ -437,6 +446,7 @@ __docker_complete_nodes() { # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. +# shellcheck disable=SC2016 __docker_services() { local fields='$2' # default: service name only [ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name @@ -509,7 +519,7 @@ __docker_pos_first_nonflag() { local argument_flags=$1 local counter=$((${subcommand_pos:-${command_pos}} + 1)) - while [ $counter -le $cword ]; do + while [ "$counter" -le "$cword" ]; do if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then (( counter++ )) # eat "=" in case of --option=arg syntax @@ -569,10 +579,10 @@ __docker_value_of_option() { local option_extglob=$(__docker_to_extglob "$1") local counter=$((command_pos + 1)) - while [ $counter -lt $cword ]; do + while [ "$counter" -lt "$cword" ]; do case ${words[$counter]} in $option_extglob ) - echo ${words[$counter + 1]} + echo "${words[$counter + 1]}" break ;; esac @@ -609,14 +619,14 @@ __docker_to_extglob() { __docker_subcommands() { local subcommands="$1" - local counter=$(($command_pos + 1)) - while [ $counter -lt $cword ]; do + local counter=$((command_pos + 1)) + while [ "$counter" -lt "$cword" ]; do case "${words[$counter]}" in $(__docker_to_extglob "$subcommands") ) subcommand_pos=$counter local subcommand=${words[$counter]} local completions_func=_docker_${command}_${subcommand//-/_} - declare -F $completions_func >/dev/null && $completions_func + declare -F "$completions_func" >/dev/null && "$completions_func" return 0 ;; esac @@ -951,7 +961,7 @@ __docker_complete_signals() { SIGUSR1 SIGUSR2 ) - COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) ) + COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo "$cur" | tr '[:lower:]' '[:upper:]')" ) ) } __docker_complete_user_group() { @@ -991,7 +1001,7 @@ _docker_docker() { ;; *) local counter=$( __docker_pos_first_nonflag "$(__docker_to_extglob "$global_options_with_args")" ) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_daemon_is_experimental && commands+=(${experimental_commands[*]}) COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) ) fi @@ -1044,7 +1054,7 @@ _docker_checkpoint_create() { ;; *) local counter=$(__docker_pos_first_nonflag '--checkpoint-dir') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_running fi ;; @@ -1065,7 +1075,7 @@ _docker_checkpoint_ls() { ;; *) local counter=$(__docker_pos_first_nonflag '--checkpoint-dir') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1086,9 +1096,9 @@ _docker_checkpoint_rm() { ;; *) local counter=$(__docker_pos_first_nonflag '--checkpoint-dir') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all - elif [ $cword -eq $(($counter + 1)) ]; then + elif [ "$cword" -eq "$((counter + 1))" ]; then COMPREPLY=( $( compgen -W "$(__docker_q checkpoint ls "$prev" | sed 1d)" -- "$cur" ) ) fi ;; @@ -1149,7 +1159,7 @@ _docker_container_attach() { ;; *) local counter=$(__docker_pos_first_nonflag '--detach-keys') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_running fi ;; @@ -1170,13 +1180,13 @@ _docker_container_commit() { *) local counter=$(__docker_pos_first_nonflag '--author|-a|--change|-c|--message|-m') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all return fi (( counter++ )) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_image_repos_and_tags return fi @@ -1191,7 +1201,7 @@ _docker_container_cp() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then case "$cur" in *:) return @@ -1206,6 +1216,7 @@ _docker_container_cp() { local containers=( ${COMPREPLY[@]} ) COMPREPLY=( $( compgen -W "${files[*]} ${containers[*]}" -- "$cur" ) ) + # shellcheck disable=SC2128 if [[ "$COMPREPLY" == *: ]]; then __docker_nospace fi @@ -1215,7 +1226,7 @@ _docker_container_cp() { fi (( counter++ )) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then if [ -e "$prev" ]; then __docker_complete_containers_all COMPREPLY=( $( compgen -W "${COMPREPLY[*]}" -S ':' ) ) @@ -1240,7 +1251,7 @@ _docker_container_diff() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1252,7 +1263,7 @@ _docker_container_exec() { case "$prev" in --env|-e) - # we do not append a "=" here because "-e VARNAME" is legal systax, too + # we do not append a "=" here because "-e VARNAME" is legal syntax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return @@ -1287,7 +1298,7 @@ _docker_container_export() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1329,7 +1340,7 @@ _docker_container_logs() { ;; *) local counter=$(__docker_pos_first_nonflag '--since|--tail') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1425,7 +1436,7 @@ _docker_container_port() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1459,7 +1470,7 @@ _docker_container_rename() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_all fi ;; @@ -1497,7 +1508,7 @@ _docker_container_rm() { ;; esac done - __docker_complete_containers_removable + __docker_complete_containers_removable "$@" ;; esac } @@ -1608,7 +1619,7 @@ _docker_container_run_and_create() { --tty -t " - if [ "$command" = "run" -o "$subcommand" = "run" ] ; then + if [ "$command" = "run" ] || [ "$subcommand" = "run" ] ; then options_with_args="$options_with_args --detach-keys " @@ -1686,7 +1697,7 @@ _docker_container_run_and_create() { return ;; --env|-e) - # we do not append a "=" here because "-e VARNAME" is legal systax, too + # we do not append a "=" here because "-e VARNAME" is legal syntax, too COMPREPLY=( $( compgen -e -- "$cur" ) ) __docker_nospace return @@ -1699,6 +1710,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) + # shellcheck disable=SC2128 if [ "$COMPREPLY" = "container:" ]; then __docker_nospace fi @@ -1753,6 +1765,7 @@ _docker_container_run_and_create() { ;; *) COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) ) + # shellcheck disable=SC2128 if [ "$COMPREPLY" = "container:" ]; then __docker_nospace fi @@ -1806,8 +1819,8 @@ _docker_container_run_and_create() { COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) - local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) - if [ $cword -eq $counter ]; then + local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) + if [ "$cword" -eq "$counter" ]; then __docker_complete_images fi ;; @@ -1816,7 +1829,7 @@ _docker_container_run_and_create() { _docker_container_start() { __docker_complete_detach_keys && return - + # shellcheck disable=SC2078 case "$prev" in --checkpoint) if [ __docker_daemon_is_experimental ] ; then @@ -1838,7 +1851,7 @@ _docker_container_start() { COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - __docker_complete_containers_stopped + __docker_complete_containers_stopped "$@" ;; esac } @@ -1884,7 +1897,7 @@ _docker_container_top() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_containers_running fi ;; @@ -1898,8 +1911,8 @@ _docker_container_unpause() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then - __docker_complete_containers_unpauseable + if [ "$cword" -eq "$counter" ]; then + __docker_complete_containers_unpauseable "$@" fi ;; esac @@ -2098,7 +2111,7 @@ _docker_daemon() { return ;; --storage-driver|-s) - COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo $cur | tr '[:upper:]' '[:lower:]')" ) ) + COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo "$cur" | tr '[:upper:]' '[:lower:]')" ) ) return ;; --storage-opt) @@ -2211,7 +2224,7 @@ _docker_export() { _docker_help() { local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then COMPREPLY=( $( compgen -W "${commands[*]}" -- "$cur" ) ) fi } @@ -2348,8 +2361,8 @@ _docker_image_build() { COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) ) ;; *) - local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) - if [ $cword -eq $counter ]; then + local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) + if [ "$cword" -eq "$counter" ]; then _filedir -d fi ;; @@ -2369,7 +2382,7 @@ _docker_image_history() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_images fi ;; @@ -2393,12 +2406,12 @@ _docker_image_import() { ;; *) local counter=$(__docker_pos_first_nonflag '--change|-c|--message|-m') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then return fi (( counter++ )) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_image_repos_and_tags return fi @@ -2493,7 +2506,7 @@ _docker_image_pull() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then for arg in "${COMP_WORDS[@]}"; do case "$arg" in --all-tags|-a) @@ -2515,7 +2528,7 @@ _docker_image_push() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_image_repos_and_tags fi ;; @@ -2567,13 +2580,13 @@ _docker_image_tag() { *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_image_repos_and_tags return fi (( counter++ )) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_image_repos_and_tags return fi @@ -2737,10 +2750,10 @@ _docker_network_connect() { COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) ;; *) - local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) - if [ $cword -eq $counter ]; then + local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) + if [ "$cword" -eq "$counter" ]; then __docker_complete_networks - elif [ $cword -eq $(($counter + 1)) ]; then + elif [ "$cword" -eq $((counter + 1)) ]; then __docker_complete_containers_all fi ;; @@ -2788,9 +2801,9 @@ _docker_network_disconnect() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_networks - elif [ $cword -eq $(($counter + 1)) ]; then + elif [ "$cword" -eq $((counter + 1)) ]; then __docker_complete_containers_in_network "$prev" fi ;; @@ -2969,8 +2982,8 @@ _docker_service_logs() { ;; *) local counter=$(__docker_pos_first_nonflag '--since|--tail') - if [ $cword -eq $counter ]; then - __docker_complete_services_and_tasks + if [ "$cword" -eq "$counter" ]; then + __docker_complete_services_and_tasks "$@" fi ;; esac @@ -3076,7 +3089,7 @@ _docker_service_ps() { ;; *) local counter=$(__docker_pos_first_nonflag '--filter|-f') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_services fi ;; @@ -3321,13 +3334,13 @@ _docker_service_update_and_create() { COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) ) ;; *) - local counter=$( __docker_pos_first_nonflag $( __docker_to_alternatives "$options_with_args" ) ) + local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) if [ "$subcommand" = "update" ] ; then - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_services fi else - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_images fi fi @@ -3466,7 +3479,7 @@ _docker_swarm_join_token() { ;; *) local counter=$( __docker_pos_first_nonflag ) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then COMPREPLY=( $( compgen -W "manager worker" -- "$cur" ) ) fi ;; @@ -3685,7 +3698,7 @@ _docker_node_update() { ;; *) local counter=$(__docker_pos_first_nonflag '--availability|--label-add|--label-rm|--role') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_nodes fi ;; @@ -3732,10 +3745,10 @@ _docker_plugin_create() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then # reponame return - elif [ $cword -eq $((counter + 1)) ]; then + elif [ "$cword" -eq $((counter + 1)) ]; then _filedir -d fi ;; @@ -3749,7 +3762,7 @@ _docker_plugin_disable() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed --filter enabled=true fi ;; @@ -3769,7 +3782,7 @@ _docker_plugin_enable() { ;; *) local counter=$(__docker_pos_first_nonflag '--timeout') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed --filter enabled=false fi ;; @@ -3849,7 +3862,7 @@ _docker_plugin_push() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed fi ;; @@ -3878,7 +3891,7 @@ _docker_plugin_set() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed fi ;; @@ -3892,10 +3905,10 @@ _docker_plugin_upgrade() { ;; *) local counter=$(__docker_pos_first_nonflag) - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed __ltrim_colon_completions "$cur" - elif [ $cword -eq $((counter + 1)) ]; then + elif [ "$cword" -eq $((counter + 1)) ]; then local plugin_images="$(__docker_plugins_installed)" COMPREPLY=( $(compgen -S : -W "${plugin_images%:*}" -- "$cur") ) __docker_nospace @@ -3930,7 +3943,7 @@ _docker_restart() { } _docker_rm() { - _docker_container_rm + _docker_container_rm "$@" } _docker_rmi() { @@ -4189,7 +4202,7 @@ _docker_stack_ps() { ;; *) local counter=$(__docker_pos_first_nonflag '--filter|-f') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi ;; @@ -4243,7 +4256,7 @@ _docker_stack_services() { ;; *) local counter=$(__docker_pos_first_nonflag '--filter|-f|--format') - if [ $cword -eq $counter ]; then + if [ "$cword" -eq "$counter" ]; then __docker_complete_stacks fi ;; @@ -4256,7 +4269,7 @@ _docker_stack_up() { _docker_start() { - _docker_container_start + _docker_container_start "$@" } _docker_stats() { @@ -4431,7 +4444,7 @@ _docker_tag() { } _docker_unpause() { - _docker_container_unpause + _docker_container_unpause "$@" } _docker_update() { @@ -4685,7 +4698,7 @@ _docker() { local command='docker' command_pos=0 subcommand_pos local counter=1 - while [ $counter -lt $cword ]; do + while [ "$counter" -lt "$cword" ]; do case "${words[$counter]}" in # save host so that completion can use custom daemon --host|-H) diff --git a/components/cli/docker.Makefile b/components/cli/docker.Makefile index ef8dbfb926..e7d8042823 100644 --- a/components/cli/docker.Makefile +++ b/components/cli/docker.Makefile @@ -7,6 +7,7 @@ DEV_DOCKER_IMAGE_NAME = docker-cli-dev LINTER_IMAGE_NAME = docker-cli-lint CROSS_IMAGE_NAME = docker-cli-cross +VALIDATE_IMAGE_NAME = docker-cli-validate MOUNTS = -v "$(CURDIR)":/go/src/github.com/docker/cli VERSION = $(shell cat VERSION) ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT @@ -25,6 +26,9 @@ build_linter_image: build_cross_image: docker build -t $(CROSS_IMAGE_NAME) -f ./dockerfiles/Dockerfile.cross . +.PHONY: build_validate_image +build_validate_image: + docker build -t $(VALIDATE_IMAGE_NAME) -f ./dockerfiles/Dockerfile.validate . # build executable using a container binary: build_docker_image @@ -80,3 +84,7 @@ manpages: build_docker_image .PHONY: yamldocs yamldocs: build_docker_image docker run -ti --rm $(MOUNTS) $(DEV_DOCKER_IMAGE_NAME) make yamldocs + +.PHONY: shellcheck +shellcheck: build_validate_image + docker run -ti --rm -v "$(CURDIR)":/tmp $(VALIDATE_IMAGE_NAME) make shellcheck diff --git a/components/cli/dockerfiles/Dockerfile.validate b/components/cli/dockerfiles/Dockerfile.validate new file mode 100644 index 0000000000..52005939ea --- /dev/null +++ b/components/cli/dockerfiles/Dockerfile.validate @@ -0,0 +1,9 @@ +FROM debian:stretch-slim + +RUN apt-get update && \ + apt-get -y install make shellcheck && \ + apt-get clean + +WORKDIR /tmp + +CMD bash diff --git a/components/cli/scripts/validate/shellcheck b/components/cli/scripts/validate/shellcheck new file mode 100755 index 0000000000..f14d1ab04d --- /dev/null +++ b/components/cli/scripts/validate/shellcheck @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e + +# Maintain an array of files to shellcheck not the best solution but will do for the time being +FILES=() +FILES+=("contrib/completion/bash/docker") +FILES+=("scripts/validate/shellcheck") + +for f in "${FILES[@]}"; do + shellcheck "$f" +done From dc6c9cd967368645a8edc793dac809f8b4e4fe31 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Huynh Date: Thu, 29 Jun 2017 22:32:01 +0100 Subject: [PATCH 03/18] Reword to remove ambiguity with go validate Signed-off-by: Jean-Pierre Huynh Upstream-commit: 2e7d24cae815cdb01931701b28bc27c9865e536f Component: cli --- components/cli/docker.Makefile | 10 +++++----- .../{Dockerfile.validate => Dockerfile.shellcheck} | 0 2 files changed, 5 insertions(+), 5 deletions(-) rename components/cli/dockerfiles/{Dockerfile.validate => Dockerfile.shellcheck} (100%) diff --git a/components/cli/docker.Makefile b/components/cli/docker.Makefile index e7d8042823..88167f1c44 100644 --- a/components/cli/docker.Makefile +++ b/components/cli/docker.Makefile @@ -7,7 +7,7 @@ DEV_DOCKER_IMAGE_NAME = docker-cli-dev LINTER_IMAGE_NAME = docker-cli-lint CROSS_IMAGE_NAME = docker-cli-cross -VALIDATE_IMAGE_NAME = docker-cli-validate +VALIDATE_IMAGE_NAME = docker-cli-shell-validate MOUNTS = -v "$(CURDIR)":/go/src/github.com/docker/cli VERSION = $(shell cat VERSION) ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT @@ -26,9 +26,9 @@ build_linter_image: build_cross_image: docker build -t $(CROSS_IMAGE_NAME) -f ./dockerfiles/Dockerfile.cross . -.PHONY: build_validate_image -build_validate_image: - docker build -t $(VALIDATE_IMAGE_NAME) -f ./dockerfiles/Dockerfile.validate . +.PHONY: build_shell_validate_image +build_shell_validate_image: + docker build -t $(VALIDATE_IMAGE_NAME) -f ./dockerfiles/Dockerfile.shellcheck . # build executable using a container binary: build_docker_image @@ -86,5 +86,5 @@ yamldocs: build_docker_image docker run -ti --rm $(MOUNTS) $(DEV_DOCKER_IMAGE_NAME) make yamldocs .PHONY: shellcheck -shellcheck: build_validate_image +shellcheck: build_shell_validate_image docker run -ti --rm -v "$(CURDIR)":/tmp $(VALIDATE_IMAGE_NAME) make shellcheck diff --git a/components/cli/dockerfiles/Dockerfile.validate b/components/cli/dockerfiles/Dockerfile.shellcheck similarity index 100% rename from components/cli/dockerfiles/Dockerfile.validate rename to components/cli/dockerfiles/Dockerfile.shellcheck From cbcb37cde860373a0c293482fb02b05f8198202f Mon Sep 17 00:00:00 2001 From: Jean-Pierre Huynh Date: Thu, 29 Jun 2017 22:35:15 +0100 Subject: [PATCH 04/18] Update dockerfile path for CicleCI build Signed-off-by: Jean-Pierre Huynh Upstream-commit: 501cf0e6d14bce2588246a8b5bfd82ac2ca9438c Component: cli --- components/cli/circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/cli/circle.yml b/components/cli/circle.yml index de056d40e4..74b6128fbb 100644 --- a/components/cli/circle.yml +++ b/components/cli/circle.yml @@ -100,7 +100,7 @@ jobs: - run: name: "Run shellcheck" command: | - dockerfile=dockerfiles/Dockerfile.validate + dockerfile=dockerfiles/Dockerfile.shellcheck echo "COPY . ." >> $dockerfile docker build -f $dockerfile --tag cli-validator:$CIRCLE_BUILD_NUM . docker run --rm cli-validator:$CIRCLE_BUILD_NUM \ From 33db8883eaeb383e4251ad18699dcb81a7f48785 Mon Sep 17 00:00:00 2001 From: Jean-Pierre Huynh Date: Thu, 29 Jun 2017 22:57:26 +0100 Subject: [PATCH 05/18] Fix code location when mounting to docker-cli-shell-validate Signed-off-by: Jean-Pierre Huynh Upstream-commit: ffe8509663b3b6d9f6d15acadbcbae9e6573dc7f Component: cli --- components/cli/docker.Makefile | 2 +- components/cli/dockerfiles/Dockerfile.shellcheck | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/cli/docker.Makefile b/components/cli/docker.Makefile index 88167f1c44..fc86fdc769 100644 --- a/components/cli/docker.Makefile +++ b/components/cli/docker.Makefile @@ -87,4 +87,4 @@ yamldocs: build_docker_image .PHONY: shellcheck shellcheck: build_shell_validate_image - docker run -ti --rm -v "$(CURDIR)":/tmp $(VALIDATE_IMAGE_NAME) make shellcheck + docker run -ti --rm $(MOUNTS) $(VALIDATE_IMAGE_NAME) make shellcheck diff --git a/components/cli/dockerfiles/Dockerfile.shellcheck b/components/cli/dockerfiles/Dockerfile.shellcheck index 52005939ea..12f665f7a7 100644 --- a/components/cli/dockerfiles/Dockerfile.shellcheck +++ b/components/cli/dockerfiles/Dockerfile.shellcheck @@ -4,6 +4,6 @@ RUN apt-get update && \ apt-get -y install make shellcheck && \ apt-get clean -WORKDIR /tmp +WORKDIR /go/src/github.com/docker/cli CMD bash From d96f150bfbc4135a629ca5e698bc63b9c624878a Mon Sep 17 00:00:00 2001 From: yuexiao-wang Date: Thu, 13 Jul 2017 16:30:44 +0800 Subject: [PATCH 06/18] Fix filters displaying for docker search Signed-off-by: yuexiao-wang Upstream-commit: bd64ad25fb73aeff9a51ad7168904253569447c0 Component: cli --- components/cli/docs/reference/commandline/search.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/cli/docs/reference/commandline/search.md b/components/cli/docs/reference/commandline/search.md index f645c78603..83a44251dd 100644 --- a/components/cli/docs/reference/commandline/search.md +++ b/components/cli/docs/reference/commandline/search.md @@ -94,7 +94,6 @@ radial/busyboxplus Full-chain, Internet enabled, busybox made from scratch. Co The flag `--limit` is the maximum number of results returned by a search. This value could be in the range between 1 and 100. The default value of `--limit` is 25. - ### Filtering The filtering flag (`-f` or `--filter`) format is a `key=value` pair. If there is more @@ -103,9 +102,8 @@ than one filter, then pass multiple flags (e.g. `--filter "foo=bar" --filter "bi The currently supported filters are: * stars (int - number of stars the image has) -* is-automated (true|false) - is the image automated or not -* is-official (true|false) - is the image official or not - +* is-automated (boolean - true or false) - is the image automated or not +* is-official (boolean - true or false) - is the image official or not #### stars @@ -121,7 +119,6 @@ progrium/busybox 50 radial/busyboxplus Full-chain, Internet enabled, busybox made... 8 [OK] ``` - #### is-automated This example displays images with a name containing 'busybox' From 5aee375eb4fad55dcb57e9dccb60bcee2364c63a Mon Sep 17 00:00:00 2001 From: Jean-Pierre Huynh Date: Thu, 13 Jul 2017 22:16:35 +0100 Subject: [PATCH 07/18] Fix inconsistencies Signed-off-by: Jean-Pierre Huynh Upstream-commit: d7748e1b01f4841947decdbe4bd315f6acf8210a Component: cli --- components/cli/contrib/completion/bash/docker | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker index 40c2abc218..0bcecf3151 100644 --- a/components/cli/contrib/completion/bash/docker +++ b/components/cli/contrib/completion/bash/docker @@ -1,8 +1,13 @@ #!/usr/bin/env bash -# shellcheck disable=SC2155 +# shellcheck disable=SC2016,SC2119,SC2155 # # Shellcheck ignore list: +# - SC2016: Expressions don't expand in single quotes, use double quotes for that. +# - SC2119: Use foo "$@" if function's $1 should mean script's $1. # - SC2155: Declare and assign separately to avoid masking return values. +# +# You can find more details for each warning at the following page: +# https://github.com/koalaman/shellcheck/wiki/ # # bash completion file for core docker commands # @@ -105,6 +110,7 @@ __docker_complete_containers_all() { __docker_complete_containers "$@" --all } +# shellcheck disable=SC2120 __docker_complete_containers_removable() { __docker_complete_containers "$@" --filter status=created --filter status=exited } @@ -113,10 +119,12 @@ __docker_complete_containers_running() { __docker_complete_containers "$@" --filter status=running } +# shellcheck disable=SC2120 __docker_complete_containers_stopped() { __docker_complete_containers "$@" --filter status=exited } +# shellcheck disable=SC2120 __docker_complete_containers_unpauseable() { __docker_complete_containers "$@" --filter status=paused } @@ -146,7 +154,6 @@ __docker_images() { esac local repo_print_command - # shellcheck disable=SC2016 if [ "${DOCKER_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then repo_print_command='print $1; print $1":"$2' else @@ -154,7 +161,6 @@ __docker_images() { fi local awk_script - # shellcheck disable=SC2016 case "$DOCKER_COMPLETION_SHOW_IMAGE_IDS" in all|non-intermediate) awk_script='NR>1 { print $3; if ($1 != "") { '"$repo_print_command"' } }' @@ -219,7 +225,7 @@ __docker_complete_networks() { COMPREPLY=( $(compgen -W "$(__docker_networks "$@")" -- "$current") ) } -# shellcheck disable=SC2016,SC2128,SC2178 +# shellcheck disable=SC2128,SC2178 __docker_complete_containers_in_network() { local containers=$(__docker_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1") COMPREPLY=( $(compgen -W "$containers" -- "$cur") ) @@ -397,7 +403,6 @@ __docker_complete_stacks() { # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. # Completions may be added with `--add`, e.g. `--add self`. -# shellcheck disable=SC2016 __docker_nodes() { local add=() local fields='$2' # default: node name only @@ -446,7 +451,6 @@ __docker_complete_nodes() { # An optional first option `--id|--name` may be used to limit the # output to the IDs or names of matching items. This setting takes # precedence over the environment setting. -# shellcheck disable=SC2016 __docker_services() { local fields='$2' # default: service name only [ "${DOCKER_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name @@ -479,6 +483,7 @@ __docker_tasks() { } # __docker_complete_services_and_tasks applies completion of services and task IDs. +# shellcheck disable=SC2120 __docker_complete_services_and_tasks() { COMPREPLY=( $(compgen -W "$(__docker_services "$@") $(__docker_tasks)" -- "$cur") ) } @@ -1508,7 +1513,7 @@ _docker_container_rm() { ;; esac done - __docker_complete_containers_removable "$@" + __docker_complete_containers_removable ;; esac } @@ -1851,7 +1856,7 @@ _docker_container_start() { COMPREPLY=( $( compgen -W "$options" -- "$cur" ) ) ;; *) - __docker_complete_containers_stopped "$@" + __docker_complete_containers_stopped ;; esac } @@ -1912,7 +1917,7 @@ _docker_container_unpause() { *) local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then - __docker_complete_containers_unpauseable "$@" + __docker_complete_containers_unpauseable fi ;; esac @@ -2111,7 +2116,7 @@ _docker_daemon() { return ;; --storage-driver|-s) - COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo "$cur" | tr '[:upper:]' '[:lower:]')" ) ) + COMPREPLY=( $( compgen -W "aufs btrfs devicemapper overlay overlay2 vfs zfs" -- "$(echo "$cur" | tr '[:upper:]' '[:lower:]')" ) ) return ;; --storage-opt) @@ -2753,7 +2758,7 @@ _docker_network_connect() { local counter=$( __docker_pos_first_nonflag "$( __docker_to_alternatives "$options_with_args" )" ) if [ "$cword" -eq "$counter" ]; then __docker_complete_networks - elif [ "$cword" -eq $((counter + 1)) ]; then + elif [ "$cword" -eq "$((counter + 1))" ]; then __docker_complete_containers_all fi ;; @@ -2803,7 +2808,7 @@ _docker_network_disconnect() { local counter=$(__docker_pos_first_nonflag) if [ "$cword" -eq "$counter" ]; then __docker_complete_networks - elif [ "$cword" -eq $((counter + 1)) ]; then + elif [ "$cword" -eq "$((counter + 1))" ]; then __docker_complete_containers_in_network "$prev" fi ;; @@ -2983,7 +2988,7 @@ _docker_service_logs() { *) local counter=$(__docker_pos_first_nonflag '--since|--tail') if [ "$cword" -eq "$counter" ]; then - __docker_complete_services_and_tasks "$@" + __docker_complete_services_and_tasks fi ;; esac @@ -3748,7 +3753,7 @@ _docker_plugin_create() { if [ "$cword" -eq "$counter" ]; then # reponame return - elif [ "$cword" -eq $((counter + 1)) ]; then + elif [ "$cword" -eq "$((counter + 1))" ]; then _filedir -d fi ;; @@ -3908,7 +3913,7 @@ _docker_plugin_upgrade() { if [ "$cword" -eq "$counter" ]; then __docker_complete_plugins_installed __ltrim_colon_completions "$cur" - elif [ "$cword" -eq $((counter + 1)) ]; then + elif [ "$cword" -eq "$((counter + 1))" ]; then local plugin_images="$(__docker_plugins_installed)" COMPREPLY=( $(compgen -S : -W "${plugin_images%:*}" -- "$cur") ) __docker_nospace @@ -3943,7 +3948,7 @@ _docker_restart() { } _docker_rm() { - _docker_container_rm "$@" + _docker_container_rm } _docker_rmi() { @@ -4269,7 +4274,7 @@ _docker_stack_up() { _docker_start() { - _docker_container_start "$@" + _docker_container_start } _docker_stats() { @@ -4444,7 +4449,7 @@ _docker_tag() { } _docker_unpause() { - _docker_container_unpause "$@" + _docker_container_unpause } _docker_update() { From 0b42de4e27fcd64fa9a33f5f99901338e177d12b Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Thu, 13 Jul 2017 12:30:38 -0400 Subject: [PATCH 08/18] Clarify docs about ARG in FROM Signed-off-by: Daniel Nephin Upstream-commit: 2880030814986e71010b573899b1f986e5be8405 Component: cli --- components/cli/docs/reference/builder.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/cli/docs/reference/builder.md b/components/cli/docs/reference/builder.md index 65f6e05f04..b0e40010f7 100644 --- a/components/cli/docs/reference/builder.md +++ b/components/cli/docs/reference/builder.md @@ -530,8 +530,10 @@ FROM extras:${CODE_VERSION} CMD /code/run-extras ``` -To use the default value of an `ARG` declared before the first `FROM` use an -`ARG` instruction without a value: +An `ARG` declared before a `FROM` is outside of a build stage, so it +can't be used in any instruction after a `FROM`. To use the default value of +an `ARG` declared before the first `FROM` use an `ARG` instruction without +a value inside of a build stage: ```Dockerfile ARG SETTINGS=default From d85711734bcc3132ddef6f6159f14ef4e0eab762 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Thu, 13 Jul 2017 14:26:37 -0400 Subject: [PATCH 09/18] More about ARG and build stages. Signed-off-by: Daniel Nephin Upstream-commit: ad5d0359886a09196e6070aa9a2aa1acd5834f55 Component: cli --- components/cli/docs/reference/builder.md | 47 +++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/components/cli/docs/reference/builder.md b/components/cli/docs/reference/builder.md index b0e40010f7..16c1b48d31 100644 --- a/components/cli/docs/reference/builder.md +++ b/components/cli/docs/reference/builder.md @@ -536,11 +536,10 @@ an `ARG` declared before the first `FROM` use an `ARG` instruction without a value inside of a build stage: ```Dockerfile -ARG SETTINGS=default - -FROM busybox -ARG SETTINGS - +ARG VERSION=latest +FROM busybox:$VERSION +ARG VERSION +RUN echo $VERSION > image_version ``` ## RUN @@ -1366,8 +1365,8 @@ defined in the Dockerfile, the build outputs a warning. [Warning] One or more build-args [foo] were not consumed. ``` -The Dockerfile author can define a single variable by specifying `ARG` once or many -variables by specifying `ARG` more than once. For example, a valid Dockerfile: +A Dockerfile may include one or more `ARG` instructions. For example, +the following is a valid Dockerfile: ``` FROM busybox @@ -1376,7 +1375,13 @@ ARG buildno ... ``` -A Dockerfile author may optionally specify a default value for an `ARG` instruction: +> **Warning:** It is not recommended to use build-time variables for +> passing secrets like github keys, user credentials etc. Build-time variable +> values are visible to any user of the image with the `docker history` command. + +### Default values + +An `ARG` instruction can optionally include a default value: ``` FROM busybox @@ -1385,8 +1390,10 @@ ARG buildno=1 ... ``` -If an `ARG` value has a default and if there is no value passed at build-time, the -builder uses the default. +If an `ARG` instruction has a default value and if there is no value passed +at build-time, the builder uses the default. + +### Scope An `ARG` variable definition comes into effect from the line on which it is defined in the `Dockerfile` not from the argument's use on the command-line or @@ -1410,9 +1417,21 @@ subsequent line 3. The `USER` at line 4 evaluates to `what_user` as `user` is defined and the `what_user` value was passed on the command line. Prior to its definition by an `ARG` instruction, any use of a variable results in an empty string. -> **Warning:** It is not recommended to use build-time variables for -> passing secrets like github keys, user credentials etc. Build-time variable -> values are visible to any user of the image with the `docker history` command. +An `ARG` instruction goes out of scope at the end of the build +stage where it was defined. To use an arg in multiple stages, each stage must +include the `ARG` instruction. + +``` +FROM busybox +ARG SETTINGS +RUN ./run/setup $SETTINGS + +FROM busybox +ARG SETTINGS +RUN ./run/other $SETTINGS +``` + +### Using ARG variables You can use an `ARG` or an `ENV` instruction to specify variables that are available to the `RUN` instruction. Environment variables defined using the @@ -1461,6 +1480,8 @@ from the command line and persist them in the final image by leveraging the `ENV` instruction. Variable expansion is only supported for [a limited set of Dockerfile instructions.](#environment-replacement) +### Predefined ARGs + Docker has a set of predefined `ARG` variables that you can use without a corresponding `ARG` instruction in the Dockerfile. From c456febc9ced5e0218b22bdc1c9b706297a7d718 Mon Sep 17 00:00:00 2001 From: allencloud Date: Mon, 10 Jul 2017 15:50:22 +0800 Subject: [PATCH 10/18] docs: add filter scope for command events and more cluster events Signed-off-by: allencloud Upstream-commit: 8639c9baf8252ccdcfb3360e0d5568c01a3942ce Component: cli --- .../cli/docs/reference/commandline/events.md | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/components/cli/docs/reference/commandline/events.md b/components/cli/docs/reference/commandline/events.md index 71475b43ec..65b4f29013 100644 --- a/components/cli/docs/reference/commandline/events.md +++ b/components/cli/docs/reference/commandline/events.md @@ -80,9 +80,9 @@ Docker images report the following events: Docker plugins report the following events: -- `install` - `enable` - `disable` +- `install` - `remove` #### Volumes @@ -90,9 +90,9 @@ Docker plugins report the following events: Docker volumes report the following events: - `create` +- `destroy` - `mount` - `unmount` -- `destroy` #### Networks @@ -100,8 +100,9 @@ Docker networks report the following events: - `create` - `connect` -- `disconnect` - `destroy` +- `disconnect` +- `remove` #### Daemons @@ -109,6 +110,38 @@ Docker daemons report the following events: - `reload` +#### Services + +Docker services report the following events: + +- `create` +- `remove` +- `update` + +#### Nodes + +Docker nodes report the following events: + +- `create` +- `remove` +- `update` + +#### Secrets + +Docker secrets report the following events: + +- `create` +- `remove` +- `update` + +#### Configs + +Docker configs report the following events: + +- `create` +- `remove` +- `update` + ### Limiting, filtering, and formatting the output #### Limit events by time @@ -149,7 +182,8 @@ The currently supported filters are: * label (`label=` or `label==`) * network (`network=`) * plugin (`plugin=`) -* type (`type=`) +* scope (`scope=`) +* type (`type=`) * volume (`volume=`) #### Format @@ -317,6 +351,29 @@ $ docker events --filter 'type=plugin' 2016-07-25T17:30:14.825557616Z plugin pull ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) 2016-07-25T17:30:14.888127370Z plugin enable ec7b87f2ce84330fe076e666f17dfc049d2d7ae0b8190763de94e1f2d105993f (name=tiborvass/sample-volume-plugin:latest) + +$ docker events -f type=service + +2017-07-12T06:34:07.999446625Z service create wj64st89fzgchxnhiqpn8p4oj (name=reverent_albattani) +2017-07-12T06:34:21.405496207Z service remove wj64st89fzgchxnhiqpn8p4oj (name=reverent_albattani) + +$ docker events -f type=node + +2017-07-12T06:21:51.951586759Z node update 3xyz5ttp1a253q74z1thwywk9 (name=ip-172-31-23-42, state.new=ready, state.old=unknown) + +$ docker events -f type=secret + +2017-07-12T06:32:13.915704367Z secret create s8o6tmlnndrgzbmdilyy5ymju (name=new_secret) +2017-07-12T06:32:37.052647783Z secret remove s8o6tmlnndrgzbmdilyy5ymju (name=new_secret) + +$ docker events -f type=config +2017-07-12T06:44:13.349037127Z config create u96zlvzdfsyb9sg4mhyxfh3rl (name=abc) +2017-07-12T06:44:36.327694184Z config remove u96zlvzdfsyb9sg4mhyxfh3rl (name=abc) + +$ docker events --filter 'scope=swarm' + +2017-07-10T07:46:50.250024503Z service create m8qcxu8081woyof7w3jaax6gk (name=affectionate_wilson) +2017-07-10T07:47:31.093797134Z secret create 6g5pufzsv438p9tbvl9j94od4 (name=new_secret) ``` ### Format the output From 42cbae8c65ca77de850c14ab456dd00c4b93888e Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 8 Jul 2017 13:33:24 -0700 Subject: [PATCH 11/18] Service privileges: CLI reference docs & completion Signed-off-by: Sebastiaan van Stijn Upstream-commit: 5cc7ac29901f5ca08ca089d2e8ff1b8858c75470 Component: cli --- components/cli/contrib/completion/bash/docker | 1 + .../reference/commandline/service_create.md | 19 +++++++++++++++++++ .../reference/commandline/service_update.md | 1 + 3 files changed, 21 insertions(+) diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker index 95cc588ca0..616adb7ebf 100644 --- a/components/cli/contrib/completion/bash/docker +++ b/components/cli/contrib/completion/bash/docker @@ -3091,6 +3091,7 @@ _docker_service_update() { # and `docker service update` _docker_service_update_and_create() { local options_with_args=" + --credential-spec --endpoint-mode --entrypoint --env -e diff --git a/components/cli/docs/reference/commandline/service_create.md b/components/cli/docs/reference/commandline/service_create.md index a1b6d18f9d..d09a6bf8e6 100644 --- a/components/cli/docs/reference/commandline/service_create.md +++ b/components/cli/docs/reference/commandline/service_create.md @@ -23,6 +23,7 @@ Create a new service Options: --constraint list Placement constraints --container-label list Container labels + --credential-spec Credential spec for managed service account (Windows only) -d, --detach Exit immediately instead of waiting for the service to converge (default true) --dns list Set custom DNS servers --dns-option list Set DNS options @@ -779,6 +780,24 @@ $ docker service create --name dns-cache -p 53:53/tcp -p 53:53/udp dns-cache $ docker service create --name dns-cache -p 53:53/udp dns-cache ``` +### Provide credential specs for managed service accounts (Windows only) + +This option is only used for services using Windows containers. The +`--credential-spec` must be in the format `file://` or +`registry://`. + +When using the `file://` format, the referenced file must be +present in the `CredentialSpecs` subdirectory in the docker data directory, +which defaults to `C:\ProgramData\Docker\` on Windows. For example, +specifying `file://spec.json` loads `C:\ProgramData\Docker\CredentialSpecs\spec.json`. + +When using the `registry://` format, the credential spec is +read from the Windows registry on the daemon's host. The specified +registry value must be located in: + + HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs + + ### Create services using templates You can use templates for some flags of `service create`, using the syntax diff --git a/components/cli/docs/reference/commandline/service_update.md b/components/cli/docs/reference/commandline/service_update.md index 93c5750eee..8f075d2c19 100644 --- a/components/cli/docs/reference/commandline/service_update.md +++ b/components/cli/docs/reference/commandline/service_update.md @@ -26,6 +26,7 @@ Options: --constraint-rm list Remove a constraint --container-label-add list Add or update a container label --container-label-rm list Remove a container label by its key + --credential-spec Credential spec for managed service account (Windows only) -d, --detach Exit immediately instead of waiting for the service to converge (default true) --dns-add list Add or update a custom DNS server --dns-option-add list Add or update a DNS option From 2dc557d71e239e8ba2f888ba8a99d7eb4d406f4a Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 15 Jul 2017 16:03:17 -0700 Subject: [PATCH 12/18] Fix: skip build-cache prune on unsupported versions Signed-off-by: Sebastiaan van Stijn Upstream-commit: 6c3a448ecb617e1c2f487525fd232f6cf3863321 Component: cli --- .../cli/cli/command/system/client_test.go | 15 ++++++++++ components/cli/cli/command/system/prune.go | 29 ++++++++++++------- .../cli/cli/command/system/prune_test.go | 15 ++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 components/cli/cli/command/system/client_test.go create mode 100644 components/cli/cli/command/system/prune_test.go diff --git a/components/cli/cli/command/system/client_test.go b/components/cli/cli/command/system/client_test.go new file mode 100644 index 0000000000..ed0e803ea8 --- /dev/null +++ b/components/cli/cli/command/system/client_test.go @@ -0,0 +1,15 @@ +package system + +import ( + "github.com/docker/docker/client" +) + +type fakeClient struct { + client.Client + + version string +} + +func (cli *fakeClient) ClientVersion() string { + return cli.version +} diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index e9383e43d3..b46fdbb78e 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -9,21 +9,23 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/prune" "github.com/docker/cli/opts" + "github.com/docker/docker/api/types/versions" units "github.com/docker/go-units" "github.com/spf13/cobra" "golang.org/x/net/context" ) type pruneOptions struct { - force bool - all bool - pruneVolumes bool - filter opts.FilterOpt + force bool + all bool + pruneBuildCache bool + pruneVolumes bool + filter opts.FilterOpt } // NewPruneCommand creates a new cobra.Command for `docker prune` func NewPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt()} + options := pruneOptions{filter: opts.NewFilterOpt(), pruneBuildCache: true} cmd := &cobra.Command{ Use: "prune [OPTIONS]", @@ -53,6 +55,9 @@ const confirmationTemplate = `WARNING! This will remove: Are you sure you want to continue?` func runPrune(dockerCli command.Cli, options pruneOptions) error { + if versions.LessThan(dockerCli.Client().ClientVersion(), "1.31") { + options.pruneBuildCache = false + } if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { return nil } @@ -86,11 +91,13 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { fmt.Fprintln(dockerCli.Out(), output) } - report, err := dockerCli.Client().BuildCachePrune(context.Background()) - if err != nil { - return err + if options.pruneBuildCache { + report, err := dockerCli.Client().BuildCachePrune(context.Background()) + if err != nil { + return err + } + spaceReclaimed += report.SpaceReclaimed } - spaceReclaimed += report.SpaceReclaimed fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) @@ -113,7 +120,9 @@ func confirmationMessage(options pruneOptions) string { } else { warnings = append(warnings, "all dangling images") } - warnings = append(warnings, "all build cache") + if options.pruneBuildCache { + warnings = append(warnings, "all build cache") + } var buffer bytes.Buffer t.Execute(&buffer, &warnings) diff --git a/components/cli/cli/command/system/prune_test.go b/components/cli/cli/command/system/prune_test.go new file mode 100644 index 0000000000..980a93865f --- /dev/null +++ b/components/cli/cli/command/system/prune_test.go @@ -0,0 +1,15 @@ +package system + +import ( + "testing" + + "github.com/docker/cli/cli/internal/test" + "github.com/stretchr/testify/assert" +) + +func TestPrunePromptPre131(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{version: "1.30"}) + cmd := NewPruneCommand(cli) + assert.NoError(t, cmd.Execute()) + assert.NotContains(t, cli.OutBuffer().String(), "all build cache") +} From 8dbc530b62d09ffc03cddb729d58b7661c0e05f2 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Tue, 18 Jul 2017 09:49:02 +0200 Subject: [PATCH 13/18] =?UTF-8?q?Remove=20useless=20prune=20package=20?= =?UTF-8?q?=F0=9F=91=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `cli/command/prune` just does some aliasing of `Prune*` methods, doesn't have any use. Signed-off-by: Vincent Demeester Upstream-commit: 3f4d91508e7d8709b8773b6ac8e7e80f0817254d Component: cli --- components/cli/cli/command/prune/prune.go | 30 -------------------- components/cli/cli/command/system/prune.go | 33 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 35 deletions(-) delete mode 100644 components/cli/cli/command/prune/prune.go diff --git a/components/cli/cli/command/prune/prune.go b/components/cli/cli/command/prune/prune.go deleted file mode 100644 index 12429da907..0000000000 --- a/components/cli/cli/command/prune/prune.go +++ /dev/null @@ -1,30 +0,0 @@ -package prune - -import ( - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/container" - "github.com/docker/cli/cli/command/image" - "github.com/docker/cli/cli/command/network" - "github.com/docker/cli/cli/command/volume" - "github.com/docker/cli/opts" -) - -// RunContainerPrune executes a prune command for containers -func RunContainerPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return container.RunPrune(dockerCli, filter) -} - -// RunVolumePrune executes a prune command for volumes -func RunVolumePrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return volume.RunPrune(dockerCli, filter) -} - -// RunImagePrune executes a prune command for images -func RunImagePrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) { - return image.RunPrune(dockerCli, all, filter) -} - -// RunNetworkPrune executes a prune command for networks -func RunNetworkPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return network.RunPrune(dockerCli, filter) -} diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index e9383e43d3..d2305822f9 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -7,7 +7,10 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/prune" + "github.com/docker/cli/cli/command/container" + "github.com/docker/cli/cli/command/image" + "github.com/docker/cli/cli/command/network" + "github.com/docker/cli/cli/command/volume" "github.com/docker/cli/opts" units "github.com/docker/go-units" "github.com/spf13/cobra" @@ -52,6 +55,26 @@ const confirmationTemplate = `WARNING! This will remove: {{- end }} Are you sure you want to continue?` +// runContainerPrune executes a prune command for containers +func runContainerPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { + return container.RunPrune(dockerCli, filter) +} + +// runNetworkPrune executes a prune command for networks +func runNetworkPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { + return network.RunPrune(dockerCli, filter) +} + +// runVolumePrune executes a prune command for volumes +func runVolumePrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { + return volume.RunPrune(dockerCli, filter) +} + +// runImagePrune executes a prune command for images +func runImagePrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) { + return image.RunPrune(dockerCli, all, filter) +} + func runPrune(dockerCli command.Cli, options pruneOptions) error { if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { return nil @@ -59,11 +82,11 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { var spaceReclaimed uint64 pruneFuncs := []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ - prune.RunContainerPrune, - prune.RunNetworkPrune, + runContainerPrune, + runNetworkPrune, } if options.pruneVolumes { - pruneFuncs = append(pruneFuncs, prune.RunVolumePrune) + pruneFuncs = append(pruneFuncs, runVolumePrune) } for _, pruneFn := range pruneFuncs { @@ -77,7 +100,7 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { } } - spc, output, err := prune.RunImagePrune(dockerCli, options.all, options.filter) + spc, output, err := runImagePrune(dockerCli, options.all, options.filter) if err != nil { return err } From 7e5b932e43d95f4412cf03fbb5f05f179392d6f9 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 17 Jul 2017 12:12:05 +0200 Subject: [PATCH 14/18] Small refactor in system prune Adapt "image prune" and "build cache prune" to have the same signature as the other prune commands, so that they can all be added to the "pruneFuncs" array. Signed-off-by: Sebastiaan van Stijn Upstream-commit: 73163ee78b2944fff9dd83bc69e7f7f211dd6280 Component: cli --- components/cli/cli/command/system/prune.go | 36 ++++++++++------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index 9afe0a317c..d542391224 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -77,6 +77,15 @@ func runImagePrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint return image.RunPrune(dockerCli, all, filter) } +// runBuildCachePrune executes a prune command for build cache +func runBuildCachePrune(dockerCli command.Cli, _ opts.FilterOpt) (uint64, string, error) { + report, err := dockerCli.Client().BuildCachePrune(context.Background()) + if err != nil { + return 0, "", err + } + return report.SpaceReclaimed, "", nil +} + func runPrune(dockerCli command.Cli, options pruneOptions) error { if versions.LessThan(dockerCli.Client().ClientVersion(), "1.31") { options.pruneBuildCache = false @@ -84,8 +93,9 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { return nil } - - var spaceReclaimed uint64 + imagePrune := func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { + return runImagePrune(dockerCli, options.all, options.filter) + } pruneFuncs := []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ runContainerPrune, runNetworkPrune, @@ -93,7 +103,12 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { if options.pruneVolumes { pruneFuncs = append(pruneFuncs, runVolumePrune) } + pruneFuncs = append(pruneFuncs, imagePrune) + if options.pruneBuildCache { + pruneFuncs = append(pruneFuncs, runBuildCachePrune) + } + var spaceReclaimed uint64 for _, pruneFn := range pruneFuncs { spc, output, err := pruneFn(dockerCli, options.filter) if err != nil { @@ -105,23 +120,6 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { } } - spc, output, err := runImagePrune(dockerCli, options.all, options.filter) - if err != nil { - return err - } - if spc > 0 { - spaceReclaimed += spc - fmt.Fprintln(dockerCli.Out(), output) - } - - if options.pruneBuildCache { - report, err := dockerCli.Client().BuildCachePrune(context.Background()) - if err != nil { - return err - } - spaceReclaimed += report.SpaceReclaimed - } - fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) return nil From ea84db7e56bc08b446455e9bf22e352325664ae1 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 18 Jul 2017 15:26:45 +0200 Subject: [PATCH 15/18] Unexport subcommands These commands were only used as subcommands, so did not have to be exported. Signed-off-by: Sebastiaan van Stijn Upstream-commit: 9c7b0d74cdd82313c9fa46a74071792c2c0c62af Component: cli --- components/cli/cli/command/system/cmd.go | 4 ++-- components/cli/cli/command/system/df.go | 4 ++-- components/cli/cli/command/system/prune.go | 4 ++-- components/cli/cli/command/system/prune_test.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/cli/cli/command/system/cmd.go b/components/cli/cli/command/system/cmd.go index 455387cd46..60979e7224 100644 --- a/components/cli/cli/command/system/cmd.go +++ b/components/cli/cli/command/system/cmd.go @@ -18,8 +18,8 @@ func NewSystemCommand(dockerCli *command.DockerCli) *cobra.Command { cmd.AddCommand( NewEventsCommand(dockerCli), NewInfoCommand(dockerCli), - NewDiskUsageCommand(dockerCli), - NewPruneCommand(dockerCli), + newDiskUsageCommand(dockerCli), + newPruneCommand(dockerCli), ) return cmd diff --git a/components/cli/cli/command/system/df.go b/components/cli/cli/command/system/df.go index d8f9bdc021..5146482f0e 100644 --- a/components/cli/cli/command/system/df.go +++ b/components/cli/cli/command/system/df.go @@ -15,8 +15,8 @@ type diskUsageOptions struct { format string } -// NewDiskUsageCommand creates a new cobra.Command for `docker df` -func NewDiskUsageCommand(dockerCli *command.DockerCli) *cobra.Command { +// newDiskUsageCommand creates a new cobra.Command for `docker df` +func newDiskUsageCommand(dockerCli *command.DockerCli) *cobra.Command { var opts diskUsageOptions cmd := &cobra.Command{ diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index 9afe0a317c..6e721ea004 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -26,8 +26,8 @@ type pruneOptions struct { filter opts.FilterOpt } -// NewPruneCommand creates a new cobra.Command for `docker prune` -func NewPruneCommand(dockerCli command.Cli) *cobra.Command { +// newPruneCommand creates a new cobra.Command for `docker prune` +func newPruneCommand(dockerCli command.Cli) *cobra.Command { options := pruneOptions{filter: opts.NewFilterOpt(), pruneBuildCache: true} cmd := &cobra.Command{ diff --git a/components/cli/cli/command/system/prune_test.go b/components/cli/cli/command/system/prune_test.go index 980a93865f..669166c998 100644 --- a/components/cli/cli/command/system/prune_test.go +++ b/components/cli/cli/command/system/prune_test.go @@ -9,7 +9,7 @@ import ( func TestPrunePromptPre131(t *testing.T) { cli := test.NewFakeCli(&fakeClient{version: "1.30"}) - cmd := NewPruneCommand(cli) + cmd := newPruneCommand(cli) assert.NoError(t, cmd.Execute()) assert.NotContains(t, cli.OutBuffer().String(), "all build cache") } From 29e4b6071dd4445d8d1e4387f1cd90ffe3746887 Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 18 Jul 2017 12:22:28 -0400 Subject: [PATCH 16/18] Cleanup dockerfiles and circle Signed-off-by: Daniel Nephin Upstream-commit: 0f91d9e6c4e3f4a0e5dc08588b636b281766951e Component: cli --- components/cli/circle.yml | 11 +++++------ components/cli/dockerfiles/Dockerfile.dev | 6 +++--- components/cli/dockerfiles/Dockerfile.lint | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/components/cli/circle.yml b/components/cli/circle.yml index 74b6128fbb..2a9c196750 100644 --- a/components/cli/circle.yml +++ b/components/cli/circle.yml @@ -4,7 +4,7 @@ jobs: lint: working_directory: /work - docker: [{image: 'docker:17.05-git'}] + docker: [{image: 'docker:17.06-git'}] steps: - checkout - setup_remote_docker: @@ -22,7 +22,7 @@ jobs: cross: working_directory: /work - docker: [{image: 'docker:17.05-git'}] + docker: [{image: 'docker:17.06-git'}] parallelism: 3 steps: - checkout @@ -48,7 +48,7 @@ jobs: test: working_directory: /work - docker: [{image: 'docker:17.05-git'}] + docker: [{image: 'docker:17.06-git'}] steps: - checkout - setup_remote_docker: @@ -75,9 +75,8 @@ jobs: validate: working_directory: /work - docker: [{image: 'docker:17.05-git'}] + docker: [{image: 'docker:17.06-git'}] steps: - - run: apk add -U git openssh - checkout - setup_remote_docker: reusable: true @@ -93,7 +92,7 @@ jobs: make -B vendor compose-jsonschema manpages yamldocs shellcheck: working_directory: /work - docker: [{image: 'docker:17.05-git'}] + docker: [{image: 'docker:17.06-git'}] steps: - checkout - setup_remote_docker diff --git a/components/cli/dockerfiles/Dockerfile.dev b/components/cli/dockerfiles/Dockerfile.dev index a80d3418f1..7f9482e612 100644 --- a/components/cli/dockerfiles/Dockerfile.dev +++ b/components/cli/dockerfiles/Dockerfile.dev @@ -4,21 +4,21 @@ FROM golang:1.8.3-alpine RUN apk add -U git make bash coreutils ARG VNDR_SHA=9909bb2b8a0b7ea464527b376dc50389c90df587 -RUN go get github.com/LK4D4/vndr && \ +RUN go get -d github.com/LK4D4/vndr && \ cd /go/src/github.com/LK4D4/vndr && \ git checkout -q "$VNDR_SHA" && \ go build -v -o /usr/bin/vndr . && \ rm -rf /go/src/* /go/pkg/* /go/bin/* ARG BINDATA_SHA=a0ff2567cfb70903282db057e799fd826784d41d -RUN go get github.com/jteeuwen/go-bindata/go-bindata && \ +RUN go get -d github.com/jteeuwen/go-bindata/go-bindata && \ cd /go/src/github.com/jteeuwen/go-bindata/go-bindata && \ git checkout -q "$BINDATA_SHA" && \ go build -v -o /usr/bin/go-bindata . && \ rm -rf /go/src/* /go/pkg/* /go/bin/* ARG FILEWATCHER_SHA=2e12ea42f6c8c089b19e992145bb94e8adaecedb -RUN go get github.com/dnephin/filewatcher && \ +RUN go get -d github.com/dnephin/filewatcher && \ cd /go/src/github.com/dnephin/filewatcher && \ git checkout -q "$FILEWATCHER_SHA" && \ go build -v -o /usr/bin/filewatcher . && \ diff --git a/components/cli/dockerfiles/Dockerfile.lint b/components/cli/dockerfiles/Dockerfile.lint index 0b9385e0d1..c981efbadc 100644 --- a/components/cli/dockerfiles/Dockerfile.lint +++ b/components/cli/dockerfiles/Dockerfile.lint @@ -3,7 +3,7 @@ FROM golang:1.8.3-alpine RUN apk add -U git ARG GOMETALINTER_SHA=4306381615a2ba2a207f8fcea02c08c6b2b0803f -RUN go get github.com/alecthomas/gometalinter && \ +RUN go get -d github.com/alecthomas/gometalinter && \ cd /go/src/github.com/alecthomas/gometalinter && \ git checkout -q "$GOMETALINTER_SHA" && \ go build -v -o /usr/local/bin/gometalinter . && \ From 7c2dc55ca3c9e5d3858a70cf06090d5f1daa876d Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 18 Jul 2017 12:25:45 -0400 Subject: [PATCH 17/18] Remove unnecessary prune function aliases. Signed-off-by: Daniel Nephin Upstream-commit: ff350a04cba8dd7c9304f1a59702a2efd3114eaa Component: cli --- components/cli/cli/command/system/prune.go | 28 ++++------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index c86025fc1f..c0bc434fb0 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -57,26 +57,6 @@ const confirmationTemplate = `WARNING! This will remove: {{- end }} Are you sure you want to continue?` -// runContainerPrune executes a prune command for containers -func runContainerPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return container.RunPrune(dockerCli, filter) -} - -// runNetworkPrune executes a prune command for networks -func runNetworkPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return network.RunPrune(dockerCli, filter) -} - -// runVolumePrune executes a prune command for volumes -func runVolumePrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return volume.RunPrune(dockerCli, filter) -} - -// runImagePrune executes a prune command for images -func runImagePrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) { - return image.RunPrune(dockerCli, all, filter) -} - // runBuildCachePrune executes a prune command for build cache func runBuildCachePrune(dockerCli command.Cli, _ opts.FilterOpt) (uint64, string, error) { report, err := dockerCli.Client().BuildCachePrune(context.Background()) @@ -94,14 +74,14 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { return nil } imagePrune := func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return runImagePrune(dockerCli, options.all, options.filter) + return image.RunPrune(dockerCli, options.all, options.filter) } pruneFuncs := []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ - runContainerPrune, - runNetworkPrune, + container.RunPrune, + network.RunPrune, } if options.pruneVolumes { - pruneFuncs = append(pruneFuncs, runVolumePrune) + pruneFuncs = append(pruneFuncs, volume.RunPrune) } pruneFuncs = append(pruneFuncs, imagePrune) if options.pruneBuildCache { From e4c6e3832215f1e5a8a91e7d0a1ca9ab7094d65b Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 18 Jul 2017 16:31:41 -0400 Subject: [PATCH 18/18] Fix CODEOWNERS patterns. Signed-off-by: Daniel Nephin Upstream-commit: cea8b4f4f33e01bf0438ab2df94fe15edd407864 Component: cli --- components/cli/.github/CODEOWNERS | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/cli/.github/CODEOWNERS b/components/cli/.github/CODEOWNERS index 855eff98ab..f3164a64b5 100644 --- a/components/cli/.github/CODEOWNERS +++ b/components/cli/.github/CODEOWNERS @@ -1,8 +1,8 @@ # Github code owners # See https://github.com/blog/2392-introducing-code-owners -cli/compose/* @dnephin @vdemeester -contrib/completion/bash/* @albers -contrib/completion/zsh/* @sdurrheimer -docs/* @mstanleyjones @vdemeester @thaJeztah -scripts/* @dnephin +cli/compose/** @dnephin @vdemeester +contrib/completion/bash/** @albers +contrib/completion/zsh/** @sdurrheimer +docs/** @mstanleyjones @vdemeester @thaJeztah +scripts/** @dnephin