|
@@ -24,7 +24,7 @@ import (
|
|
|
)
|
|
|
|
|
|
func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
|
- opts := newServiceOptions()
|
|
|
+ serviceOpts := newServiceOptions()
|
|
|
|
|
|
cmd := &cobra.Command{
|
|
|
Use: "update [OPTIONS] SERVICE",
|
|
@@ -40,36 +40,33 @@ func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|
|
flags.String("args", "", "Service command args")
|
|
|
flags.Bool("rollback", false, "Rollback to previous specification")
|
|
|
flags.Bool("force", false, "Force update even if no changes require it")
|
|
|
- addServiceFlags(cmd, opts)
|
|
|
+ addServiceFlags(cmd, serviceOpts)
|
|
|
|
|
|
flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable")
|
|
|
flags.Var(newListOptsVar(), flagGroupRemove, "Remove a previously added supplementary user group from the container")
|
|
|
flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key")
|
|
|
flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key")
|
|
|
flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path")
|
|
|
- flags.Var(newListOptsVar().WithValidator(validatePublishRemove), flagPublishRemove, "Remove a published port by its target port")
|
|
|
- flags.MarkHidden(flagPublishRemove)
|
|
|
- flags.Var(newListOptsVar(), flagPortRemove, "Remove a port(target-port mandatory)")
|
|
|
+ // flags.Var(newListOptsVar().WithValidator(validatePublishRemove), flagPublishRemove, "Remove a published port by its target port")
|
|
|
+ flags.Var(&opts.PortOpt{}, flagPublishRemove, "Remove a published port by its target port")
|
|
|
flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint")
|
|
|
flags.Var(newListOptsVar(), flagDNSRemove, "Remove a custom DNS server")
|
|
|
flags.Var(newListOptsVar(), flagDNSOptionRemove, "Remove a DNS option")
|
|
|
flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove a DNS search domain")
|
|
|
flags.Var(newListOptsVar(), flagHostRemove, "Remove a custom host-to-IP mapping (host:ip)")
|
|
|
- flags.Var(&opts.labels, flagLabelAdd, "Add or update a service label")
|
|
|
- flags.Var(&opts.containerLabels, flagContainerLabelAdd, "Add or update a container label")
|
|
|
- flags.Var(&opts.env, flagEnvAdd, "Add or update an environment variable")
|
|
|
+ flags.Var(&serviceOpts.labels, flagLabelAdd, "Add or update a service label")
|
|
|
+ flags.Var(&serviceOpts.containerLabels, flagContainerLabelAdd, "Add or update a container label")
|
|
|
+ flags.Var(&serviceOpts.env, flagEnvAdd, "Add or update an environment variable")
|
|
|
flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret")
|
|
|
- flags.Var(&opts.secrets, flagSecretAdd, "Add or update a secret on a service")
|
|
|
- flags.Var(&opts.mounts, flagMountAdd, "Add or update a mount on a service")
|
|
|
- flags.Var(&opts.constraints, flagConstraintAdd, "Add or update a placement constraint")
|
|
|
- flags.Var(&opts.endpoint.publishPorts, flagPublishAdd, "Add or update a published port")
|
|
|
- flags.MarkHidden(flagPublishAdd)
|
|
|
- flags.Var(&opts.endpoint.expandedPorts, flagPortAdd, "Add or update a port")
|
|
|
- flags.Var(&opts.groups, flagGroupAdd, "Add an additional supplementary user group to the container")
|
|
|
- flags.Var(&opts.dns, flagDNSAdd, "Add or update a custom DNS server")
|
|
|
- flags.Var(&opts.dnsOption, flagDNSOptionAdd, "Add or update a DNS option")
|
|
|
- flags.Var(&opts.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain")
|
|
|
- flags.Var(&opts.hosts, flagHostAdd, "Add or update a custom host-to-IP mapping (host:ip)")
|
|
|
+ flags.Var(&serviceOpts.secrets, flagSecretAdd, "Add or update a secret on a service")
|
|
|
+ flags.Var(&serviceOpts.mounts, flagMountAdd, "Add or update a mount on a service")
|
|
|
+ flags.Var(&serviceOpts.constraints, flagConstraintAdd, "Add or update a placement constraint")
|
|
|
+ flags.Var(&serviceOpts.endpoint.publishPorts, flagPublishAdd, "Add or update a published port")
|
|
|
+ flags.Var(&serviceOpts.groups, flagGroupAdd, "Add an additional supplementary user group to the container")
|
|
|
+ flags.Var(&serviceOpts.dns, flagDNSAdd, "Add or update a custom DNS server")
|
|
|
+ flags.Var(&serviceOpts.dnsOption, flagDNSOptionAdd, "Add or update a DNS option")
|
|
|
+ flags.Var(&serviceOpts.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain")
|
|
|
+ flags.Var(&serviceOpts.hosts, flagHostAdd, "Add or update a custom host-to-IP mapping (host:ip)")
|
|
|
|
|
|
return cmd
|
|
|
}
|
|
@@ -276,7 +273,7 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if anyChanged(flags, flagPublishAdd, flagPublishRemove, flagPortAdd, flagPortRemove) {
|
|
|
+ if anyChanged(flags, flagPublishAdd, flagPublishRemove) {
|
|
|
if spec.EndpointSpec == nil {
|
|
|
spec.EndpointSpec = &swarm.EndpointSpec{}
|
|
|
}
|
|
@@ -633,18 +630,11 @@ func (r byPortConfig) Less(i, j int) bool {
|
|
|
|
|
|
func portConfigToString(portConfig *swarm.PortConfig) string {
|
|
|
protocol := portConfig.Protocol
|
|
|
- if protocol == "" {
|
|
|
- protocol = "tcp"
|
|
|
- }
|
|
|
-
|
|
|
mode := portConfig.PublishMode
|
|
|
- if mode == "" {
|
|
|
- mode = "ingress"
|
|
|
- }
|
|
|
-
|
|
|
return fmt.Sprintf("%v:%v/%s/%s", portConfig.PublishedPort, portConfig.TargetPort, protocol, mode)
|
|
|
}
|
|
|
|
|
|
+// FIXME(vdemeester) port to opts.PortOpt
|
|
|
// This validation is only used for `--publish-rm`.
|
|
|
// The `--publish-rm` takes:
|
|
|
// <TargetPort>[/<Protocol>] (e.g., 80, 80/tcp, 53/udp)
|
|
@@ -665,58 +655,21 @@ func validatePublishRemove(val string) (string, error) {
|
|
|
func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error {
|
|
|
// The key of the map is `port/protocol`, e.g., `80/tcp`
|
|
|
portSet := map[string]swarm.PortConfig{}
|
|
|
- // Check to see if there are any conflict in flags.
|
|
|
- if flags.Changed(flagPublishAdd) {
|
|
|
- values := flags.Lookup(flagPublishAdd).Value.(*opts.ListOpts).GetAll()
|
|
|
- ports, portBindings, _ := nat.ParsePortSpecs(values)
|
|
|
-
|
|
|
- for port := range ports {
|
|
|
- newConfigs := ConvertPortToPortConfig(port, portBindings)
|
|
|
- for _, entry := range newConfigs {
|
|
|
- if v, ok := portSet[portConfigToString(&entry)]; ok && v != entry {
|
|
|
- return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", entry.PublishedPort, entry.TargetPort, entry.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
|
|
|
- }
|
|
|
- portSet[portConfigToString(&entry)] = entry
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if flags.Changed(flagPortAdd) {
|
|
|
- for _, entry := range flags.Lookup(flagPortAdd).Value.(*opts.PortOpt).Value() {
|
|
|
- if v, ok := portSet[portConfigToString(&entry)]; ok && v != entry {
|
|
|
- return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", entry.PublishedPort, entry.TargetPort, entry.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
|
|
|
- }
|
|
|
- portSet[portConfigToString(&entry)] = entry
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- // Override previous PortConfig in service if there is any duplicate
|
|
|
+ // Build the current list of portConfig
|
|
|
for _, entry := range *portConfig {
|
|
|
if _, ok := portSet[portConfigToString(&entry)]; !ok {
|
|
|
portSet[portConfigToString(&entry)] = entry
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.ListOpts).GetAll()
|
|
|
- removePortCSV := flags.Lookup(flagPortRemove).Value.(*opts.ListOpts).GetAll()
|
|
|
- removePortOpts := &opts.PortOpt{}
|
|
|
- for _, portCSV := range removePortCSV {
|
|
|
- if err := removePortOpts.Set(portCSV); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
newPorts := []swarm.PortConfig{}
|
|
|
+
|
|
|
+ // Clean current ports
|
|
|
+ toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.PortOpt).Value()
|
|
|
portLoop:
|
|
|
for _, port := range portSet {
|
|
|
- for _, rawTargetPort := range toRemove {
|
|
|
- targetPort := nat.Port(rawTargetPort)
|
|
|
- if equalPort(targetPort, port) {
|
|
|
- continue portLoop
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for _, pConfig := range removePortOpts.Value() {
|
|
|
+ for _, pConfig := range toRemove {
|
|
|
if equalProtocol(port.Protocol, pConfig.Protocol) &&
|
|
|
port.TargetPort == pConfig.TargetPort &&
|
|
|
equalPublishMode(port.PublishMode, pConfig.PublishMode) {
|
|
@@ -727,6 +680,23 @@ portLoop:
|
|
|
newPorts = append(newPorts, port)
|
|
|
}
|
|
|
|
|
|
+ // Check to see if there are any conflict in flags.
|
|
|
+ if flags.Changed(flagPublishAdd) {
|
|
|
+ ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value()
|
|
|
+
|
|
|
+ for _, port := range ports {
|
|
|
+ if v, ok := portSet[portConfigToString(&port)]; ok {
|
|
|
+ if v != port {
|
|
|
+ fmt.Println("v", v)
|
|
|
+ return fmt.Errorf("conflicting port mapping between %v:%v/%s and %v:%v/%s", port.PublishedPort, port.TargetPort, port.Protocol, v.PublishedPort, v.TargetPort, v.Protocol)
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ //portSet[portConfigToString(&port)] = port
|
|
|
+ newPorts = append(newPorts, port)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Sort the PortConfig to avoid unnecessary updates
|
|
|
sort.Sort(byPortConfig(newPorts))
|
|
|
*portConfig = newPorts
|