-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IPV6 APIVIP Handling #589
base: main
Are you sure you want to change the base?
IPV6 APIVIP Handling #589
Changes from 5 commits
bcafb09
26e8725
1e82f22
9a6cd09
090d385
d66ad0b
38dc6b7
cdca128
7582178
86843c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -821,3 +821,47 @@ func TestConfigureKubernetes_SuccessfulRKE2ServerWithManifests(t *testing.T) { | |
assert.Contains(t, contents, "name: my-nginx") | ||
assert.Contains(t, contents, "image: nginx:1.14.2") | ||
} | ||
|
||
func TestKubernetesVIPManifestValidIPV4(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit-picking, but I'd align these two names from "IPV4"/"IPV6" to IPv4 too, as the rest of the code/prints. |
||
k8s := &image.Kubernetes{ | ||
Version: "v1.30.3+rke2r1", | ||
Network: image.Network{ | ||
APIVIP: "192.168.1.1", | ||
}, | ||
} | ||
|
||
manifest, err := kubernetesVIPManifest(k8s) | ||
require.NoError(t, err) | ||
|
||
assert.Contains(t, manifest, "- 192.168.1.1/32") | ||
assert.Contains(t, manifest, "- name: rke2-api") | ||
} | ||
|
||
func TestKubernetesVIPManifestValidIPV6(t *testing.T) { | ||
k8s := &image.Kubernetes{ | ||
Version: "v1.30.3+k3s1", | ||
Network: image.Network{ | ||
APIVIP: "fd12:3456:789a::21", | ||
}, | ||
} | ||
|
||
manifest, err := kubernetesVIPManifest(k8s) | ||
require.NoError(t, err) | ||
fmt.Println(manifest) | ||
atanasdinov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
assert.Contains(t, manifest, "- fd12:3456:789a::21/128") | ||
assert.Contains(t, manifest, "- name: k8s-api") | ||
assert.NotContains(t, manifest, "rke2") | ||
} | ||
|
||
func TestKubernetesVIPManifestInvalidIP(t *testing.T) { | ||
k8s := &image.Kubernetes{ | ||
Version: "v1.30.3+k3s1", | ||
Network: image.Network{ | ||
APIVIP: "1111", | ||
}, | ||
} | ||
|
||
_, err := kubernetesVIPManifest(k8s) | ||
require.ErrorContains(t, err, "parsing kubernetes APIVIP address: ParseAddr(\"1111\"): unable to parse IP") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,20 @@ import ( | |
|
||
var validNetwork = image.Network{ | ||
APIHost: "host.com", | ||
APIVIP: "127.0.0.1", | ||
APIVIP: "192.168.1.1", | ||
} | ||
|
||
var multiNode = []image.Node{ | ||
atanasdinov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
Hostname: "foo", | ||
Type: image.KubernetesNodeTypeServer, | ||
Initialiser: true, | ||
}, | ||
{ | ||
Hostname: "bar", | ||
Type: image.KubernetesNodeTypeServer, | ||
Initialiser: true, | ||
}, | ||
} | ||
|
||
func TestValidateKubernetes(t *testing.T) { | ||
|
@@ -78,7 +91,10 @@ func TestValidateKubernetes(t *testing.T) { | |
`failures all sections`: { | ||
K8s: image.Kubernetes{ | ||
Version: "v1.30.3", | ||
Network: validNetwork, | ||
Network: image.Network{ | ||
APIHost: "host.com", | ||
APIVIP: "127.0.0.1", | ||
}, | ||
Nodes: []image.Node{ | ||
{ | ||
Type: image.KubernetesNodeTypeServer, | ||
|
@@ -116,6 +132,7 @@ func TestValidateKubernetes(t *testing.T) { | |
"Helm chart 'name' field must be defined.", | ||
"Helm repository 'name' field for \"apache-repo\" must match the 'repositoryName' field in at least one defined Helm chart.", | ||
"Helm chart 'repositoryName' \"another-apache-repo\" for Helm chart \"\" does not match the name of any defined repository.", | ||
"Invalid non-unicast cluster API address (127.0.0.1) for field 'apiVIP'.", | ||
}, | ||
}, | ||
} | ||
|
@@ -185,24 +202,6 @@ func TestValidateNodes(t *testing.T) { | |
Nodes: []image.Node{}, | ||
}, | ||
}, | ||
`with nodes - no network config`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{}, | ||
Nodes: []image.Node{ | ||
{ | ||
Hostname: "host1", | ||
Type: image.KubernetesNodeTypeServer, | ||
}, | ||
{ | ||
Hostname: "host2", | ||
Type: image.KubernetesNodeTypeAgent, | ||
}, | ||
}, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"The 'apiVIP' field is required in the 'network' section when defining entries under 'nodes'.", | ||
}, | ||
}, | ||
`no hostname`: { | ||
K8s: image.Kubernetes{ | ||
Network: validNetwork, | ||
|
@@ -1079,3 +1078,102 @@ func TestValidateAdditionalArtifacts(t *testing.T) { | |
}) | ||
} | ||
} | ||
|
||
func TestValidateNetwork(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey Danial, glad to see that most of my code has been reused :) |
||
tests := map[string]struct { | ||
K8s image.Kubernetes | ||
ExpectedFailedMessages []string | ||
}{ | ||
`no network defined`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{}, | ||
Nodes: multiNode, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"The 'apiVIP' field is required in the 'network' section when defining entries under 'nodes'.", | ||
}, | ||
}, | ||
`valid ipv4`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "192.168.1.1", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
}, | ||
`valid ipv6`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "fd12:3456:789a::21", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
}, | ||
`invalid ipv4`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "500.168.1.1", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"Invalid APIVIP address \"500.168.1.1\" for field 'apiVIP'.", | ||
"\"500.168.1.1\" is not an IPV4 or IPV6 address, only IPV4 and IPV6 addresses are valid for field 'apiVIP'.", | ||
"Invalid non-unicast cluster API address (500.168.1.1) for field 'apiVIP'.", | ||
}, | ||
}, | ||
`non-unicast ipv4`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "127.0.0.1", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"Invalid non-unicast cluster API address (127.0.0.1) for field 'apiVIP'.", | ||
}, | ||
}, | ||
`invalid ipv6`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "xxxx:3456:789a::21", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"Invalid APIVIP address \"xxxx:3456:789a::21\" for field 'apiVIP'.", | ||
"\"xxxx:3456:789a::21\" is not an IPV4 or IPV6 address, only IPV4 and IPV6 addresses are valid for field 'apiVIP'.", | ||
"Invalid non-unicast cluster API address (xxxx:3456:789a::21) for field 'apiVIP'.", | ||
}, | ||
}, | ||
`non-unicast ipv6`: { | ||
K8s: image.Kubernetes{ | ||
Network: image.Network{ | ||
APIVIP: "ff02::1", | ||
}, | ||
Nodes: multiNode, | ||
}, | ||
ExpectedFailedMessages: []string{ | ||
"Invalid non-unicast cluster API address (ff02::1) for field 'apiVIP'.", | ||
}, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
k := test.K8s | ||
failures := validateNetwork(&k) | ||
assert.Len(t, failures, len(test.ExpectedFailedMessages)) | ||
|
||
var foundMessages []string | ||
for _, foundValidation := range failures { | ||
foundMessages = append(foundMessages, foundValidation.UserMessage) | ||
} | ||
|
||
for _, expectedMessage := range test.ExpectedFailedMessages { | ||
assert.Contains(t, foundMessages, expectedMessage) | ||
} | ||
|
||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this should read as
apiVIP
instead of all caps, since that's what the field is named in the definition. But I don't feel particularly strongly if you decide to keep it like this.