Skip to content

Commit

Permalink
use the configured resolv.conf
Browse files Browse the repository at this point in the history
 The nameserver values could come from manually defined properties
 or the host itself

Revert "k8s topgun: behaviour: skip containerd dns tests"
This reverts commit 0b03e84.

Signed-off-by: Bishoy Youssef <byoussef@pivotal.io>
Co-authored-by: Vikram Yadav <vyadav@pivotal.io>
Co-authored-by: Izabela Gomes <igomes@pivotal.io>
  • Loading branch information
3 people committed Aug 26, 2020
1 parent d0b12f8 commit 8f98888
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 23 deletions.
3 changes: 0 additions & 3 deletions topgun/k8s/dns_proxy_test.go
Expand Up @@ -74,9 +74,6 @@ var _ = Describe("DNS Resolution", func() {
expectedDnsProxyBehaviour := func(runtime string) {
DescribeTable("different proxy settings",
func(c Case) {
if runtime == containerdRuntime && c.enableDnsProxy == "false" {
Skip("Skip test until https://github.com/concourse/concourse/issues/5967 is resolv'ed :P")
}
setupDeployment(runtime, c.enableDnsProxy, c.dnsServer)

sess := fly.Start("execute", "-c", "tasks/dns-proxy-task.yml", "-v", "url="+c.addressFunction())
Expand Down
32 changes: 20 additions & 12 deletions worker/runtime/cni_network.go
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"path/filepath"
"strings"

"github.com/concourse/concourse/worker/runtime/iptables"
"github.com/containerd/containerd"
Expand Down Expand Up @@ -47,10 +48,6 @@ const (
)

var (
// defaultNameServers is the default set of nameservers used.
//
defaultNameServers = []string{"8.8.8.8"}

// defaultCNINetworkConfig is the default configuration for the CNI network
// created to put concourse containers into.
//
Expand Down Expand Up @@ -112,7 +109,9 @@ func WithCNIBinariesDir(dir string) CNINetworkOpt {
//
func WithNameServers(nameservers []string) CNINetworkOpt {
return func(n *cniNetwork) {
n.nameServers = nameservers
for _, ns := range nameservers {
n.nameServers = append(n.nameServers, "nameserver "+ns)
}
}
}

Expand Down Expand Up @@ -177,7 +176,6 @@ func NewCNINetwork(opts ...CNINetworkOpt) (*cniNetwork, error) {
n := &cniNetwork{
binariesDir: binariesDir,
config: defaultCNINetworkConfig,
nameServers: defaultNameServers,
}

for _, opt := range opts {
Expand Down Expand Up @@ -207,7 +205,7 @@ func NewCNINetwork(opts ...CNINetworkOpt) (*cniNetwork, error) {
n.ipt, err = iptables.New()

if err != nil {
return nil, fmt.Errorf("failed to initialized iptables")
return nil, fmt.Errorf("failed to initialize iptables")
}
}

Expand All @@ -227,9 +225,14 @@ func (n cniNetwork) SetupMounts(handle string) ([]specs.Mount, error) {
return nil, fmt.Errorf("creating /etc/hosts: %w", err)
}

resolvContents, err := n.generateResolvConfContents()
if err != nil {
return nil, fmt.Errorf("generating resolv.conf: %w", err)
}

resolvConf, err := n.store.Create(
filepath.Join(handle, "/resolv.conf"),
n.generateResolvConfContents(),
resolvContents,
)
if err != nil {
return nil, fmt.Errorf("creating /etc/resolv.conf: %w", err)
Expand Down Expand Up @@ -273,13 +276,18 @@ func (n cniNetwork) SetupRestrictedNetworks() error {
return nil
}

func (n cniNetwork) generateResolvConfContents() []byte {
func (n cniNetwork) generateResolvConfContents() ([]byte, error) {
contents := ""
for _, n := range n.nameServers {
contents = contents + "nameserver " + n + "\n"
resolvConfEntries := n.nameServers
var err error

if len(n.nameServers) == 0 {
resolvConfEntries, err = ParseHostResolveConf("/etc/resolv.conf")
}

return []byte(contents)
contents = strings.Join(resolvConfEntries, "\n")

return []byte(contents), err
}

func (n cniNetwork) Add(ctx context.Context, task containerd.Task) error {
Expand Down
19 changes: 13 additions & 6 deletions worker/runtime/cni_network_test.go
Expand Up @@ -3,9 +3,11 @@ package runtime_test
import (
"context"
"errors"
"strings"

"github.com/concourse/concourse/worker/runtime"
"github.com/concourse/concourse/worker/runtime/libcontainerd/libcontainerdfakes"
"github.com/concourse/concourse/worker/runtime/iptables/iptablesfakes"
"github.com/concourse/concourse/worker/runtime/libcontainerd/libcontainerdfakes"
"github.com/concourse/concourse/worker/runtime/runtimefakes"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -100,31 +102,36 @@ func (s *CNINetworkSuite) TestSetupMountsReturnsMountpoints() {
})
}

func (s *CNINetworkSuite) TestSetupMountsCallsStoreWithNoNameServer() {
func (s *CNINetworkSuite) TestSetupMountsCallsStoreWithNameServers() {
network, err := runtime.NewCNINetwork(
runtime.WithCNIFileStore(s.store),
runtime.WithNameServers([]string{"6.6.7.7", "1.2.3.4"}),
)
s.NoError(err)

_, err = network.SetupMounts("some-handle")
s.NoError(err)

_, resolvConfContents := s.store.CreateArgsForCall(1)
s.Equal(resolvConfContents, []byte("nameserver 8.8.8.8\n"))
s.Equal(resolvConfContents, []byte("nameserver 6.6.7.7\nnameserver 1.2.3.4"))
}

func (s *CNINetworkSuite) TestSetupMountsCallsStoreWithOneNameServer() {
func (s *CNINetworkSuite) TestSetupMountsCallsStoreWithoutNameServers() {
network, err := runtime.NewCNINetwork(
runtime.WithCNIFileStore(s.store),
runtime.WithNameServers([]string{"6.6.7.7", "1.2.3.4"}),
)
s.NoError(err)

_, err = network.SetupMounts("some-handle")
s.NoError(err)

actualResolvContents, err := runtime.ParseHostResolveConf("/etc/resolv.conf")
s.NoError(err)

contents := strings.Join(actualResolvContents, "\n")

_, resolvConfContents := s.store.CreateArgsForCall(1)
s.Equal(resolvConfContents, []byte("nameserver 6.6.7.7\nnameserver 1.2.3.4\n"))
s.Equal(resolvConfContents, []byte(contents))
}

func (s *CNINetworkSuite) TestSetupRestrictedNetworksCreatesEmptyAdminChain() {
Expand Down
2 changes: 1 addition & 1 deletion worker/runtime/integration/integration_test.go
Expand Up @@ -491,7 +491,7 @@ func (s *IntegrationSuite) TestCustomDNS() {
s.NoError(err)

s.Equal(exitCode, 0)
expectedDNSServer := "nameserver 1.1.1.1\nnameserver 1.2.3.4\n"
expectedDNSServer := "nameserver 1.1.1.1\nnameserver 1.2.3.4"
s.Equal(expectedDNSServer, buf.String())
}

Expand Down
56 changes: 56 additions & 0 deletions worker/runtime/resolvconf_parser.go
@@ -0,0 +1,56 @@
package runtime

import (
"fmt"
"io/ioutil"
"regexp"
"strings"

"code.cloudfoundry.org/localip"
)

// Parse resolve.conf file from the provided path.
// implementation is based on guardian's implementation
// here: https://github.com/cloudfoundry/guardian/blob/master/kawasaki/dns/resolv_compiler.go
func ParseHostResolveConf(path string) ([]string, error) {

resolvConf, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("unable to read host's resolv.conf: %w", err)
}

resolvContents := string(resolvConf)

loopbackNameserver := regexp.MustCompile(`^\s*nameserver\s+127\.0\.0\.\d+\s*$`)
if loopbackNameserver.MatchString(resolvContents) {
ip, err := localip.LocalIP()
if err != nil {
return nil, err
}
return []string{"nameserver " + ip}, nil
}

var entries []string

for _, resolvEntry := range strings.Split(strings.TrimSpace(resolvContents), "\n") {
if resolvEntry == "" {
continue
}

if !strings.HasPrefix(resolvEntry, "nameserver") {
entries = append(entries, strings.TrimSpace(resolvEntry))
continue
}

pattern := regexp.MustCompile(`127\.\d{1,3}\.\d{1,3}\.\d{1,3}`)
if !pattern.MatchString(strings.TrimSpace(resolvEntry)) {
nameserverFields := strings.Fields(resolvEntry)
if len(nameserverFields) != 2 {
continue
}
entries = append(entries, strings.Join(nameserverFields, " "))
}
}

return entries, nil
}
49 changes: 49 additions & 0 deletions worker/runtime/resolvconf_parser_test.go
@@ -0,0 +1,49 @@
package runtime_test

import (
"io/ioutil"
"os"
"path"

"code.cloudfoundry.org/localip"
"github.com/concourse/concourse/worker/runtime"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)

type ResolveconfParserSuite struct {
suite.Suite
*require.Assertions
}

func (s *ResolveconfParserSuite) TestParseHostResolvConf() {
file := `
nameserver 8.8.8.8
nameserver 127.0.0.16
nameserver something 9.9.9.9
search something
`

tmpDir, _ := ioutil.TempDir("", "test-resolv")
defer os.RemoveAll(tmpDir)
ioutil.WriteFile(path.Join(tmpDir, "resolv.conf"), []byte(file), 0644)

entries, err := runtime.ParseHostResolveConf(path.Join(tmpDir, "resolv.conf"))
s.NoError(err)

s.Equal([]string{"nameserver 8.8.8.8", "search something"}, entries)
}

func (s *ResolveconfParserSuite) TestParseHostResolvConfWithLoopback() {
file := `nameserver 127.0.0.1`

tmpDir, _ := ioutil.TempDir("", "test-resolv-noloopback")
defer os.RemoveAll(tmpDir)
ioutil.WriteFile(path.Join(tmpDir, "resolv.conf"), []byte(file), 0644)

entries, err := runtime.ParseHostResolveConf(path.Join(tmpDir, "resolv.conf"))
s.NoError(err)

ip, _ := localip.LocalIP()
s.Equal([]string{"nameserver " + ip}, entries)
}
1 change: 1 addition & 0 deletions worker/runtime/suite_test.go
Expand Up @@ -18,4 +18,5 @@ func TestSuite(t *testing.T) {
suite.Run(t, &RootfsManagerSuite{Assertions: require.New(t)})
suite.Run(t, &UserNamespaceSuite{Assertions: require.New(t)})
suite.Run(t, &TimeoutLockSuite{Assertions: require.New(t)})
suite.Run(t, &ResolveconfParserSuite{Assertions: require.New(t)})
}
2 changes: 1 addition & 1 deletion worker/workercmd/containerd.go
Expand Up @@ -152,7 +152,7 @@ func (cmd *WorkerCommand) containerdRunner(logger lager.Logger) (ifrit.Runner, e

dnsServers := cmd.Containerd.DNSServers
if cmd.Containerd.DNS.Enable {
dnsProxyRunner, err := cmd.dnsProxyRunner(logger.Session("dns-proxy"))
dnsProxyRunner, err := cmd.dnsProxyRunner(logger.Session("dns-proxy"))
if err != nil {
return nil, err
}
Expand Down

0 comments on commit 8f98888

Please sign in to comment.