mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #39295 from tiborvass/buildkit-systemd-resolvconf
build: buildkit now also uses systemd's resolv.conf
This commit is contained in:
commit
a6e1502575
8 changed files with 55 additions and 182 deletions
|
@ -9,18 +9,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/internal/procfs"
|
||||
"github.com/docker/docker/pkg/fileutils"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/libnetwork/resolvconf"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultResolvConf = "/etc/resolv.conf"
|
||||
alternateResolvConf = "/run/systemd/resolve/resolv.conf"
|
||||
)
|
||||
|
||||
// On Linux, plugins use a static path for storing execution state,
|
||||
// instead of deriving path from daemon's exec-root. This is because
|
||||
// plugin socket files are created here and they cannot exceed max
|
||||
|
@ -148,20 +143,5 @@ func setupResolvConf(config *config.Config) {
|
|||
if config.ResolvConf != "" {
|
||||
return
|
||||
}
|
||||
|
||||
config.ResolvConf = defaultResolvConf
|
||||
pids, err := procfs.PidOf("systemd-resolved")
|
||||
if err != nil {
|
||||
logrus.Errorf("unable to check systemd-resolved status: %s", err)
|
||||
return
|
||||
}
|
||||
if len(pids) > 0 && pids[0] > 0 {
|
||||
_, err := os.Stat(alternateResolvConf)
|
||||
if err == nil {
|
||||
logrus.Infof("systemd-resolved is running, so using resolvconf: %s", alternateResolvConf)
|
||||
config.ResolvConf = alternateResolvConf
|
||||
return
|
||||
}
|
||||
logrus.Infof("systemd-resolved is running, but %s is not present, fallback to %s", alternateResolvConf, defaultResolvConf)
|
||||
}
|
||||
config.ResolvConf = resolvconf.Path()
|
||||
}
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
package procfs
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// PidOf finds process(es) with a specified name (regexp match)
|
||||
// and return their pid(s)
|
||||
func PidOf(name string) ([]int, error) {
|
||||
if len(name) == 0 {
|
||||
return []int{}, fmt.Errorf("name should not be empty")
|
||||
}
|
||||
re, err := regexp.Compile("(^|/)" + name + "$")
|
||||
if err != nil {
|
||||
return []int{}, err
|
||||
}
|
||||
return getPids(re), nil
|
||||
}
|
||||
|
||||
func getPids(re *regexp.Regexp) []int {
|
||||
pids := []int{}
|
||||
|
||||
dirFD, err := os.Open("/proc")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer dirFD.Close()
|
||||
|
||||
for {
|
||||
// Read a small number at a time in case there are many entries, we don't want to
|
||||
// allocate a lot here.
|
||||
ls, err := dirFD.Readdir(10)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, entry := range ls {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the directory is not a number (i.e. not a PID), skip it
|
||||
pid, err := strconv.Atoi(entry.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
cmdline, err := ioutil.ReadFile(filepath.Join("/proc", entry.Name(), "cmdline"))
|
||||
if err != nil {
|
||||
logrus.Infof("Error reading file %s: %+v", filepath.Join("/proc", entry.Name(), "cmdline"), err)
|
||||
continue
|
||||
}
|
||||
|
||||
// The bytes we read have '\0' as a separator for the command line
|
||||
parts := bytes.SplitN(cmdline, []byte{0}, 2)
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
// Split the command line itself we are interested in just the first part
|
||||
exe := strings.FieldsFunc(string(parts[0]), func(c rune) bool {
|
||||
return unicode.IsSpace(c) || c == ':'
|
||||
})
|
||||
if len(exe) == 0 {
|
||||
continue
|
||||
}
|
||||
// Check if the name of the executable is what we are looking for
|
||||
if re.MatchString(exe[0]) {
|
||||
// Grab the PID from the directory path
|
||||
pids = append(pids, pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pids
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package procfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestPidOf(t *testing.T) {
|
||||
pids, err := PidOf(filepath.Base(os.Args[0]))
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, len(pids) == 1)
|
||||
assert.DeepEqual(t, pids[0], os.Getpid())
|
||||
}
|
||||
|
||||
func BenchmarkGetPids(b *testing.B) {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
|
||||
b.Skipf("not supported on GOOS=%s", runtime.GOOS)
|
||||
}
|
||||
|
||||
re, err := regexp.Compile("(^|/)" + filepath.Base(os.Args[0]) + "$")
|
||||
assert.Check(b, err == nil)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
pids := getPids(re)
|
||||
|
||||
b.StopTimer()
|
||||
assert.Check(b, len(pids) > 0)
|
||||
assert.Check(b, pids[0] == os.Getpid())
|
||||
b.StartTimer()
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ github.com/imdario/mergo 7c29201646fa3de8506f70121347
|
|||
golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c
|
||||
|
||||
# buildkit
|
||||
github.com/moby/buildkit 37d53758a68d9f5cede1806dbb2da7c3caa8d5bc
|
||||
github.com/moby/buildkit 1f89ec125f84c097bdf3a063be622c4238dba5f8
|
||||
github.com/tonistiigi/fsutil 3bbb99cdbd76619ab717299830c60f6f2a533a6b
|
||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||
github.com/opentracing/opentracing-go 1361b9cd60be79c4c3a7fa9841b3c132e40066a7
|
||||
|
@ -39,7 +39,7 @@ github.com/gofrs/flock 7f43ea2e6a643ad441fc12d0ecc0
|
|||
# libnetwork
|
||||
|
||||
# When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy.installer accordingly
|
||||
github.com/docker/libnetwork 5ac07abef4eee176423fdc1b870d435258e2d381
|
||||
github.com/docker/libnetwork fc5a7d91d54cc98f64fc28f9e288b46a0bee756c
|
||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
||||
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
|
||||
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
|
|
20
vendor/github.com/docker/libnetwork/controller.go
generated
vendored
20
vendor/github.com/docker/libnetwork/controller.go
generated
vendored
|
@ -339,7 +339,6 @@ func (c *controller) clusterAgentInit() {
|
|||
}
|
||||
}
|
||||
case cluster.EventNodeLeave:
|
||||
keysAvailable = false
|
||||
c.agentOperationStart()
|
||||
c.Lock()
|
||||
c.keys = nil
|
||||
|
@ -706,11 +705,17 @@ const overlayDSROptionString = "dsr"
|
|||
// NewNetwork creates a new network of the specified network type. The options
|
||||
// are network specific and modeled in a generic way.
|
||||
func (c *controller) NewNetwork(networkType, name string, id string, options ...NetworkOption) (Network, error) {
|
||||
var (
|
||||
cap *driverapi.Capability
|
||||
err error
|
||||
t *network
|
||||
)
|
||||
|
||||
if id != "" {
|
||||
c.networkLocker.Lock(id)
|
||||
defer c.networkLocker.Unlock(id)
|
||||
|
||||
if _, err := c.NetworkByID(id); err == nil {
|
||||
if _, err = c.NetworkByID(id); err == nil {
|
||||
return nil, NetworkNameError(id)
|
||||
}
|
||||
}
|
||||
|
@ -739,15 +744,10 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
|
|||
}
|
||||
|
||||
network.processOptions(options...)
|
||||
if err := network.validateConfiguration(); err != nil {
|
||||
if err = network.validateConfiguration(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
cap *driverapi.Capability
|
||||
err error
|
||||
)
|
||||
|
||||
// Reset network types, force local scope and skip allocation and
|
||||
// plumbing for configuration networks. Reset of the config-only
|
||||
// network drivers is needed so that this special network is not
|
||||
|
@ -794,11 +794,11 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
|
|||
// From this point on, we need the network specific configuration,
|
||||
// which may come from a configuration-only network
|
||||
if network.configFrom != "" {
|
||||
t, err := c.getConfigNetwork(network.configFrom)
|
||||
t, err = c.getConfigNetwork(network.configFrom)
|
||||
if err != nil {
|
||||
return nil, types.NotFoundErrorf("configuration network %q does not exist", network.configFrom)
|
||||
}
|
||||
if err := t.applyConfigurationTo(network); err != nil {
|
||||
if err = t.applyConfigurationTo(network); err != nil {
|
||||
return nil, types.InternalErrorf("Failed to apply configuration: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
|
|
42
vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go
generated
vendored
42
vendor/github.com/docker/libnetwork/resolvconf/resolvconf.go
generated
vendored
|
@ -15,10 +15,44 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// DefaultResolvConf points to the default file used for dns configuration on a linux machine
|
||||
DefaultResolvConf = "/etc/resolv.conf"
|
||||
// defaultPath is the default path to the resolv.conf that contains information to resolve DNS. See Path().
|
||||
defaultPath = "/etc/resolv.conf"
|
||||
// alternatePath is a path different from defaultPath, that may be used to resolve DNS. See Path().
|
||||
alternatePath = "/run/systemd/resolve/resolv.conf"
|
||||
)
|
||||
|
||||
var (
|
||||
detectSystemdResolvConfOnce sync.Once
|
||||
pathAfterSystemdDetection = defaultPath
|
||||
)
|
||||
|
||||
// Path returns the path to the resolv.conf file that libnetwork should use.
|
||||
//
|
||||
// When /etc/resolv.conf contains 127.0.0.53 as the only nameserver, then
|
||||
// it is assumed systemd-resolved manages DNS. Because inside the container 127.0.0.53
|
||||
// is not a valid DNS server, Path() returns /run/systemd/resolve/resolv.conf
|
||||
// which is the resolv.conf that systemd-resolved generates and manages.
|
||||
// Otherwise Path() returns /etc/resolv.conf.
|
||||
//
|
||||
// Errors are silenced as they will inevitably resurface at future open/read calls.
|
||||
//
|
||||
// More information at https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html#/etc/resolv.conf
|
||||
func Path() string {
|
||||
detectSystemdResolvConfOnce.Do(func() {
|
||||
candidateResolvConf, err := ioutil.ReadFile(defaultPath)
|
||||
if err != nil {
|
||||
// silencing error as it will resurface at next calls trying to read defaultPath
|
||||
return
|
||||
}
|
||||
ns := GetNameservers(candidateResolvConf, types.IP)
|
||||
if len(ns) == 1 && ns[0] == "127.0.0.53" {
|
||||
pathAfterSystemdDetection = alternatePath
|
||||
logrus.Infof("detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: %s", alternatePath)
|
||||
}
|
||||
})
|
||||
return pathAfterSystemdDetection
|
||||
}
|
||||
|
||||
var (
|
||||
// Note: the default IPv4 & IPv6 resolvers are set to Google's Public DNS
|
||||
defaultIPv4Dns = []string{"nameserver 8.8.8.8", "nameserver 8.8.4.4"}
|
||||
|
@ -55,7 +89,7 @@ type File struct {
|
|||
|
||||
// Get returns the contents of /etc/resolv.conf and its hash
|
||||
func Get() (*File, error) {
|
||||
return GetSpecific(DefaultResolvConf)
|
||||
return GetSpecific(Path())
|
||||
}
|
||||
|
||||
// GetSpecific returns the contents of the user specified resolv.conf file and its hash
|
||||
|
@ -78,7 +112,7 @@ func GetIfChanged() (*File, error) {
|
|||
lastModified.Lock()
|
||||
defer lastModified.Unlock()
|
||||
|
||||
resolv, err := ioutil.ReadFile("/etc/resolv.conf")
|
||||
resolv, err := ioutil.ReadFile(Path())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
4
vendor/github.com/docker/libnetwork/sandbox_dns_unix.go
generated
vendored
4
vendor/github.com/docker/libnetwork/sandbox_dns_unix.go
generated
vendored
|
@ -213,8 +213,8 @@ func (sb *sandbox) setupDNS() error {
|
|||
|
||||
originResolvConfPath := sb.config.originResolvConfPath
|
||||
if originResolvConfPath == "" {
|
||||
// if not specified fallback to default /etc/resolv.conf
|
||||
originResolvConfPath = resolvconf.DefaultResolvConf
|
||||
// fallback if not specified
|
||||
originResolvConfPath = resolvconf.Path()
|
||||
}
|
||||
currRC, err := resolvconf.GetSpecific(originResolvConfPath)
|
||||
if err != nil {
|
||||
|
|
2
vendor/github.com/moby/buildkit/executor/oci/resolvconf.go
generated
vendored
2
vendor/github.com/moby/buildkit/executor/oci/resolvconf.go
generated
vendored
|
@ -29,7 +29,7 @@ func GetResolvConf(ctx context.Context, stateDir string) (string, error) {
|
|||
generate = true
|
||||
}
|
||||
if !generate {
|
||||
fiMain, err := os.Stat("/etc/resolv.conf")
|
||||
fiMain, err := os.Stat(resolvconf.Path())
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
|
|
Loading…
Reference in a new issue