From bf43d2a58d706ee9f31a3e441c5f45cc8263b341 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Tue, 27 Dec 2016 17:39:24 +0100 Subject: [PATCH] Make docker stack deploy a little bit more indempotent Sort some slice fields before sending them to the swarm api so that it won't trigger an update. Signed-off-by: Vincent Demeester --- cli/compose/convert/service.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/cli/compose/convert/service.go b/cli/compose/convert/service.go index 7597c0f568..05e4fa4d14 100644 --- a/cli/compose/convert/service.go +++ b/cli/compose/convert/service.go @@ -2,6 +2,7 @@ package convert import ( "fmt" + "sort" "time" "github.com/docker/docker/api/types/container" @@ -98,9 +99,9 @@ func convertService( Command: service.Entrypoint, Args: service.Command, Hostname: service.Hostname, - Hosts: convertExtraHosts(service.ExtraHosts), + Hosts: sortStrings(convertExtraHosts(service.ExtraHosts)), Healthcheck: healthcheck, - Env: convertEnvironment(service.Environment), + Env: sortStrings(convertEnvironment(service.Environment)), Labels: AddStackLabel(namespace, service.Labels), Dir: service.WorkingDir, User: service.User, @@ -125,6 +126,17 @@ func convertService( return serviceSpec, nil } +func sortStrings(strs []string) []string { + sort.Strings(strs) + return strs +} + +type byNetworkTarget []swarm.NetworkAttachmentConfig + +func (a byNetworkTarget) Len() int { return len(a) } +func (a byNetworkTarget) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byNetworkTarget) Less(i, j int) bool { return a[i].Target < a[j].Target } + func convertServiceNetworks( networks map[string]*composetypes.ServiceNetworkConfig, networkConfigs networkMap, @@ -160,6 +172,9 @@ func convertServiceNetworks( Aliases: append(aliases, name), }) } + + sort.Sort(byNetworkTarget(nets)) + return nets, nil } @@ -294,6 +309,12 @@ func convertResources(source composetypes.Resources) (*swarm.ResourceRequirement } +type byPublishedPort []swarm.PortConfig + +func (a byPublishedPort) Len() int { return len(a) } +func (a byPublishedPort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byPublishedPort) Less(i, j int) bool { return a[i].PublishedPort < a[j].PublishedPort } + func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) { portConfigs := []swarm.PortConfig{} ports, portBindings, err := nat.ParsePortSpecs(source) @@ -307,6 +328,9 @@ func convertEndpointSpec(source []string) (*swarm.EndpointSpec, error) { opts.ConvertPortToPortConfig(port, portBindings)...) } + // Sorting to make sure these are always in the same order + sort.Sort(byPublishedPort(portConfigs)) + return &swarm.EndpointSpec{Ports: portConfigs}, nil }