Skip to content

Commit 2a0269a

Browse files
committed
feat: Allow pod subnet to be specified via annotation
1 parent a35440e commit 2a0269a

File tree

3 files changed

+55
-43
lines changed

3 files changed

+55
-43
lines changed

pkg/handlers/cni/calico/handler.go

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111
"io"
1212
"io/fs"
1313

14-
"github.com/go-logr/logr"
1514
corev1 "k8s.io/api/core/v1"
1615
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1716
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1817
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme"
18+
"k8s.io/apimachinery/pkg/runtime"
1919
"k8s.io/apimachinery/pkg/runtime/schema"
2020
"k8s.io/apimachinery/pkg/runtime/serializer/json"
2121
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -33,8 +33,6 @@ import (
3333

3434
const (
3535
CNILabelValue = "calico"
36-
37-
DefaultPodSubnet = "192.168.0.0/16"
3836
)
3937

4038
type CalicoCNI struct {
@@ -88,38 +86,54 @@ func (s *CalicoCNI) AfterControlPlaneInitialized(
8886
// will update for failure response properly.
8987
resp.SetStatus(runtimehooksv1.ResponseStatusSuccess)
9088

91-
if v, ok := req.Cluster.GetLabels()[cni.CNILabelKey]; !ok || v != CNILabelValue {
92-
log.V(4).Info("Skipping Calico CNI handler, CNI provider is not calico")
89+
if v, ok := req.Cluster.GetLabels()[cni.CNIProviderLabelKey]; !ok || v != CNILabelValue {
90+
log.V(4).Info(
91+
fmt.Sprintf(
92+
"Skipping Calico CNI handler, cluster does not specify %q as value of CNI provider label %q",
93+
CNILabelValue,
94+
cni.CNIProviderLabelKey,
95+
),
96+
)
9397
return
9498
}
9599

96100
manifestsFS, ok := providerManifestsFS[req.Cluster.Spec.InfrastructureRef.Kind]
97101
if !ok {
98-
log.V(4).Info("Skipping Calico CNI handler, unknown CNI provider")
102+
log.V(4).Info(
103+
fmt.Sprintf(
104+
"Skipping Calico CNI handler, no default configured for infrastructure provider %q",
105+
req.Cluster.Spec.InfrastructureRef.Kind,
106+
),
107+
)
99108
return
100109
}
101110

102-
if err := applyTigeraOperatorCRS(ctx, s.client, &req.Cluster, log); err != nil {
111+
log.Info("Ensuring Tigera CRS and manifests ConfigMap exist in cluster namespace")
112+
tigeraObjs := generateTigeraOperatorCRS(&req.Cluster)
113+
if err := client.ServerSideApply(ctx, s.client, tigeraObjs...); err != nil {
103114
log.Error(err, "failed to apply Tigera ClusterResourceSet")
104115
resp.SetStatus(runtimehooksv1.ResponseStatusFailure)
105116
resp.SetMessage(fmt.Sprintf("failed to apply Tigera ClusterResourceSet: %v", err))
117+
return
118+
}
119+
120+
log.Info("Ensuring Calico installation CRS and ConfigMap exist in cluster namespace")
121+
calicoCNIObjs, err := generateProviderCNICRS(manifestsFS, &req.Cluster, s.client.Scheme())
122+
if err != nil {
123+
log.Error(err, "failed to generate provider CNI CRS")
124+
resp.SetStatus(runtimehooksv1.ResponseStatusFailure)
125+
resp.SetMessage(fmt.Sprintf("failed to generate provider CNI CRS: %v", err))
126+
return
106127
}
107128

108-
if err := applyProviderCNICRS(ctx, manifestsFS, s.client, &req.Cluster, log); err != nil {
129+
if err := client.ServerSideApply(ctx, s.client, calicoCNIObjs...); err != nil {
109130
log.Error(err, "failed to apply CNI installation ClusterResourceSet")
110131
resp.SetStatus(runtimehooksv1.ResponseStatusFailure)
111132
resp.SetMessage(fmt.Sprintf("failed to apply CNI installation ClusterResourceSet: %v", err))
112133
}
113134
}
114135

115-
func applyTigeraOperatorCRS(
116-
ctx context.Context,
117-
c ctrlclient.Client,
118-
cluster *capiv1.Cluster,
119-
log logr.Logger,
120-
) error {
121-
log.Info("Ensuring Tigera CRS and manifests ConfigMap exist in cluster namespace")
122-
136+
func generateTigeraOperatorCRS(cluster *capiv1.Cluster) []ctrlclient.Object {
123137
// Set the namespace on the tigera configmap to apply by deep copying and then mutating.
124138
namespacedTigeraConfigMap := &corev1.ConfigMap{}
125139
tigeraConfigMap.DeepCopyInto(namespacedTigeraConfigMap)
@@ -141,32 +155,24 @@ func applyTigeraOperatorCRS(
141155
}},
142156
Strategy: string(crsv1.ClusterResourceSetStrategyReconcile),
143157
ClusterSelector: metav1.LabelSelector{
144-
MatchLabels: map[string]string{cni.CNILabelKey: CNILabelValue},
158+
MatchLabels: map[string]string{cni.CNIProviderLabelKey: CNILabelValue},
145159
},
146160
},
147161
}
148162

149-
return client.ServerSideApply(ctx, c, namespacedTigeraConfigMap, tigeraCRS)
163+
return []ctrlclient.Object{namespacedTigeraConfigMap, tigeraCRS}
150164
}
151165

152-
func applyProviderCNICRS(
153-
ctx context.Context,
154-
manifestsFS fs.FS,
155-
c ctrlclient.Client,
156-
cluster *capiv1.Cluster,
157-
log logr.Logger,
158-
) error {
159-
log.Info("Ensuring Calico installation CRS and ConfigMap exist in cluster namespace")
160-
166+
func generateProviderCNICRS(manifestsFS fs.FS, cluster *capiv1.Cluster, scheme *runtime.Scheme) ([]ctrlclient.Object, error) {
161167
readers, cleanup, err := readersForManifestsInFS(manifestsFS)
162168
if err != nil {
163-
return fmt.Errorf("failed to read embedded manifests: %w", err)
169+
return nil, fmt.Errorf("failed to read embedded manifests: %w", err)
164170
}
165171
defer func() { _ = cleanup() }()
166172

167173
parsed, err := parser.ReadersToUnstructured(readers...)
168174
if err != nil {
169-
return fmt.Errorf("failed to parse embedded manifests: %w", err)
175+
return nil, fmt.Errorf("failed to parse embedded manifests: %w", err)
170176
}
171177

172178
cm := &corev1.ConfigMap{
@@ -191,51 +197,55 @@ func applyProviderCNICRS(
191197
},
192198
)
193199

200+
podSubnet, podSubnetSpecified := cluster.GetAnnotations()[cni.PodSubnetAnnotationKey]
201+
194202
var b bytes.Buffer
195203

196204
for _, o := range parsed {
197-
if o.GetObjectKind().GroupVersionKind().GroupKind() == calicoInstallationGK {
205+
if podSubnetSpecified &&
206+
podSubnet != "" &&
207+
o.GetObjectKind().GroupVersionKind().GroupKind() == calicoInstallationGK {
198208
obj := o.(*unstructured.Unstructured).Object
199209

200210
ipPoolsRef, exists, err := unstructured.NestedFieldNoCopy(
201211
obj,
202212
"spec", "calicoNetwork", "ipPools",
203213
)
204214
if err != nil {
205-
return fmt.Errorf("failed to get ipPools from unstructured object: %w", err)
215+
return nil, fmt.Errorf("failed to get ipPools from unstructured object: %w", err)
206216
}
207217
if !exists {
208-
return fmt.Errorf("missing ipPools in unstructured object")
218+
return nil, fmt.Errorf("missing ipPools in unstructured object")
209219
}
210220

211221
ipPools := ipPoolsRef.([]interface{})
212222

213223
err = unstructured.SetNestedField(
214224
ipPools[0].(map[string]interface{}),
215-
DefaultPodSubnet,
225+
podSubnet,
216226
"cidr",
217227
)
218228
if err != nil {
219-
return fmt.Errorf("failed to set default pod subnet: %w", err)
229+
return nil, fmt.Errorf("failed to set default pod subnet: %w", err)
220230
}
221231

222232
err = unstructured.SetNestedSlice(obj, ipPools, "spec", "calicoNetwork", "ipPools")
223233
if err != nil {
224-
return fmt.Errorf("failed to update ipPools: %w", err)
234+
return nil, fmt.Errorf("failed to update ipPools: %w", err)
225235
}
226236
}
227237

228238
if err := yamlSerializer.Encode(o, &b); err != nil {
229-
return fmt.Errorf("failed to serialize manifests: %w", err)
239+
return nil, fmt.Errorf("failed to serialize manifests: %w", err)
230240
}
231241

232242
_, _ = b.WriteString("\n---\n")
233243
}
234244

235245
cm.Data["manifests"] = b.String()
236246

237-
if err := controllerutil.SetOwnerReference(cluster, cm, c.Scheme()); err != nil {
238-
return fmt.Errorf("failed to set owner reference: %w", err)
247+
if err := controllerutil.SetOwnerReference(cluster, cm, scheme); err != nil {
248+
return nil, fmt.Errorf("failed to set owner reference: %w", err)
239249
}
240250

241251
crs := &crsv1.ClusterResourceSet{
@@ -259,11 +269,11 @@ func applyProviderCNICRS(
259269
},
260270
}
261271

262-
if err := controllerutil.SetOwnerReference(cluster, crs, c.Scheme()); err != nil {
263-
return fmt.Errorf("failed to set owner reference: %w", err)
272+
if err := controllerutil.SetOwnerReference(cluster, crs, scheme); err != nil {
273+
return nil, fmt.Errorf("failed to set owner reference: %w", err)
264274
}
265275

266-
return client.ServerSideApply(ctx, c, cm, crs)
276+
return []ctrlclient.Object{cm, crs}, nil
267277
}
268278

269279
func readersForManifestsInFS(

pkg/handlers/cni/calico/manifests/docker/installation.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ spec:
1515
# Note: The ipPools section cannot be modified post-install.
1616
ipPools:
1717
- blockSize: 26
18-
cidr: ${POD_SUBNET}
18+
cidr: 192.168.0.0/16
1919
encapsulation: VXLANCrossSubnet
2020
natOutgoing: Enabled
2121
nodeSelector: all()

pkg/handlers/cni/constants.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ package cni
66
import "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers"
77

88
const (
9-
CNILabelKey = handlers.MetadataDomain + "/cni"
9+
CNIProviderLabelKey = handlers.MetadataDomain + "/cni"
10+
11+
PodSubnetAnnotationKey = handlers.MetadataDomain + "/pod-subnet"
1012
)

0 commit comments

Comments
 (0)