Skip to content

Commit 5e640ad

Browse files
committed
refactor: add VirtualIPSpec API and a handler
1 parent b95ddc3 commit 5e640ad

File tree

22 files changed

+435
-265
lines changed

22 files changed

+435
-265
lines changed

api/v1alpha1/common_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,10 @@ type ControlPlaneEndpointSpec struct {
3737
// +kubebuilder:validation:Minimum=1
3838
// +kubebuilder:validation:Maximum=65535
3939
Port int32 `json:"port"`
40+
41+
// Configuration for the virtual IP provider.
42+
// +optional
43+
VirtualIPSpec *ControlPlaneVirtualIPSpec `json:"virtualIP,omitempty"`
4044
}
45+
46+
type ControlPlaneVirtualIPSpec struct{}

api/v1alpha1/crds/caren.nutanix.com_nutanixclusterconfigs.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ spec:
476476
maximum: 65535
477477
minimum: 1
478478
type: integer
479+
virtualIP:
480+
description: Configuration for the virtual IP provider.
481+
type: object
479482
required:
480483
- host
481484
- port

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 21 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/content/customization/nutanix/control-plane-endpoint.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ spec:
2222
controlPlaneEndpoint:
2323
host: x.x.x.x
2424
port: 6443
25+
virtualIP: {}
2526
```
2627
2728
Applying this configuration will result in the following value being set:
@@ -36,3 +37,22 @@ spec:
3637
host: x.x.x.x
3738
port: 6443
3839
```
40+
41+
- `KubeadmControlPlaneTemplate`
42+
43+
```yaml
44+
spec:
45+
kubeadmConfigSpec:
46+
files:
47+
- content: |
48+
apiVersion: v1
49+
kind: Pod
50+
metadata:
51+
name: kube-vip
52+
namespace: kube-system
53+
spec:
54+
...
55+
owner: root:root
56+
path: /etc/kubernetes/manifests/kube-vip.yaml
57+
permissions: "0600"
58+
```

examples/capi-quick-start/nutanix-cluster-calico-crs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ spec:
112112
controlPlaneEndpoint:
113113
host: ${CONTROL_PLANE_ENDPOINT_IP}
114114
port: 6443
115+
virtualIP: {}
115116
prismCentralEndpoint:
116117
credentials:
117118
name: ${CLUSTER_NAME}-pc-creds

examples/capi-quick-start/nutanix-cluster-calico-helm-addon.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ spec:
112112
controlPlaneEndpoint:
113113
host: ${CONTROL_PLANE_ENDPOINT_IP}
114114
port: 6443
115+
virtualIP: {}
115116
prismCentralEndpoint:
116117
credentials:
117118
name: ${CLUSTER_NAME}-pc-creds

examples/capi-quick-start/nutanix-cluster-cilium-crs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ spec:
112112
controlPlaneEndpoint:
113113
host: ${CONTROL_PLANE_ENDPOINT_IP}
114114
port: 6443
115+
virtualIP: {}
115116
prismCentralEndpoint:
116117
credentials:
117118
name: ${CLUSTER_NAME}-pc-creds

examples/capi-quick-start/nutanix-cluster-cilium-helm-addon.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ spec:
112112
controlPlaneEndpoint:
113113
host: ${CONTROL_PLANE_ENDPOINT_IP}
114114
port: 6443
115+
virtualIP: {}
115116
prismCentralEndpoint:
116117
credentials:
117118
name: ${CLUSTER_NAME}-pc-creds

hack/examples/bases/nutanix/clusterclass/kustomization.yaml.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ patches:
3939
path: "/spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/certSANs"
4040

4141
# Delete the kube-vip file.
42-
# Will be templated and added back in the handler.
42+
# Will be templated and added back in the handler if enabled.
4343
- target:
4444
kind: KubeadmControlPlaneTemplate
4545
patch: |-

hack/examples/patches/nutanix/initialize-variables.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
controlPlaneEndpoint:
1111
host: ${CONTROL_PLANE_ENDPOINT_IP}
1212
port: 6443
13+
virtualIP: {}
1314
prismCentralEndpoint:
1415
url: https://${NUTANIX_ENDPOINT}:9440
1516
insecure: ${NUTANIX_INSECURE}

pkg/common/controlplaneendpoint/virtualip/fromreader.go

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package controlplanevirtualip
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"github.com/spf13/pflag"
11+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
12+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
13+
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
14+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
15+
ctrl "sigs.k8s.io/controller-runtime"
16+
"sigs.k8s.io/controller-runtime/pkg/client"
17+
18+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/v1alpha1"
19+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/mutation"
20+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/patches"
21+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/patches/selectors"
22+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/variables"
23+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/controlplanevirtualip/providers"
24+
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/options"
25+
)
26+
27+
const (
28+
// VariableName is the external patch variable name.
29+
VariableName = "controlPlaneEndpoint"
30+
)
31+
32+
type Config struct {
33+
*options.GlobalOptions
34+
35+
defaultKubeVipConfigMapName string
36+
}
37+
38+
func (c *Config) AddFlags(prefix string, flags *pflag.FlagSet) {
39+
flags.StringVar(
40+
&c.defaultKubeVipConfigMapName,
41+
prefix+".default-kube-vip-template-configmap-name",
42+
"default-kube-vip-template",
43+
"default ConfigMap name that holds the kube-vip template used for the control-plane virtual IP",
44+
)
45+
}
46+
47+
type ControlPlaneVirtualIP struct {
48+
client client.Reader
49+
config *Config
50+
51+
variableName string
52+
variableFieldPath []string
53+
}
54+
55+
// NewControlPlaneVirtualIP is different from other generic handlers.
56+
// It requires variableName and variableFieldPath to be passed from another provider specific handler.
57+
// The code is here to be shared across different providers.
58+
func NewControlPlaneVirtualIP(
59+
cl client.Reader,
60+
config *Config,
61+
variableName string,
62+
variableFieldPath ...string,
63+
) *ControlPlaneVirtualIP {
64+
return &ControlPlaneVirtualIP{
65+
client: cl,
66+
config: config,
67+
variableName: variableName,
68+
variableFieldPath: variableFieldPath,
69+
}
70+
}
71+
72+
func (h *ControlPlaneVirtualIP) Mutate(
73+
ctx context.Context,
74+
obj *unstructured.Unstructured,
75+
vars map[string]apiextensionsv1.JSON,
76+
holderRef runtimehooksv1.HolderReference,
77+
_ client.ObjectKey,
78+
_ mutation.ClusterGetter,
79+
) error {
80+
log := ctrl.LoggerFrom(ctx).WithValues(
81+
"holderRef", holderRef,
82+
)
83+
84+
controlPlaneEndpointVar, err := variables.Get[v1alpha1.ControlPlaneEndpointSpec](
85+
vars,
86+
h.variableName,
87+
h.variableFieldPath...,
88+
)
89+
if err != nil {
90+
if variables.IsNotFoundError(err) {
91+
log.V(5).Info("ControlPlaneEndpoint variable not defined")
92+
return nil
93+
}
94+
return err
95+
}
96+
97+
log = log.WithValues(
98+
"variableName",
99+
h.variableName,
100+
"variableFieldPath",
101+
h.variableFieldPath,
102+
"variableValue",
103+
controlPlaneEndpointVar,
104+
)
105+
106+
if controlPlaneEndpointVar.VirtualIPSpec == nil {
107+
log.V(5).Info("ControlPlane VirtualIP not set")
108+
return nil
109+
}
110+
111+
// only kube-vip is supported, but more providers can be added in the future
112+
virtualIPProvider := providers.NewKubeVIPFromConfigMapProvider(
113+
h.client,
114+
h.config.defaultKubeVipConfigMapName,
115+
h.config.DefaultsNamespace(),
116+
)
117+
118+
return patches.MutateIfApplicable(
119+
obj,
120+
vars,
121+
&holderRef,
122+
selectors.ControlPlane(),
123+
log,
124+
func(obj *controlplanev1.KubeadmControlPlaneTemplate) error {
125+
virtualIPProviderFile, getFileErr := virtualIPProvider.GetFile(ctx, controlPlaneEndpointVar)
126+
if getFileErr != nil {
127+
return getFileErr
128+
}
129+
130+
log.WithValues(
131+
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
132+
"patchedObjectName", client.ObjectKeyFromObject(obj),
133+
).Info(fmt.Sprintf(
134+
"adding %s static Pod file to control plane kubeadm config spec",
135+
virtualIPProvider.Name(),
136+
))
137+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files = append(
138+
obj.Spec.Template.Spec.KubeadmConfigSpec.Files,
139+
*virtualIPProviderFile,
140+
)
141+
return nil
142+
},
143+
)
144+
}

0 commit comments

Comments
 (0)