mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add config support to executor backend
Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
a58cc35ab8
commit
9e9fc7b57c
14 changed files with 208 additions and 50 deletions
|
@ -87,8 +87,9 @@ type CommonContainer struct {
|
||||||
MountPoints map[string]*volume.MountPoint
|
MountPoints map[string]*volume.MountPoint
|
||||||
HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable
|
HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable
|
||||||
ExecCommands *exec.Store `json:"-"`
|
ExecCommands *exec.Store `json:"-"`
|
||||||
SecretStore agentexec.SecretGetter `json:"-"`
|
DependencyStore agentexec.DependencyGetter `json:"-"`
|
||||||
SecretReferences []*swarmtypes.SecretReference
|
SecretReferences []*swarmtypes.SecretReference
|
||||||
|
ConfigReferences []*swarmtypes.ConfigReference
|
||||||
// logDriver for closing
|
// logDriver for closing
|
||||||
LogDriver logger.Logger `json:"-"`
|
LogDriver logger.Logger `json:"-"`
|
||||||
LogCopier *logger.Copier `json:"-"`
|
LogCopier *logger.Copier `json:"-"`
|
||||||
|
@ -966,3 +967,14 @@ func getSecretTargetPath(r *swarmtypes.SecretReference) string {
|
||||||
|
|
||||||
return filepath.Join(containerSecretMountPath, r.File.Name)
|
return filepath.Join(containerSecretMountPath, r.File.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigsDirPath returns the path to the directory where configs are stored on
|
||||||
|
// disk.
|
||||||
|
func (container *Container) ConfigsDirPath() string {
|
||||||
|
return filepath.Join(container.Root, "configs")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigFilePath returns the path to the on-disk location of a config.
|
||||||
|
func (container *Container) ConfigFilePath(configRef swarmtypes.ConfigReference) string {
|
||||||
|
return filepath.Join(container.ConfigsDirPath(), configRef.ConfigID)
|
||||||
|
}
|
||||||
|
|
|
@ -277,6 +277,23 @@ func (container *Container) UnmountSecrets() error {
|
||||||
return detachMounted(container.SecretMountPath())
|
return detachMounted(container.SecretMountPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigMounts returns the mounts for configs.
|
||||||
|
func (container *Container) ConfigMounts() []Mount {
|
||||||
|
var mounts []Mount
|
||||||
|
for _, configRef := range container.ConfigReferences {
|
||||||
|
if configRef.File == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mounts = append(mounts, Mount{
|
||||||
|
Source: container.ConfigFilePath(*configRef),
|
||||||
|
Destination: configRef.File.Name,
|
||||||
|
Writable: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateContainer updates configuration of a container.
|
// UpdateContainer updates configuration of a container.
|
||||||
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
|
||||||
container.Lock()
|
container.Lock()
|
||||||
|
|
|
@ -42,8 +42,9 @@ type Backend interface {
|
||||||
ContainerWaitWithContext(ctx context.Context, name string) error
|
ContainerWaitWithContext(ctx context.Context, name string) error
|
||||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||||
ContainerKill(name string, sig uint64) error
|
ContainerKill(name string, sig uint64) error
|
||||||
SetContainerSecretStore(name string, store exec.SecretGetter) error
|
SetContainerDependencyStore(name string, store exec.DependencyGetter) error
|
||||||
SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error
|
SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error
|
||||||
|
SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error
|
||||||
SystemInfo() (*types.Info, error)
|
SystemInfo() (*types.Info, error)
|
||||||
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
||||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
||||||
|
|
|
@ -33,21 +33,21 @@ import (
|
||||||
// are mostly naked calls to the client API, seeded with information from
|
// are mostly naked calls to the client API, seeded with information from
|
||||||
// containerConfig.
|
// containerConfig.
|
||||||
type containerAdapter struct {
|
type containerAdapter struct {
|
||||||
backend executorpkg.Backend
|
backend executorpkg.Backend
|
||||||
container *containerConfig
|
container *containerConfig
|
||||||
secrets exec.SecretGetter
|
dependencies exec.DependencyGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContainerAdapter(b executorpkg.Backend, task *api.Task, secrets exec.SecretGetter) (*containerAdapter, error) {
|
func newContainerAdapter(b executorpkg.Backend, task *api.Task, dependencies exec.DependencyGetter) (*containerAdapter, error) {
|
||||||
ctnr, err := newContainerConfig(task)
|
ctnr, err := newContainerConfig(task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &containerAdapter{
|
return &containerAdapter{
|
||||||
container: ctnr,
|
container: ctnr,
|
||||||
backend: b,
|
backend: b,
|
||||||
secrets: secrets,
|
dependencies: dependencies,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,13 +243,18 @@ func (c *containerAdapter) create(ctx context.Context) error {
|
||||||
return errors.New("unable to get container from task spec")
|
return errors.New("unable to get container from task spec")
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure secrets
|
if err := c.backend.SetContainerDependencyStore(cr.ID, c.dependencies); err != nil {
|
||||||
if err := c.backend.SetContainerSecretStore(cr.ID, c.secrets); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
refs := convert.SecretReferencesFromGRPC(container.Secrets)
|
// configure secrets
|
||||||
if err := c.backend.SetContainerSecretReferences(cr.ID, refs); err != nil {
|
secretRefs := convert.SecretReferencesFromGRPC(container.Secrets)
|
||||||
|
if err := c.backend.SetContainerSecretReferences(cr.ID, secretRefs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
configRefs := convert.ConfigReferencesFromGRPC(container.Configs)
|
||||||
|
if err := c.backend.SetContainerConfigReferences(cr.ID, configRefs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ type networkAttacherController struct {
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNetworkAttacherController(b executorpkg.Backend, task *api.Task, secrets exec.SecretGetter) (*networkAttacherController, error) {
|
func newNetworkAttacherController(b executorpkg.Backend, task *api.Task, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
|
||||||
adapter, err := newContainerAdapter(b, task, secrets)
|
adapter, err := newContainerAdapter(b, task, dependencies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ type controller struct {
|
||||||
var _ exec.Controller = &controller{}
|
var _ exec.Controller = &controller{}
|
||||||
|
|
||||||
// NewController returns a docker exec runner for the provided task.
|
// NewController returns a docker exec runner for the provided task.
|
||||||
func newController(b executorpkg.Backend, task *api.Task, secrets exec.SecretGetter) (*controller, error) {
|
func newController(b executorpkg.Backend, task *api.Task, dependencies exec.DependencyGetter) (*controller, error) {
|
||||||
adapter, err := newContainerAdapter(b, task, secrets)
|
adapter, err := newContainerAdapter(b, task, dependencies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,23 +14,23 @@ import (
|
||||||
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
||||||
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
||||||
networktypes "github.com/docker/libnetwork/types"
|
networktypes "github.com/docker/libnetwork/types"
|
||||||
|
"github.com/docker/swarmkit/agent"
|
||||||
"github.com/docker/swarmkit/agent/exec"
|
"github.com/docker/swarmkit/agent/exec"
|
||||||
"github.com/docker/swarmkit/agent/secrets"
|
|
||||||
"github.com/docker/swarmkit/api"
|
"github.com/docker/swarmkit/api"
|
||||||
"github.com/docker/swarmkit/api/naming"
|
"github.com/docker/swarmkit/api/naming"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type executor struct {
|
type executor struct {
|
||||||
backend executorpkg.Backend
|
backend executorpkg.Backend
|
||||||
secrets exec.SecretsManager
|
dependencies exec.DependencyManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExecutor returns an executor from the docker client.
|
// NewExecutor returns an executor from the docker client.
|
||||||
func NewExecutor(b executorpkg.Backend) exec.Executor {
|
func NewExecutor(b executorpkg.Backend) exec.Executor {
|
||||||
return &executor{
|
return &executor{
|
||||||
backend: b,
|
backend: b,
|
||||||
secrets: secrets.NewManager(),
|
dependencies: agent.NewDependencyManager(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +162,10 @@ func (e *executor) Configure(ctx context.Context, node *api.Node) error {
|
||||||
|
|
||||||
// Controller returns a docker container runner.
|
// Controller returns a docker container runner.
|
||||||
func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
|
func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
|
||||||
|
dependencyGetter := agent.Restrict(e.dependencies, t)
|
||||||
|
|
||||||
if t.Spec.GetAttachment() != nil {
|
if t.Spec.GetAttachment() != nil {
|
||||||
return newNetworkAttacherController(e.backend, t, e.secrets)
|
return newNetworkAttacherController(e.backend, t, dependencyGetter)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctlr exec.Controller
|
var ctlr exec.Controller
|
||||||
|
@ -188,7 +190,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
|
||||||
return ctlr, fmt.Errorf("unsupported runtime type: %q", r.Generic.Kind)
|
return ctlr, fmt.Errorf("unsupported runtime type: %q", r.Generic.Kind)
|
||||||
}
|
}
|
||||||
case *api.TaskSpec_Container:
|
case *api.TaskSpec_Container:
|
||||||
c, err := newController(e.backend, t, secrets.Restrict(e.secrets, t))
|
c, err := newController(e.backend, t, dependencyGetter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctlr, err
|
return ctlr, err
|
||||||
}
|
}
|
||||||
|
@ -218,7 +220,11 @@ func (e *executor) SetNetworkBootstrapKeys(keys []*api.EncryptionKey) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *executor) Secrets() exec.SecretsManager {
|
func (e *executor) Secrets() exec.SecretsManager {
|
||||||
return e.secrets
|
return e.dependencies.Secrets()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *executor) Configs() exec.ConfigsManager {
|
||||||
|
return e.dependencies.Configs()
|
||||||
}
|
}
|
||||||
|
|
||||||
type sortedPlugins []api.PluginDescription
|
type sortedPlugins []api.PluginDescription
|
||||||
|
|
23
daemon/configs.go
Normal file
23
daemon/configs.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetContainerConfigReferences sets the container config references needed
|
||||||
|
func (daemon *Daemon) SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error {
|
||||||
|
if !configsSupported() && len(refs) > 0 {
|
||||||
|
logrus.Warn("configs are not supported on this platform")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := daemon.GetContainer(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ConfigReferences = refs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
7
daemon/configs_linux.go
Normal file
7
daemon/configs_linux.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
func configsSupported() bool {
|
||||||
|
return true
|
||||||
|
}
|
7
daemon/configs_unsupported.go
Normal file
7
daemon/configs_unsupported.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
func configsSupported() bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -145,6 +145,13 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
||||||
localMountPath := c.SecretMountPath()
|
localMountPath := c.SecretMountPath()
|
||||||
logrus.Debugf("secrets: setting up secret dir: %s", localMountPath)
|
logrus.Debugf("secrets: setting up secret dir: %s", localMountPath)
|
||||||
|
|
||||||
|
// retrieve possible remapped range start for root UID, GID
|
||||||
|
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||||
|
// create tmpfs
|
||||||
|
if err := idtools.MkdirAllAs(localMountPath, 0700, rootUID, rootGID); err != nil {
|
||||||
|
return errors.Wrap(err, "error creating secret local mount path")
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if setupErr != nil {
|
if setupErr != nil {
|
||||||
// cleanup
|
// cleanup
|
||||||
|
@ -156,25 +163,20 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// retrieve possible remapped range start for root UID, GID
|
|
||||||
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
|
||||||
// create tmpfs
|
|
||||||
if err := idtools.MkdirAllAs(localMountPath, 0700, rootUID, rootGID); err != nil {
|
|
||||||
return errors.Wrap(err, "error creating secret local mount path")
|
|
||||||
}
|
|
||||||
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootUID, rootGID)
|
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootUID, rootGID)
|
||||||
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev,nosuid,noexec,"+tmpfsOwnership); err != nil {
|
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev,nosuid,noexec,"+tmpfsOwnership); err != nil {
|
||||||
return errors.Wrap(err, "unable to setup secret mount")
|
return errors.Wrap(err, "unable to setup secret mount")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, s := range c.SecretReferences {
|
if c.DependencyStore == nil {
|
||||||
if c.SecretStore == nil {
|
return fmt.Errorf("secret store is not initialized")
|
||||||
return fmt.Errorf("secret store is not initialized")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
for _, s := range c.SecretReferences {
|
||||||
// TODO (ehazlett): use type switch when more are supported
|
// TODO (ehazlett): use type switch when more are supported
|
||||||
if s.File == nil {
|
if s.File == nil {
|
||||||
return fmt.Errorf("secret target type is not a file target")
|
logrus.Error("secret target type is not a file target")
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// secrets are created in the SecretMountPath on the host, at a
|
// secrets are created in the SecretMountPath on the host, at a
|
||||||
|
@ -188,7 +190,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
||||||
"name": s.File.Name,
|
"name": s.File.Name,
|
||||||
"path": fPath,
|
"path": fPath,
|
||||||
}).Debug("injecting secret")
|
}).Debug("injecting secret")
|
||||||
secret := c.SecretStore.Get(s.SecretID)
|
secret := c.DependencyStore.Secrets().Get(s.SecretID)
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
return fmt.Errorf("unable to get secret from secret store")
|
return fmt.Errorf("unable to get secret from secret store")
|
||||||
}
|
}
|
||||||
|
@ -220,6 +222,74 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) {
|
||||||
|
if len(c.ConfigReferences) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
localPath := c.ConfigsDirPath()
|
||||||
|
logrus.Debugf("configs: setting up config dir: %s", localPath)
|
||||||
|
|
||||||
|
// retrieve possible remapped range start for root UID, GID
|
||||||
|
rootUID, rootGID := daemon.GetRemappedUIDGID()
|
||||||
|
// create tmpfs
|
||||||
|
if err := idtools.MkdirAllAs(localPath, 0700, rootUID, rootGID); err != nil {
|
||||||
|
return errors.Wrap(err, "error creating config dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if setupErr != nil {
|
||||||
|
if err := os.RemoveAll(localPath); err != nil {
|
||||||
|
logrus.Errorf("error cleaning up config dir: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if c.DependencyStore == nil {
|
||||||
|
return fmt.Errorf("config store is not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, configRef := range c.ConfigReferences {
|
||||||
|
// TODO (ehazlett): use type switch when more are supported
|
||||||
|
if configRef.File == nil {
|
||||||
|
logrus.Error("config target type is not a file target")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fPath := c.ConfigFilePath(*configRef)
|
||||||
|
|
||||||
|
log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath})
|
||||||
|
|
||||||
|
if err := idtools.MkdirAllAs(filepath.Dir(fPath), 0700, rootUID, rootGID); err != nil {
|
||||||
|
return errors.Wrap(err, "error creating config path")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("injecting config")
|
||||||
|
config := c.DependencyStore.Configs().Get(configRef.ConfigID)
|
||||||
|
if config == nil {
|
||||||
|
return fmt.Errorf("unable to get config from config store")
|
||||||
|
}
|
||||||
|
if err := ioutil.WriteFile(fPath, config.Spec.Data, configRef.File.Mode); err != nil {
|
||||||
|
return errors.Wrap(err, "error injecting config")
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, err := strconv.Atoi(configRef.File.UID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gid, err := strconv.Atoi(configRef.File.GID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Chown(fPath, rootUID+uid, rootGID+gid); err != nil {
|
||||||
|
return errors.Wrap(err, "error setting ownership for config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func killProcessDirectly(container *container.Container) error {
|
func killProcessDirectly(container *container.Container) error {
|
||||||
if _, err := container.WaitStop(10 * time.Second); err != nil {
|
if _, err := container.WaitStop(10 * time.Second); err != nil {
|
||||||
// Ensure that we don't kill ourselves
|
// Ensure that we don't kill ourselves
|
||||||
|
|
17
daemon/dependency.go
Normal file
17
daemon/dependency.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/swarmkit/agent/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetContainerDependencyStore sets the dependency store backend for the container
|
||||||
|
func (daemon *Daemon) SetContainerDependencyStore(name string, store exec.DependencyGetter) error {
|
||||||
|
c, err := daemon.GetContainer(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.DependencyStore = store
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -737,6 +737,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := daemon.setupConfigDir(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
ms, err := daemon.setupMounts(c)
|
ms, err := daemon.setupMounts(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -754,6 +758,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||||
ms = append(ms, m...)
|
ms = append(ms, m...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ms = append(ms, c.ConfigMounts()...)
|
||||||
|
|
||||||
sort.Sort(mounts(ms))
|
sort.Sort(mounts(ms))
|
||||||
if err := setMounts(daemon, &s, c, ms); err != nil {
|
if err := setMounts(daemon, &s, c, ms); err != nil {
|
||||||
return nil, fmt.Errorf("linux mounts: %v", err)
|
return nil, fmt.Errorf("linux mounts: %v", err)
|
||||||
|
|
|
@ -3,21 +3,8 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||||
"github.com/docker/swarmkit/agent/exec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetContainerSecretStore sets the secret store backend for the container
|
|
||||||
func (daemon *Daemon) SetContainerSecretStore(name string, store exec.SecretGetter) error {
|
|
||||||
c, err := daemon.GetContainer(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.SecretStore = store
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetContainerSecretReferences sets the container secret references needed
|
// SetContainerSecretReferences sets the container secret references needed
|
||||||
func (daemon *Daemon) SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error {
|
func (daemon *Daemon) SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error {
|
||||||
if !secretsSupported() && len(refs) > 0 {
|
if !secretsSupported() && len(refs) > 0 {
|
||||||
|
|
Loading…
Reference in a new issue