mirror of https://github.com/docker/cli.git
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 <vincent@sbr.pm>
This commit is contained in:
parent
facb22573d
commit
0cf2e6353a
|
@ -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{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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/\"")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue