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:
parent
e23965d620
commit
e2f09fa6dd
8 changed files with 32 additions and 16 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ func newTestControllerWithMount(m api.Mount) (*controller, error) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil,
|
||||||
|
nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControllerValidateMountBind(t *testing.T) {
|
func TestControllerValidateMountBind(t *testing.T) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue