1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Add support for .Node.Hostname templating in swarm services

Signed-off-by: Carlo Mion <mion00@gmail.com>
This commit is contained in:
Carlo Mion 2017-08-30 21:45:05 +02:00
parent e23965d620
commit e2f09fa6dd
8 changed files with 32 additions and 16 deletions

View file

@ -41,8 +41,8 @@ type containerAdapter struct {
dependencies exec.DependencyGetter dependencies exec.DependencyGetter
} }
func newContainerAdapter(b executorpkg.Backend, task *api.Task, dependencies exec.DependencyGetter) (*containerAdapter, error) { func newContainerAdapter(b executorpkg.Backend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*containerAdapter, error) {
ctnr, err := newContainerConfig(task) ctnr, err := newContainerConfig(task, node)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -20,8 +20,8 @@ type networkAttacherController struct {
closed chan struct{} closed chan struct{}
} }
func newNetworkAttacherController(b executorpkg.Backend, task *api.Task, dependencies exec.DependencyGetter) (*networkAttacherController, error) { func newNetworkAttacherController(b executorpkg.Backend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*networkAttacherController, error) {
adapter, err := newContainerAdapter(b, task, dependencies) adapter, err := newContainerAdapter(b, task, node, dependencies)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -48,12 +48,12 @@ type containerConfig struct {
// newContainerConfig returns a validated container config. No methods should // newContainerConfig returns a validated container config. No methods should
// return an error if this function returns without error. // return an error if this function returns without error.
func newContainerConfig(t *api.Task) (*containerConfig, error) { func newContainerConfig(t *api.Task, node *api.NodeDescription) (*containerConfig, error) {
var c containerConfig var c containerConfig
return &c, c.setTask(t) return &c, c.setTask(t, node)
} }
func (c *containerConfig) setTask(t *api.Task) error { func (c *containerConfig) setTask(t *api.Task, node *api.NodeDescription) error {
if t.Spec.GetContainer() == nil && t.Spec.GetAttachment() == nil { if t.Spec.GetContainer() == nil && t.Spec.GetAttachment() == nil {
return exec.ErrRuntimeUnsupported return exec.ErrRuntimeUnsupported
} }
@ -78,7 +78,7 @@ func (c *containerConfig) setTask(t *api.Task) error {
c.task = t c.task = t
if t.Spec.GetContainer() != nil { if t.Spec.GetContainer() != nil {
preparedSpec, err := template.ExpandContainerSpec(nil, t) preparedSpec, err := template.ExpandContainerSpec(node, t)
if err != nil { if err != nil {
return err return err
} }

View file

@ -40,8 +40,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, dependencies exec.DependencyGetter) (*controller, error) { func newController(b executorpkg.Backend, task *api.Task, node *api.NodeDescription, dependencies exec.DependencyGetter) (*controller, error) {
adapter, err := newContainerAdapter(b, task, dependencies) adapter, err := newContainerAdapter(b, task, node, dependencies)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
"sync"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
@ -26,6 +27,8 @@ type executor struct {
backend executorpkg.Backend backend executorpkg.Backend
pluginBackend plugin.Backend pluginBackend plugin.Backend
dependencies exec.DependencyManager dependencies exec.DependencyManager
mutex sync.Mutex // This mutex protects the following node field
node *api.NodeDescription
} }
// NewExecutor returns an executor from the docker client. // NewExecutor returns an executor from the docker client.
@ -124,6 +127,11 @@ func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
}, },
} }
// Save the node information in the executor field
e.mutex.Lock()
e.node = description
e.mutex.Unlock()
return description, nil return description, nil
} }
@ -168,8 +176,13 @@ func (e *executor) Configure(ctx context.Context, node *api.Node) error {
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) dependencyGetter := agent.Restrict(e.dependencies, t)
// Get the node description from the executor field
e.mutex.Lock()
nodeDescription := e.node
e.mutex.Unlock()
if t.Spec.GetAttachment() != nil { if t.Spec.GetAttachment() != nil {
return newNetworkAttacherController(e.backend, t, dependencyGetter) return newNetworkAttacherController(e.backend, t, nodeDescription, dependencyGetter)
} }
var ctlr exec.Controller var ctlr exec.Controller
@ -198,7 +211,7 @@ func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
return ctlr, fmt.Errorf("unsupported runtime type: %q", runtimeKind) return ctlr, fmt.Errorf("unsupported runtime type: %q", runtimeKind)
} }
case *api.TaskSpec_Container: case *api.TaskSpec_Container:
c, err := newController(e.backend, t, dependencyGetter) c, err := newController(e.backend, t, nodeDescription, dependencyGetter)
if err != nil { if err != nil {
return ctlr, err return ctlr, err
} }

View file

@ -52,7 +52,7 @@ func TestHealthStates(t *testing.T) {
EventsService: e, EventsService: e,
} }
controller, err := newController(daemon, task, nil) controller, err := newController(daemon, task, nil, nil)
if err != nil { if err != nil {
t.Fatalf("create controller fail %v", err) t.Fatalf("create controller fail %v", err)
} }

View file

@ -26,7 +26,8 @@ func newTestControllerWithMount(m api.Mount) (*controller, error) {
}, },
}, },
}, },
}, nil) }, nil,
nil)
} }
func TestControllerValidateMountBind(t *testing.T) { func TestControllerValidateMountBind(t *testing.T) {

View file

@ -169,8 +169,10 @@ func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *check.C) {
func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *check.C) { func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *check.C) {
d := s.AddDaemon(c, true, true) d := s.AddDaemon(c, true, true)
hostname, err := d.Cmd("node", "inspect", "--format", "{{.Description.Hostname}}", "self")
c.Assert(err, checker.IsNil, check.Commentf(hostname))
out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "test", "--hostname", "{{.Service.Name}}-{{.Task.Slot}}", "busybox", "top") out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "test", "--hostname", "{{.Service.Name}}-{{.Task.Slot}}-{{.Node.Hostname}}", "busybox", "top")
c.Assert(err, checker.IsNil, check.Commentf(out)) c.Assert(err, checker.IsNil, check.Commentf(out))
// make sure task has been deployed. // make sure task has been deployed.
@ -179,7 +181,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *check.C) {
containers := d.ActiveContainers() containers := d.ActiveContainers()
out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.Hostname}}", containers[0]) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.Hostname}}", containers[0])
c.Assert(err, checker.IsNil, check.Commentf(out)) c.Assert(err, checker.IsNil, check.Commentf(out))
c.Assert(strings.Split(out, "\n")[0], checker.Equals, "test-1", check.Commentf("hostname with templating invalid")) c.Assert(strings.Split(out, "\n")[0], checker.Equals, "test-1-"+strings.Split(hostname, "\n")[0], check.Commentf("hostname with templating invalid"))
} }
// Test case for #24270 // Test case for #24270