diff --git a/cli/command/formatter/history_test.go b/cli/command/formatter/history_test.go index dcbdc027da7b..fb2758bd66c3 100644 --- a/cli/command/formatter/history_test.go +++ b/cli/command/formatter/history_test.go @@ -1,13 +1,13 @@ package formatter import ( + "bytes" + "runtime" "strconv" "strings" "testing" "time" - "bytes" - "github.com/docker/docker/api/types/image" "github.com/docker/docker/pkg/stringid" "github.com/stretchr/testify/assert" @@ -50,6 +50,10 @@ func TestHistoryContext_ID(t *testing.T) { } func TestHistoryContext_CreatedSince(t *testing.T) { + dateStr := "2009-11-10T23:00:00Z" + if runtime.GOOS == "windows" { + dateStr = "2009-11-11T00:00:00+01:00" + } var ctx historyContext cases := []historyCase{ { @@ -64,7 +68,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 000000000000..8c0a05a6b8a2 --- /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/fs" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "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.NoError(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) + require.NoError(t, err) + + files, err := ioutil.ReadDir(dest.Path()) + require.NoError(t, err) + for _, fileInfo := range files { + assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid) + assert.Equal(t, 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 2b672fdc1d46..7566f8869e5d 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" @@ -16,47 +14,11 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/archive" "github.com/gotestyourself/gotestyourself/fs" - "github.com/gotestyourself/gotestyourself/skip" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "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.NoError(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) - require.NoError(t, err) - - files, err := ioutil.ReadDir(dest.Path()) - require.NoError(t, err) - for _, fileInfo := range files { - assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid) - assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid) - } -} func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) { dest, err := ioutil.TempDir("", "test-build-compress-dest") require.NoError(t, err) diff --git a/cli/command/plugin/create_test.go b/cli/command/plugin/create_test.go index 739e4197eb51..a72a8fd69a21 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,11 @@ func TestCreateErrorOnContextDirWithoutConfig(t *testing.T) { cmd := newCreateCommand(cli) cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()}) cmd.SetOutput(ioutil.Discard) - testutil.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." + } + testutil.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 7f3133148ca7..23e9474fe4b7 100644 --- a/cli/command/stack/swarm/deploy_composefile_test.go +++ b/cli/command/stack/swarm/deploy_composefile_test.go @@ -35,6 +35,7 @@ func TestValidateExternalNetworks(t *testing.T) { expectedMsg: "Unexpected", }, { + // 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", }, diff --git a/cli/command/trust/key_generate_test.go b/cli/command/trust/key_generate_test.go index faf6f3187388..1bf147317f25 100644 --- a/cli/command/trust/key_generate_test.go +++ b/cli/command/trust/key_generate_test.go @@ -130,7 +130,7 @@ func TestValidateKeyArgs(t *testing.T) { assert.NoError(t, ioutil.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms)) err = validateKeyArgs("a", pubKeyCWD) assert.Error(t, err) - assert.Equal(t, err.Error(), fmt.Sprintf("public key file already exists: \"%s/a.pub\"", pubKeyCWD)) + assert.Equal(t, err.Error(), fmt.Sprintf("public key file already exists: \"%s\"", filepath.Join(pubKeyCWD, "a.pub"))) err = validateKeyArgs("a", "/random/dir/") assert.Error(t, err) diff --git a/cli/command/trust/key_load_test.go b/cli/command/trust/key_load_test.go index 5902b366670c..d0f90decd9c1 100644 --- a/cli/command/trust/key_load_test.go +++ b/cli/command/trust/key_load_test.go @@ -6,11 +6,13 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "testing" "github.com/docker/cli/cli/config" "github.com/docker/cli/internal/test" "github.com/docker/cli/internal/test/testutil" + "github.com/gotestyourself/gotestyourself/skip" "github.com/stretchr/testify/assert" "github.com/theupdateframework/notary" "github.com/theupdateframework/notary/passphrase" @@ -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, func() bool { return 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, func() bool { return 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, func() bool { return runtime.GOOS == "windows" }) pubKeyDir, err := ioutil.TempDir("", "key-load-test-pubkey-") assert.NoError(t, err) defer os.RemoveAll(pubKeyDir) diff --git a/cli/command/trust/signer_add_test.go b/cli/command/trust/signer_add_test.go index a27f161cb792..6d7057b4d6ef 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.EqualError(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.EqualError(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.EqualError(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.EqualError(t, err, expectedError) // Call with real file path tmpfile, err := ioutil.TempFile("", "pemfile") assert.NoError(t, err) diff --git a/cli/compose/loader/full-struct_test.go b/cli/compose/loader/full-struct_test.go index 3f2a587bcedd..5ae0fc065693 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, homeDir string) string { + return fmt.Sprintf(string(`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 f27539f88f33..ae226997a7de 100644 --- a/cli/compose/loader/types_test.go +++ b/cli/compose/loader/types_test.go @@ -8,314 +8,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, homeDir) actual, err := yaml.Marshal(cfg) assert.NoError(t, err)