mirror of https://github.com/docker/cli.git
Merge pull request #27567 from yongtang/24391-dns-setting
Add custom DNS settings to service definition
This commit is contained in:
commit
f0c8571e5f
|
@ -41,6 +41,9 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")
|
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")
|
||||||
flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port")
|
flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port")
|
||||||
flags.StringSliceVar(&opts.groups, flagGroup, []string{}, "Set one or more supplementary user groups for the container")
|
flags.StringSliceVar(&opts.groups, flagGroup, []string{}, "Set one or more supplementary user groups for the container")
|
||||||
|
flags.Var(&opts.dns, flagDNS, "Set custom DNS servers")
|
||||||
|
flags.Var(&opts.dnsOptions, flagDNSOptions, "Set DNS options")
|
||||||
|
flags.Var(&opts.dnsSearch, flagDNSSearch, "Set custom DNS search domains")
|
||||||
|
|
||||||
flags.SetInterspersed(false)
|
flags.SetInterspersed(false)
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -296,6 +296,9 @@ type serviceOptions struct {
|
||||||
groups []string
|
groups []string
|
||||||
tty bool
|
tty bool
|
||||||
mounts opts.MountOpt
|
mounts opts.MountOpt
|
||||||
|
dns opts.ListOpts
|
||||||
|
dnsSearch opts.ListOpts
|
||||||
|
dnsOptions opts.ListOpts
|
||||||
|
|
||||||
resources resourceOptions
|
resources resourceOptions
|
||||||
stopGrace DurationOpt
|
stopGrace DurationOpt
|
||||||
|
@ -325,7 +328,10 @@ func newServiceOptions() *serviceOptions {
|
||||||
endpoint: endpointOptions{
|
endpoint: endpointOptions{
|
||||||
ports: opts.NewListOpts(ValidatePort),
|
ports: opts.NewListOpts(ValidatePort),
|
||||||
},
|
},
|
||||||
logDriver: newLogDriverOptions(),
|
logDriver: newLogDriverOptions(),
|
||||||
|
dns: opts.NewListOpts(opts.ValidateIPAddress),
|
||||||
|
dnsOptions: opts.NewListOpts(nil),
|
||||||
|
dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,16 +364,21 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
|
||||||
},
|
},
|
||||||
TaskTemplate: swarm.TaskSpec{
|
TaskTemplate: swarm.TaskSpec{
|
||||||
ContainerSpec: swarm.ContainerSpec{
|
ContainerSpec: swarm.ContainerSpec{
|
||||||
Image: opts.image,
|
Image: opts.image,
|
||||||
Args: opts.args,
|
Args: opts.args,
|
||||||
Env: currentEnv,
|
Env: currentEnv,
|
||||||
Hostname: opts.hostname,
|
Hostname: opts.hostname,
|
||||||
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
|
Labels: runconfigopts.ConvertKVStringsToMap(opts.containerLabels.GetAll()),
|
||||||
Dir: opts.workdir,
|
Dir: opts.workdir,
|
||||||
User: opts.user,
|
User: opts.user,
|
||||||
Groups: opts.groups,
|
Groups: opts.groups,
|
||||||
TTY: opts.tty,
|
TTY: opts.tty,
|
||||||
Mounts: opts.mounts.Value(),
|
Mounts: opts.mounts.Value(),
|
||||||
|
DNSConfig: &swarm.DNSConfig{
|
||||||
|
Nameservers: opts.dns.GetAll(),
|
||||||
|
Search: opts.dnsSearch.GetAll(),
|
||||||
|
Options: opts.dnsOptions.GetAll(),
|
||||||
|
},
|
||||||
StopGracePeriod: opts.stopGrace.Value(),
|
StopGracePeriod: opts.stopGrace.Value(),
|
||||||
},
|
},
|
||||||
Networks: convertNetworks(opts.networks),
|
Networks: convertNetworks(opts.networks),
|
||||||
|
@ -463,6 +474,15 @@ const (
|
||||||
flagContainerLabel = "container-label"
|
flagContainerLabel = "container-label"
|
||||||
flagContainerLabelRemove = "container-label-rm"
|
flagContainerLabelRemove = "container-label-rm"
|
||||||
flagContainerLabelAdd = "container-label-add"
|
flagContainerLabelAdd = "container-label-add"
|
||||||
|
flagDNS = "dns"
|
||||||
|
flagDNSRemove = "dns-rm"
|
||||||
|
flagDNSAdd = "dns-add"
|
||||||
|
flagDNSOptions = "dns-options"
|
||||||
|
flagDNSOptionsRemove = "dns-options-rm"
|
||||||
|
flagDNSOptionsAdd = "dns-options-add"
|
||||||
|
flagDNSSearch = "dns-search"
|
||||||
|
flagDNSSearchRemove = "dns-search-rm"
|
||||||
|
flagDNSSearchAdd = "dns-search-add"
|
||||||
flagEndpointMode = "endpoint-mode"
|
flagEndpointMode = "endpoint-mode"
|
||||||
flagHostname = "hostname"
|
flagHostname = "hostname"
|
||||||
flagEnv = "env"
|
flagEnv = "env"
|
||||||
|
|
|
@ -48,6 +48,9 @@ func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path")
|
flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path")
|
||||||
flags.Var(newListOptsVar(), flagPublishRemove, "Remove a published port by its target port")
|
flags.Var(newListOptsVar(), flagPublishRemove, "Remove a published port by its target port")
|
||||||
flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint")
|
flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint")
|
||||||
|
flags.Var(newListOptsVar(), flagDNSRemove, "Remove custom DNS servers")
|
||||||
|
flags.Var(newListOptsVar(), flagDNSOptionsRemove, "Remove DNS options")
|
||||||
|
flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove DNS search domains")
|
||||||
flags.Var(&opts.labels, flagLabelAdd, "Add or update a service label")
|
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.containerLabels, flagContainerLabelAdd, "Add or update a container label")
|
||||||
flags.Var(&opts.env, flagEnvAdd, "Add or update an environment variable")
|
flags.Var(&opts.env, flagEnvAdd, "Add or update an environment variable")
|
||||||
|
@ -55,6 +58,10 @@ func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
flags.StringSliceVar(&opts.constraints, flagConstraintAdd, []string{}, "Add or update a placement constraint")
|
flags.StringSliceVar(&opts.constraints, flagConstraintAdd, []string{}, "Add or update a placement constraint")
|
||||||
flags.Var(&opts.endpoint.ports, flagPublishAdd, "Add or update a published port")
|
flags.Var(&opts.endpoint.ports, flagPublishAdd, "Add or update a published port")
|
||||||
flags.StringSliceVar(&opts.groups, flagGroupAdd, []string{}, "Add an additional supplementary user group to the container")
|
flags.StringSliceVar(&opts.groups, flagGroupAdd, []string{}, "Add an additional supplementary user group to the container")
|
||||||
|
flags.Var(&opts.dns, flagDNSAdd, "Add or update custom DNS servers")
|
||||||
|
flags.Var(&opts.dnsOptions, flagDNSOptionsAdd, "Add or update DNS options")
|
||||||
|
flags.Var(&opts.dnsSearch, flagDNSSearchAdd, "Add or update custom DNS search domains")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +264,15 @@ func updateService(flags *pflag.FlagSet, spec *swarm.ServiceSpec) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if anyChanged(flags, flagDNSAdd, flagDNSRemove, flagDNSOptionsAdd, flagDNSOptionsRemove, flagDNSSearchAdd, flagDNSSearchRemove) {
|
||||||
|
if cspec.DNSConfig == nil {
|
||||||
|
cspec.DNSConfig = &swarm.DNSConfig{}
|
||||||
|
}
|
||||||
|
if err := updateDNSConfig(flags, &cspec.DNSConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := updateLogDriver(flags, &spec.TaskTemplate); err != nil {
|
if err := updateLogDriver(flags, &spec.TaskTemplate); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -484,6 +500,71 @@ func updateGroups(flags *pflag.FlagSet, groups *[]string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeDuplicates(entries []string) []string {
|
||||||
|
hit := map[string]bool{}
|
||||||
|
newEntries := []string{}
|
||||||
|
for _, v := range entries {
|
||||||
|
if !hit[v] {
|
||||||
|
newEntries = append(newEntries, v)
|
||||||
|
hit[v] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateDNSConfig(flags *pflag.FlagSet, config **swarm.DNSConfig) error {
|
||||||
|
newConfig := &swarm.DNSConfig{}
|
||||||
|
|
||||||
|
nameservers := (*config).Nameservers
|
||||||
|
if flags.Changed(flagDNSAdd) {
|
||||||
|
values := flags.Lookup(flagDNSAdd).Value.(*opts.ListOpts).GetAll()
|
||||||
|
nameservers = append(nameservers, values...)
|
||||||
|
}
|
||||||
|
nameservers = removeDuplicates(nameservers)
|
||||||
|
toRemove := buildToRemoveSet(flags, flagDNSRemove)
|
||||||
|
for _, nameserver := range nameservers {
|
||||||
|
if _, exists := toRemove[nameserver]; !exists {
|
||||||
|
newConfig.Nameservers = append(newConfig.Nameservers, nameserver)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort so that result is predictable.
|
||||||
|
sort.Strings(newConfig.Nameservers)
|
||||||
|
|
||||||
|
search := (*config).Search
|
||||||
|
if flags.Changed(flagDNSSearchAdd) {
|
||||||
|
values := flags.Lookup(flagDNSSearchAdd).Value.(*opts.ListOpts).GetAll()
|
||||||
|
search = append(search, values...)
|
||||||
|
}
|
||||||
|
search = removeDuplicates(search)
|
||||||
|
toRemove = buildToRemoveSet(flags, flagDNSSearchRemove)
|
||||||
|
for _, entry := range search {
|
||||||
|
if _, exists := toRemove[entry]; !exists {
|
||||||
|
newConfig.Search = append(newConfig.Search, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort so that result is predictable.
|
||||||
|
sort.Strings(newConfig.Search)
|
||||||
|
|
||||||
|
options := (*config).Options
|
||||||
|
if flags.Changed(flagDNSOptionsAdd) {
|
||||||
|
values := flags.Lookup(flagDNSOptionsAdd).Value.(*opts.ListOpts).GetAll()
|
||||||
|
options = append(options, values...)
|
||||||
|
}
|
||||||
|
options = removeDuplicates(options)
|
||||||
|
toRemove = buildToRemoveSet(flags, flagDNSOptionsRemove)
|
||||||
|
for _, option := range options {
|
||||||
|
if _, exists := toRemove[option]; !exists {
|
||||||
|
newConfig.Options = append(newConfig.Options, option)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort so that result is predictable.
|
||||||
|
sort.Strings(newConfig.Options)
|
||||||
|
|
||||||
|
*config = newConfig
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type byPortConfig []swarm.PortConfig
|
type byPortConfig []swarm.PortConfig
|
||||||
|
|
||||||
func (r byPortConfig) Len() int { return len(r) }
|
func (r byPortConfig) Len() int { return len(r) }
|
||||||
|
|
|
@ -120,6 +120,52 @@ func TestUpdateGroups(t *testing.T) {
|
||||||
assert.Equal(t, groups[2], "wheel")
|
assert.Equal(t, groups[2], "wheel")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdateDNSConfig(t *testing.T) {
|
||||||
|
flags := newUpdateCommand(nil).Flags()
|
||||||
|
|
||||||
|
// IPv4, with duplicates
|
||||||
|
flags.Set("dns-add", "1.1.1.1")
|
||||||
|
flags.Set("dns-add", "1.1.1.1")
|
||||||
|
flags.Set("dns-add", "2.2.2.2")
|
||||||
|
flags.Set("dns-rm", "3.3.3.3")
|
||||||
|
flags.Set("dns-rm", "2.2.2.2")
|
||||||
|
// IPv6
|
||||||
|
flags.Set("dns-add", "2001:db8:abc8::1")
|
||||||
|
// Invalid dns record
|
||||||
|
assert.Error(t, flags.Set("dns-add", "x.y.z.w"), "x.y.z.w is not an ip address")
|
||||||
|
|
||||||
|
// domains with duplicates
|
||||||
|
flags.Set("dns-search-add", "example.com")
|
||||||
|
flags.Set("dns-search-add", "example.com")
|
||||||
|
flags.Set("dns-search-add", "example.org")
|
||||||
|
flags.Set("dns-search-rm", "example.org")
|
||||||
|
// Invalid dns search domain
|
||||||
|
assert.Error(t, flags.Set("dns-search-add", "example$com"), "example$com is not a valid domain")
|
||||||
|
|
||||||
|
flags.Set("dns-options-add", "ndots:9")
|
||||||
|
flags.Set("dns-options-rm", "timeout:3")
|
||||||
|
|
||||||
|
config := &swarm.DNSConfig{
|
||||||
|
Nameservers: []string{"3.3.3.3", "5.5.5.5"},
|
||||||
|
Search: []string{"localdomain"},
|
||||||
|
Options: []string{"timeout:3"},
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDNSConfig(flags, &config)
|
||||||
|
|
||||||
|
assert.Equal(t, len(config.Nameservers), 3)
|
||||||
|
assert.Equal(t, config.Nameservers[0], "1.1.1.1")
|
||||||
|
assert.Equal(t, config.Nameservers[1], "2001:db8:abc8::1")
|
||||||
|
assert.Equal(t, config.Nameservers[2], "5.5.5.5")
|
||||||
|
|
||||||
|
assert.Equal(t, len(config.Search), 2)
|
||||||
|
assert.Equal(t, config.Search[0], "example.com")
|
||||||
|
assert.Equal(t, config.Search[1], "localdomain")
|
||||||
|
|
||||||
|
assert.Equal(t, len(config.Options), 1)
|
||||||
|
assert.Equal(t, config.Options[0], "ndots:9")
|
||||||
|
}
|
||||||
|
|
||||||
func TestUpdateMounts(t *testing.T) {
|
func TestUpdateMounts(t *testing.T) {
|
||||||
flags := newUpdateCommand(nil).Flags()
|
flags := newUpdateCommand(nil).Flags()
|
||||||
flags.Set("mount-add", "type=volume,source=vol2,target=/toadd")
|
flags.Set("mount-add", "type=volume,source=vol2,target=/toadd")
|
||||||
|
|
Loading…
Reference in New Issue