Skip to content

Commit

Permalink
feat: Support ignoring ranges and CIDRs for node IPs (#194)
Browse files Browse the repository at this point in the history
This allows passing ranges and CIDRs in addition to plain IP addresses
to be ignored when discovering node IPs. This is a workaround for IPs in
metallb ranges being added as node IPs.
  • Loading branch information
jimmidyson authored Dec 12, 2024
1 parent 13108d7 commit 5d9e97b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 24 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/nutanix-cloud-native/prism-go-client v0.5.1
github.com/onsi/ginkgo/v2 v2.20.2
github.com/onsi/gomega v1.34.2
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
k8s.io/api v0.31.1
k8s.io/apimachinery v0.31.1
k8s.io/client-go v0.31.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down
8 changes: 6 additions & 2 deletions internal/testing/mock/mock_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,13 @@ func CreateMockEnvironment(ctx context.Context, kClient *fake.Clientset) (*MockE
filteredAddressesVM := getDefaultVMSpec(MockVMNameFilteredNodeAddresses, cluster)
filteredAddressesVM.Status.Resources.NicList = []*prismClientV3.VMNicOutputStatus{{
IPEndpointList: []*prismClientV3.IPAddress{{
IP: ptr.To("127.100.100.1"),
IP: ptr.To("127.100.10.1"),
}, {
IP: ptr.To("127.200.200.1"),
IP: ptr.To("127.200.20.1"),
}, {
IP: ptr.To("127.200.100.64"),
}, {
IP: ptr.To("127.200.200.10"),
}, {
IP: ptr.To(MockIP),
}},
Expand Down
8 changes: 5 additions & 3 deletions pkg/provider/instances_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"go4.org/netipx"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/client-go/kubernetes/fake"
Expand Down Expand Up @@ -67,9 +68,10 @@ var _ = Describe("Test InstancesV2", func() {
}
i = instancesV2{
nutanixManager: &nutanixManager{
config: categoryTopologyConfig,
client: kClient,
nutanixClient: mock.CreateMockClient(*mockEnvironment),
config: categoryTopologyConfig,
client: kClient,
nutanixClient: mock.CreateMockClient(*mockEnvironment),
ignoredNodeIPs: &netipx.IPSet{},
},
}
})
Expand Down
42 changes: 36 additions & 6 deletions pkg/provider/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ package provider
import (
"context"
"fmt"
"net/netip"
"strings"

prismclientv3 "github.com/nutanix-cloud-native/prism-go-client/v3"
"go4.org/netipx"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/informers"
clientset "k8s.io/client-go/kubernetes"
Expand All @@ -38,16 +40,40 @@ type nutanixManager struct {
client clientset.Interface
config config.Config
nutanixClient interfaces.Client
ignoredNodeIPs map[string]struct{}
ignoredNodeIPs *netipx.IPSet
}

func newNutanixManager(config config.Config) (*nutanixManager, error) {
klog.V(1).Info("Creating new newNutanixManager")

// Initialize the ignoredNodeIPs map
ignoredNodeIPs := make(map[string]struct{}, len(config.IgnoredNodeIPs))
// Initialize the ignoredNodeIPs set
ignoredIPsBuilder := netipx.IPSetBuilder{}
for _, ip := range config.IgnoredNodeIPs {
ignoredNodeIPs[ip] = struct{}{}
switch {
case strings.Contains(ip, "-"):
ipRange, err := netipx.ParseIPRange(ip)
if err != nil {
return nil, fmt.Errorf("failed to parse ignoredNodeIPs IP range %q: %v", ip, err)
}
ignoredIPsBuilder.AddRange(ipRange)
case strings.Contains(ip, "/"):
prefix, err := netip.ParsePrefix(ip)
if err != nil {
return nil, fmt.Errorf("failed to parse ignoredNodeIPs IP prefix %q: %v", ip, err)
}
ignoredIPsBuilder.AddPrefix(prefix)
default:
parsedIP, err := netip.ParseAddr(ip)
if err != nil {
return nil, fmt.Errorf("failed to parse ignoredNodeIPs IP %q: %v", ip, err)
}
ignoredIPsBuilder.Add(parsedIP)
}
}

ignoredIPSet, err := ignoredIPsBuilder.IPSet()
if err != nil {
return nil, fmt.Errorf("failed to build ignoredNodeIPs IP set: %v", err)
}

m := &nutanixManager{
Expand All @@ -56,7 +82,7 @@ func newNutanixManager(config config.Config) (*nutanixManager, error) {
config: config,
clientCache: prismclientv3.NewClientCache(prismclientv3.WithSessionAuth(true)),
},
ignoredNodeIPs: ignoredNodeIPs,
ignoredNodeIPs: ignoredIPSet,
}
return m, nil
}
Expand Down Expand Up @@ -280,8 +306,12 @@ func (n *nutanixManager) getNodeAddresses(_ context.Context, vm *prismclientv3.V
for _, nic := range vm.Status.Resources.NicList {
for _, ipEndpoint := range nic.IPEndpointList {
if ipEndpoint.IP != nil {
parsedIP, err := netip.ParseAddr(*ipEndpoint.IP)
if err != nil {
return addresses, fmt.Errorf("failed to parse IP address %q: %v", *ipEndpoint.IP, err)
}
// Ignore the IP address if it is one of the specified ignoredNodeIPs.
if _, ok := n.ignoredNodeIPs[*ipEndpoint.IP]; !ok {
if !n.ignoredNodeIPs.Contains(parsedIP) {
addresses = append(addresses, v1.NodeAddress{
Type: v1.NodeInternalIP,
Address: *ipEndpoint.IP,
Expand Down
25 changes: 12 additions & 13 deletions pkg/provider/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,22 @@ var _ = Describe("Test Manager", func() {
nutanixClient := mock.CreateMockClient(*mockEnvironment)
nClient, err = nutanixClient.Get()
Expect(err).ToNot(HaveOccurred())
m = nutanixManager{
config: config.Config{
mgr, err := newNutanixManager(
config.Config{
TopologyDiscovery: config.TopologyDiscovery{
Type: config.CategoriesTopologyDiscoveryType,
TopologyCategories: &config.TopologyCategories{
RegionCategory: mock.MockDefaultRegion,
ZoneCategory: mock.MockDefaultZone,
},
},
IgnoredNodeIPs: []string{"127.100.100.1", "127.200.200.1"},
IgnoredNodeIPs: []string{"127.100.10.1", "127.200.20.1", "127.200.100.1/24", "127.200.200.1-127.200.200.10"},
},
client: kClient,
nutanixClient: nutanixClient,
ignoredNodeIPs: map[string]struct{}{
"127.100.100.1": struct{}{},
"127.200.200.1": struct{}{},
},
}
)
Expect(err).ShouldNot(HaveOccurred())
mgr.client = kClient
mgr.nutanixClient = nutanixClient
m = *mgr
})

Context("Test HasEmptyTopologyInfo", func() {
Expand Down Expand Up @@ -158,9 +156,10 @@ var _ = Describe("Test Manager", func() {
addresses, err := m.getNodeAddresses(ctx, vm)
Expect(err).ShouldNot(HaveOccurred())
Expect(len(addresses)).To(Equal(2), "Received addresses: %v", addresses)
Expect(addresses).Should(ContainElement(v1.NodeAddress{Type: v1.NodeInternalIP, Address: mock.MockIP}))
Expect(addresses).ShouldNot(ContainElement(v1.NodeAddress{Type: v1.NodeInternalIP, Address: "127.100.100.1"}))
Expect(addresses).ShouldNot(ContainElement(v1.NodeAddress{Type: v1.NodeInternalIP, Address: "127.200.200.1"}))
Expect(addresses).Should(ConsistOf(
v1.NodeAddress{Type: v1.NodeInternalIP, Address: mock.MockIP},
v1.NodeAddress{Type: v1.NodeHostName, Address: *vm.Spec.Name},
))
})
})

Expand Down

0 comments on commit 5d9e97b

Please # to comment.