Merge component 'engine' from git@github.com:docker/engine master
This commit is contained in:
@ -5922,7 +5922,7 @@ paths:
|
||||
headers:
|
||||
X-Docker-Container-Path-Stat:
|
||||
type: "string"
|
||||
description: "TODO"
|
||||
description: "A base64 - encoded JSON object with some filesystem header information about the path"
|
||||
400:
|
||||
description: "Bad parameter"
|
||||
schema:
|
||||
@ -7589,6 +7589,7 @@ paths:
|
||||
schema:
|
||||
type: "object"
|
||||
title: "VolumeListResponse"
|
||||
description: "Volume list response"
|
||||
required: [Volumes, Warnings]
|
||||
properties:
|
||||
Volumes:
|
||||
@ -7665,6 +7666,8 @@ paths:
|
||||
description: "Volume configuration"
|
||||
schema:
|
||||
type: "object"
|
||||
description: "Volume configuration"
|
||||
title: "VolumeConfig"
|
||||
properties:
|
||||
Name:
|
||||
description: "The new volume's name. If not specified, Docker generates a name."
|
||||
|
||||
@ -8,10 +8,8 @@ package {{ .Package }}
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
|
||||
{{ range .DefaultImports }}{{ printf "%q" . }}
|
||||
{{ end }}
|
||||
{{ range $key, $value := .Imports }}{{ $key }} {{ printf "%q" $value }}
|
||||
|
||||
@ -7,7 +7,7 @@ package volume
|
||||
// See hack/generate-swagger-api.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// VolumeCreateBody
|
||||
// VolumeCreateBody Volume configuration
|
||||
// swagger:model VolumeCreateBody
|
||||
type VolumeCreateBody struct {
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ package volume
|
||||
|
||||
import "github.com/docker/docker/api/types"
|
||||
|
||||
// VolumeListOKBody
|
||||
// VolumeListOKBody Volume list response
|
||||
// swagger:model VolumeListOKBody
|
||||
type VolumeListOKBody struct {
|
||||
|
||||
|
||||
@ -274,11 +274,17 @@ func (d *dispatchRequest) getImageOrStage(name string, platform *specs.Platform)
|
||||
}
|
||||
return imageMount.Image(), nil
|
||||
}
|
||||
func (d *dispatchRequest) getFromImage(shlex *shell.Lex, name string, platform *specs.Platform) (builder.Image, error) {
|
||||
name, err := d.getExpandedString(shlex, name)
|
||||
func (d *dispatchRequest) getFromImage(shlex *shell.Lex, basename string, platform *specs.Platform) (builder.Image, error) {
|
||||
name, err := d.getExpandedString(shlex, basename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Empty string is interpreted to FROM scratch by images.GetImageAndReleasableLayer,
|
||||
// so validate expanded result is not empty.
|
||||
if name == "" {
|
||||
return nil, errors.Errorf("base name (%s) should not be blank", basename)
|
||||
}
|
||||
|
||||
return d.getImageOrStage(name, platform)
|
||||
}
|
||||
|
||||
|
||||
@ -157,6 +157,22 @@ func TestFromWithArg(t *testing.T) {
|
||||
assert.Check(t, is.Len(sb.state.buildArgs.GetAllMeta(), 1))
|
||||
}
|
||||
|
||||
func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
|
||||
b := newBuilderWithMockBackend()
|
||||
args := NewBuildArgs(make(map[string]*string))
|
||||
|
||||
metaArg := instructions.ArgCommand{}
|
||||
cmd := &instructions.Stage{
|
||||
BaseName: "${THETAG}",
|
||||
}
|
||||
err := processMetaArg(metaArg, shell.NewLex('\\'), args)
|
||||
|
||||
sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
|
||||
assert.NilError(t, err)
|
||||
err = initializeStage(sb, cmd)
|
||||
assert.Error(t, err, "base name (${THETAG}) should not be blank")
|
||||
}
|
||||
|
||||
func TestFromWithUndefinedArg(t *testing.T) {
|
||||
tag, expected := "sometag", "expectedthisid"
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
package client // import "github.com/docker/docker/client"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// BuildCancel requests the daemon to cancel ongoing build request
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
@ -12,7 +13,6 @@ import (
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/net/context"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
|
||||
@ -25,70 +25,9 @@ import (
|
||||
|
||||
// SystemInfo returns information about the host server the daemon is running on.
|
||||
func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
||||
kernelVersion := "<unknown>"
|
||||
if kv, err := kernel.GetKernelVersion(); err != nil {
|
||||
logrus.Warnf("Could not get kernel version: %v", err)
|
||||
} else {
|
||||
kernelVersion = kv.String()
|
||||
}
|
||||
|
||||
operatingSystem := "<unknown>"
|
||||
if s, err := operatingsystem.GetOperatingSystem(); err != nil {
|
||||
logrus.Warnf("Could not get operating system name: %v", err)
|
||||
} else {
|
||||
operatingSystem = s
|
||||
}
|
||||
|
||||
// Don't do containerized check on Windows
|
||||
if runtime.GOOS != "windows" {
|
||||
if inContainer, err := operatingsystem.IsContainerized(); err != nil {
|
||||
logrus.Errorf("Could not determine if daemon is containerized: %v", err)
|
||||
operatingSystem += " (error determining if containerized)"
|
||||
} else if inContainer {
|
||||
operatingSystem += " (containerized)"
|
||||
}
|
||||
}
|
||||
|
||||
meminfo, err := system.ReadMemInfo()
|
||||
if err != nil {
|
||||
logrus.Errorf("Could not read system memory info: %v", err)
|
||||
meminfo = &system.MemInfo{}
|
||||
}
|
||||
|
||||
sysInfo := sysinfo.New(true)
|
||||
cRunning, cPaused, cStopped := stateCtr.get()
|
||||
|
||||
securityOptions := []string{}
|
||||
if sysInfo.AppArmor {
|
||||
securityOptions = append(securityOptions, "name=apparmor")
|
||||
}
|
||||
if sysInfo.Seccomp && supportsSeccomp {
|
||||
profile := daemon.seccompProfilePath
|
||||
if profile == "" {
|
||||
profile = "default"
|
||||
}
|
||||
securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
|
||||
}
|
||||
if selinuxEnabled() {
|
||||
securityOptions = append(securityOptions, "name=selinux")
|
||||
}
|
||||
rootIDs := daemon.idMappings.RootPair()
|
||||
if rootIDs.UID != 0 || rootIDs.GID != 0 {
|
||||
securityOptions = append(securityOptions, "name=userns")
|
||||
}
|
||||
|
||||
var ds [][2]string
|
||||
drivers := ""
|
||||
statuses := daemon.imageService.LayerStoreStatus()
|
||||
for os, gd := range daemon.graphDrivers {
|
||||
ds = append(ds, statuses[os]...)
|
||||
drivers += gd
|
||||
if len(daemon.graphDrivers) > 1 {
|
||||
drivers += fmt.Sprintf(" (%s) ", os)
|
||||
}
|
||||
}
|
||||
drivers = strings.TrimSpace(drivers)
|
||||
|
||||
v := &types.Info{
|
||||
ID: daemon.ID,
|
||||
Containers: cRunning + cPaused + cStopped,
|
||||
@ -96,27 +35,25 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
||||
ContainersPaused: cPaused,
|
||||
ContainersStopped: cStopped,
|
||||
Images: daemon.imageService.CountImages(),
|
||||
Driver: drivers,
|
||||
DriverStatus: ds,
|
||||
Plugins: daemon.showPluginsInfo(),
|
||||
IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled,
|
||||
BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled,
|
||||
BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled,
|
||||
Debug: debug.IsEnabled(),
|
||||
Name: hostName(),
|
||||
NFd: fileutils.GetTotalUsedFds(),
|
||||
NGoroutines: runtime.NumGoroutine(),
|
||||
SystemTime: time.Now().Format(time.RFC3339Nano),
|
||||
LoggingDriver: daemon.defaultLogConfig.Type,
|
||||
CgroupDriver: daemon.getCgroupDriver(),
|
||||
NEventsListener: daemon.EventsService.SubscribersCount(),
|
||||
KernelVersion: kernelVersion,
|
||||
OperatingSystem: operatingSystem,
|
||||
KernelVersion: kernelVersion(),
|
||||
OperatingSystem: operatingSystem(),
|
||||
IndexServerAddress: registry.IndexServer,
|
||||
OSType: platform.OSType,
|
||||
Architecture: platform.Architecture,
|
||||
RegistryConfig: daemon.RegistryService.ServiceConfig(),
|
||||
NCPU: sysinfo.NumCPU(),
|
||||
MemTotal: meminfo.MemTotal,
|
||||
MemTotal: memInfo().MemTotal,
|
||||
GenericResources: daemon.genericResources,
|
||||
DockerRootDir: daemon.configStore.Root,
|
||||
Labels: daemon.configStore.Labels,
|
||||
@ -128,32 +65,21 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
||||
HTTPSProxy: sockets.GetProxyEnv("https_proxy"),
|
||||
NoProxy: sockets.GetProxyEnv("no_proxy"),
|
||||
LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
|
||||
SecurityOptions: securityOptions,
|
||||
Isolation: daemon.defaultIsolation,
|
||||
}
|
||||
|
||||
// Retrieve platform specific info
|
||||
daemon.FillPlatformInfo(v, sysInfo)
|
||||
|
||||
hostname := ""
|
||||
if hn, err := os.Hostname(); err != nil {
|
||||
logrus.Warnf("Could not get hostname: %v", err)
|
||||
} else {
|
||||
hostname = hn
|
||||
}
|
||||
v.Name = hostname
|
||||
daemon.fillPlatformInfo(v, sysInfo)
|
||||
daemon.fillDriverInfo(v)
|
||||
daemon.fillPluginsInfo(v)
|
||||
daemon.fillSecurityOptions(v, sysInfo)
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// SystemVersion returns version information about the daemon.
|
||||
func (daemon *Daemon) SystemVersion() types.Version {
|
||||
kernelVersion := "<unknown>"
|
||||
if kv, err := kernel.GetKernelVersion(); err != nil {
|
||||
logrus.Warnf("Could not get kernel version: %v", err)
|
||||
} else {
|
||||
kernelVersion = kv.String()
|
||||
}
|
||||
kernelVersion := kernelVersion()
|
||||
|
||||
v := types.Version{
|
||||
Components: []types.ComponentVersion{
|
||||
@ -192,15 +118,100 @@ func (daemon *Daemon) SystemVersion() types.Version {
|
||||
return v
|
||||
}
|
||||
|
||||
func (daemon *Daemon) showPluginsInfo() types.PluginsInfo {
|
||||
var pluginsInfo types.PluginsInfo
|
||||
func (daemon *Daemon) fillDriverInfo(v *types.Info) {
|
||||
var ds [][2]string
|
||||
drivers := ""
|
||||
statuses := daemon.imageService.LayerStoreStatus()
|
||||
for os, gd := range daemon.graphDrivers {
|
||||
ds = append(ds, statuses[os]...)
|
||||
drivers += gd
|
||||
if len(daemon.graphDrivers) > 1 {
|
||||
drivers += fmt.Sprintf(" (%s) ", os)
|
||||
}
|
||||
}
|
||||
drivers = strings.TrimSpace(drivers)
|
||||
|
||||
pluginsInfo.Volume = daemon.volumes.GetDriverList()
|
||||
pluginsInfo.Network = daemon.GetNetworkDriverList()
|
||||
// The authorization plugins are returned in the order they are
|
||||
// used as they constitute a request/response modification chain.
|
||||
pluginsInfo.Authorization = daemon.configStore.AuthorizationPlugins
|
||||
pluginsInfo.Log = logger.ListDrivers()
|
||||
|
||||
return pluginsInfo
|
||||
v.Driver = drivers
|
||||
v.DriverStatus = ds
|
||||
}
|
||||
|
||||
func (daemon *Daemon) fillPluginsInfo(v *types.Info) {
|
||||
v.Plugins = types.PluginsInfo{
|
||||
Volume: daemon.volumes.GetDriverList(),
|
||||
Network: daemon.GetNetworkDriverList(),
|
||||
|
||||
// The authorization plugins are returned in the order they are
|
||||
// used as they constitute a request/response modification chain.
|
||||
Authorization: daemon.configStore.AuthorizationPlugins,
|
||||
Log: logger.ListDrivers(),
|
||||
}
|
||||
}
|
||||
|
||||
func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
var securityOptions []string
|
||||
if sysInfo.AppArmor {
|
||||
securityOptions = append(securityOptions, "name=apparmor")
|
||||
}
|
||||
if sysInfo.Seccomp && supportsSeccomp {
|
||||
profile := daemon.seccompProfilePath
|
||||
if profile == "" {
|
||||
profile = "default"
|
||||
}
|
||||
securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
|
||||
}
|
||||
if selinuxEnabled() {
|
||||
securityOptions = append(securityOptions, "name=selinux")
|
||||
}
|
||||
if rootIDs := daemon.idMappings.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
|
||||
securityOptions = append(securityOptions, "name=userns")
|
||||
}
|
||||
v.SecurityOptions = securityOptions
|
||||
}
|
||||
|
||||
func hostName() string {
|
||||
hostname := ""
|
||||
if hn, err := os.Hostname(); err != nil {
|
||||
logrus.Warnf("Could not get hostname: %v", err)
|
||||
} else {
|
||||
hostname = hn
|
||||
}
|
||||
return hostname
|
||||
}
|
||||
|
||||
func kernelVersion() string {
|
||||
kernelVersion := "<unknown>"
|
||||
if kv, err := kernel.GetKernelVersion(); err != nil {
|
||||
logrus.Warnf("Could not get kernel version: %v", err)
|
||||
} else {
|
||||
kernelVersion = kv.String()
|
||||
}
|
||||
return kernelVersion
|
||||
}
|
||||
|
||||
func memInfo() *system.MemInfo {
|
||||
memInfo, err := system.ReadMemInfo()
|
||||
if err != nil {
|
||||
logrus.Errorf("Could not read system memory info: %v", err)
|
||||
memInfo = &system.MemInfo{}
|
||||
}
|
||||
return memInfo
|
||||
}
|
||||
|
||||
func operatingSystem() string {
|
||||
operatingSystem := "<unknown>"
|
||||
if s, err := operatingsystem.GetOperatingSystem(); err != nil {
|
||||
logrus.Warnf("Could not get operating system name: %v", err)
|
||||
} else {
|
||||
operatingSystem = s
|
||||
}
|
||||
// Don't do containerized check on Windows
|
||||
if runtime.GOOS != "windows" {
|
||||
if inContainer, err := operatingsystem.IsContainerized(); err != nil {
|
||||
logrus.Errorf("Could not determine if daemon is containerized: %v", err)
|
||||
operatingSystem += " (error determining if containerized)"
|
||||
} else if inContainer {
|
||||
operatingSystem += " (containerized)"
|
||||
}
|
||||
}
|
||||
return operatingSystem
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// FillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
// fillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
v.MemoryLimit = sysInfo.MemoryLimit
|
||||
v.SwapLimit = sysInfo.SwapLimit
|
||||
v.KernelMemory = sysInfo.KernelMemory
|
||||
|
||||
@ -5,6 +5,6 @@ import (
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
)
|
||||
|
||||
// FillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) FillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
// fillPlatformInfo fills the platform related info.
|
||||
func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
|
||||
}
|
||||
|
||||
@ -7,111 +7,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSwarmSuite) TestConfigCreate(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
testName := "test_config"
|
||||
id := d.CreateConfig(c, swarm.ConfigSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: testName,
|
||||
},
|
||||
Data: []byte("TESTINGDATA"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
|
||||
|
||||
config := d.GetConfig(c, id)
|
||||
c.Assert(config.Spec.Name, checker.Equals, testName)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestConfigCreateWithLabels(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
testName := "test_config"
|
||||
id := d.CreateConfig(c, swarm.ConfigSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: testName,
|
||||
Labels: map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
},
|
||||
},
|
||||
Data: []byte("TESTINGDATA"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
|
||||
|
||||
config := d.GetConfig(c, id)
|
||||
c.Assert(config.Spec.Name, checker.Equals, testName)
|
||||
c.Assert(len(config.Spec.Labels), checker.Equals, 2)
|
||||
c.Assert(config.Spec.Labels["key1"], checker.Equals, "value1")
|
||||
c.Assert(config.Spec.Labels["key2"], checker.Equals, "value2")
|
||||
}
|
||||
|
||||
// Test case for 28884
|
||||
func (s *DockerSwarmSuite) TestConfigCreateResolve(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
name := "test_config"
|
||||
id := d.CreateConfig(c, swarm.ConfigSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: name,
|
||||
},
|
||||
Data: []byte("foo"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("configs: %s", id))
|
||||
|
||||
fake := d.CreateConfig(c, swarm.ConfigSpec{
|
||||
Annotations: swarm.Annotations{
|
||||
Name: id,
|
||||
},
|
||||
Data: []byte("fake foo"),
|
||||
})
|
||||
c.Assert(fake, checker.Not(checker.Equals), "", check.Commentf("configs: %s", fake))
|
||||
|
||||
out, err := d.Cmd("config", "ls")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, name)
|
||||
c.Assert(out, checker.Contains, fake)
|
||||
|
||||
out, err = d.Cmd("config", "rm", id)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, id)
|
||||
|
||||
// Fake one will remain
|
||||
out, err = d.Cmd("config", "ls")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Not(checker.Contains), name)
|
||||
c.Assert(out, checker.Contains, fake)
|
||||
|
||||
// Remove based on name prefix of the fake one
|
||||
// (which is the same as the ID of foo one) should not work
|
||||
// as search is only done based on:
|
||||
// - Full ID
|
||||
// - Full Name
|
||||
// - Partial ID (prefix)
|
||||
out, err = d.Cmd("config", "rm", id[:5])
|
||||
c.Assert(err, checker.Not(checker.IsNil))
|
||||
c.Assert(out, checker.Not(checker.Contains), id)
|
||||
out, err = d.Cmd("config", "ls")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Not(checker.Contains), name)
|
||||
c.Assert(out, checker.Contains, fake)
|
||||
|
||||
// Remove based on ID prefix of the fake one should succeed
|
||||
out, err = d.Cmd("config", "rm", fake[:5])
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Contains, fake[:5])
|
||||
out, err = d.Cmd("config", "ls")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(out, checker.Not(checker.Contains), name)
|
||||
c.Assert(out, checker.Not(checker.Contains), id)
|
||||
c.Assert(out, checker.Not(checker.Contains), fake)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestConfigCreateWithFile(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
|
||||
@ -1644,9 +1644,9 @@ func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
|
||||
c.Assert(waitRun("first"), check.IsNil)
|
||||
dockerCmd(c, "run", "-d", "--net=internal", "--name=second", "busybox:glibc", "top")
|
||||
c.Assert(waitRun("second"), check.IsNil)
|
||||
out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "www.google.com")
|
||||
out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "8.8.8.8")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(out, checker.Contains, "ping: bad address")
|
||||
c.Assert(out, checker.Contains, "100% packet loss")
|
||||
_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
|
||||
c.Assert(err, check.IsNil)
|
||||
}
|
||||
|
||||
@ -45,19 +45,10 @@ func TestConfigList(t *testing.T) {
|
||||
|
||||
config1ID := createConfig(ctx, t, client, testName1, []byte("TESTINGDATA1"), map[string]string{"type": "production"})
|
||||
|
||||
names := func(entries []swarmtypes.Config) []string {
|
||||
var values []string
|
||||
for _, entry := range entries {
|
||||
values = append(values, entry.Spec.Name)
|
||||
}
|
||||
sort.Strings(values)
|
||||
return values
|
||||
}
|
||||
|
||||
// test by `config ls`
|
||||
entries, err := client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), testNames))
|
||||
assert.Check(t, is.DeepEqual(configNamesFromList(entries), testNames))
|
||||
|
||||
testCases := []struct {
|
||||
filters filters.Args
|
||||
@ -92,7 +83,7 @@ func TestConfigList(t *testing.T) {
|
||||
Filters: tc.filters,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(names(entries), tc.expected))
|
||||
assert.Check(t, is.DeepEqual(configNamesFromList(entries), tc.expected))
|
||||
|
||||
}
|
||||
}
|
||||
@ -354,3 +345,89 @@ func TestConfigInspect(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(config, insp))
|
||||
}
|
||||
|
||||
func TestConfigCreateWithLabels(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client := d.NewClientT(t)
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
labels := map[string]string{
|
||||
"key1": "value1",
|
||||
"key2": "value2",
|
||||
}
|
||||
testName := t.Name()
|
||||
configID := createConfig(ctx, t, client, testName, []byte("TESTINGDATA"), labels)
|
||||
|
||||
insp, _, err := client.ConfigInspectWithRaw(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(insp.Spec.Name, testName))
|
||||
assert.Check(t, is.Equal(2, len(insp.Spec.Labels)))
|
||||
assert.Check(t, is.Equal("value1", insp.Spec.Labels["key1"]))
|
||||
assert.Check(t, is.Equal("value2", insp.Spec.Labels["key2"]))
|
||||
}
|
||||
|
||||
// Test case for 28884
|
||||
func TestConfigCreateResolve(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType != "linux")
|
||||
|
||||
defer setupTest(t)()
|
||||
d := swarm.NewSwarm(t, testEnv)
|
||||
defer d.Stop(t)
|
||||
client := d.NewClientT(t)
|
||||
defer client.Close()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
configName := "test_config_" + t.Name()
|
||||
|
||||
configID := createConfig(ctx, t, client, configName, []byte("foo"), nil)
|
||||
fakeName := configID
|
||||
fakeID := createConfig(ctx, t, client, fakeName, []byte("fake foo"), nil)
|
||||
|
||||
entries, err := client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Contains(configNamesFromList(entries), configName))
|
||||
assert.Assert(t, is.Contains(configNamesFromList(entries), fakeName))
|
||||
|
||||
err = client.ConfigRemove(ctx, configID)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Fake one will remain
|
||||
entries, err = client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.DeepEqual(configNamesFromList(entries), []string{fakeName}))
|
||||
|
||||
// Remove based on name prefix of the fake one
|
||||
// (which is the same as the ID of foo one) should not work
|
||||
// as search is only done based on:
|
||||
// - Full ID
|
||||
// - Full Name
|
||||
// - Partial ID (prefix)
|
||||
err = client.ConfigRemove(ctx, configID[:5])
|
||||
assert.Assert(t, nil != err)
|
||||
entries, err = client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.DeepEqual(configNamesFromList(entries), []string{fakeName}))
|
||||
|
||||
// Remove based on ID prefix of the fake one should succeed
|
||||
err = client.ConfigRemove(ctx, fakeID[:5])
|
||||
assert.NilError(t, err)
|
||||
entries, err = client.ConfigList(ctx, types.ConfigListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, is.Equal(0, len(entries)))
|
||||
}
|
||||
|
||||
func configNamesFromList(entries []swarmtypes.Config) []string {
|
||||
var values []string
|
||||
for _, entry := range entries {
|
||||
values = append(values, entry.Spec.Name)
|
||||
}
|
||||
sort.Strings(values)
|
||||
return values
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user