Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query hosts dns servers and populate nodes config with it #1650

Merged
merged 7 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions clab/clab.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/srl-labs/containerlab/runtime/docker"
"github.com/srl-labs/containerlab/runtime/ignite"
"github.com/srl-labs/containerlab/types"
"github.com/srl-labs/containerlab/utils"
"golang.org/x/crypto/ssh"
"golang.org/x/exp/slices"
)
Expand Down Expand Up @@ -760,3 +761,31 @@ func (c *CLab) ResolveLinks() error {

return nil
}

func (c *CLab) PrepareDNSServers() error {
// extract DNS servers from relevant resolv.conf files
DNSServers, err := utils.ExtractDNSServerFromResolvConf([]string{"/etc/resolv.conf", "/run/systemd/resolve/resolv.conf"})
if err != nil {
return err
}

// no DNS Servers found, return
if len(DNSServers) == 0 {
return nil
}

// if no dns servers are explicitly configured,
// we set the DNS servers that we've discovered.
for _, n := range c.Nodes {
config := n.Config()
if config.DNS == nil {
config.DNS = &types.DNSConfig{}
}

if n.Config().DNS.Servers == nil {
n.Config().DNS.Servers = DNSServers
}
}

return nil
}
4 changes: 4 additions & 0 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ func deployFn(_ *cobra.Command, _ []string) error {
return err
}

if err := c.PrepareDNSServers(); err != nil {
hellt marked this conversation as resolved.
Show resolved Hide resolved
return err
}

// determine the number of node and link worker
nodeWorkers, _, err := countWorkers(uint(len(c.Nodes)), uint(len(c.Links)), maxWorkers)
if err != nil {
Expand Down
18 changes: 12 additions & 6 deletions nodes/srl/srl.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ set / system gnmi-server admin-state enable network-instance mgmt admin-state en
set / system gnmi-server rate-limit 65000
set / system gnmi-server trace-options [ request response common ]
set / system gnmi-server unix-socket admin-state enable
{{- if .DNSServers }}
set / system dns network-instance mgmt
set / system dns server-list [ {{ range $dnsserver := .DNSServers}}{{$dnsserver}} {{ end }}]
{{- end }}
set / system json-rpc-server admin-state enable network-instance mgmt http admin-state enable
set / system json-rpc-server admin-state enable network-instance mgmt https admin-state enable tls-profile clab-profile
set / system snmp community public
Expand Down Expand Up @@ -553,6 +557,7 @@ type srlTemplateData struct {
IFaces map[string]tplIFace
SSHPubKeys string
MgmtMTU int
DNSServers []string
}

// tplIFace template interface struct.
Expand All @@ -573,12 +578,13 @@ func (n *srl) addDefaultConfig(ctx context.Context) error {
// struct that holds data used in templating of the default config snippet

tplData := srlTemplateData{
TLSKey: n.Cfg.TLSKey,
TLSCert: n.Cfg.TLSCert,
TLSAnchor: n.Cfg.TLSAnchor,
Banner: b,
IFaces: map[string]tplIFace{},
MgmtMTU: 0,
TLSKey: n.Cfg.TLSKey,
TLSCert: n.Cfg.TLSCert,
TLSAnchor: n.Cfg.TLSAnchor,
Banner: b,
IFaces: map[string]tplIFace{},
MgmtMTU: 0,
DNSServers: n.Config().DNS.Servers,
}

n.filterSSHPubKeys()
Expand Down
56 changes: 56 additions & 0 deletions utils/resolve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package utils

import (
"bufio"
"os"
"regexp"
"strings"

log "github.com/sirupsen/logrus"
)

// ExtractDNSServerFromResolvConf takes a list of filenames
// the files are supposed to be formated in the resolv.conf format.
// it will extract ipv4 DNS server addresses and return these
func ExtractDNSServerFromResolvConf(filenames []string) ([]string, error) {
hellt marked this conversation as resolved.
Show resolved Hide resolved
DNSServersMap := map[string]struct{}{}

for _, filename := range filenames {
readFile, err := os.Open(filename)
if err != nil {
log.Debugf("Error opening host DNS config %s: %v", filename, err)
continue
}

fileScanner := bufio.NewScanner(readFile)
fileScanner.Split(bufio.ScanLines)
ipPattern := `\s*nameserver\s+((\d{1,3}\.){3}\d{1,3})`
// Compile the regular expression.
re := regexp.MustCompile(ipPattern)

// check line by line for a match
for fileScanner.Scan() {
if match := re.FindStringSubmatch(fileScanner.Text()); match != nil {
// skip 127.x.y.z addresses
if strings.HasPrefix(match[1], "127") {
continue
}
DNSServersMap[match[1]] = struct{}{}
}
}
// close the file
readFile.Close()
}

// if we've not found any DNS Servers we return
if len(DNSServersMap) == 0 {
return nil, nil
}

// convert the map into a slice
DNSServers := make([]string, 0, len(DNSServersMap))
for k := range DNSServersMap {
DNSServers = append(DNSServers, k)
}
return DNSServers, nil
}