Skip to content

Commit

Permalink
Use IPPool DNS servers for ElfMachine (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
haijianyang authored Sep 13, 2022
1 parent aac8ba6 commit e1f6c95
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 11 deletions.
23 changes: 14 additions & 9 deletions controllers/elfmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
capecontext "github.com/smartxworks/cluster-api-provider-elf/pkg/context"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apitypes "k8s.io/apimachinery/pkg/types"
kerrors "k8s.io/apimachinery/pkg/util/errors"
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
capiutil "sigs.k8s.io/cluster-api/util"
"sigs.k8s.io/cluster-api/util/annotations"
Expand Down Expand Up @@ -245,7 +244,12 @@ func (r *ElfMachineReconciler) reconcileIPAddress(ctx *context.MachineContext) (
return ctrl.Result{}, nil
}

var errs []error
defer func() {
if len(ctx.ElfMachine.Spec.Network.Nameservers) > 0 {
ctx.ElfMachine.Spec.Network.Nameservers = ipamutil.LimitDNSServers(ctx.ElfMachine.Spec.Network.Nameservers)
}
}()

requeueAfter := time.Duration(0)
for i := 0; i < len(devices); i++ {
if !ipamutil.NeedsAllocateIPForDevice(devices[i]) {
Expand All @@ -254,19 +258,17 @@ func (r *ElfMachineReconciler) reconcileIPAddress(ctx *context.MachineContext) (

result, err := r.reconcileDeviceIPAddress(ctx, ipPool, i)
if err != nil {
errs = append(errs, err)
ctx.Logger.Error(err, fmt.Sprintf("failed to set IP address for device %d", i))
return reconcile.Result{}, err
}

if result.RequeueAfter != 0 {
requeueAfter = result.RequeueAfter
}
}

if len(errs) > 0 {
if requeueAfter == time.Duration(0) {
requeueAfter = config.DefaultRequeue
}

return reconcile.Result{RequeueAfter: requeueAfter}, kerrors.NewAggregate(errs)
if requeueAfter == 0 && len(ipPool.GetDNSServers()) > 0 {
ctx.ElfMachine.Spec.Network.Nameservers = append(ctx.ElfMachine.Spec.Network.Nameservers, ipPool.GetDNSServers()...)
}

ctx.Logger.Info("Set IP address successfully")
Expand Down Expand Up @@ -300,6 +302,9 @@ func (r *ElfMachineReconciler) reconcileDeviceIPAddress(ctx *context.MachineCont
device.IPAddrs = []string{ip.GetAddress()}
device.Netmask = ip.GetMask()
device.Routes = []capev1.NetworkDeviceRouteSpec{{Gateway: ip.GetGateway()}}
if len(ip.GetDNSServers()) > 0 {
ctx.ElfMachine.Spec.Network.Nameservers = append(ctx.ElfMachine.Spec.Network.Nameservers, ip.GetDNSServers()...)
}

return ctrl.Result{}, nil
}
Expand Down
5 changes: 5 additions & 0 deletions controllers/elfmachine_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,11 @@ var _ = Describe("ElfMachineReconciler", func() {
It("should set IP for devices when IP ready", func() {
metal3IPPool.Namespace = ipam.DefaultIPPoolNamespace
metal3IPPool.Labels = map[string]string{ipam.DefaultIPPoolKey: "true"}
metal3IPPool.Spec.DNSServers = append(metal3IPPool.Spec.DNSServers, ipamv1.IPAddressStr("1.1.1.1"), ipamv1.IPAddressStr("4.4.4.4"))
metal3IPClaim, metal3IPAddress = fake.NewMetal3IPObjects(metal3IPPool, ipamutil.GetFormattedClaimName(elfMachine.Name, 0))
metal3IPAddress.Spec.DNSServers = append(metal3IPAddress.Spec.DNSServers, ipamv1.IPAddressStr("2.2.2.2"), ipamv1.IPAddressStr("3.3.3.3"))
setMetal3IPForClaim(metal3IPClaim, metal3IPAddress)
elfMachine.Spec.Network.Nameservers = []string{"3.3.3.3"}
ctrlContext := newCtrlContexts(elfCluster, cluster, elfMachine, machine, elfMachineTemplate, metal3IPPool, metal3IPClaim, metal3IPAddress)
fake.InitOwnerReferences(ctrlContext, elfCluster, cluster, elfMachine, machine)

Expand All @@ -231,6 +234,8 @@ var _ = Describe("ElfMachineReconciler", func() {
Expect(logBuffer.String()).To(ContainSubstring("Set IP address successfully"))
Expect(ctrlContext.Client.Get(ctrlContext, capiutil.ObjectKey(elfMachine), elfMachine)).To(Succeed())
Expect(elfMachine.Spec.Network.Devices[0].IPAddrs).To(Equal([]string{string(metal3IPAddress.Spec.Address)}))
// DNS server is unique and DNS server priority of ElfMachine is higher than IPPool.
Expect(elfMachine.Spec.Network.Nameservers).To(Equal([]string{"3.3.3.3", "2.2.2.2", "1.1.1.1"}))
Expect(ctrlutil.ContainsFinalizer(elfMachine, MachineStaticIPFinalizer)).To(BeTrue())
})

Expand Down
2 changes: 1 addition & 1 deletion pkg/ipam/metal3io/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (m *Metal3IP) GetAddress() string {

func (m *Metal3IP) GetDNSServers() []string {
dnsServers := make([]string, 0, len(m.Spec.DNSServers))
for i := 0; i < len(dnsServers); i++ {
for i := 0; i < len(m.Spec.DNSServers); i++ {
dnsServers = append(dnsServers, string(m.Spec.DNSServers[i]))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/ipam/metal3io/ippool.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (m *Metal3IPPool) GetGateway() string {
func (m *Metal3IPPool) GetDNSServers() []string {
dnsServers := make([]string, 0, len(m.IPPool.Spec.DNSServers))
for i := 0; i < len(m.IPPool.Spec.DNSServers); i++ {
dnsServers[i] = string(m.IPPool.Spec.DNSServers[i])
dnsServers = append(dnsServers, string(m.IPPool.Spec.DNSServers[i]))
}

return dnsServers
Expand Down
41 changes: 41 additions & 0 deletions pkg/ipam/util/util.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package util

import (
Expand All @@ -12,6 +28,11 @@ import (
"github.com/smartxworks/cluster-api-provider-elf-static-ip/pkg/ipam"
)

// Elf virtual machine support three DNS servers.
const (
DNSServerLimit = 3
)

func HasStaticIPDevice(devices []capev1.NetworkDeviceSpec) bool {
for _, device := range devices {
if IsStaticIPDevice(device) {
Expand Down Expand Up @@ -60,6 +81,26 @@ func ValidateIP(ip ipam.IPAddress) error {
return nil
}

func LimitDNSServers(sourceDNSServers []string) []string {
dnsServers := []string{}
set := make(map[string]struct{}, len(sourceDNSServers))
for i := 0; i < len(sourceDNSServers); i++ {
if _, ok := set[sourceDNSServers[i]]; ok {
continue
}

dnsServers = append(dnsServers, sourceDNSServers[i])
set[sourceDNSServers[i]] = struct{}{}
}

limit := DNSServerLimit
if limit > len(dnsServers) {
limit = len(dnsServers)
}

return dnsServers[:limit]
}

func IgnoreNotFound(err error) error {
if apierrors.IsNotFound(err) {
return nil
Expand Down
45 changes: 45 additions & 0 deletions pkg/ipam/util/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package util

import (
"testing"

"github.com/onsi/gomega"
)

func TestLimitDNSServers(t *testing.T) {
g := gomega.NewGomegaWithT(t)

testCases := []struct {
name string
sourceDNSServers []string
dnsServers []string
}{
{"should return empty server", []string{}, []string{}},
{"should return one server", []string{"1.1.1.1"}, []string{"1.1.1.1"}},
{"should filter duplicate servers", []string{"1.1.1.1", "1.1.1.1"}, []string{"1.1.1.1"}},
{"should limit servers", []string{"1.1.1.1", "2.2.2.2", "3.3.3.3", "4.4.4.4"}, []string{"1.1.1.1", "2.2.2.2", "3.3.3.3"}},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
dnsServers := LimitDNSServers(tc.sourceDNSServers)
g.Expect(dnsServers).To(gomega.Equal(tc.dnsServers))
})
}
}

0 comments on commit e1f6c95

Please sign in to comment.