mirror of https://github.com/docker/cli.git
Merge pull request #905 from vdemeester/appveyor-setup
Add appveyor setup to build and unit test
This commit is contained in:
commit
310127a7d0
|
@ -0,0 +1,23 @@
|
||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
clone_folder: c:\gopath\src\github.com\docker\cli
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
GOVERSION: 1.10
|
||||||
|
DEPVERSION: v0.4.1
|
||||||
|
|
||||||
|
install:
|
||||||
|
- rmdir c:\go /s /q
|
||||||
|
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
|
||||||
|
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
|
||||||
|
deploy: false
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- ps: .\scripts\make.ps1 -Binary
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- ps: .\scripts\make.ps1 -TestUnit
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
cliconfig "github.com/docker/cli/cli/config"
|
cliconfig "github.com/docker/cli/cli/config"
|
||||||
|
@ -20,6 +21,9 @@ import (
|
||||||
|
|
||||||
func TestNewAPIClientFromFlags(t *testing.T) {
|
func TestNewAPIClientFromFlags(t *testing.T) {
|
||||||
host := "unix://path"
|
host := "unix://path"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
host = "npipe://./"
|
||||||
|
}
|
||||||
opts := &flags.CommonOptions{Hosts: []string{host}}
|
opts := &flags.CommonOptions{Hosts: []string{host}}
|
||||||
configFile := &configfile.ConfigFile{
|
configFile := &configfile.ConfigFile{
|
||||||
HTTPHeaders: map[string]string{
|
HTTPHeaders: map[string]string{
|
||||||
|
|
|
@ -121,7 +121,12 @@ func TestRunCopyToContainerFromFileWithTrailingSlash(t *testing.T) {
|
||||||
}
|
}
|
||||||
cli := test.NewFakeCli(&fakeClient{})
|
cli := test.NewFakeCli(&fakeClient{})
|
||||||
err := runCopy(cli, options)
|
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) {
|
func TestRunCopyToContainerSourceDoesNotExist(t *testing.T) {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package formatter
|
package formatter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
|
@ -51,6 +50,7 @@ func TestHistoryContext_ID(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHistoryContext_CreatedSince(t *testing.T) {
|
func TestHistoryContext_CreatedSince(t *testing.T) {
|
||||||
|
dateStr := "2009-11-10T23:00:00Z"
|
||||||
var ctx historyContext
|
var ctx historyContext
|
||||||
cases := []historyCase{
|
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()},
|
h: image.HistoryResponseItem{Created: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()},
|
||||||
trunc: false,
|
trunc: false,
|
||||||
human: 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"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
"syscall"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
|
@ -18,45 +16,9 @@ import (
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||||
"github.com/gotestyourself/gotestyourself/fs"
|
"github.com/gotestyourself/gotestyourself/fs"
|
||||||
"github.com/gotestyourself/gotestyourself/skip"
|
|
||||||
"golang.org/x/net/context"
|
"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) {
|
func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) {
|
||||||
dest, err := ioutil.TempDir("", "test-build-compress-dest")
|
dest, err := ioutil.TempDir("", "test-build-compress-dest")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
|
@ -14,7 +15,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateErrors(t *testing.T) {
|
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 {
|
testCases := []struct {
|
||||||
args []string
|
args []string
|
||||||
expectedError string
|
expectedError string
|
||||||
|
@ -29,7 +33,7 @@ func TestCreateErrors(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
args: []string{"plugin-foo", "nonexistent_context_dir"},
|
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 := newCreateCommand(cli)
|
||||||
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
|
cmd.SetArgs([]string{"plugin-foo", tmpDir.Path()})
|
||||||
cmd.SetOutput(ioutil.Discard)
|
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) {
|
func TestCreateErrorOnInvalidConfig(t *testing.T) {
|
||||||
|
|
|
@ -33,10 +33,13 @@ func TestValidateExternalNetworks(t *testing.T) {
|
||||||
inspectError: errors.New("Unexpected"),
|
inspectError: errors.New("Unexpected"),
|
||||||
expectedMsg: "Unexpected",
|
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",
|
{
|
||||||
},
|
inspectError: errors.New("host net does not exist on swarm classic"),
|
||||||
|
network: "host",
|
||||||
|
},
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
network: "user",
|
network: "user",
|
||||||
expectedMsg: "is not in the right scope",
|
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))
|
assert.NilError(t, ioutil.WriteFile(filepath.Join(pubKeyCWD, "a.pub"), []byte("abc"), notary.PrivExecPerms))
|
||||||
err = validateKeyArgs("a", pubKeyCWD)
|
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/")
|
err = validateKeyArgs("a", "/random/dir/")
|
||||||
assert.Error(t, err, "public key path does not exist: \"/random/dir/\"")
|
assert.Error(t, err, "public key path does not exist: \"/random/dir/\"")
|
||||||
|
|
|
@ -6,12 +6,14 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||||
|
"github.com/gotestyourself/gotestyourself/skip"
|
||||||
"github.com/theupdateframework/notary"
|
"github.com/theupdateframework/notary"
|
||||||
"github.com/theupdateframework/notary/passphrase"
|
"github.com/theupdateframework/notary/passphrase"
|
||||||
"github.com/theupdateframework/notary/storage"
|
"github.com/theupdateframework/notary/storage"
|
||||||
|
@ -20,6 +22,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTrustKeyLoadErrors(t *testing.T) {
|
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 {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
|
@ -40,7 +46,7 @@ func TestTrustKeyLoadErrors(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "not-a-key",
|
name: "not-a-key",
|
||||||
args: []string{"iamnotakey"},
|
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",
|
expectedOutput: "Loading key from \"iamnotakey\"...\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -109,6 +115,7 @@ var testKeys = map[string][]byte{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadKeyFromPath(t *testing.T) {
|
func TestLoadKeyFromPath(t *testing.T) {
|
||||||
|
skip.If(t, runtime.GOOS == "windows")
|
||||||
for keyID, keyBytes := range testKeys {
|
for keyID, keyBytes := range testKeys {
|
||||||
t.Run(fmt.Sprintf("load-key-id-%s-from-path", keyID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("load-key-id-%s-from-path", keyID), func(t *testing.T) {
|
||||||
testLoadKeyFromPath(t, keyID, keyBytes)
|
testLoadKeyFromPath(t, keyID, keyBytes)
|
||||||
|
@ -163,6 +170,7 @@ func testLoadKeyFromPath(t *testing.T, privKeyID string, privKeyFixture []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadKeyTooPermissive(t *testing.T) {
|
func TestLoadKeyTooPermissive(t *testing.T) {
|
||||||
|
skip.If(t, runtime.GOOS == "windows")
|
||||||
for keyID, keyBytes := range testKeys {
|
for keyID, keyBytes := range testKeys {
|
||||||
t.Run(fmt.Sprintf("load-key-id-%s-too-permissive", keyID), func(t *testing.T) {
|
t.Run(fmt.Sprintf("load-key-id-%s-too-permissive", keyID), func(t *testing.T) {
|
||||||
testLoadKeyTooPermissive(t, keyBytes)
|
testLoadKeyTooPermissive(t, keyBytes)
|
||||||
|
@ -219,6 +227,7 @@ H3nzy2O6Q/ct4BjOBKa+WCdRtPo78bA+C/7t81ADQO8Jqaj59W50rwoqDQ==
|
||||||
-----END PUBLIC KEY-----`)
|
-----END PUBLIC KEY-----`)
|
||||||
|
|
||||||
func TestLoadPubKeyFailure(t *testing.T) {
|
func TestLoadPubKeyFailure(t *testing.T) {
|
||||||
|
skip.If(t, runtime.GOOS == "windows")
|
||||||
pubKeyDir, err := ioutil.TempDir("", "key-load-test-pubkey-")
|
pubKeyDir, err := ioutil.TempDir("", "key-load-test-pubkey-")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
defer os.RemoveAll(pubKeyDir)
|
defer os.RemoveAll(pubKeyDir)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"github.com/docker/cli/cli/config"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
"github.com/gotestyourself/gotestyourself/assert"
|
"github.com/gotestyourself/gotestyourself/assert"
|
||||||
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
is "github.com/gotestyourself/gotestyourself/assert/cmp"
|
||||||
|
"github.com/gotestyourself/gotestyourself/skip"
|
||||||
"github.com/theupdateframework/notary"
|
"github.com/theupdateframework/notary"
|
||||||
"github.com/theupdateframework/notary/client"
|
"github.com/theupdateframework/notary/client"
|
||||||
"github.com/theupdateframework/notary/client/changelist"
|
"github.com/theupdateframework/notary/client/changelist"
|
||||||
|
@ -127,6 +129,7 @@ func TestGetOrGenerateNotaryKey(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddStageSigners(t *testing.T) {
|
func TestAddStageSigners(t *testing.T) {
|
||||||
|
skip.If(t, runtime.GOOS == "windows", "FIXME: not supported currently")
|
||||||
tmpDir, err := ioutil.TempDir("", "notary-test-")
|
tmpDir, err := ioutil.TempDir("", "notary-test-")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/config"
|
"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.SetArgs([]string{"--key", "/path/to/key.pem", "alice", "alpine"})
|
||||||
|
|
||||||
cmd.SetOutput(ioutil.Discard)
|
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) {
|
func TestSignerAddCommandInvalidRepoName(t *testing.T) {
|
||||||
|
@ -127,7 +132,11 @@ func TestSignerAddCommandInvalidRepoName(t *testing.T) {
|
||||||
func TestIngestPublicKeys(t *testing.T) {
|
func TestIngestPublicKeys(t *testing.T) {
|
||||||
// Call with a bad path
|
// Call with a bad path
|
||||||
_, err := ingestPublicKeys([]string{"foo", "bar"})
|
_, 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
|
// Call with real file path
|
||||||
tmpfile, err := ioutil.TempFile("", "pemfile")
|
tmpfile, err := ioutil.TempFile("", "pemfile")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package loader
|
package loader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/compose/types"
|
"github.com/docker/cli/cli/compose/types"
|
||||||
|
@ -313,10 +315,10 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
|
||||||
{Target: "/var/lib/mysql", Type: "volume"},
|
{Target: "/var/lib/mysql", Type: "volume"},
|
||||||
{Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"},
|
{Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"},
|
||||||
{Source: workingDir, Target: "/code", 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: homeDir + "/configs", Target: "/etc/configs/", Type: "bind", ReadOnly: true},
|
||||||
{Source: "datavolume", Target: "/var/lib/mysql", Type: "volume"},
|
{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{
|
{Target: "/opt", Type: "tmpfs", Tmpfs: &types.ServiceVolumeTmpfs{
|
||||||
Size: int64(10000),
|
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) {
|
func TestMarshallConfig(t *testing.T) {
|
||||||
cfg := fullExampleConfig("/foo", "/bar")
|
workingDir := "/foo"
|
||||||
expected := `version: "3.6"
|
homeDir := "/bar"
|
||||||
services:
|
cfg := fullExampleConfig(workingDir, homeDir)
|
||||||
foo:
|
expected := fullExampleYAML(workingDir)
|
||||||
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: {}
|
|
||||||
`
|
|
||||||
|
|
||||||
actual, err := yaml.Marshal(cfg)
|
actual, err := yaml.Marshal(cfg)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
|
@ -155,7 +155,7 @@ func pullManifestList(ctx context.Context, ref reference.Named, repo distributio
|
||||||
}
|
}
|
||||||
v, ok := manifest.(*schema2.DeserializedManifest)
|
v, ok := manifest.(*schema2.DeserializedManifest)
|
||||||
if !ok {
|
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)
|
manifestRef, err := reference.WithDigest(ref, manifestDescriptor.Digest)
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
<#
|
||||||
|
.NOTES
|
||||||
|
Summary: Windows native build script.
|
||||||
|
|
||||||
|
It does however provided the minimum necessary to support parts of local Windows
|
||||||
|
development and Windows to Windows CI.
|
||||||
|
|
||||||
|
Usage Examples (run from repo root):
|
||||||
|
"scripts/make.ps1 -Client" to build docker.exe client 64-bit binary (remote repo)
|
||||||
|
"scripts/make.ps1 -TestUnit" to run unit tests
|
||||||
|
"scripts/make.ps1 -Daemon -TestUnit" to build the daemon and run unit tests
|
||||||
|
"scripts/make.ps1 -All" to run everything this script knows about that can run in a container
|
||||||
|
"scripts/make.ps1" to build the daemon binary (same as -Daemon)
|
||||||
|
"scripts/make.ps1 -Binary" shortcut to -Client and -Daemon
|
||||||
|
|
||||||
|
.PARAMETER Binary
|
||||||
|
Builds the client and daemon binaries. A convenient shortcut to `make.ps1 -Client -Daemon`.
|
||||||
|
|
||||||
|
.PARAMETER Race
|
||||||
|
Use -race in go build and go test.
|
||||||
|
|
||||||
|
.PARAMETER Noisy
|
||||||
|
Use -v in go build.
|
||||||
|
|
||||||
|
.PARAMETER ForceBuildAll
|
||||||
|
Use -a in go build.
|
||||||
|
|
||||||
|
.PARAMETER NoOpt
|
||||||
|
Use -gcflags -N -l in go build to disable optimisation (can aide debugging).
|
||||||
|
|
||||||
|
.PARAMETER CommitSuffix
|
||||||
|
Adds a custom string to be appended to the commit ID (spaces are stripped).
|
||||||
|
|
||||||
|
.PARAMETER TestUnit
|
||||||
|
Runs unit tests.
|
||||||
|
|
||||||
|
.PARAMETER All
|
||||||
|
Runs everything this script knows about that can run in a container.
|
||||||
|
|
||||||
|
|
||||||
|
TODO
|
||||||
|
- Unify the head commit
|
||||||
|
- Add golint and other checks (swagger maybe?)
|
||||||
|
|
||||||
|
#>
|
||||||
|
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$False)][switch]$Binary,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$Race,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$Noisy,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$ForceBuildAll,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$NoOpt,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$TestUnit,
|
||||||
|
[Parameter(Mandatory=$False)][switch]$All
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$ProgressPreference = "SilentlyContinue"
|
||||||
|
$pushed=$False # To restore the directory if we have temporarily pushed to one.
|
||||||
|
|
||||||
|
# Build a binary (client or daemon)
|
||||||
|
Function Execute-Build($additionalBuildTags, $directory) {
|
||||||
|
# Generate the build flags
|
||||||
|
$buildTags = "autogen"
|
||||||
|
if ($Noisy) { $verboseParm=" -v" }
|
||||||
|
if ($Race) { Write-Warning "Using race detector"; $raceParm=" -race"}
|
||||||
|
if ($ForceBuildAll) { $allParm=" -a" }
|
||||||
|
if ($NoOpt) { $optParm=" -gcflags "+""""+"-N -l"+"""" }
|
||||||
|
if ($additionalBuildTags -ne "") { $buildTags += $(" " + $additionalBuildTags) }
|
||||||
|
|
||||||
|
# Do the go build in the appropriate directory
|
||||||
|
# Note -linkmode=internal is required to be able to debug on Windows.
|
||||||
|
# https://github.com/golang/go/issues/14319#issuecomment-189576638
|
||||||
|
Write-Host "INFO: Building..."
|
||||||
|
Push-Location $root\cmd\$directory; $global:pushed=$True
|
||||||
|
$buildCommand = "go build" + `
|
||||||
|
$raceParm + `
|
||||||
|
$verboseParm + `
|
||||||
|
$allParm + `
|
||||||
|
$optParm + `
|
||||||
|
" -tags """ + $buildTags + """" + `
|
||||||
|
" -ldflags """ + "-linkmode=internal" + """" + `
|
||||||
|
" -o $root\build\"+$directory+".exe"
|
||||||
|
Invoke-Expression $buildCommand
|
||||||
|
if ($LASTEXITCODE -ne 0) { Throw "Failed to compile" }
|
||||||
|
Pop-Location; $global:pushed=$False
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the unit tests
|
||||||
|
Function Run-UnitTests() {
|
||||||
|
Write-Host "INFO: Running unit tests..."
|
||||||
|
$testPath="./..."
|
||||||
|
$goListCommand = "go list -e -f '{{if ne .Name """ + '\"github.com/docker/cli\"' + """}}{{.ImportPath}}{{end}}' $testPath"
|
||||||
|
$pkgList = $(Invoke-Expression $goListCommand)
|
||||||
|
if ($LASTEXITCODE -ne 0) { Throw "go list for unit tests failed" }
|
||||||
|
$pkgList = $pkgList | Select-String -Pattern "github.com/docker/cli"
|
||||||
|
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/vendor"
|
||||||
|
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/man"
|
||||||
|
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/e2e"
|
||||||
|
$pkgList = $pkgList -replace "`r`n", " "
|
||||||
|
$goTestCommand = "go test" + $raceParm + " -cover -ldflags -w -tags """ + "autogen" + """ -a """ + "-test.timeout=10m" + """ $pkgList"
|
||||||
|
Invoke-Expression $goTestCommand
|
||||||
|
if ($LASTEXITCODE -ne 0) { Throw "Unit tests failed" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start of main code.
|
||||||
|
Try {
|
||||||
|
Write-Host -ForegroundColor Cyan "INFO: make.ps1 starting at $(Get-Date)"
|
||||||
|
|
||||||
|
# Get to the root of the repo
|
||||||
|
$root = $(Split-Path $MyInvocation.MyCommand.Definition -Parent | Split-Path -Parent)
|
||||||
|
Push-Location $root
|
||||||
|
|
||||||
|
# Handle the "-All" shortcut to turn on all things we can handle.
|
||||||
|
# Note we expressly only include the items which can run in a container - the validations tests cannot
|
||||||
|
# as they require the .git directory which is excluded from the image by .dockerignore
|
||||||
|
if ($All) { $Client=$True; $TestUnit=$True }
|
||||||
|
|
||||||
|
# Handle the "-Binary" shortcut to build both client and daemon.
|
||||||
|
if ($Binary) { $Client = $True; }
|
||||||
|
|
||||||
|
# Verify git is installed
|
||||||
|
if ($(Get-Command git -ErrorAction SilentlyContinue) -eq $nil) { Throw "Git does not appear to be installed" }
|
||||||
|
|
||||||
|
# Verify go is installed
|
||||||
|
if ($(Get-Command go -ErrorAction SilentlyContinue) -eq $nil) { Throw "GoLang does not appear to be installed" }
|
||||||
|
|
||||||
|
# Build the binaries
|
||||||
|
if ($Client) {
|
||||||
|
# Create the build directory if it doesn't exist
|
||||||
|
if (-not (Test-Path ".\build")) { New-Item ".\build" -ItemType Directory | Out-Null }
|
||||||
|
|
||||||
|
# Perform the actual build
|
||||||
|
Execute-Build "" "docker"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run unit tests
|
||||||
|
if ($TestUnit) { Run-UnitTests }
|
||||||
|
|
||||||
|
# Gratuitous ASCII art.
|
||||||
|
if ($Client) {
|
||||||
|
Write-Host
|
||||||
|
Write-Host -ForegroundColor Green " ________ ____ __."
|
||||||
|
Write-Host -ForegroundColor Green " \_____ \ `| `|/ _`|"
|
||||||
|
Write-Host -ForegroundColor Green " / `| \`| `<"
|
||||||
|
Write-Host -ForegroundColor Green " / `| \ `| \"
|
||||||
|
Write-Host -ForegroundColor Green " \_______ /____`|__ \"
|
||||||
|
Write-Host -ForegroundColor Green " \/ \/"
|
||||||
|
Write-Host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Catch [Exception] {
|
||||||
|
Write-Host -ForegroundColor Red ("`nERROR: make.ps1 failed:`n$_")
|
||||||
|
|
||||||
|
# More gratuitous ASCII art.
|
||||||
|
Write-Host
|
||||||
|
Write-Host -ForegroundColor Red "___________ .__.__ .___"
|
||||||
|
Write-Host -ForegroundColor Red "\_ _____/____ `|__`| `| ____ __`| _/"
|
||||||
|
Write-Host -ForegroundColor Red " `| __) \__ \ `| `| `| _/ __ \ / __ `| "
|
||||||
|
Write-Host -ForegroundColor Red " `| \ / __ \`| `| `|_\ ___// /_/ `| "
|
||||||
|
Write-Host -ForegroundColor Red " \___ / (____ /__`|____/\___ `>____ `| "
|
||||||
|
Write-Host -ForegroundColor Red " \/ \/ \/ \/ "
|
||||||
|
Write-Host
|
||||||
|
|
||||||
|
Throw $_
|
||||||
|
}
|
||||||
|
Finally {
|
||||||
|
Pop-Location # As we pushed to the root of the repo as the very first thing
|
||||||
|
if ($global:pushed) { Pop-Location }
|
||||||
|
Write-Host -ForegroundColor Cyan "INFO: make.ps1 ended at $(Get-Date)"
|
||||||
|
}
|
|
@ -2,4 +2,4 @@
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
shellcheck contrib/completion/bash/docker
|
shellcheck contrib/completion/bash/docker
|
||||||
find scripts/ -type f | grep -v scripts/winresources | xargs shellcheck
|
find scripts/ -type f | grep -v scripts/winresources | grep -v '.*.ps1' | xargs shellcheck
|
||||||
|
|
Loading…
Reference in New Issue