From 0d903e38ed84923647cae849cea8f01b0bd5afb2 Mon Sep 17 00:00:00 2001 From: Aditya R Date: Mon, 21 Nov 2022 11:07:05 +0530 Subject: [PATCH] libnetwork, Network: add field NetworkDNSServers for network scoped dns libnetwork must allow to pass network_dns_servers so aardvark and netavark can consume it and enabled network scoped dns. Feature implemented at netavark and aardvark end * Netavark: https://github.com/containers/netavark/pull/497 Signed-off-by: Aditya R --- libnetwork/cni/config.go | 3 +++ libnetwork/cni/config_test.go | 10 ++++++++++ libnetwork/netavark/config.go | 11 +++++++++++ libnetwork/netavark/config_test.go | 30 ++++++++++++++++++++++++++++++ libnetwork/types/network.go | 4 ++++ 5 files changed, 58 insertions(+) diff --git a/libnetwork/cni/config.go b/libnetwork/cni/config.go index aa94e73d1..8e9418ad5 100644 --- a/libnetwork/cni/config.go +++ b/libnetwork/cni/config.go @@ -36,6 +36,9 @@ func (n *cniNetwork) NetworkCreate(net types.Network) (types.Network, error) { // networkCreate will fill out the given network struct and return the new network entry. // If defaultNet is true it will not validate against used subnets and it will not write the cni config to disk. func (n *cniNetwork) networkCreate(newNetwork *types.Network, defaultNet bool) (*network, error) { + if len(newNetwork.NetworkDNSServers) > 0 { + return nil, fmt.Errorf("NetworkDNSServers cannot be configured for backend CNI: %w", types.ErrInvalidArg) + } // if no driver is set use the default one if newNetwork.Driver == "" { newNetwork.Driver = types.DefaultNetworkDriver diff --git a/libnetwork/cni/config_test.go b/libnetwork/cni/config_test.go index 6c333d0b3..4f0a3fde0 100644 --- a/libnetwork/cni/config_test.go +++ b/libnetwork/cni/config_test.go @@ -143,6 +143,16 @@ var _ = Describe("Config", func() { Expect(network2.Subnets[0].Subnet.Contains(network1.Subnets[0].Subnet.IP)).To(BeFalse()) }) + It("create network with NetworDNSServers with DNSEnabled=false", func() { + network := types.Network{ + NetworkDNSServers: []string{"8.8.8.8", "3.3.3.3"}, + DNSEnabled: false, + } + _, err := libpodNet.NetworkCreate(network) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(`NetworkDNSServers cannot be configured for backend CNI`)) + }) + It("create bridge config", func() { network := types.Network{Driver: "bridge"} network1, err := libpodNet.NetworkCreate(network) diff --git a/libnetwork/netavark/config.go b/libnetwork/netavark/config.go index 6d0212ada..292981657 100644 --- a/libnetwork/netavark/config.go +++ b/libnetwork/netavark/config.go @@ -137,6 +137,17 @@ func (n *netavarkNetwork) networkCreate(newNetwork *types.Network, defaultNet bo // when we do not have ipam we must disable dns internalutil.IpamNoneDisableDNS(newNetwork) + // process NetworkDNSServers + if len(newNetwork.NetworkDNSServers) > 0 && !newNetwork.DNSEnabled { + return nil, fmt.Errorf("Cannot set NetworkDNSServers if DNS is not enabled for the network: %w", types.ErrInvalidArg) + } + // validate ip address + for _, dnsServer := range newNetwork.NetworkDNSServers { + if net.ParseIP(dnsServer) == nil { + return nil, fmt.Errorf("Unable to parse ip %s specified in NetworkDNSServers: %w", dnsServer, types.ErrInvalidArg) + } + } + // add gateway when not internal or dns enabled addGateway := !newNetwork.Internal || newNetwork.DNSEnabled err = internalutil.ValidateSubnets(newNetwork, addGateway, usedNetworks) diff --git a/libnetwork/netavark/config_test.go b/libnetwork/netavark/config_test.go index 60c16396f..5b3fd4003 100644 --- a/libnetwork/netavark/config_test.go +++ b/libnetwork/netavark/config_test.go @@ -618,6 +618,36 @@ var _ = Describe("Config", func() { Expect(network1.Internal).To(BeTrue()) }) + It("create network with NetworDNSServers", func() { + network := types.Network{ + NetworkDNSServers: []string{"8.8.8.8", "3.3.3.3"}, + DNSEnabled: true, + } + network1, err := libpodNet.NetworkCreate(network) + Expect(err).To(BeNil()) + Expect(network1.NetworkDNSServers).To(Equal([]string{"8.8.8.8", "3.3.3.3"})) + }) + + It("create network with NetworDNSServers with invalid IP", func() { + network := types.Network{ + NetworkDNSServers: []string{"a.b.c.d", "3.3.3.3"}, + DNSEnabled: true, + } + _, err := libpodNet.NetworkCreate(network) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(`Unable to parse ip a.b.c.d`)) + }) + + It("create network with NetworDNSServers with DNSEnabled=false", func() { + network := types.Network{ + NetworkDNSServers: []string{"8.8.8.8", "3.3.3.3"}, + DNSEnabled: false, + } + _, err := libpodNet.NetworkCreate(network) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(`Cannot set NetworkDNSServers if DNS is not enabled for the network`)) + }) + It("create network with labels", func() { network := types.Network{ Labels: map[string]string{ diff --git a/libnetwork/types/network.go b/libnetwork/types/network.go index e69d6e6e1..d0e6d1796 100644 --- a/libnetwork/types/network.go +++ b/libnetwork/types/network.go @@ -56,6 +56,10 @@ type Network struct { // DNSEnabled is whether name resolution is active for container on // this Network. Only supported with the bridge driver. DNSEnabled bool `json:"dns_enabled"` + // List of custom DNS server for podman's DNS resolver at network level, + // all the containers attached to this network will consider resolvers + // configured at network level. + NetworkDNSServers []string `json:"network_dns_servers,omitempty"` // Labels is a set of key-value labels that have been applied to the // Network. Labels map[string]string `json:"labels,omitempty"`