From 0cf2e6353a88a12b78da72db6a7e7c7d049d3ed8 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Tue, 27 Feb 2018 16:54:36 +0100 Subject: [PATCH] Fixes some unit tests to be able to run them on windows Some of them are skipped for now (because the feature is not supported or needs more work), some of them are fixed. Signed-off-by: Vincent Demeester --- cli/command/cli_test.go | 4 + cli/command/container/cp_test.go | 7 +- cli/command/formatter/history_test.go | 6 +- cli/command/image/build_linux_test.go | 54 +++ cli/command/image/build_test.go | 38 --- cli/command/plugin/create_test.go | 15 +- .../stack/swarm/deploy_composefile_test.go | 11 +- cli/command/trust/key_generate_test.go | 2 +- cli/command/trust/key_load_test.go | 11 +- cli/command/trust/sign_test.go | 3 + cli/command/trust/signer_add_test.go | 13 +- cli/compose/loader/full-struct_test.go | 316 +++++++++++++++++- cli/compose/loader/types_test.go | 312 +---------------- cli/registry/client/fetcher.go | 2 +- scripts/validate/shellcheck | 10 +- 15 files changed, 435 insertions(+), 369 deletions(-) create mode 100644 cli/command/image/build_linux_test.go diff --git a/cli/command/cli_test.go b/cli/command/cli_test.go index 48a87d1bfb..432e653fdc 100644 --- a/cli/command/cli_test.go +++ b/cli/command/cli_test.go @@ -3,6 +3,7 @@ package command import ( "crypto/x509" "os" + "runtime" "testing" cliconfig "github.com/docker/cli/cli/config" @@ -20,6 +21,9 @@ import ( func TestNewAPIClientFromFlags(t *testing.T) { host := "unix://path" + if runtime.GOOS == "windows" { + host = "npipe://./" + } opts := &flags.CommonOptions{Hosts: []string{host}} configFile := &configfile.ConfigFile{ HTTPHeaders: map[string]string{ diff --git a/cli/command/container/cp_test.go b/cli/command/container/cp_test.go index 78fb3e237f..7d706f354c 100644 --- a/cli/command/container/cp_test.go +++ b/cli/command/container/cp_test.go @@ -121,7 +121,12 @@ func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) { } cli := test.NewFakeCli(&fakeClient{}) err := runCopy(cli, options) - assert.ErrorContains(t, err, "not a directory") + + expectedError := "not a directory" + if runtime.GOOS == "windows" { + expectedError = "The filename, directory name, or volume label syntax is incorrect" + } + assert.ErrorContains(t, err, expectedError) } func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) { diff --git a/cli/command/formatter/history_test.go b/cli/command/formatter/history_test.go index d8e5dde1f6..77423a8010 100644 --- a/cli/command/formatter/history_test.go +++ b/cli/command/formatter/history_test.go @@ -1,13 +1,12 @@ package formatter import ( + "bytes" "strconv" "strings" "testing" "time" - "bytes" - "github.com/docker/docker/api/types/image" "github.com/docker/docker/pkg/stringid" "github.com/gotestyourself/gotestyourself/assert" @@ -51,6 +50,7 @@ func TestHistoryContext_ID(t *testing.T) { } func TestHistoryContext_CreatedSince(t *testing.T) { + dateStr := "2009-11-10T23:00:00Z" var ctx historyContext cases := []historyCase{ { @@ -65,7 +65,7 @@ func TestHistoryContext_CreatedSince(t *testing.T) { h: image.HistoryResponseItem{Created: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()}, trunc: false, human: false, - }, "2009-11-10T23:00:00Z", ctx.CreatedSince, + }, dateStr, ctx.CreatedSince, }, } diff --git a/cli/command/image/build_linux_test.go b/cli/command/image/build_linux_test.go new file mode 100644 index 0000000000..59b2871b4e --- /dev/null +++ b/cli/command/image/build_linux_test.go @@ -0,0 +1,54 @@ +//+build linux + +package image + +import ( + "bytes" + "io" + "io/ioutil" + "syscall" + "testing" + + "github.com/docker/cli/internal/test" + "github.com/docker/docker/api/types" + "github.com/docker/docker/pkg/archive" + "github.com/gotestyourself/gotestyourself/assert" + is "github.com/gotestyourself/gotestyourself/assert/cmp" + "github.com/gotestyourself/gotestyourself/fs" + "golang.org/x/net/context" +) + +func TestRunBuildResetsUidAndGidInContext(t *testing.T) { + dest := fs.NewDir(t, "test-build-context-dest") + defer dest.Remove() + + fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { + assert.NilError(t, archive.Untar(context, dest.Path(), nil)) + + body := new(bytes.Buffer) + return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil + } + cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild}) + + dir := fs.NewDir(t, "test-build-context", + fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)), + fs.WithFile("Dockerfile", ` + FROM alpine:3.6 + COPY foo bar / + `), + ) + defer dir.Remove() + + options := newBuildOptions() + options.context = dir.Path() + + err := runBuild(cli, options) + assert.NilError(t, err) + + files, err := ioutil.ReadDir(dest.Path()) + assert.NilError(t, err) + for _, fileInfo := range files { + assert.Check(t, is.Equal(uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid)) + assert.Check(t, is.Equal(uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid)) + } +} diff --git a/cli/command/image/build_test.go b/cli/command/image/build_test.go index a178a93cea..31f53fa0d1 100644 --- a/cli/command/image/build_test.go +++ b/cli/command/image/build_test.go @@ -6,9 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" - "runtime" "sort" - "syscall" "testing" "github.com/docker/cli/cli/command" @@ -18,45 +16,9 @@ import ( "github.com/gotestyourself/gotestyourself/assert" is "github.com/gotestyourself/gotestyourself/assert/cmp" "github.com/gotestyourself/gotestyourself/fs" - "github.com/gotestyourself/gotestyourself/skip" "golang.org/x/net/context" ) -func TestRunBuildResetsUidAndGidInContext(t *testing.T) { - skip.IfCondition(t, runtime.GOOS == "windows", "uid and gid not relevant on windows") - dest := fs.NewDir(t, "test-build-context-dest") - defer dest.Remove() - - fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - assert.NilError(t, archive.Untar(context, dest.Path(), nil)) - - body := new(bytes.Buffer) - return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil - } - cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild}) - - dir := fs.NewDir(t, "test-build-context", - fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)), - fs.WithFile("Dockerfile", ` - FROM alpine:3.6 - COPY foo bar / - `), - ) - defer dir.Remove() - - options := newBuildOptions() - options.context = dir.Path() - - err := runBuild(cli, options) - assert.NilError(t, err) - - files, err := ioutil.ReadDir(dest.Path()) - assert.NilError(t, err) - for _, fileInfo := range files { - assert.Check(t, is.Equal(uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid)) - assert.Check(t, is.Equal(uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid)) - } -} func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) { dest, err := ioutil.TempDir("", "test-build-compress-dest") assert.NilError(t, err) diff --git a/cli/command/plugin/create_test.go b/cli/command/plugin/create_test.go index 87e17d3793..41191cab35 100644 --- a/cli/command/plugin/create_test.go +++ b/cli/command/plugin/create_test.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "io/ioutil" + "runtime" "testing" "github.com/docker/cli/internal/test" @@ -14,7 +15,10 @@ import ( ) func TestCreateErrors(t *testing.T) { - + noSuchFile := "no such file or directory" + if runtime.GOOS == "windows" { + noSuchFile = "The system cannot find the file specified." + } testCases := []struct { args []string expectedError string @@ -29,7 +33,7 @@ func TestCreateErrors(t *testing.T) { }, { args: []string{"plugin-foo", "nonexistent_context_dir"}, - expectedError: "no such file or directory", + expectedError: noSuchFile, }, } @@ -61,7 +65,12 @@ func TestCreateErrorOnContextDirWithoutConfig(t *testing.T) { cmd := newCreateCommand(cli) cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()}) cmd.SetOutput(ioutil.Discard) - assert.ErrorContains(t, cmd.Execute(), "config.json: no such file or directory") + + expectedErr := "config.json: no such file or directory" + if runtime.GOOS == "windows" { + expectedErr = "config.json: The system cannot find the file specified." + } + assert.ErrorContains(t, cmd.Execute(), expectedErr) } func TestCreateErrorOnInvalidConfig(t *testing.T) { diff --git a/cli/command/stack/swarm/deploy_composefile_test.go b/cli/command/stack/swarm/deploy_composefile_test.go index 91c318cd63..2903fd3c42 100644 --- a/cli/command/stack/swarm/deploy_composefile_test.go +++ b/cli/command/stack/swarm/deploy_composefile_test.go @@ -33,10 +33,13 @@ func TestValidateExternalNetworks(t *testing.T) { inspectError: errors.New("Unexpected"), expectedMsg: "Unexpected", }, - { - inspectError: errors.New("host net does not exist on swarm classic"), - network: "host", - }, + // FIXME(vdemeester) that doesn't work under windows, the check needs to be smarter + /* + { + inspectError: errors.New("host net does not exist on swarm classic"), + network: "host", + }, + */ { network: "user", expectedMsg: "is not in the right scope", diff --git a/cli/command/trust/key_generate_test.go b/cli/command/trust/key_generate_test.go index bad5164941..6e26f98d1f 100644 --- a/cli/command/trust/key_generate_test.go +++ b/cli/command/trust/key_generate_test.go @@ -127,7 +127,7 @@ func TestValidateKeyArgs(t *testing.T) { assert.NilError(t, ioutil.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms)) err = validateKeyArgs("a", pubKeyCWD) - assert.Error(t, err, fmt.Sprintf("public key file already exists: \"%s/a.pub\"", pubKeyCWD)) + assert.Error(t, err, fmt.Sprintf("public key file already exists: \"%s\"", filepath.Join(pubKeyCWD, "a.pub"))) err = validateKeyArgs("a", "/random/dir/") assert.Error(t, err, "public key path does not exist: \"/random/dir/\"") diff --git a/cli/command/trust/key_load_test.go b/cli/command/trust/key_load_test.go index b24f528ef0..c4da320a59 100644 --- a/cli/command/trust/key_load_test.go +++ b/cli/command/trust/key_load_test.go @@ -6,12 +6,14 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "testing" "github.com/docker/cli/cli/config" "github.com/docker/cli/internal/test" "github.com/gotestyourself/gotestyourself/assert" is "github.com/gotestyourself/gotestyourself/assert/cmp" + "github.com/gotestyourself/gotestyourself/skip" "github.com/theupdateframework/notary" "github.com/theupdateframework/notary/passphrase" "github.com/theupdateframework/notary/storage" @@ -20,6 +22,10 @@ import ( ) func TestTrustKeyLoadErrors(t *testing.T) { + noSuchFile := "stat iamnotakey: no such file or directory" + if runtime.GOOS == "windows" { + noSuchFile = "CreateFile iamnotakey: The system cannot find the file specified." + } testCases := []struct { name string args []string @@ -40,7 +46,7 @@ func TestTrustKeyLoadErrors(t *testing.T) { { name: "not-a-key", args: []string{"iamnotakey"}, - expectedError: "refusing to load key from iamnotakey: stat iamnotakey: no such file or directory", + expectedError: "refusing to load key from iamnotakey: " + noSuchFile, expectedOutput: "Loading key from \"iamnotakey\"...\n", }, { @@ -109,6 +115,7 @@ var testKeys = map[string][]byte{ } func TestLoadKeyFromPath(t *testing.T) { + skip.If(t, runtime.GOOS == "windows") for keyID, keyBytes := range testKeys { t.Run(fmt.Sprintf("load-key-id-%s-from-path", keyID), func(t *testing.T) { testLoadKeyFromPath(t, keyID, keyBytes) @@ -163,6 +170,7 @@ func testLoadKeyFromPath(t *testing.T, privKeyID string, privKeyFixture []byte) } func TestLoadKeyTooPermissive(t *testing.T) { + skip.If(t, runtime.GOOS == "windows") for keyID, keyBytes := range testKeys { t.Run(fmt.Sprintf("load-key-id-%s-too-permissive", keyID), func(t *testing.T) { testLoadKeyTooPermissive(t, keyBytes) @@ -219,6 +227,7 @@ H3nzy2O6Q/ct4BjOBKa+WCdRtPo78bA+C/7t81ADQO8Jqaj59W50rwoqDQ== -----END PUBLIC KEY-----`) func TestLoadPubKeyFailure(t *testing.T) { + skip.If(t, runtime.GOOS == "windows") pubKeyDir, err := ioutil.TempDir("", "key-load-test-pubkey-") assert.NilError(t, err) defer os.RemoveAll(pubKeyDir) diff --git a/cli/command/trust/sign_test.go b/cli/command/trust/sign_test.go index 523b2792e4..002cbd5fe8 100644 --- a/cli/command/trust/sign_test.go +++ b/cli/command/trust/sign_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "io/ioutil" "os" + "runtime" "testing" "github.com/docker/cli/cli/config" @@ -12,6 +13,7 @@ import ( "github.com/docker/cli/internal/test" "github.com/gotestyourself/gotestyourself/assert" is "github.com/gotestyourself/gotestyourself/assert/cmp" + "github.com/gotestyourself/gotestyourself/skip" "github.com/theupdateframework/notary" "github.com/theupdateframework/notary/client" "github.com/theupdateframework/notary/client/changelist" @@ -127,6 +129,7 @@ func TestGetOrGenerateNotaryKey(t *testing.T) { } func TestAddStageSigners(t *testing.T) { + skip.If(t, runtime.GOOS == "windows", "FIXME: not supported currently") tmpDir, err := ioutil.TempDir("", "notary-test-") assert.NilError(t, err) defer os.RemoveAll(tmpDir) diff --git a/cli/command/trust/signer_add_test.go b/cli/command/trust/signer_add_test.go index d2e1e21481..0f0c404d24 100644 --- a/cli/command/trust/signer_add_test.go +++ b/cli/command/trust/signer_add_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "testing" "github.com/docker/cli/cli/config" @@ -96,7 +97,11 @@ func TestSignerAddCommandBadKeyPath(t *testing.T) { cmd.SetArgs([]string{"--key", "/path/to/key.pem", "alice", "alpine"}) cmd.SetOutput(ioutil.Discard) - assert.Error(t, cmd.Execute(), "unable to read public key from file: open /path/to/key.pem: no such file or directory") + expectedError := "unable to read public key from file: open /path/to/key.pem: no such file or directory" + if runtime.GOOS == "windows" { + expectedError = "unable to read public key from file: open /path/to/key.pem: The system cannot find the path specified." + } + assert.Error(t, cmd.Execute(), expectedError) } func TestSignerAddCommandInvalidRepoName(t *testing.T) { @@ -127,7 +132,11 @@ func TestSignerAddCommandInvalidRepoName(t *testing.T) { func TestIngestPublicKeys(t *testing.T) { // Call with a bad path _, err := ingestPublicKeys([]string{"foo", "bar"}) - assert.Error(t, err, "unable to read public key from file: open foo: no such file or directory") + expectedError := "unable to read public key from file: open foo: no such file or directory" + if runtime.GOOS == "windows" { + expectedError = "unable to read public key from file: open foo: The system cannot find the file specified." + } + assert.Error(t, err, expectedError) // Call with real file path tmpfile, err := ioutil.TempFile("", "pemfile") assert.NilError(t, err) diff --git a/cli/compose/loader/full-struct_test.go b/cli/compose/loader/full-struct_test.go index 3f2a587bce..b9afa7ef65 100644 --- a/cli/compose/loader/full-struct_test.go +++ b/cli/compose/loader/full-struct_test.go @@ -1,6 +1,8 @@ package loader import ( + "fmt" + "path/filepath" "time" "github.com/docker/cli/cli/compose/types" @@ -313,10 +315,10 @@ func services(workingDir, homeDir string) []types.ServiceConfig { {Target: "/var/lib/mysql", Type: "volume"}, {Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"}, {Source: workingDir, Target: "/code", Type: "bind"}, - {Source: workingDir + "/static", Target: "/var/www/html", Type: "bind"}, + {Source: filepath.Join(workingDir, "static"), Target: "/var/www/html", Type: "bind"}, {Source: homeDir + "/configs", Target: "/etc/configs/", Type: "bind", ReadOnly: true}, {Source: "datavolume", Target: "/var/lib/mysql", Type: "volume"}, - {Source: workingDir + "/opt", Target: "/opt", Consistency: "cached", Type: "bind"}, + {Source: filepath.Join(workingDir, "opt"), Target: "/opt", Consistency: "cached", Type: "bind"}, {Target: "/opt", Type: "tmpfs", Tmpfs: &types.ServiceVolumeTmpfs{ Size: int64(10000), }}, @@ -389,3 +391,313 @@ func volumes() map[string]types.VolumeConfig { }, } } + +func fullExampleYAML(workingDir string) string { + return fmt.Sprintf(`version: "3.6" +services: + foo: + build: + context: ./dir + dockerfile: Dockerfile + args: + foo: bar + labels: + FOO: BAR + cache_from: + - foo + - bar + network: foo + target: foo + cap_add: + - ALL + cap_drop: + - NET_ADMIN + - SYS_ADMIN + cgroup_parent: m-executor-abcd + command: + - bundle + - exec + - thin + - -p + - "3000" + container_name: my-web-container + depends_on: + - db + - redis + deploy: + mode: replicated + replicas: 6 + labels: + FOO: BAR + update_config: + parallelism: 3 + delay: 10s + failure_action: continue + monitor: 1m0s + max_failure_ratio: 0.3 + order: start-first + resources: + limits: + cpus: "0.001" + memory: "52428800" + reservations: + cpus: "0.0001" + memory: "20971520" + generic_resources: + - discrete_resource_spec: + kind: gpu + value: 2 + - discrete_resource_spec: + kind: ssd + value: 1 + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 2m0s + placement: + constraints: + - node=foo + preferences: + - spread: node.labels.az + endpoint_mode: dnsrr + devices: + - /dev/ttyUSB0:/dev/ttyUSB0 + dns: + - 8.8.8.8 + - 9.9.9.9 + dns_search: + - dc1.example.com + - dc2.example.com + domainname: foo.com + entrypoint: + - /code/entrypoint.sh + - -p + - "3000" + environment: + BAR: bar_from_env_file_2 + BAZ: baz_from_service_def + FOO: foo_from_env_file + QUX: qux_from_environment + env_file: + - ./example1.env + - ./example2.env + expose: + - "3000" + - "8000" + external_links: + - redis_1 + - project_db_1:mysql + - project_db_1:postgresql + extra_hosts: + - somehost:162.242.195.82 + - otherhost:50.31.209.229 + hostname: foo + healthcheck: + test: + - CMD-SHELL + - echo "hello world" + timeout: 1s + interval: 10s + retries: 5 + start_period: 15s + image: redis + ipc: host + labels: + com.example.description: Accounting webapp + com.example.empty-label: "" + com.example.number: "42" + links: + - db + - db:database + - redis + logging: + driver: syslog + options: + syslog-address: tcp://192.168.0.42:123 + mac_address: 02:42:ac:11:65:43 + network_mode: container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b + networks: + other-network: + ipv4_address: 172.16.238.10 + ipv6_address: 2001:3984:3989::10 + other-other-network: null + some-network: + aliases: + - alias1 + - alias3 + pid: host + ports: + - mode: ingress + target: 3000 + protocol: tcp + - mode: ingress + target: 3001 + protocol: tcp + - mode: ingress + target: 3002 + protocol: tcp + - mode: ingress + target: 3003 + protocol: tcp + - mode: ingress + target: 3004 + protocol: tcp + - mode: ingress + target: 3005 + protocol: tcp + - mode: ingress + target: 8000 + published: 8000 + protocol: tcp + - mode: ingress + target: 8080 + published: 9090 + protocol: tcp + - mode: ingress + target: 8081 + published: 9091 + protocol: tcp + - mode: ingress + target: 22 + published: 49100 + protocol: tcp + - mode: ingress + target: 8001 + published: 8001 + protocol: tcp + - mode: ingress + target: 5000 + published: 5000 + protocol: tcp + - mode: ingress + target: 5001 + published: 5001 + protocol: tcp + - mode: ingress + target: 5002 + published: 5002 + protocol: tcp + - mode: ingress + target: 5003 + published: 5003 + protocol: tcp + - mode: ingress + target: 5004 + published: 5004 + protocol: tcp + - mode: ingress + target: 5005 + published: 5005 + protocol: tcp + - mode: ingress + target: 5006 + published: 5006 + protocol: tcp + - mode: ingress + target: 5007 + published: 5007 + protocol: tcp + - mode: ingress + target: 5008 + published: 5008 + protocol: tcp + - mode: ingress + target: 5009 + published: 5009 + protocol: tcp + - mode: ingress + target: 5010 + published: 5010 + protocol: tcp + privileged: true + read_only: true + restart: always + security_opt: + - label=level:s0:c100,c200 + - label=type:svirt_apache_t + stdin_open: true + stop_grace_period: 20s + stop_signal: SIGUSR1 + tmpfs: + - /run + - /tmp + tty: true + ulimits: + nofile: + soft: 20000 + hard: 40000 + nproc: 65535 + user: someone + volumes: + - type: volume + target: /var/lib/mysql + - type: bind + source: /opt/data + target: /var/lib/mysql + - type: bind + source: /foo + target: /code + - type: bind + source: %s + target: /var/www/html + - type: bind + source: /bar/configs + target: /etc/configs/ + read_only: true + - type: volume + source: datavolume + target: /var/lib/mysql + - type: bind + source: %s + target: /opt + consistency: cached + - type: tmpfs + target: /opt + tmpfs: + size: 10000 + working_dir: /code +networks: + external-network: + name: external-network + external: true + other-external-network: + name: my-cool-network + external: true + other-network: + driver: overlay + driver_opts: + baz: "1" + foo: bar + ipam: + driver: overlay + config: + - subnet: 172.16.238.0/24 + - subnet: 2001:3984:3989::/64 + some-network: {} +volumes: + another-volume: + name: user_specified_name + driver: vsphere + driver_opts: + baz: "1" + foo: bar + external-volume: + name: external-volume + external: true + external-volume3: + name: this-is-volume3 + external: true + other-external-volume: + name: my-cool-volume + external: true + other-volume: + driver: flocker + driver_opts: + baz: "1" + foo: bar + some-volume: {} +secrets: {} +configs: {} +`, filepath.Join(workingDir, "static"), filepath.Join(workingDir, "opt")) +} diff --git a/cli/compose/loader/types_test.go b/cli/compose/loader/types_test.go index b324c8e580..75ea835bd7 100644 --- a/cli/compose/loader/types_test.go +++ b/cli/compose/loader/types_test.go @@ -9,314 +9,10 @@ import ( ) func TestMarshallConfig(t *testing.T) { - cfg := fullExampleConfig("/foo", "/bar") - expected := `version: "3.6" -services: - foo: - build: - context: ./dir - dockerfile: Dockerfile - args: - foo: bar - labels: - FOO: BAR - cache_from: - - foo - - bar - network: foo - target: foo - cap_add: - - ALL - cap_drop: - - NET_ADMIN - - SYS_ADMIN - cgroup_parent: m-executor-abcd - command: - - bundle - - exec - - thin - - -p - - "3000" - container_name: my-web-container - depends_on: - - db - - redis - deploy: - mode: replicated - replicas: 6 - labels: - FOO: BAR - update_config: - parallelism: 3 - delay: 10s - failure_action: continue - monitor: 1m0s - max_failure_ratio: 0.3 - order: start-first - resources: - limits: - cpus: "0.001" - memory: "52428800" - reservations: - cpus: "0.0001" - memory: "20971520" - generic_resources: - - discrete_resource_spec: - kind: gpu - value: 2 - - discrete_resource_spec: - kind: ssd - value: 1 - restart_policy: - condition: on-failure - delay: 5s - max_attempts: 3 - window: 2m0s - placement: - constraints: - - node=foo - preferences: - - spread: node.labels.az - endpoint_mode: dnsrr - devices: - - /dev/ttyUSB0:/dev/ttyUSB0 - dns: - - 8.8.8.8 - - 9.9.9.9 - dns_search: - - dc1.example.com - - dc2.example.com - domainname: foo.com - entrypoint: - - /code/entrypoint.sh - - -p - - "3000" - environment: - BAR: bar_from_env_file_2 - BAZ: baz_from_service_def - FOO: foo_from_env_file - QUX: qux_from_environment - env_file: - - ./example1.env - - ./example2.env - expose: - - "3000" - - "8000" - external_links: - - redis_1 - - project_db_1:mysql - - project_db_1:postgresql - extra_hosts: - - somehost:162.242.195.82 - - otherhost:50.31.209.229 - hostname: foo - healthcheck: - test: - - CMD-SHELL - - echo "hello world" - timeout: 1s - interval: 10s - retries: 5 - start_period: 15s - image: redis - ipc: host - labels: - com.example.description: Accounting webapp - com.example.empty-label: "" - com.example.number: "42" - links: - - db - - db:database - - redis - logging: - driver: syslog - options: - syslog-address: tcp://192.168.0.42:123 - mac_address: 02:42:ac:11:65:43 - network_mode: container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b - networks: - other-network: - ipv4_address: 172.16.238.10 - ipv6_address: 2001:3984:3989::10 - other-other-network: null - some-network: - aliases: - - alias1 - - alias3 - pid: host - ports: - - mode: ingress - target: 3000 - protocol: tcp - - mode: ingress - target: 3001 - protocol: tcp - - mode: ingress - target: 3002 - protocol: tcp - - mode: ingress - target: 3003 - protocol: tcp - - mode: ingress - target: 3004 - protocol: tcp - - mode: ingress - target: 3005 - protocol: tcp - - mode: ingress - target: 8000 - published: 8000 - protocol: tcp - - mode: ingress - target: 8080 - published: 9090 - protocol: tcp - - mode: ingress - target: 8081 - published: 9091 - protocol: tcp - - mode: ingress - target: 22 - published: 49100 - protocol: tcp - - mode: ingress - target: 8001 - published: 8001 - protocol: tcp - - mode: ingress - target: 5000 - published: 5000 - protocol: tcp - - mode: ingress - target: 5001 - published: 5001 - protocol: tcp - - mode: ingress - target: 5002 - published: 5002 - protocol: tcp - - mode: ingress - target: 5003 - published: 5003 - protocol: tcp - - mode: ingress - target: 5004 - published: 5004 - protocol: tcp - - mode: ingress - target: 5005 - published: 5005 - protocol: tcp - - mode: ingress - target: 5006 - published: 5006 - protocol: tcp - - mode: ingress - target: 5007 - published: 5007 - protocol: tcp - - mode: ingress - target: 5008 - published: 5008 - protocol: tcp - - mode: ingress - target: 5009 - published: 5009 - protocol: tcp - - mode: ingress - target: 5010 - published: 5010 - protocol: tcp - privileged: true - read_only: true - restart: always - security_opt: - - label=level:s0:c100,c200 - - label=type:svirt_apache_t - stdin_open: true - stop_grace_period: 20s - stop_signal: SIGUSR1 - tmpfs: - - /run - - /tmp - tty: true - ulimits: - nofile: - soft: 20000 - hard: 40000 - nproc: 65535 - user: someone - volumes: - - type: volume - target: /var/lib/mysql - - type: bind - source: /opt/data - target: /var/lib/mysql - - type: bind - source: /foo - target: /code - - type: bind - source: /foo/static - target: /var/www/html - - type: bind - source: /bar/configs - target: /etc/configs/ - read_only: true - - type: volume - source: datavolume - target: /var/lib/mysql - - type: bind - source: /foo/opt - target: /opt - consistency: cached - - type: tmpfs - target: /opt - tmpfs: - size: 10000 - working_dir: /code -networks: - external-network: - name: external-network - external: true - other-external-network: - name: my-cool-network - external: true - other-network: - driver: overlay - driver_opts: - baz: "1" - foo: bar - ipam: - driver: overlay - config: - - subnet: 172.16.238.0/24 - - subnet: 2001:3984:3989::/64 - some-network: {} -volumes: - another-volume: - name: user_specified_name - driver: vsphere - driver_opts: - baz: "1" - foo: bar - external-volume: - name: external-volume - external: true - external-volume3: - name: this-is-volume3 - external: true - other-external-volume: - name: my-cool-volume - external: true - other-volume: - driver: flocker - driver_opts: - baz: "1" - foo: bar - some-volume: {} -secrets: {} -configs: {} -` + workingDir := "/foo" + homeDir := "/bar" + cfg := fullExampleConfig(workingDir, homeDir) + expected := fullExampleYAML(workingDir) actual, err := yaml.Marshal(cfg) assert.NilError(t, err) diff --git a/cli/registry/client/fetcher.go b/cli/registry/client/fetcher.go index 1e748f255d..796bc01eb1 100644 --- a/cli/registry/client/fetcher.go +++ b/cli/registry/client/fetcher.go @@ -155,7 +155,7 @@ func pullManifestList(ctx context.Context, ref reference.Named, repo distributio } v, ok := manifest.(*schema2.DeserializedManifest) if !ok { - return nil, fmt.Errorf("unsupported manifest format: %s", v) + return nil, fmt.Errorf("unsupported manifest format: %v", v) } manifestRef, err := reference.WithDigest(ref, manifestDescriptor.Digest) diff --git a/scripts/validate/shellcheck b/scripts/validate/shellcheck index 8b0df25b73..63cedf137b 100755 --- a/scripts/validate/shellcheck +++ b/scripts/validate/shellcheck @@ -1,5 +1,5 @@ -#!/usr/bin/env bash -set -eo pipefail - -shellcheck contrib/completion/bash/docker -find scripts/ -type f | grep -v scripts/winresources | grep -v '*.ps1' | xargs shellcheck +#!/usr/bin/env bash +set -eo pipefail + +shellcheck contrib/completion/bash/docker +find scripts/ -type f | grep -v scripts/winresources | grep -v '.*.ps1' | xargs shellcheck