Skip to content

Commit 130177b

Browse files
committed
feat: CNI provider deployment via variables instead of labels
1 parent 2b313d0 commit 130177b

File tree

12 files changed

+393
-152
lines changed

12 files changed

+393
-152
lines changed

api/v1alpha1/clusterconfig_types.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ import (
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
99

10+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
1011
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/openapi/patterns"
1112
)
1213

14+
const (
15+
CNIProviderCalico = "calico"
16+
)
17+
1318
//+kubebuilder:object:root=true
1419

1520
// ClusterConfig is the Schema for the clusterconfigs API.
@@ -33,6 +38,9 @@ type ClusterConfigSpec struct {
3338

3439
// +optional
3540
ExtraAPIServerCertSANs ExtraAPIServerCertSANs `json:"extraAPIServerCertSANs,omitempty"`
41+
42+
// +optional
43+
CNI *CNI `json:"cni,omitempty"`
3644
}
3745

3846
func (ClusterConfigSpec) VariableSchema() clusterv1.VariableSchema {
@@ -47,6 +55,7 @@ func (ClusterConfigSpec) VariableSchema() clusterv1.VariableSchema {
4755
OpenAPIV3Schema,
4856
"proxy": HTTPProxy{}.VariableSchema().OpenAPIV3Schema,
4957
"extraAPIServerCertSANs": ExtraAPIServerCertSANs{}.VariableSchema().OpenAPIV3Schema,
58+
"cni": CNI{}.VariableSchema().OpenAPIV3Schema,
5059
},
5160
},
5261
}
@@ -128,6 +137,33 @@ func (ExtraAPIServerCertSANs) VariableSchema() clusterv1.VariableSchema {
128137
}
129138
}
130139

140+
// CNI required for providing CNI configuration.
141+
type CNI struct {
142+
Provider string `json:"provider,omitempty"`
143+
}
144+
145+
func (CNI) VariableSchema() clusterv1.VariableSchema {
146+
supportedCNIProviders := []string{CNIProviderCalico}
147+
148+
cniProviderEnumVals, err := variables.ValuesToEnumJSON(supportedCNIProviders...)
149+
if err != nil {
150+
panic(err)
151+
}
152+
153+
return clusterv1.VariableSchema{
154+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
155+
Type: "object",
156+
Properties: map[string]clusterv1.JSONSchemaProps{
157+
"provider": {
158+
Description: "CNI provider to deploy",
159+
Type: "string",
160+
Enum: cniProviderEnumVals,
161+
},
162+
},
163+
},
164+
}
165+
}
166+
131167
// +kubebuilder:object:root=true
132168
func init() {
133169
SchemeBuilder.Register(&ClusterConfig{})

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

charts/capi-runtime-extensions/templates/deployment.yaml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,10 @@ spec:
2929
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
3030
args:
3131
- --webhook-cert-dir=/runtimehooks-certs/
32-
- --calicocni.defaultsNamespace=$(POD_NAMESPACE)
32+
- --calicocni.defaultsNamespace={{ .Release.Namespace }}
3333
{{- range $key, $value := .Values.extraArgs }}
3434
- --{{ $key }}={{ $value }}
3535
{{- end }}
36-
env:
37-
- name: POD_NAMESPACE
38-
valueFrom:
39-
fieldRef:
40-
fieldPath: metadata.namespace
4136
{{- if .Values.env }}
4237
{{- range $key, $value := .Values.env }}
4338
- name: "{{ $key }}"

cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func main() {
116116

117117
servicelbgc.New(mgr.GetClient()),
118118

119-
calico.New(mgr.GetClient(), calicoCNIConfig),
119+
calico.New(mgr.GetClient(), calicoCNIConfig, clusterconfig.VariableName, "cni"),
120120

121121
httpproxy.NewVariable(),
122122
httpproxy.NewPatch(mgr.GetClient(), httpproxy.VariableName),
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package variables
5+
6+
import (
7+
"encoding/json"
8+
"fmt"
9+
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
)
12+
13+
func ValuesToEnumJSON[T any](vals ...T) ([]apiextensionsv1.JSON, error) {
14+
enumJSON := make([]apiextensionsv1.JSON, 0, len(vals))
15+
16+
for _, v := range vals {
17+
enumVal, err := json.Marshal(v)
18+
if err != nil {
19+
return nil, fmt.Errorf("failed to marshal enum value: %v", v)
20+
}
21+
enumJSON = append(enumJSON, apiextensionsv1.JSON{Raw: enumVal})
22+
}
23+
24+
return enumJSON, nil
25+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package variables
4+
5+
import (
6+
"testing"
7+
8+
"github.com/onsi/gomega"
9+
)
10+
11+
func TestValuesToEnumJSON(t *testing.T) {
12+
t.Parallel()
13+
14+
testCases := []struct {
15+
name string
16+
input []interface{}
17+
expected []interface{}
18+
}{{
19+
name: "Empty input",
20+
input: []any{},
21+
expected: []interface{}{},
22+
}, {
23+
name: "Single value",
24+
input: []any{"value1"},
25+
expected: []interface{}{`"value1"`},
26+
}, {
27+
name: "Multiple values",
28+
input: []interface{}{"value1", "value2", "value3"},
29+
expected: []interface{}{`"value1"`, `"value2"`, `"value3"`},
30+
}, {
31+
name: "Multiple integer values",
32+
input: []interface{}{1, 2, 3},
33+
expected: []interface{}{`1`, `2`, `3`},
34+
}, {
35+
name: "Multiple integer array values",
36+
input: []interface{}{[]int{1, 2}, []int{2, 3}, []int{49, 64}},
37+
expected: []interface{}{`[1,2]`, `[2,3]`, `[49,64]`},
38+
}, {
39+
name: "Multiple string array values",
40+
input: []interface{}{
41+
[]string{"value1", "value2"},
42+
[]string{"value2", "value3"},
43+
[]string{"value49", "value64"},
44+
},
45+
expected: []interface{}{
46+
`["value1","value2"]`,
47+
`["value2","value3"]`,
48+
`["value49","value64"]`,
49+
},
50+
}}
51+
52+
for i := range testCases {
53+
tt := testCases[i]
54+
55+
t.Run(tt.name, func(t *testing.T) {
56+
t.Parallel()
57+
58+
g := gomega.NewWithT(t)
59+
60+
// Call the function under test
61+
jsonData, err := ValuesToEnumJSON(tt.input...)
62+
g.Expect(err).NotTo(gomega.HaveOccurred())
63+
64+
// Assert the result
65+
g.Expect(jsonData).To(gomega.HaveLen(len(tt.expected)))
66+
for i, expected := range tt.expected {
67+
g.Expect(string(jsonData[i].Raw)).To(gomega.Equal(expected))
68+
}
69+
})
70+
}
71+
}

common/pkg/capi/clustertopology/variables/variable.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1010
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
11+
"sigs.k8s.io/cluster-api/api/v1beta1"
1112
"sigs.k8s.io/cluster-api/exp/runtime/topologymutation"
1213
)
1314

@@ -45,3 +46,21 @@ func Get[T any](
4546
err = json.Unmarshal(jsonValue, &value)
4647
return value, err == nil, err
4748
}
49+
50+
// ClusterVariablesToVariablesMap converts a list of ClusterVariables to a map of JSON (name is the map key).
51+
// See: https://github.com/kubernetes-sigs/cluster-api/blob/v1.5.1/internal/controllers/topology/cluster/patches/variables/variables.go#L445
52+
//
53+
//nolint:lll // Long URLs in comments above. Adding nolint:lll here because it doesn't work in comment lines. See: https://github.com/golangci/golangci-lint/issues/3983
54+
func ClusterVariablesToVariablesMap(
55+
variables []v1beta1.ClusterVariable,
56+
) map[string]apiextensionsv1.JSON {
57+
if variables == nil {
58+
return nil
59+
}
60+
61+
variablesMap := make(map[string]apiextensionsv1.JSON, len(variables))
62+
for i := range variables {
63+
variablesMap[variables[i].Name] = variables[i].Value
64+
}
65+
return variablesMap
66+
}

0 commit comments

Comments
 (0)