mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
review changes
- fix lint issues - use errors pkg for wrapping errors - cleanup on error when setting up secrets mount - fix erroneous import - remove unneeded switch for secret reference mode - return single mount for secrets instead of slice Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
parent
3716ec25b4
commit
857e60c2f9
12 changed files with 96 additions and 40 deletions
|
@ -11,7 +11,7 @@ type Secret struct {
|
|||
|
||||
type SecretSpec struct {
|
||||
Annotations
|
||||
Data []byte `json",omitempty"`
|
||||
Data []byte `json:",omitempty"`
|
||||
}
|
||||
|
||||
type SecretReferenceMode int
|
||||
|
|
|
@ -3,6 +3,7 @@ package service
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -31,6 +32,13 @@ func parseSecretString(secretString string) (string, string, error) {
|
|||
} else {
|
||||
targetName = secretName
|
||||
}
|
||||
|
||||
// ensure target is a filename only; no paths allowed
|
||||
tDir, _ := filepath.Split(targetName)
|
||||
if tDir != "" {
|
||||
return "", "", fmt.Errorf("target must not have a path")
|
||||
}
|
||||
|
||||
return secretName, targetName, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container
|
||||
const (
|
||||
// DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container
|
||||
DefaultSHMSize int64 = 67108864
|
||||
containerSecretMountPath = "/run/secrets"
|
||||
)
|
||||
|
@ -178,6 +178,7 @@ func (container *Container) NetworkMounts() []Mount {
|
|||
return mounts
|
||||
}
|
||||
|
||||
// SecretMountPath returns the path of the secret mount for the container
|
||||
func (container *Container) SecretMountPath() string {
|
||||
return filepath.Join(container.Root, "secrets")
|
||||
}
|
||||
|
@ -267,19 +268,19 @@ func (container *Container) IpcMounts() []Mount {
|
|||
return mounts
|
||||
}
|
||||
|
||||
// SecretMounts returns the list of Secret mounts
|
||||
func (container *Container) SecretMounts() []Mount {
|
||||
var mounts []Mount
|
||||
// SecretMount returns the list of Secret mounts
|
||||
func (container *Container) SecretMount() Mount {
|
||||
var mount Mount
|
||||
|
||||
if len(container.Secrets) > 0 {
|
||||
mounts = append(mounts, Mount{
|
||||
mount = Mount{
|
||||
Source: container.SecretMountPath(),
|
||||
Destination: containerSecretMountPath,
|
||||
Writable: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return mounts
|
||||
return mount
|
||||
}
|
||||
|
||||
// UnmountSecrets unmounts the local tmpfs for secrets
|
||||
|
|
|
@ -79,12 +79,9 @@ func containerSpecFromGRPC(c *swarmapi.ContainerSpec) types.ContainerSpec {
|
|||
func secretReferencesToGRPC(sr []*types.SecretReference) []*swarmapi.SecretReference {
|
||||
refs := []*swarmapi.SecretReference{}
|
||||
for _, s := range sr {
|
||||
var mode swarmapi.SecretReference_Mode
|
||||
switch s.Mode {
|
||||
case types.SecretReferenceSystem:
|
||||
mode := swarmapi.SecretReference_FILE
|
||||
if s.Mode == types.SecretReferenceSystem {
|
||||
mode = swarmapi.SecretReference_SYSTEM
|
||||
default:
|
||||
mode = swarmapi.SecretReference_FILE
|
||||
}
|
||||
refs = append(refs, &swarmapi.SecretReference{
|
||||
SecretID: s.SecretID,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
swarmtypes "github.com/docker/docker/api/types/swarm"
|
||||
swarmapi "github.com/docker/swarmkit/api"
|
||||
"github.com/docker/swarmkit/protobuf/ptypes"
|
||||
|
@ -9,7 +8,6 @@ import (
|
|||
|
||||
// SecretFromGRPC converts a grpc Secret to a Secret.
|
||||
func SecretFromGRPC(s *swarmapi.Secret) swarmtypes.Secret {
|
||||
logrus.Debugf("%+v", s)
|
||||
secret := swarmtypes.Secret{
|
||||
ID: s.ID,
|
||||
Digest: s.Digest,
|
||||
|
@ -33,14 +31,12 @@ func SecretFromGRPC(s *swarmapi.Secret) swarmtypes.Secret {
|
|||
}
|
||||
|
||||
// SecretSpecToGRPC converts Secret to a grpc Secret.
|
||||
func SecretSpecToGRPC(s swarmtypes.SecretSpec) (swarmapi.SecretSpec, error) {
|
||||
spec := swarmapi.SecretSpec{
|
||||
func SecretSpecToGRPC(s swarmtypes.SecretSpec) swarmapi.SecretSpec {
|
||||
return swarmapi.SecretSpec{
|
||||
Annotations: swarmapi.Annotations{
|
||||
Name: s.Name,
|
||||
Labels: s.Labels,
|
||||
},
|
||||
Data: s.Data,
|
||||
}
|
||||
|
||||
return spec, nil
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package container
|
|||
|
||||
import (
|
||||
executorpkg "github.com/docker/docker/daemon/cluster/executor"
|
||||
"github.com/docker/swarmkit/agent/exec"
|
||||
"github.com/docker/swarmkit/api"
|
||||
"golang.org/x/net/context"
|
||||
"src/github.com/docker/swarmkit/agent/exec"
|
||||
)
|
||||
|
||||
// networkAttacherController implements agent.Controller against docker's API.
|
||||
|
|
|
@ -63,10 +63,7 @@ func (c *Cluster) CreateSecret(s types.SecretSpec) (string, error) {
|
|||
ctx, cancel := c.getRequestContext()
|
||||
defer cancel()
|
||||
|
||||
secretSpec, err := convert.SecretSpecToGRPC(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
secretSpec := convert.SecretSpecToGRPC(s)
|
||||
|
||||
r, err := c.node.client.CreateSecret(ctx,
|
||||
&swarmapi.CreateSecretRequest{Spec: &secretSpec})
|
||||
|
@ -111,10 +108,7 @@ func (c *Cluster) UpdateSecret(id string, version uint64, spec types.SecretSpec)
|
|||
ctx, cancel := c.getRequestContext()
|
||||
defer cancel()
|
||||
|
||||
secretSpec, err := convert.SecretSpecToGRPC(spec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
secretSpec := convert.SecretSpecToGRPC(spec)
|
||||
|
||||
if _, err := c.client.UpdateSecret(ctx,
|
||||
&swarmapi.UpdateSecretRequest{
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/links"
|
||||
|
@ -25,6 +26,7 @@ import (
|
|||
"github.com/opencontainers/runc/libcontainer/devices"
|
||||
"github.com/opencontainers/runc/libcontainer/label"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func u32Ptr(i int64) *uint32 { u := uint32(i); return &u }
|
||||
|
@ -146,36 +148,58 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) error {
|
|||
localMountPath := c.SecretMountPath()
|
||||
logrus.Debugf("secrets: setting up secret dir: %s", localMountPath)
|
||||
|
||||
var setupErr error
|
||||
|
||||
defer func(err error) {
|
||||
if err != nil {
|
||||
// cleanup
|
||||
_ = detachMounted(localMountPath)
|
||||
|
||||
if err := os.RemoveAll(localMountPath); err != nil {
|
||||
log.Errorf("error cleaning up secret mount: %s", err)
|
||||
}
|
||||
}
|
||||
}(setupErr)
|
||||
|
||||
// create tmpfs
|
||||
if err := os.MkdirAll(localMountPath, 0700); err != nil {
|
||||
return fmt.Errorf("error creating secret local mount path: %s", err)
|
||||
setupErr = errors.Wrap(err, "error creating secret local mount path")
|
||||
}
|
||||
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "nodev"); err != nil {
|
||||
return fmt.Errorf("unable to setup secret mount: %s", err)
|
||||
setupErr = errors.Wrap(err, "unable to setup secret mount")
|
||||
}
|
||||
|
||||
for _, s := range c.Secrets {
|
||||
fPath := filepath.Join(localMountPath, s.Target)
|
||||
if err := os.MkdirAll(filepath.Dir(fPath), 0700); err != nil {
|
||||
return fmt.Errorf("error creating secret mount path: %s", err)
|
||||
// ensure that the target is a filename only; no paths allowed
|
||||
tDir, tPath := filepath.Split(s.Target)
|
||||
if tDir != "" {
|
||||
setupErr = fmt.Errorf("error creating secret: secret must not have a path")
|
||||
}
|
||||
|
||||
logrus.Debugf("injecting secret: name=%s path=%s", s.Name, fPath)
|
||||
fPath := filepath.Join(localMountPath, tPath)
|
||||
if err := os.MkdirAll(filepath.Dir(fPath), 0700); err != nil {
|
||||
setupErr = errors.Wrap(err, "error creating secret mount path")
|
||||
}
|
||||
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
"path": fPath,
|
||||
}).Debug("injecting secret")
|
||||
if err := ioutil.WriteFile(fPath, s.Data, s.Mode); err != nil {
|
||||
return fmt.Errorf("error injecting secret: %s", err)
|
||||
setupErr = errors.Wrap(err, "error injecting secret")
|
||||
}
|
||||
|
||||
if err := os.Chown(fPath, s.Uid, s.Gid); err != nil {
|
||||
return fmt.Errorf("error setting ownership for secret: %s", err)
|
||||
setupErr = errors.Wrap(err, "error setting ownership for secret")
|
||||
}
|
||||
}
|
||||
|
||||
// remount secrets ro
|
||||
if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "remount,ro"); err != nil {
|
||||
return fmt.Errorf("unable to remount secret dir as readonly: %s", err)
|
||||
setupErr = errors.Wrap(err, "unable to remount secret dir as readonly")
|
||||
}
|
||||
|
||||
return nil
|
||||
return setupErr
|
||||
}
|
||||
|
||||
func killProcessDirectly(container *container.Container) error {
|
||||
|
|
|
@ -718,7 +718,8 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
|||
}
|
||||
ms = append(ms, tmpfsMounts...)
|
||||
|
||||
ms = append(ms, c.SecretMounts()...)
|
||||
ms = append(ms, c.SecretMount())
|
||||
|
||||
sort.Sort(mounts(ms))
|
||||
if err := setMounts(daemon, &s, c, ms); err != nil {
|
||||
return nil, fmt.Errorf("linux mounts: %v", err)
|
||||
|
|
|
@ -5,8 +5,9 @@ import (
|
|||
containertypes "github.com/docker/docker/api/types/container"
|
||||
)
|
||||
|
||||
// SetContainerSecrets sets the container secrets needed
|
||||
func (daemon *Daemon) SetContainerSecrets(name string, secrets []*containertypes.ContainerSecret) error {
|
||||
if !secretsSupported() {
|
||||
if !secretsSupported() && len(secrets) > 0 {
|
||||
logrus.Warn("secrets are not supported on this platform")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -284,6 +284,16 @@ func (d *SwarmDaemon) listServices(c *check.C) []swarm.Service {
|
|||
return services
|
||||
}
|
||||
|
||||
func (d *SwarmDaemon) listSecrets(c *check.C) []swarm.Service {
|
||||
status, out, err := d.SockRequest("GET", "/secrets", nil)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
|
||||
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
|
||||
|
||||
secrets := []swarm.Secret{}
|
||||
c.Assert(json.Unmarshal(out, &secrets), checker.IsNil)
|
||||
return services
|
||||
}
|
||||
|
||||
func (d *SwarmDaemon) getSwarm(c *check.C) swarm.Swarm {
|
||||
var sw swarm.Swarm
|
||||
status, out, err := d.SockRequest("GET", "/swarm", nil)
|
||||
|
|
|
@ -1263,3 +1263,27 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *check.C) {
|
|||
c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
|
||||
waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestAPISwarmSecretsEmptyList(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
secrets := d.listSecrets(c)
|
||||
c.Assert(secrets, checker.NotNil)
|
||||
c.Assert(len(secrets), checker.Equals, 0, check.Commentf("secrets: %#v", secrets))
|
||||
}
|
||||
|
||||
//func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *check.C) {
|
||||
// d := s.AddDaemon(c, true, true)
|
||||
//
|
||||
// instances := 2
|
||||
// id := d.createService(c, simpleTestService, setInstances(instances))
|
||||
// waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances)
|
||||
//
|
||||
// service := d.getService(c, id)
|
||||
// instances = 5
|
||||
// d.updateService(c, service, setInstances(instances))
|
||||
// waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, instances)
|
||||
//
|
||||
// d.removeService(c, service.ID)
|
||||
// waitAndAssert(c, defaultReconciliationTimeout, d.checkActiveContainerCount, checker.Equals, 0)
|
||||
//}
|
||||
|
|
Loading…
Reference in a new issue