diff --git a/drivers/docker/config.go b/drivers/docker/config.go index b3069d766..571fff474 100644 --- a/drivers/docker/config.go +++ b/drivers/docker/config.go @@ -48,10 +48,10 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) { // dockerd auth authConf := map[string]interface{}{} if v, ok := opts["docker.auth.config"]; ok { - authConf["auth_config"] = v + authConf["config"] = v } if v, ok := opts["docker.auth.helper"]; ok { - authConf["auth_helper"] = v + authConf["helper"] = v } conf["auth"] = authConf @@ -78,12 +78,14 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) { conf["gc"] = gcConf // volume options + volConf := map[string]interface{}{} if v, err := strconv.ParseBool(opts["docker.volumes.enabled"]); err == nil { - conf["volumes_enabled"] = v + volConf["enabled"] = v } if v, ok := opts["docker.volumes.selinuxlabel"]; ok { - conf["volumes_selinuxlabel"] = v + volConf["selinuxlabel"] = v } + conf["volumes"] = volConf // capabilities if v, ok := opts["docker.caps.whitelist"]; ok { @@ -121,6 +123,31 @@ var ( } // configSpec is the hcl specification returned by the ConfigSchema RPC + // and is used to parse the contents of the 'plugin "docker" {...}' block. + // Example: + // plugin "docker" { + // endpoint = "unix:///var/run/docker.sock" + // auth { + // config = "/etc/docker-auth.json" + // helper = "docker-credential-aws" + // } + // tls { + // cert = "/etc/nomad/nomad.pub" + // key = "/etc/nomad/nomad.pem" + // ca = "/etc/nomad/nomad.cert" + // } + // gc { + // image = true + // image_delay = "5m" + // container = false + // } + // volumes { + // enabled = true + // selinuxlabel = "z" + // } + // allow_privileged = false + // allow_caps = ["CHOWN", "NET_RAW" ... ] + // } configSpec = hclspec.NewObject(map[string]*hclspec.Spec{ "endpoint": hclspec.NewAttr("endpoint", "string", false), "auth": hclspec.NewBlock("auth", false, hclspec.NewObject(map[string]*hclspec.Spec{ @@ -143,12 +170,14 @@ var ( hclspec.NewLiteral("true"), ), })), - "volumes_enabled": hclspec.NewDefault( - hclspec.NewAttr("volumes_enabled", "bool", false), - hclspec.NewLiteral("true"), - ), - "volumes_selinuxlabel": hclspec.NewAttr("volumes_selinuxlabel", "string", false), - "allow_privileged": hclspec.NewAttr("allow_privileged", "bool", false), + "volumes": hclspec.NewBlock("volumes", false, hclspec.NewObject(map[string]*hclspec.Spec{ + "enabled": hclspec.NewDefault( + hclspec.NewAttr("enabled", "bool", false), + hclspec.NewLiteral("true"), + ), + "selinuxlabel": hclspec.NewAttr("selinuxlabel", "string", false), + })), + "allow_privileged": hclspec.NewAttr("allow_privileged", "bool", false), "allow_caps": hclspec.NewDefault( hclspec.NewAttr("allow_caps", "list(string)", false), hclspec.NewLiteral(`["CHOWN","DAC_OVERRIDE","FSETID","FOWNER","MKNOD","NET_RAW","SETGID","SETUID","SETFCAP","SETPCAP","NET_BIND_SERVICE","SYS_CHROOT","KILL","AUDIT_WRITE"]`), @@ -322,14 +351,13 @@ type DockerVolumeDriverConfig struct { } type DriverConfig struct { - Endpoint string `codec:"endpoint"` - AuthConfig AuthConfig `codec:"auth"` - TLS TLSConfig `codec:"tls"` - GC GCConfig `codec:"gc"` - VolumesEnabled bool `codec:"volumes_enabled"` - VolumesSelinuxLabel string `codec:"volumes_selinuxlabel"` - AllowPrivileged bool `codec:"allow_privileged"` - AllowCaps []string `codec:"allow_caps"` + Endpoint string `codec:"endpoint"` + Auth AuthConfig `codec:"auth"` + TLS TLSConfig `codec:"tls"` + GC GCConfig `codec:"gc"` + Volumes VolumeConfig `codec:"volumes"` + AllowPrivileged bool `codec:"allow_privileged"` + AllowCaps []string `codec:"allow_caps"` } type AuthConfig struct { @@ -349,3 +377,8 @@ type GCConfig struct { imageDelayDuration time.Duration `codec:"-"` Container bool `codec:"container"` } + +type VolumeConfig struct { + Enabled bool `codec:"enabled"` + SelinuxLabel string `codec:"selinuxlabel"` +} diff --git a/drivers/docker/driver.go b/drivers/docker/driver.go index 519538654..04699ff78 100644 --- a/drivers/docker/driver.go +++ b/drivers/docker/driver.go @@ -531,9 +531,8 @@ func (d *Driver) pullImage(task *drivers.TaskConfig, driverConfig *TaskConfig, c "image": dockerImageRef(repo, tag), }, }) - coordinator, callerID := d.getDockerCoordinator(client, task) - return coordinator.PullImage(driverConfig.Image, authOptions, callerID, d.emitEventFunc(task)) + return d.coordinator.PullImage(driverConfig.Image, authOptions, task.ID, d.emitEventFunc(task)) } func (d *Driver) emitEventFunc(task *drivers.TaskConfig) LogEventFn { @@ -555,8 +554,8 @@ type authBackend func(string) (*docker.AuthConfiguration, error) func (d *Driver) resolveRegistryAuthentication(driverConfig *TaskConfig, repo string) (*docker.AuthConfiguration, error) { return firstValidAuth(repo, []authBackend{ authFromTaskConfig(driverConfig), - authFromDockerConfig(d.config.AuthConfig), - authFromHelper(d.config.AuthHelper), + authFromDockerConfig(d.config.Auth.Config), + authFromHelper(d.config.Auth.Helper), }) } @@ -581,8 +580,7 @@ func (d *Driver) loadImage(task *drivers.TaskConfig, driverConfig *TaskConfig, c return "", recoverableErrTimeouts(err) } - coordinator, callerID := d.getDockerCoordinator(client, task) - coordinator.IncrementImageReference(dockerImage.ID, driverConfig.Image, callerID) + d.coordinator.IncrementImageReference(dockerImage.ID, driverConfig.Image, task.ID) return dockerImage.ID, nil } @@ -593,7 +591,7 @@ func (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConf secretDirBind := fmt.Sprintf("%s:%s", task.TaskDir().SecretsDir, task.Env[env.SecretsDir]) binds := []string{allocDirBind, taskLocalBind, secretDirBind} - if !d.config.VolumesEnabled && driverConfig.VolumeDriver != "" { + if !d.config.Volumes.Enabled && driverConfig.VolumeDriver != "" { return nil, fmt.Errorf("'volumes_enabled' is false; cannot use volume driver %q", driverConfig.VolumeDriver) } @@ -608,7 +606,7 @@ func (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConf // Absolute paths aren't always supported if filepath.IsAbs(parts[0]) { - if !d.config.VolumesEnabled { + if !d.config.Volumes.Enabled { // Disallow mounting arbitrary absolute paths return nil, fmt.Errorf("'volumes_enabled' is false; cannot mount host paths: %+q", userbind) } @@ -627,7 +625,7 @@ func (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConf binds = append(binds, strings.Join(parts, ":")) } - if selinuxLabel := d.config.VolumesSelinuxLabel; selinuxLabel != "" { + if selinuxLabel := d.config.Volumes.SelinuxLabel; selinuxLabel != "" { // Apply SELinux Label to each volume for i := range binds { binds[i] = fmt.Sprintf("%s:%s", binds[i], selinuxLabel) @@ -670,7 +668,7 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T } hostConfig := &docker.HostConfig{ - Memory: task.Resources.LinuxResources.MemoryLimitBytes, + Memory: task.Resources.LinuxResources.MemoryLimitBytes, CPUShares: task.Resources.LinuxResources.CPUShares, // Binds are used to mount a host volume into the container. We mount a @@ -1103,12 +1101,11 @@ func (d *Driver) DestroyTask(taskID string, force bool) error { // doesn't exist or is still in use. Requires the global client to already be // initialized. func (d *Driver) cleanupImage(handle *taskHandle) error { - if !d.config.ImageGC { + if !d.config.GC.Image { return nil } - coordinator, callerID := d.getDockerCoordinator(client, handle.task) - coordinator.RemoveImage(handle.container.Image, callerID) + d.coordinator.RemoveImage(handle.container.Image, handle.task.ID) return nil }