зеркало из https://github.com/microsoft/docker.git
Merge branch 'master' into discordianfish-https_client
Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
This commit is contained in:
Коммит
aa63ece2ec
|
@ -18,6 +18,7 @@ type Config struct {
|
|||
Root string
|
||||
AutoRestart bool
|
||||
Dns []string
|
||||
DnsSearch []string
|
||||
EnableIptables bool
|
||||
EnableIpForward bool
|
||||
DefaultIp net.IP
|
||||
|
@ -49,6 +50,9 @@ func ConfigFromJob(job *engine.Job) *Config {
|
|||
if dns := job.GetenvList("Dns"); dns != nil {
|
||||
config.Dns = dns
|
||||
}
|
||||
if dnsSearch := job.GetenvList("DnsSearch"); dnsSearch != nil {
|
||||
config.DnsSearch = dnsSearch
|
||||
}
|
||||
if mtu := job.GetenvInt("Mtu"); mtu != 0 {
|
||||
config.Mtu = mtu
|
||||
} else {
|
||||
|
|
|
@ -48,6 +48,7 @@ func main() {
|
|||
flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specified by -H when running in daemon mode; use '' (the empty string) to disable setting of a group")
|
||||
flEnableCors = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
|
||||
flDns = opts.NewListOpts(opts.ValidateIp4Address)
|
||||
flDnsSearch = opts.NewListOpts(opts.ValidateDomain)
|
||||
flEnableIptables = flag.Bool([]string{"#iptables", "-iptables"}, true, "Enable Docker's addition of iptables rules")
|
||||
flEnableIpForward = flag.Bool([]string{"#ip-forward", "-ip-forward"}, true, "Enable net.ipv4.ip_forward")
|
||||
flDefaultIp = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
|
||||
|
@ -63,6 +64,7 @@ func main() {
|
|||
flKey = flag.String([]string{"-tlskey"}, dockerConfDir+defaultKeyFile, "Path to TLS key file")
|
||||
)
|
||||
flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers")
|
||||
flag.Var(&flDnsSearch, []string{"-dns-search"}, "Force Docker to use specific DNS search domains")
|
||||
flag.Var(&flHosts, []string{"H", "-host"}, "tcp://host:port, unix://path/to/socket, fd://* or fd://socketfd to use in daemon mode. Multiple sockets can be specified")
|
||||
|
||||
flag.Parse()
|
||||
|
@ -134,6 +136,7 @@ func main() {
|
|||
job.Setenv("Root", realRoot)
|
||||
job.SetenvBool("AutoRestart", *flAutoRestart)
|
||||
job.SetenvList("Dns", flDns.GetAll())
|
||||
job.SetenvList("DnsSearch", flDnsSearch.GetAll())
|
||||
job.SetenvBool("EnableIptables", *flEnableIptables)
|
||||
job.SetenvBool("EnableIpForward", *flEnableIpForward)
|
||||
job.Setenv("BridgeIface", *bridgeName)
|
||||
|
|
|
@ -136,6 +136,7 @@ Create a container
|
|||
},
|
||||
"VolumesFrom":"",
|
||||
"WorkingDir":"",
|
||||
"DisableNetwork": false,
|
||||
"ExposedPorts":{
|
||||
"22/tcp": {}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ Commands
|
|||
--bip="": Use this CIDR notation address for the network bridge's IP, not compatible with -b
|
||||
-d, --daemon=false: Enable daemon mode
|
||||
--dns=[]: Force docker to use specific DNS servers
|
||||
--dns-search=[]: Force Docker to use specific DNS search domains
|
||||
-g, --graph="/var/lib/docker": Path to use as the root of the docker runtime
|
||||
--icc=true: Enable inter-container communication
|
||||
--ip="0.0.0.0": Default IP address to use when binding container ports
|
||||
|
@ -101,6 +102,8 @@ To force Docker to use devicemapper as the storage driver, use ``docker -d -s de
|
|||
|
||||
To set the DNS server for all Docker containers, use ``docker -d --dns 8.8.8.8``.
|
||||
|
||||
To set the DNS search domain for all Docker containers, use ``docker -d --dns-search example.com``.
|
||||
|
||||
To run the daemon with debug output, use ``docker -d -D``.
|
||||
|
||||
To use lxc as the execution driver, use ``docker -d -e lxc``.
|
||||
|
@ -401,6 +404,7 @@ not overridden in the JSON hash will be merged in.
|
|||
"VolumesFrom" : "",
|
||||
"Cmd" : ["cat", "-e", "/etc/resolv.conf"],
|
||||
"Dns" : ["8.8.8.8", "8.8.4.4"],
|
||||
"DnsSearch" : ["example.com"],
|
||||
"MemorySwap" : 0,
|
||||
"AttachStdin" : false,
|
||||
"AttachStderr" : false,
|
||||
|
@ -1136,6 +1140,7 @@ image is removed.
|
|||
-t, --tty=false: Allocate a pseudo-tty
|
||||
-u, --user="": Username or UID
|
||||
--dns=[]: Set custom dns servers for the container
|
||||
--dns-search=[]: Set custom DNS search domains for the container
|
||||
-v, --volume=[]: Create a bind mount to a directory or file with: [host-path]:[container-path]:[rw|ro]. If a directory "container-path" is missing, then docker creates a new volume.
|
||||
--volumes-from="": Mount all volumes from the given container(s)
|
||||
--entrypoint="": Overwrite the default entrypoint set by the image
|
||||
|
@ -1293,7 +1298,7 @@ A complete example
|
|||
$ sudo docker run -d --name static static-web-files sh
|
||||
$ sudo docker run -d --expose=8098 --name riak riakserver
|
||||
$ sudo docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver
|
||||
$ sudo docker run -d -p 1443:443 --dns=dns.dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
|
||||
$ sudo docker run -d -p 1443:443 --dns=dns.dev.org --dns-search=dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver
|
||||
$ sudo docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log
|
||||
|
||||
This example shows 5 containers that might be set up to test a web application change:
|
||||
|
@ -1301,7 +1306,7 @@ This example shows 5 containers that might be set up to test a web application c
|
|||
1. Start a pre-prepared volume image ``static-web-files`` (in the background) that has CSS, image and static HTML in it, (with a ``VOLUME`` instruction in the ``Dockerfile`` to allow the web server to use those files);
|
||||
2. Start a pre-prepared ``riakserver`` image, give the container name ``riak`` and expose port ``8098`` to any containers that link to it;
|
||||
3. Start the ``appserver`` image, restricting its memory usage to 100MB, setting two environment variables ``DEVELOPMENT`` and ``BRANCH`` and bind-mounting the current directory (``$(pwd)``) in the container in read-only mode as ``/app/bin``;
|
||||
4. Start the ``webserver``, mapping port ``443`` in the container to port ``1443`` on the Docker server, setting the DNS server to ``dns.dev.org``, creating a volume to put the log files into (so we can access it from another container), then importing the files from the volume exposed by the ``static`` container, and linking to all exposed ports from ``riak`` and ``app``. Lastly, we set the hostname to ``web.sven.dev.org`` so its consistent with the pre-generated SSL certificate;
|
||||
4. Start the ``webserver``, mapping port ``443`` in the container to port ``1443`` on the Docker server, setting the DNS server to ``dns.dev.org`` and DNS search domain to ``dev.org``, creating a volume to put the log files into (so we can access it from another container), then importing the files from the volume exposed by the ``static`` container, and linking to all exposed ports from ``riak`` and ``app``. Lastly, we set the hostname to ``web.sven.dev.org`` so its consistent with the pre-generated SSL certificate;
|
||||
5. Finally, we create a container that runs ``tail -f access.log`` using the logs volume from the ``web`` container, setting the workdir to ``/var/log/httpd``. The ``--rm`` option means that when the container exits, the container's layer is removed.
|
||||
|
||||
|
||||
|
|
13
opts/opts.go
13
opts/opts.go
|
@ -136,3 +136,16 @@ func ValidateIp4Address(val string) (string, error) {
|
|||
}
|
||||
return "", fmt.Errorf("%s is not an ip4 address", val)
|
||||
}
|
||||
|
||||
func ValidateDomain(val string) (string, error) {
|
||||
alpha := regexp.MustCompile(`[a-zA-Z]`)
|
||||
if alpha.FindString(val) == "" {
|
||||
return "", fmt.Errorf("%s is not a valid domain", val)
|
||||
}
|
||||
re := regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
|
||||
ns := re.FindSubmatch([]byte(val))
|
||||
if len(ns) > 0 {
|
||||
return string(ns[1]), nil
|
||||
}
|
||||
return "", fmt.Errorf("%s is not a valid domain", val)
|
||||
}
|
||||
|
|
|
@ -22,3 +22,57 @@ func TestValidateIP4(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestValidateDomain(t *testing.T) {
|
||||
valid := []string{
|
||||
`a`,
|
||||
`a.`,
|
||||
`1.foo`,
|
||||
`17.foo`,
|
||||
`foo.bar`,
|
||||
`foo.bar.baz`,
|
||||
`foo.bar.`,
|
||||
`foo.bar.baz`,
|
||||
`foo1.bar2`,
|
||||
`foo1.bar2.baz`,
|
||||
`1foo.2bar.`,
|
||||
`1foo.2bar.baz`,
|
||||
`foo-1.bar-2`,
|
||||
`foo-1.bar-2.baz`,
|
||||
`foo-1.bar-2.`,
|
||||
`foo-1.bar-2.baz`,
|
||||
`1-foo.2-bar`,
|
||||
`1-foo.2-bar.baz`,
|
||||
`1-foo.2-bar.`,
|
||||
`1-foo.2-bar.baz`,
|
||||
}
|
||||
|
||||
invalid := []string{
|
||||
``,
|
||||
`.`,
|
||||
`17`,
|
||||
`17.`,
|
||||
`.17`,
|
||||
`17-.`,
|
||||
`17-.foo`,
|
||||
`.foo`,
|
||||
`foo-.bar`,
|
||||
`-foo.bar`,
|
||||
`foo.bar-`,
|
||||
`foo.bar-.baz`,
|
||||
`foo.-bar`,
|
||||
`foo.-bar.baz`,
|
||||
}
|
||||
|
||||
for _, domain := range valid {
|
||||
if ret, err := ValidateDomain(domain); err != nil || ret == "" {
|
||||
t.Fatalf("ValidateDomain(`"+domain+"`) got %s %s", ret, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, domain := range invalid {
|
||||
if ret, err := ValidateDomain(domain); err == nil || ret != "" {
|
||||
t.Fatalf("ValidateDomain(`"+domain+"`) got %s %s", ret, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ func Compare(a, b *Config) bool {
|
|||
}
|
||||
if len(a.Cmd) != len(b.Cmd) ||
|
||||
len(a.Dns) != len(b.Dns) ||
|
||||
len(a.DnsSearch) != len(b.DnsSearch) ||
|
||||
len(a.Env) != len(b.Env) ||
|
||||
len(a.PortSpecs) != len(b.PortSpecs) ||
|
||||
len(a.ExposedPorts) != len(b.ExposedPorts) ||
|
||||
|
@ -38,6 +39,11 @@ func Compare(a, b *Config) bool {
|
|||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(a.DnsSearch); i++ {
|
||||
if a.DnsSearch[i] != b.DnsSearch[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(a.Env); i++ {
|
||||
if a.Env[i] != b.Env[i] {
|
||||
return false
|
||||
|
|
|
@ -26,6 +26,7 @@ type Config struct {
|
|||
Env []string
|
||||
Cmd []string
|
||||
Dns []string
|
||||
DnsSearch []string
|
||||
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
||||
Volumes map[string]struct{}
|
||||
VolumesFrom string
|
||||
|
@ -68,6 +69,9 @@ func ContainerConfigFromJob(job *engine.Job) *Config {
|
|||
if Dns := job.GetenvList("Dns"); Dns != nil {
|
||||
config.Dns = Dns
|
||||
}
|
||||
if DnsSearch := job.GetenvList("DnsSearch"); DnsSearch != nil {
|
||||
config.DnsSearch = DnsSearch
|
||||
}
|
||||
if Entrypoint := job.GetenvList("Entrypoint"); Entrypoint != nil {
|
||||
config.Entrypoint = Entrypoint
|
||||
}
|
||||
|
|
|
@ -164,6 +164,7 @@ func TestCompare(t *testing.T) {
|
|||
volumes1["/test1"] = struct{}{}
|
||||
config1 := Config{
|
||||
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||
DnsSearch: []string{"foo", "bar"},
|
||||
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "11111111",
|
||||
|
@ -171,6 +172,7 @@ func TestCompare(t *testing.T) {
|
|||
}
|
||||
config2 := Config{
|
||||
Dns: []string{"0.0.0.0", "2.2.2.2"},
|
||||
DnsSearch: []string{"foo", "bar"},
|
||||
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "11111111",
|
||||
|
@ -178,6 +180,7 @@ func TestCompare(t *testing.T) {
|
|||
}
|
||||
config3 := Config{
|
||||
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||
DnsSearch: []string{"foo", "bar"},
|
||||
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "11111111",
|
||||
|
@ -185,6 +188,7 @@ func TestCompare(t *testing.T) {
|
|||
}
|
||||
config4 := Config{
|
||||
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||
DnsSearch: []string{"foo", "bar"},
|
||||
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "22222222",
|
||||
|
@ -194,11 +198,20 @@ func TestCompare(t *testing.T) {
|
|||
volumes2["/test2"] = struct{}{}
|
||||
config5 := Config{
|
||||
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||
DnsSearch: []string{"foo", "bar"},
|
||||
PortSpecs: []string{"0000:0000", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "11111111",
|
||||
Volumes: volumes2,
|
||||
}
|
||||
config6 := Config{
|
||||
Dns: []string{"1.1.1.1", "2.2.2.2"},
|
||||
DnsSearch: []string{"foos", "bars"},
|
||||
PortSpecs: []string{"1111:1111", "2222:2222"},
|
||||
Env: []string{"VAR1=1", "VAR2=2"},
|
||||
VolumesFrom: "11111111",
|
||||
Volumes: volumes1,
|
||||
}
|
||||
if Compare(&config1, &config2) {
|
||||
t.Fatalf("Compare should return false, Dns are different")
|
||||
}
|
||||
|
@ -211,6 +224,9 @@ func TestCompare(t *testing.T) {
|
|||
if Compare(&config1, &config5) {
|
||||
t.Fatalf("Compare should return false, Volumes are different")
|
||||
}
|
||||
if Compare(&config1, &config6) {
|
||||
t.Fatalf("Compare should return false, DnsSearch are different")
|
||||
}
|
||||
if !Compare(&config1, &config1) {
|
||||
t.Fatalf("Compare should return true")
|
||||
}
|
||||
|
|
|
@ -100,6 +100,12 @@ func Merge(userConf, imageConf *Config) error {
|
|||
//duplicates aren't an issue here
|
||||
userConf.Dns = append(userConf.Dns, imageConf.Dns...)
|
||||
}
|
||||
if userConf.DnsSearch == nil || len(userConf.DnsSearch) == 0 {
|
||||
userConf.DnsSearch = imageConf.DnsSearch
|
||||
} else {
|
||||
//duplicates aren't an issue here
|
||||
userConf.DnsSearch = append(userConf.DnsSearch, imageConf.DnsSearch...)
|
||||
}
|
||||
if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
|
||||
userConf.Entrypoint = imageConf.Entrypoint
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|||
flPublish opts.ListOpts
|
||||
flExpose opts.ListOpts
|
||||
flDns opts.ListOpts
|
||||
flDnsSearch = opts.NewListOpts(opts.ValidateDomain)
|
||||
flVolumesFrom opts.ListOpts
|
||||
flLxcOpts opts.ListOpts
|
||||
|
||||
|
@ -73,6 +74,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|||
cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
|
||||
cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
|
||||
cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
||||
cmd.Var(&flDnsSearch, []string{"-dns-search"}, "Set custom dns search domains")
|
||||
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
||||
cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
||||
|
||||
|
@ -196,6 +198,7 @@ func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Conf
|
|||
Env: flEnv.GetAll(),
|
||||
Cmd: runCmd,
|
||||
Dns: flDns.GetAll(),
|
||||
DnsSearch: flDnsSearch.GetAll(),
|
||||
Image: image,
|
||||
Volumes: flVolumes.GetMap(),
|
||||
VolumesFrom: strings.Join(flVolumesFrom.GetAll(), ","),
|
||||
|
|
|
@ -493,13 +493,19 @@ func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Containe
|
|||
}
|
||||
|
||||
// If custom dns exists, then create a resolv.conf for the container
|
||||
if len(config.Dns) > 0 || len(runtime.config.Dns) > 0 {
|
||||
var dns []string
|
||||
if len(config.Dns) > 0 || len(runtime.config.Dns) > 0 || len(config.DnsSearch) > 0 || len(runtime.config.DnsSearch) > 0 {
|
||||
dns := utils.GetNameservers(resolvConf)
|
||||
dnsSearch := utils.GetSearchDomains(resolvConf)
|
||||
if len(config.Dns) > 0 {
|
||||
dns = config.Dns
|
||||
} else {
|
||||
} else if len(runtime.config.Dns) > 0 {
|
||||
dns = runtime.config.Dns
|
||||
}
|
||||
if len(config.DnsSearch) > 0 {
|
||||
dnsSearch = config.DnsSearch
|
||||
} else if len(runtime.config.DnsSearch) > 0 {
|
||||
dnsSearch = runtime.config.DnsSearch
|
||||
}
|
||||
container.ResolvConfPath = path.Join(container.root, "resolv.conf")
|
||||
f, err := os.Create(container.ResolvConfPath)
|
||||
if err != nil {
|
||||
|
@ -511,6 +517,11 @@ func (runtime *Runtime) Create(config *runconfig.Config, name string) (*Containe
|
|||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
if len(dnsSearch) > 0 {
|
||||
if _, err := f.Write([]byte("search " + strings.Join(dnsSearch, " ") + "\n")); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
container.ResolvConfPath = "/etc/resolv.conf"
|
||||
}
|
||||
|
|
|
@ -731,54 +731,78 @@ func GetResolvConf() ([]byte, error) {
|
|||
// CheckLocalDns looks into the /etc/resolv.conf,
|
||||
// it returns true if there is a local nameserver or if there is no nameserver.
|
||||
func CheckLocalDns(resolvConf []byte) bool {
|
||||
var parsedResolvConf = StripComments(resolvConf, []byte("#"))
|
||||
if !bytes.Contains(parsedResolvConf, []byte("nameserver")) {
|
||||
return true
|
||||
}
|
||||
for _, ip := range [][]byte{
|
||||
[]byte("127.0.0.1"),
|
||||
[]byte("127.0.1.1"),
|
||||
} {
|
||||
if bytes.Contains(parsedResolvConf, ip) {
|
||||
return true
|
||||
for _, line := range GetLines(resolvConf, []byte("#")) {
|
||||
if !bytes.Contains(line, []byte("nameserver")) {
|
||||
continue
|
||||
}
|
||||
for _, ip := range [][]byte{
|
||||
[]byte("127.0.0.1"),
|
||||
[]byte("127.0.1.1"),
|
||||
} {
|
||||
if bytes.Contains(line, ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
// StripComments parses input into lines and strips away comments.
|
||||
func StripComments(input []byte, commentMarker []byte) []byte {
|
||||
// GetLines parses input into lines and strips away comments.
|
||||
func GetLines(input []byte, commentMarker []byte) [][]byte {
|
||||
lines := bytes.Split(input, []byte("\n"))
|
||||
var output []byte
|
||||
var output [][]byte
|
||||
for _, currentLine := range lines {
|
||||
var commentIndex = bytes.Index(currentLine, commentMarker)
|
||||
if commentIndex == -1 {
|
||||
output = append(output, currentLine...)
|
||||
output = append(output, currentLine)
|
||||
} else {
|
||||
output = append(output, currentLine[:commentIndex]...)
|
||||
output = append(output, currentLine[:commentIndex])
|
||||
}
|
||||
output = append(output, []byte("\n")...)
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// GetNameservers returns nameservers (if any) listed in /etc/resolv.conf
|
||||
func GetNameservers(resolvConf []byte) []string {
|
||||
nameservers := []string{}
|
||||
re := regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
|
||||
for _, line := range GetLines(resolvConf, []byte("#")) {
|
||||
var ns = re.FindSubmatch(line)
|
||||
if len(ns) > 0 {
|
||||
nameservers = append(nameservers, string(ns[1]))
|
||||
}
|
||||
}
|
||||
return nameservers
|
||||
}
|
||||
|
||||
// GetNameserversAsCIDR returns nameservers (if any) listed in
|
||||
// /etc/resolv.conf as CIDR blocks (e.g., "1.2.3.4/32")
|
||||
// This function's output is intended for net.ParseCIDR
|
||||
func GetNameserversAsCIDR(resolvConf []byte) []string {
|
||||
var parsedResolvConf = StripComments(resolvConf, []byte("#"))
|
||||
nameservers := []string{}
|
||||
re := regexp.MustCompile(`^\s*nameserver\s*(([0-9]+\.){3}([0-9]+))\s*$`)
|
||||
for _, line := range bytes.Split(parsedResolvConf, []byte("\n")) {
|
||||
var ns = re.FindSubmatch(line)
|
||||
if len(ns) > 0 {
|
||||
nameservers = append(nameservers, string(ns[1])+"/32")
|
||||
}
|
||||
for _, nameserver := range GetNameservers(resolvConf) {
|
||||
nameservers = append(nameservers, nameserver+"/32")
|
||||
}
|
||||
|
||||
return nameservers
|
||||
}
|
||||
|
||||
// GetSearchDomains returns search domains (if any) listed in /etc/resolv.conf
|
||||
// If more than one search line is encountered, only the contents of the last
|
||||
// one is returned.
|
||||
func GetSearchDomains(resolvConf []byte) []string {
|
||||
re := regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`)
|
||||
domains := []string{}
|
||||
for _, line := range GetLines(resolvConf, []byte("#")) {
|
||||
match := re.FindSubmatch(line)
|
||||
if match == nil {
|
||||
continue
|
||||
}
|
||||
domains = strings.Fields(string(match[1]))
|
||||
}
|
||||
return domains
|
||||
}
|
||||
|
||||
// FIXME: Change this not to receive default value as parameter
|
||||
func ParseHost(defaultHost string, defaultUnix, addr string) (string, error) {
|
||||
var (
|
||||
|
|
|
@ -444,6 +444,30 @@ func TestParsePortMapping(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetNameservers(t *testing.T) {
|
||||
for resolv, result := range map[string][]string{`
|
||||
nameserver 1.2.3.4
|
||||
nameserver 40.3.200.10
|
||||
search example.com`: {"1.2.3.4", "40.3.200.10"},
|
||||
`search example.com`: {},
|
||||
`nameserver 1.2.3.4
|
||||
search example.com
|
||||
nameserver 4.30.20.100`: {"1.2.3.4", "4.30.20.100"},
|
||||
``: {},
|
||||
` nameserver 1.2.3.4 `: {"1.2.3.4"},
|
||||
`search example.com
|
||||
nameserver 1.2.3.4
|
||||
#nameserver 4.3.2.1`: {"1.2.3.4"},
|
||||
`search example.com
|
||||
nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4"},
|
||||
} {
|
||||
test := GetNameservers([]byte(resolv))
|
||||
if !StrSlicesEqual(test, result) {
|
||||
t.Fatalf("Wrong nameserver string {%s} should be %v. Input: %s", test, result, resolv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNameserversAsCIDR(t *testing.T) {
|
||||
for resolv, result := range map[string][]string{`
|
||||
nameserver 1.2.3.4
|
||||
|
@ -468,6 +492,33 @@ nameserver 1.2.3.4 # not 4.3.2.1`: {"1.2.3.4/32"},
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetSearchDomains(t *testing.T) {
|
||||
for resolv, result := range map[string][]string{
|
||||
`search example.com`: {"example.com"},
|
||||
`search example.com # ignored`: {"example.com"},
|
||||
` search example.com `: {"example.com"},
|
||||
` search example.com # ignored`: {"example.com"},
|
||||
`search foo.example.com example.com`: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com `: {"foo.example.com", "example.com"},
|
||||
` search foo.example.com example.com # ignored`: {"foo.example.com", "example.com"},
|
||||
``: {},
|
||||
`# ignored`: {},
|
||||
`nameserver 1.2.3.4
|
||||
search foo.example.com example.com`: {"foo.example.com", "example.com"},
|
||||
`nameserver 1.2.3.4
|
||||
search dup1.example.com dup2.example.com
|
||||
search foo.example.com example.com`: {"foo.example.com", "example.com"},
|
||||
`nameserver 1.2.3.4
|
||||
search foo.example.com example.com
|
||||
nameserver 4.30.20.100`: {"foo.example.com", "example.com"},
|
||||
} {
|
||||
test := GetSearchDomains([]byte(resolv))
|
||||
if !StrSlicesEqual(test, result) {
|
||||
t.Fatalf("Wrong search domain string {%s} should be %v. Input: %s", test, result, resolv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func StrSlicesEqual(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
|
Загрузка…
Ссылка в новой задаче