Skip to content

Commit

Permalink
Merge pull request #9 from Nordix/dns-mael
Browse files Browse the repository at this point in the history
✨Add dnsServer to IPPool and IPAddress
  • Loading branch information
metal3-io-bot authored Jul 20, 2020
2 parents 82a1839 + 9b13f7f commit d267e70
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 23 deletions.
3 changes: 3 additions & 0 deletions api/v1alpha1/ipaddress_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ type IPAddressSpec struct {

// Address contains the IP address
Address IPAddressStr `json:"address"`

// DNSServers is the list of dns servers
DNSServers []IPAddressStr `json:"dnsServers,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
6 changes: 6 additions & 0 deletions api/v1alpha1/ippool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type Pool struct {

// Gateway is the gateway ip address
Gateway *IPAddressStr `json:"gateway,omitempty"`

// DNSServers is the list of dns servers
DNSServers []IPAddressStr `json:"dnsServers,omitempty"`
}

// IPPoolSpec defines the desired state of IPPool.
Expand All @@ -69,6 +72,9 @@ type IPPoolSpec struct {
// Gateway is the gateway ip address
Gateway *IPAddressStr `json:"gateway,omitempty"`

// DNSServers is the list of dns servers
DNSServers []IPAddressStr `json:"dnsServers,omitempty"`

// +kubebuilder:validation:MinLength=1
// namePrefix is the prefix used to generate the IPAddress object names
NamePrefix string `json:"namePrefix"`
Expand Down
15 changes: 15 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions config/crd/bases/ipam.metal3.io_ipaddresses.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ spec:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
dnsServers:
description: DNSServers is the list of dns servers
items:
description: IPAddress is used for validation of an IP address
pattern: ((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$))
type: string
type: array
gateway:
description: Gateway is the gateway ip address
pattern: ((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$))
Expand Down
14 changes: 14 additions & 0 deletions config/crd/bases/ipam.metal3.io_ippools.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ spec:
description: ClusterName is the name of the Cluster this object belongs
to.
type: string
dnsServers:
description: DNSServers is the list of dns servers
items:
description: IPAddress is used for validation of an IP address
pattern: ((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$))
type: string
type: array
gateway:
description: Gateway is the gateway ip address
pattern: ((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$))
Expand All @@ -65,6 +72,13 @@ spec:
description: MetaDataIPAddress contains the info to render th ip
address. It is IP-version agnostic
properties:
dnsServers:
description: DNSServers is the list of dns servers
items:
description: IPAddress is used for validation of an IP address
pattern: ((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$))
type: string
type: array
end:
description: End is the last IP address that can be rendered.
It is used as a validation that the rendered IP is in bound.
Expand Down
29 changes: 17 additions & 12 deletions ipam/ippool_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,25 +230,20 @@ func (m *IPPoolManager) updateAddress(ctx context.Context,

func (m *IPPoolManager) allocateAddress(addressClaim *ipamv1.IPClaim,
addresses map[ipamv1.IPAddressStr]string,
) (ipamv1.IPAddressStr, int, *ipamv1.IPAddressStr, error) {
) (ipamv1.IPAddressStr, int, *ipamv1.IPAddressStr, []ipamv1.IPAddressStr, error) {
var err error

// Get pre-allocated addresses
allocatedAddress, ipAllocated := m.IPPool.Spec.PreAllocations[addressClaim.Name]
// If the IP is pre-allocated, the default prefix and gateway are used
prefix := m.IPPool.Spec.Prefix
gateway := m.IPPool.Spec.Gateway
dnsServers := m.IPPool.Spec.DNSServers

for _, pool := range m.IPPool.Spec.Pools {
if ipAllocated {
break
}
if pool.Prefix != 0 {
prefix = pool.Prefix
}
if pool.Gateway != nil {
gateway = pool.Gateway
}
index := 0
for !ipAllocated {
allocatedAddress, err = getIPAddress(pool, index)
Expand All @@ -258,14 +253,23 @@ func (m *IPPoolManager) allocateAddress(addressClaim *ipamv1.IPClaim,
index++
if _, ok := addresses[allocatedAddress]; !ok && allocatedAddress != "" {
ipAllocated = true
if pool.Prefix != 0 {
prefix = pool.Prefix
}
if pool.Gateway != nil {
gateway = pool.Gateway
}
if len(pool.DNSServers) != 0 {
dnsServers = pool.DNSServers
}
}
}
}
if !ipAllocated {
addressClaim.Status.ErrorMessage = pointer.StringPtr("Exhausted IP Pools")
return "", 0, nil, errors.New("Exhausted IP Pools")
return "", 0, nil, []ipamv1.IPAddressStr{}, errors.New("Exhausted IP Pools")
}
return allocatedAddress, prefix, gateway, nil
return allocatedAddress, prefix, gateway, dnsServers, nil
}

func (m *IPPoolManager) createAddress(ctx context.Context,
Expand All @@ -288,7 +292,7 @@ func (m *IPPoolManager) createAddress(ctx context.Context,
// Get a new index for this machine
m.Log.Info("Getting address", "Claim", addressClaim.Name)
// Get a new IP for this owner
allocatedAddress, prefix, gateway, err := m.allocateAddress(addressClaim, addresses)
allocatedAddress, prefix, gateway, dnsServers, err := m.allocateAddress(addressClaim, addresses)
if err != nil {
return addresses, err
}
Expand Down Expand Up @@ -337,8 +341,9 @@ func (m *IPPoolManager) createAddress(ctx context.Context,
Name: addressClaim.Name,
Namespace: m.IPPool.Namespace,
},
Prefix: prefix,
Gateway: gateway,
Prefix: prefix,
Gateway: gateway,
DNSServers: dnsServers,
},
}

Expand Down
91 changes: 80 additions & 11 deletions ipam/ippool_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,13 +679,14 @@ var _ = Describe("IPPool manager", func() {
)

type testCaseAllocateAddress struct {
ipPool *ipamv1.IPPool
ipClaim *ipamv1.IPClaim
addresses map[ipamv1.IPAddressStr]string
expectedAddress ipamv1.IPAddressStr
expectedPrefix int
expectedGateway *ipamv1.IPAddressStr
expectError bool
ipPool *ipamv1.IPPool
ipClaim *ipamv1.IPClaim
addresses map[ipamv1.IPAddressStr]string
expectedAddress ipamv1.IPAddressStr
expectedPrefix int
expectedGateway *ipamv1.IPAddressStr
expectedDNSServers []ipamv1.IPAddressStr
expectError bool
}

DescribeTable("Test AllocateAddress",
Expand All @@ -694,7 +695,7 @@ var _ = Describe("IPPool manager", func() {
klogr.New(),
)
Expect(err).NotTo(HaveOccurred())
allocatedAddress, prefix, gateway, err := ipPoolMgr.allocateAddress(
allocatedAddress, prefix, gateway, dnsServers, err := ipPoolMgr.allocateAddress(
tc.ipClaim, tc.addresses,
)
if tc.expectError {
Expand All @@ -706,6 +707,7 @@ var _ = Describe("IPPool manager", func() {
Expect(allocatedAddress).To(Equal(tc.expectedAddress))
Expect(prefix).To(Equal(tc.expectedPrefix))
Expect(*gateway).To(Equal(*tc.expectedGateway))
Expect(dnsServers).To(Equal(tc.expectedDNSServers))
},
Entry("Empty pools", testCaseAllocateAddress{
ipPool: &ipamv1.IPPool{
Expand All @@ -727,13 +729,19 @@ var _ = Describe("IPPool manager", func() {
End: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.20")),
Prefix: 26,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.1.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
},
},
PreAllocations: map[string]ipamv1.IPAddressStr{
"TestRef": ipamv1.IPAddressStr("192.168.0.15"),
},
Prefix: 24,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
},
},
ipClaim: &ipamv1.IPClaim{
Expand All @@ -743,7 +751,10 @@ var _ = Describe("IPPool manager", func() {
},
expectedAddress: ipamv1.IPAddressStr("192.168.0.15"),
expectedGateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.1")),
expectedPrefix: 24,
expectedDNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
expectedPrefix: 24,
}),
Entry("One pool, with start and existing address", testCaseAllocateAddress{
ipPool: &ipamv1.IPPool{
Expand Down Expand Up @@ -780,10 +791,16 @@ var _ = Describe("IPPool manager", func() {
End: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.20")),
Prefix: 24,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
},
},
Prefix: 26,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.1.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
},
},
ipClaim: &ipamv1.IPClaim{
Expand All @@ -797,7 +814,50 @@ var _ = Describe("IPPool manager", func() {
},
expectedAddress: ipamv1.IPAddressStr("192.168.0.13"),
expectedGateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.1")),
expectedPrefix: 24,
expectedDNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
expectedPrefix: 24,
}),
Entry("two pools, with subnet and override prefix in first", testCaseAllocateAddress{
ipPool: &ipamv1.IPPool{
Spec: ipamv1.IPPoolSpec{
Pools: []ipamv1.Pool{
ipamv1.Pool{
Start: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.10")),
End: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.0.10")),
Prefix: 24,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.1.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
},
ipamv1.Pool{
Subnet: (*ipamv1.IPSubnetStr)(pointer.StringPtr("192.168.1.10/24")),
},
},
Prefix: 26,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.2.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
},
},
ipClaim: &ipamv1.IPClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "TestRef",
},
},
addresses: map[ipamv1.IPAddressStr]string{
ipamv1.IPAddressStr("192.168.1.11"): "bcde",
ipamv1.IPAddressStr("192.168.0.10"): "abcd",
},
expectedAddress: ipamv1.IPAddressStr("192.168.1.12"),
expectedGateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.2.1")),
expectedDNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
expectedPrefix: 26,
}),
Entry("two pools, with subnet and override prefix", testCaseAllocateAddress{
ipPool: &ipamv1.IPPool{
Expand All @@ -811,10 +871,16 @@ var _ = Describe("IPPool manager", func() {
Subnet: (*ipamv1.IPSubnetStr)(pointer.StringPtr("192.168.1.10/24")),
Prefix: 24,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.1.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
},
},
Prefix: 26,
Gateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.2.1")),
DNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.4.4"),
},
},
},
ipClaim: &ipamv1.IPClaim{
Expand All @@ -828,7 +894,10 @@ var _ = Describe("IPPool manager", func() {
},
expectedAddress: ipamv1.IPAddressStr("192.168.1.12"),
expectedGateway: (*ipamv1.IPAddressStr)(pointer.StringPtr("192.168.1.1")),
expectedPrefix: 24,
expectedDNSServers: []ipamv1.IPAddressStr{
ipamv1.IPAddressStr("8.8.8.8"),
},
expectedPrefix: 24,
}),
Entry("Exhausted pools start", testCaseAllocateAddress{
ipPool: &ipamv1.IPPool{
Expand Down

0 comments on commit d267e70

Please sign in to comment.