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