Skip to content

Commit 3c91ca5

Browse files
authored
feat: Add Calico CNI AWS ingress rules (#206)
1 parent 2abf01b commit 3c91ca5

File tree

11 files changed

+454
-55
lines changed

11 files changed

+454
-55
lines changed

common/pkg/capi/apis/decoders.go

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,23 @@ package apis
55

66
import (
77
"k8s.io/apimachinery/pkg/runtime"
8-
"k8s.io/apimachinery/pkg/runtime/schema"
98
"k8s.io/apimachinery/pkg/runtime/serializer"
10-
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
11-
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
12-
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
13-
14-
capav1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
15-
capdv1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
169
)
1710

18-
var capiCoreGroups = []schema.GroupVersion{
19-
controlplanev1.GroupVersion,
20-
bootstrapv1.GroupVersion,
21-
capiv1.GroupVersion,
11+
func DecoderForScheme(scheme *runtime.Scheme) runtime.Decoder {
12+
return serializer.NewCodecFactory(scheme).UniversalDecoder(
13+
scheme.PrioritizedVersionsAllGroups()...,
14+
)
2215
}
2316

2417
func CAPIDecoder() runtime.Decoder {
25-
return serializer.NewCodecFactory(CAPIScheme()).UniversalDecoder(capiCoreGroups...)
18+
return DecoderForScheme(CAPIScheme())
2619
}
2720

2821
func CAPDDecoder() runtime.Decoder {
29-
return serializer.NewCodecFactory(CAPDScheme()).UniversalDecoder(
30-
append(
31-
[]schema.GroupVersion{capdv1.GroupVersion},
32-
capiCoreGroups...,
33-
)...,
34-
)
22+
return DecoderForScheme(CAPDScheme())
3523
}
3624

3725
func CAPADecoder() runtime.Decoder {
38-
return serializer.NewCodecFactory(CAPAScheme()).UniversalDecoder(
39-
append(
40-
[]schema.GroupVersion{capav1.GroupVersion},
41-
capiCoreGroups...,
42-
)...,
43-
)
26+
return DecoderForScheme(CAPAScheme())
4427
}

common/pkg/capi/apis/schemes.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,41 @@ import (
1414
capdv1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
1515
)
1616

17-
func CAPIScheme() *runtime.Scheme {
17+
func NewScheme(registerFuncs ...func(*runtime.Scheme) error) *runtime.Scheme {
18+
sb := runtime.NewSchemeBuilder(registerFuncs...)
1819
scheme := runtime.NewScheme()
19-
20-
utilruntime.Must(bootstrapv1.AddToScheme(scheme))
21-
utilruntime.Must(controlplanev1.AddToScheme(scheme))
22-
utilruntime.Must(capiv1.AddToScheme(scheme))
23-
20+
utilruntime.Must(sb.AddToScheme(scheme))
2421
return scheme
2522
}
2623

27-
func CAPAScheme() *runtime.Scheme {
28-
scheme := runtime.NewScheme()
24+
func CAPIRegisterFuncs() []func(*runtime.Scheme) error {
25+
return []func(*runtime.Scheme) error{
26+
bootstrapv1.AddToScheme,
27+
controlplanev1.AddToScheme,
28+
capiv1.AddToScheme,
29+
}
30+
}
2931

30-
utilruntime.Must(bootstrapv1.AddToScheme(scheme))
31-
utilruntime.Must(controlplanev1.AddToScheme(scheme))
32-
utilruntime.Must(capiv1.AddToScheme(scheme))
33-
utilruntime.Must(capav1.AddToScheme(scheme))
32+
func CAPARegisterFuncs() []func(*runtime.Scheme) error {
33+
return []func(*runtime.Scheme) error{
34+
capav1.AddToScheme,
35+
}
36+
}
3437

35-
return scheme
38+
func CAPDRegisterFuncs() []func(*runtime.Scheme) error {
39+
return []func(*runtime.Scheme) error{
40+
capdv1.AddToScheme,
41+
}
3642
}
3743

38-
func CAPDScheme() *runtime.Scheme {
39-
scheme := runtime.NewScheme()
44+
func CAPIScheme() *runtime.Scheme {
45+
return NewScheme(CAPIRegisterFuncs()...)
46+
}
4047

41-
utilruntime.Must(bootstrapv1.AddToScheme(scheme))
42-
utilruntime.Must(controlplanev1.AddToScheme(scheme))
43-
utilruntime.Must(capiv1.AddToScheme(scheme))
44-
utilruntime.Must(capdv1.AddToScheme(scheme))
48+
func CAPAScheme() *runtime.Scheme {
49+
return NewScheme(append(CAPIRegisterFuncs(), CAPARegisterFuncs()...)...)
50+
}
4551

46-
return scheme
52+
func CAPDScheme() *runtime.Scheme {
53+
return NewScheme(append(CAPIRegisterFuncs(), CAPDRegisterFuncs()...)...)
4754
}

common/pkg/testutils/capitest/serializer/tojson.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"encoding/json"
99

1010
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
11+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
1112
)
1213

1314
func ToJSON(v any) []byte {
@@ -21,12 +22,9 @@ func ToJSON(v any) []byte {
2122
data, err = json.Marshal(v)
2223
}
2324

24-
if err != nil {
25-
panic(err)
26-
}
25+
utilruntime.Must(err)
26+
2727
compacted := &bytes.Buffer{}
28-
if err := json.Compact(compacted, data); err != nil {
29-
panic(err)
30-
}
28+
utilruntime.Must(json.Compact(compacted, data))
3129
return compacted.Bytes()
3230
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package calico
5+
6+
import (
7+
"context"
8+
_ "embed"
9+
10+
"github.com/go-logr/logr"
11+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
12+
"k8s.io/apimachinery/pkg/runtime"
13+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
14+
"sigs.k8s.io/cluster-api/exp/runtime/topologymutation"
15+
ctrl "sigs.k8s.io/controller-runtime"
16+
"sigs.k8s.io/controller-runtime/pkg/client"
17+
18+
"github.com/d2iq-labs/capi-runtime-extensions/api/v1alpha1"
19+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/apis"
20+
commonhandlers "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers"
21+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
22+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches"
23+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches/selectors"
24+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
25+
capav1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
26+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/clusterconfig"
27+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation/cni"
28+
)
29+
30+
const (
31+
// HandlerNamePatch is the name of the inject handler.
32+
HandlerNamePatch = "CalicoCNIPatch"
33+
)
34+
35+
type calicoPatchHandler struct {
36+
variableName string
37+
variableFieldPath []string
38+
}
39+
40+
var (
41+
_ commonhandlers.Named = &calicoPatchHandler{}
42+
_ mutation.GeneratePatches = &calicoPatchHandler{}
43+
_ mutation.MetaMutator = &calicoPatchHandler{}
44+
)
45+
46+
func NewPatch() *calicoPatchHandler {
47+
return newCalicoPatchHandler(cni.VariableName)
48+
}
49+
50+
func NewMetaPatch() *calicoPatchHandler {
51+
return newCalicoPatchHandler(clusterconfig.MetaVariableName, cni.VariableName)
52+
}
53+
54+
func newCalicoPatchHandler(
55+
variableName string,
56+
variableFieldPath ...string,
57+
) *calicoPatchHandler {
58+
return &calicoPatchHandler{
59+
variableName: variableName,
60+
variableFieldPath: variableFieldPath,
61+
}
62+
}
63+
64+
func (h *calicoPatchHandler) Name() string {
65+
return HandlerNamePatch
66+
}
67+
68+
func (h *calicoPatchHandler) Mutate(
69+
ctx context.Context,
70+
obj runtime.Object,
71+
vars map[string]apiextensionsv1.JSON,
72+
holderRef runtimehooksv1.HolderReference,
73+
_ client.ObjectKey,
74+
) error {
75+
log := ctrl.LoggerFrom(ctx).WithValues(
76+
"holderRef", holderRef,
77+
)
78+
79+
cniVar, found, err := variables.Get[v1alpha1.CNI](
80+
vars,
81+
h.variableName,
82+
h.variableFieldPath...,
83+
)
84+
if err != nil {
85+
return err
86+
}
87+
if !found {
88+
log.V(5).Info("cni variable not defined")
89+
return nil
90+
}
91+
if cniVar.Provider != v1alpha1.CNIProviderCalico {
92+
log.V(5).
93+
WithValues("cniProvider", cniVar.Provider).
94+
Info("CNI provider not defined as Calico - skipping")
95+
return nil
96+
}
97+
98+
log = log.WithValues(
99+
"variableName",
100+
h.variableName,
101+
"variableFieldPath",
102+
h.variableFieldPath,
103+
"variableValue",
104+
cniVar,
105+
)
106+
107+
return patches.Generate(
108+
obj,
109+
vars,
110+
&holderRef,
111+
selectors.InfrastructureCluster(capav1.GroupVersion.Version, "AWSClusterTemplate"),
112+
log,
113+
mutateAWSClusterTemplateFunc(log),
114+
)
115+
}
116+
117+
func (h *calicoPatchHandler) GeneratePatches(
118+
ctx context.Context,
119+
req *runtimehooksv1.GeneratePatchesRequest,
120+
resp *runtimehooksv1.GeneratePatchesResponse,
121+
) {
122+
topologymutation.WalkTemplates(
123+
ctx,
124+
apis.DecoderForScheme(apis.CAPAScheme()),
125+
req,
126+
resp,
127+
func(
128+
ctx context.Context,
129+
obj runtime.Object,
130+
vars map[string]apiextensionsv1.JSON,
131+
holderRef runtimehooksv1.HolderReference,
132+
) error {
133+
return h.Mutate(ctx, obj, vars, holderRef, client.ObjectKey{})
134+
},
135+
)
136+
}
137+
138+
func mutateAWSClusterTemplateFunc(log logr.Logger) func(obj *capav1.AWSClusterTemplate) error {
139+
return func(obj *capav1.AWSClusterTemplate) error {
140+
log.WithValues(
141+
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
142+
"patchedObjectName", client.ObjectKeyFromObject(obj),
143+
).Info("setting CNI ingress rules in AWS cluster spec")
144+
145+
if obj.Spec.Template.Spec.NetworkSpec.CNI == nil {
146+
obj.Spec.Template.Spec.NetworkSpec.CNI = &capav1.CNISpec{}
147+
}
148+
obj.Spec.Template.Spec.NetworkSpec.CNI.CNIIngressRules = append(
149+
obj.Spec.Template.Spec.NetworkSpec.CNI.CNIIngressRules,
150+
capav1.CNIIngressRule{
151+
Description: "typha (calico)",
152+
Protocol: capav1.SecurityGroupProtocolTCP,
153+
FromPort: 5473,
154+
ToPort: 5473,
155+
},
156+
capav1.CNIIngressRule{
157+
Description: "bgp (calico)",
158+
Protocol: capav1.SecurityGroupProtocolTCP,
159+
FromPort: 179,
160+
ToPort: 179,
161+
},
162+
capav1.CNIIngressRule{
163+
Description: "IP-in-IP (calico)",
164+
Protocol: capav1.SecurityGroupProtocolIPinIP,
165+
FromPort: -1,
166+
ToPort: 65535,
167+
},
168+
capav1.CNIIngressRule{
169+
Description: "node metrics (calico)",
170+
Protocol: capav1.SecurityGroupProtocolTCP,
171+
FromPort: 9091,
172+
ToPort: 9091,
173+
},
174+
capav1.CNIIngressRule{
175+
Description: "typha metrics (calico)",
176+
Protocol: capav1.SecurityGroupProtocolTCP,
177+
FromPort: 9093,
178+
ToPort: 9093,
179+
},
180+
)
181+
182+
return nil
183+
}
184+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package calico
5+
6+
import (
7+
"testing"
8+
9+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
10+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/aws/mutation/cni/calico/tests"
11+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/mutation/cni"
12+
)
13+
14+
func TestGeneratePatches(t *testing.T) {
15+
t.Parallel()
16+
17+
tests.TestGeneratePatches(
18+
t,
19+
func() mutation.GeneratePatches { return NewPatch() },
20+
cni.VariableName,
21+
)
22+
}

0 commit comments

Comments
 (0)