bridge: support IPAM DNS settings

Previously, the bridge plugin ignored DNS settings returned
from an IPAM plugin (e.g. the host-local plugin parsing
resolv.conf to configure DNS). With this change, the bridge plugin
uses IPAM DNS settings.

Similarly to #388, this change will use incoming DNS settings if set,
otherwise IPAM plugin returned DNS settings

Signed-off-by: Kern Walster <walster@amazon.com>
This commit is contained in:
Kern Walster 2022-04-21 05:05:06 +00:00
parent 0c39335765
commit a70e87c3aa
2 changed files with 60 additions and 2 deletions

View File

@ -489,6 +489,7 @@ func cmdAdd(args *skel.CmdArgs) error {
result.IPs = ipamResult.IPs result.IPs = ipamResult.IPs
result.Routes = ipamResult.Routes result.Routes = ipamResult.Routes
result.DNS = ipamResult.DNS
if len(result.IPs) == 0 { if len(result.IPs) == 0 {
return errors.New("IPAM plugin returned missing IP config") return errors.New("IPAM plugin returned missing IP config")
@ -611,18 +612,29 @@ func cmdAdd(args *skel.CmdArgs) error {
} }
brInterface.Mac = br.Attrs().HardwareAddr.String() brInterface.Mac = br.Attrs().HardwareAddr.String()
result.DNS = n.DNS
// Return an error requested by testcases, if any // Return an error requested by testcases, if any
if debugPostIPAMError != nil { if debugPostIPAMError != nil {
return debugPostIPAMError return debugPostIPAMError
} }
// Use incoming DNS settings if provided, otherwise use the
// settings that were already configued by the IPAM plugin
if dnsConfSet(n.DNS) {
result.DNS = n.DNS
}
success = true success = true
return types.PrintResult(result, cniVersion) return types.PrintResult(result, cniVersion)
} }
func dnsConfSet(dnsConf types.DNS) bool {
return dnsConf.Nameservers != nil ||
dnsConf.Search != nil ||
dnsConf.Options != nil ||
dnsConf.Domain != ""
}
func cmdDel(args *skel.CmdArgs) error { func cmdDel(args *skel.CmdArgs) error {
n, _, err := loadNetConf(args.StdinData, args.Args) n, _, err := loadNetConf(args.StdinData, args.Args)
if err != nil { if err != nil {

View File

@ -45,6 +45,7 @@ const (
BRNAME = "bridge0" BRNAME = "bridge0"
BRNAMEVLAN = "bridge0.100" BRNAMEVLAN = "bridge0.100"
IFNAME = "eth0" IFNAME = "eth0"
NAMESERVER = "192.0.2.0"
) )
type Net struct { type Net struct {
@ -70,6 +71,7 @@ type testCase struct {
subnet string // Single subnet config: Subnet CIDR subnet string // Single subnet config: Subnet CIDR
gateway string // Single subnet config: Gateway gateway string // Single subnet config: Gateway
ranges []rangeInfo // Ranges list (multiple subnets config) ranges []rangeInfo // Ranges list (multiple subnets config)
resolvConf string // host-local resolvConf file path
isGW bool isGW bool
isLayer2 bool isLayer2 bool
expGWCIDRs []string // Expected gateway addresses in CIDR form expGWCIDRs []string // Expected gateway addresses in CIDR form
@ -139,6 +141,9 @@ const (
ipamDataDirStr = `, ipamDataDirStr = `,
"dataDir": "%s"` "dataDir": "%s"`
ipamResolvConfStr = `,
"resolvConf": "%s"`
ipMasqConfStr = `, ipMasqConfStr = `,
"ipMasq": %t` "ipMasq": %t`
@ -215,6 +220,9 @@ func (tc testCase) netConfJSON(dataDir string) string {
if tc.ranges != nil { if tc.ranges != nil {
conf += tc.rangesConfig() conf += tc.rangesConfig()
} }
if tc.resolvConf != "" {
conf += tc.resolvConfConfig()
}
conf += ipamEndStr conf += ipamEndStr
} }
} else { } else {
@ -252,6 +260,26 @@ func (tc testCase) rangesConfig() string {
return conf + rangesEndStr return conf + rangesEndStr
} }
func (tc testCase) resolvConfConfig() string {
conf := fmt.Sprintf(ipamResolvConfStr, tc.resolvConf)
return conf
}
func newResolvConf() (string, error) {
f, err := ioutil.TempFile("", "host_local_resolv")
if err != nil {
return "", err
}
defer f.Close()
name := f.Name()
_, err = f.WriteString(fmt.Sprintf("nameserver %s", NAMESERVER))
return name, err
}
func deleteResolvConf(path string) error {
return os.Remove(path)
}
var counter uint var counter uint
// createCmdArgs generates network configuration and creates command // createCmdArgs generates network configuration and creates command
@ -565,6 +593,11 @@ func (tester *testerV10x) cmdAddTest(tc testCase, dataDir string) (types.Result,
Expect(link.Attrs().HardwareAddr.String()).NotTo(Equal(bridgeMAC)) Expect(link.Attrs().HardwareAddr.String()).NotTo(Equal(bridgeMAC))
} }
// Check that resolvConf was used properly
if !tc.isLayer2 && tc.resolvConf != "" {
Expect(result.DNS.Nameservers).To(Equal([]string{NAMESERVER}))
}
return nil return nil
}) })
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
@ -1587,6 +1620,9 @@ var _ = Describe("bridge Operations", func() {
var originalNS, targetNS ns.NetNS var originalNS, targetNS ns.NetNS
var dataDir string var dataDir string
resolvConf, err := newResolvConf()
Expect(err).NotTo(HaveOccurred())
BeforeEach(func() { BeforeEach(func() {
// Create a new NetNS so we don't modify the host // Create a new NetNS so we don't modify the host
var err error var err error
@ -1610,6 +1646,10 @@ var _ = Describe("bridge Operations", func() {
Expect(testutils.UnmountNS(targetNS)).To(Succeed()) Expect(testutils.UnmountNS(targetNS)).To(Succeed())
}) })
AfterSuite(func() {
deleteResolvConf(resolvConf)
})
for _, ver := range testutils.AllSpecVersions { for _, ver := range testutils.AllSpecVersions {
// Redefine ver inside for scope so real value is picked up by each dynamically defined It() // Redefine ver inside for scope so real value is picked up by each dynamically defined It()
// See Gingkgo's "Patterns for dynamically generating tests" documentation. // See Gingkgo's "Patterns for dynamically generating tests" documentation.
@ -1706,6 +1746,12 @@ var _ = Describe("bridge Operations", func() {
AddErr010: "CNI version 0.1.0 does not support more than 1 address per family", AddErr010: "CNI version 0.1.0 does not support more than 1 address per family",
DelErr010: "CNI version 0.1.0 does not support more than 1 address per family", DelErr010: "CNI version 0.1.0 does not support more than 1 address per family",
}, },
{
// with resolvConf DNS settings
subnet: "10.1.2.0/24",
expGWCIDRs: []string{"10.1.2.1/24"},
resolvConf: resolvConf,
},
} { } {
tc := tc tc := tc
i := i i := i