Skip to content

Commit

Permalink
BUGFIX Add Add Nutanix CCM ignore node IPs list
Browse files Browse the repository at this point in the history
  • Loading branch information
adiantum committed Dec 12, 2024
1 parent ff41392 commit 090ab32
Show file tree
Hide file tree
Showing 70 changed files with 3,437 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ spec:
bundle for users that configured their Prism Central with certificates
from non-publicly trusted CAs
type: string
ccmExcludeNodeIPs:
description: CcmExcludeIPs is the optional list of IP addresses that
should be excluded from the CCM IP pool for nodes. List should be
valid IP addresses and IP address ranges.
items:
type: string
type: array
credentialRef:
description: CredentialRef is the reference to the secret name that
contains the credentials for the Nutanix Prism Central. The namespace
Expand Down
5 changes: 5 additions & 0 deletions pkg/api/v1alpha1/nutanixdatacenterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ type NutanixDatacenterConfigSpec struct {
// FailureDomains is the optional list of failure domains for the Nutanix Datacenter.
// +optional
FailureDomains []NutanixDatacenterFailureDomain `json:"failureDomains,omitempty"`

// CcmExcludeIPs is the optional list of IP addresses that should be excluded from the CCM IP pool for nodes.
// List should be valid IP addresses and IP address ranges.
// +optional
CcmExcludeNodeIPs []string `json:"ccmExcludeNodeIPs,omitempty"`
}

// NutanixDatacenterFailureDomain defines the failure domain for the Nutanix Datacenter.
Expand Down
5 changes: 5 additions & 0 deletions pkg/api/v1alpha1/zz_generated.deepcopy.go

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

3 changes: 2 additions & 1 deletion pkg/providers/nutanix/config/cp-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@ data:
"enableCustomLabeling": false,
"topologyDiscovery": {
"type": "Prism"
}
},
"ignoredNodeIPs": [{{ range $i, $ip := .ccmIgnoredNodeIPs }}{{ if $i }}, {{ end }}"{{ $ip }}"{{ end }}]
}
---
apiVersion: rbac.authorization.k8s.io/v1
Expand Down
137 changes: 137 additions & 0 deletions pkg/providers/nutanix/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net"
"strings"

"sigs.k8s.io/yaml"

Expand Down Expand Up @@ -176,9 +179,12 @@ func buildTemplateMapCP(

failureDomains := generateNutanixFailureDomains(datacenterSpec.FailureDomains)

ccmIgnoredNodeIPs := generateCcmIgnoredNodeIPsList(clusterSpec)

values := map[string]interface{}{
"auditPolicy": auditPolicy,
"apiServerExtraArgs": apiServerExtraArgs.ToPartialYaml(),
"ccmIgnoredNodeIPs": ccmIgnoredNodeIPs,
"cloudProviderImage": versionsBundle.Nutanix.CloudProvider.VersionedImage(),
"clusterName": clusterSpec.Cluster.Name,
"controlPlaneEndpointIp": clusterSpec.Cluster.Spec.ControlPlaneConfiguration.Endpoint.Host,
Expand Down Expand Up @@ -519,3 +525,134 @@ func generateNutanixFailureDomains(eksNutanixFailureDomains []v1alpha1.NutanixDa
}
return failureDomains
}

func incrementIP(ip net.IP) {
for i := len(ip) - 1; i >= 0; i-- {
ip[i]++
if ip[i] > 0 {
break
}
}
}

func compareIP(ip1, ip2 net.IP) (int, error) {
if len(ip1) != len(ip2) {
return -1, fmt.Errorf("IP addresses are not the same protocol")
}

for i := 0; i < len(ip1); i++ {
if ip1[i] < ip2[i] {
return -1, nil
}
if ip1[i] > ip2[i] {
return 1, nil
}
}

return 0, nil
}

func addKubeVipToIgnoredNodeIPsList(clusterSpec *cluster.Spec, result []string) []string {
kubeVipStr := clusterSpec.Cluster.Spec.ControlPlaneConfiguration.Endpoint.Host
if kubeVipStr != "" {
kubeVip, err := net.ResolveIPAddr("ip", kubeVipStr)
if err != nil {
// log error and continue
log.Printf("error resolving kube-vip IP address %s: %v", kubeVipStr, err)
} else {
result = append(result, kubeVip.IP.String())
}
}

return result
}

func addCIDRToIgnoredNodeIPsList(cidr string, result []string) []string {
ip, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
// log error and continue
log.Printf("error parsing CIDR %s: %v", cidr, err)
return result
}

// Add all ip addresses in the range to the list
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incrementIP(ip) {
if ip != nil {
result = append(result, ip.String())
}
}

return result
}

func addIPRangeToIgnoredNodeIPsList(ipRangeStr string, result []string) []string {
// Parse the range
ipRange := strings.Split(ipRangeStr, "-")
if len(ipRange) != 2 {
// log error and return
log.Printf("error parsing range %s: expected 2 values, got %d", ipRangeStr, len(ipRange))
return result
}

// Parse the start and end of the range
start := net.ParseIP(strings.TrimSpace(ipRange[0]))
end := net.ParseIP(strings.TrimSpace(ipRange[1]))
if start == nil || end == nil {
// log error and return
log.Printf("error parsing range %s: invalid IP address", ipRangeStr)
return result
}

cmp, err := compareIP(start, end)
if err != nil {
// log error and return
log.Printf("error comparing IP addresses %s and %s: %v", start.String(), end.String(), err)
return result
}

if cmp >= 0 {
// swap start and end if start is greater than end
start, end = end, start
}

// Add all ip addresses in the range to the list
for ip := start; !ip.Equal(end); incrementIP(ip) {
result = append(result, ip.String())
}

result = append(result, end.String())

return result
}

func addIPAddressToIgnoredNodeIPsList(ipAddrStr string, result []string) []string {
ip := net.ParseIP(ipAddrStr)
if ip == nil {
// log error and return
log.Printf("error parsing IP address %s", ipAddrStr)
return result
}

result = append(result, ip.String())
return result
}

func generateCcmIgnoredNodeIPsList(clusterSpec *cluster.Spec) []string {
result := make([]string, 0)

// Add kube-vip to the list
result = addKubeVipToIgnoredNodeIPsList(clusterSpec, result)

for _, IPAddrOrRange := range clusterSpec.NutanixDatacenter.Spec.CcmExcludeNodeIPs {
addrOrRange := strings.TrimSpace(IPAddrOrRange)
if strings.Contains(addrOrRange, "/") {
result = addCIDRToIgnoredNodeIPsList(addrOrRange, result)
} else if strings.Contains(addrOrRange, "-") {
result = addIPRangeToIgnoredNodeIPsList(addrOrRange, result)
} else {
result = addIPAddressToIgnoredNodeIPsList(addrOrRange, result)
}
}

return result
}
86 changes: 86 additions & 0 deletions pkg/providers/nutanix/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,92 @@ func TestTemplateBuilderFailureDomains(t *testing.T) {
}
}

func TestTemplateBuilderCcmExcludeNodeIPs(t *testing.T) {
for _, tc := range []struct {
Input string
Output string
ChangeFn func(clusterSpec *cluster.Spec) *cluster.Spec
}{
{
Input: "testdata/eksa-cluster-ccm-exclude-node-ips.yaml",
Output: "testdata/expected_cluster_ccm_exclude_node_ips.yaml",
ChangeFn: func(clusterSpec *cluster.Spec) *cluster.Spec {
excludeNodeIPs := []string{
"127.100.200.101",
"10.10.10.10-10.10.10.13",
"10.123.0.0/29",
}
clusterSpec.NutanixDatacenter.Spec.CcmExcludeNodeIPs = excludeNodeIPs

return clusterSpec
},
},
{
Input: "testdata/eksa-cluster-ccm-exclude-node-ips.yaml",
Output: "testdata/expected_cluster_ccm_exclude_node_ips.yaml",
ChangeFn: func(clusterSpec *cluster.Spec) *cluster.Spec {
excludeNodeIPs := []string{
"127.100.200.101",
"10.10.10.10-10.10.10.13",
"10.123.0.0/29",
"10.10.10.20-10.10.10.30-10.10.20.30",
}
clusterSpec.NutanixDatacenter.Spec.CcmExcludeNodeIPs = excludeNodeIPs

return clusterSpec
},
},
{
Input: "testdata/eksa-cluster-ccm-exclude-node-ips.yaml",
Output: "testdata/expected_cluster_ccm_exclude_node_ips.yaml",
ChangeFn: func(clusterSpec *cluster.Spec) *cluster.Spec {
excludeNodeIPs := []string{
"127.100.200.101",
"10.10.10.10-10.10.10.13",
"10.123.0.0/29",
"244.244.1",
}
clusterSpec.NutanixDatacenter.Spec.CcmExcludeNodeIPs = excludeNodeIPs

return clusterSpec
},
},
{
Input: "testdata/eksa-cluster-ccm-exclude-node-ips.yaml",
Output: "testdata/expected_cluster_ccm_exclude_node_ips.yaml",
ChangeFn: func(clusterSpec *cluster.Spec) *cluster.Spec {
excludeNodeIPs := []string{
"127.100.200.101",
"10.10.10.10-10.10.10.13",
"10.123.0.0/29",
"10.21.0.5/55",
}
clusterSpec.NutanixDatacenter.Spec.CcmExcludeNodeIPs = excludeNodeIPs

return clusterSpec
},
},
} {
clusterSpec := test.NewFullClusterSpec(t, tc.Input)

machineCfg := clusterSpec.NutanixMachineConfig(clusterSpec.Cluster.Spec.ControlPlaneConfiguration.MachineGroupRef.Name)

t.Setenv(constants.EksaNutanixUsernameKey, "admin")
t.Setenv(constants.EksaNutanixPasswordKey, "password")
creds := GetCredsFromEnv()

clusterSpec = tc.ChangeFn(clusterSpec)

bldr := NewNutanixTemplateBuilder(&clusterSpec.NutanixDatacenter.Spec, &machineCfg.Spec, nil,
map[string]anywherev1.NutanixMachineConfigSpec{}, creds, time.Now)

cpSpec, err := bldr.GenerateCAPISpecControlPlane(clusterSpec)
assert.NoError(t, err)
assert.NotNil(t, cpSpec)
test.AssertContentToFile(t, string(cpSpec), tc.Output)
}
}

func minimalNutanixConfigSpec(t *testing.T) (*anywherev1.NutanixDatacenterConfig, *anywherev1.NutanixMachineConfig, map[string]anywherev1.NutanixMachineConfigSpec) {
dcConf := &anywherev1.NutanixDatacenterConfig{}
err := yaml.Unmarshal([]byte(nutanixDatacenterConfigSpec), dcConf)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: test
count: 1
endpoint:
host: test
host: 10.199.199.1
certSANs: ["foo.bar"]
machineGroupRef:
name: test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: test
count: 1
endpoint:
host: test
host: 10.199.199.1
certSANs: ["11.11.11.11"]
machineGroupRef:
name: test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: test
count: 1
endpoint:
host: test
host: 10.199.199.1
machineGroupRef:
name: test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: test
count: 1
endpoint:
host: test
host: 10.199.199.1
machineGroupRef:
name: test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: test
count: 1
endpoint:
host: test
host: 10.199.199.1
machineGroupRef:
name: test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: eksa-unit-test
count: 3
endpoint:
host: test-ip
host: 10.199.199.1
machineGroupRef:
name: eksa-unit-test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: eksa-unit-test
count: 3
endpoint:
host: test-ip
host: 10.199.199.1
machineGroupRef:
name: eksa-unit-test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: eksa-unit-test
count: 3
endpoint:
host: test-ip
host: 10.199.199.1
machineGroupRef:
name: eksa-unit-test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
name: eksa-unit-test
count: 3
endpoint:
host: test-ip
host: 10.199.199.1
machineGroupRef:
name: eksa-unit-test
kind: NutanixMachineConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: anywhere.eks.amazonaws.com/v1alpha1
kind: NutanixDatacenterConfig
metadata:
name: eksa-unit-test
namespace: default
spec:
endpoint: "prism.nutanix.com"
port: 9440
credentialRef:
kind: Secret
name: "nutanix-credentials"
ccmExcludeNodeIPs:
- 10.0.0.1
- 10.0.0.0/24
- 10.0.0.10-10.0.0.30
Loading

0 comments on commit 090ab32

Please sign in to comment.