Skip to content

Commit 572735b

Browse files
dkoshkinShalin Patel
and
Shalin Patel
authored
feat: add AWS IAM instance profile patch (#216)
New AWS patch for control-plane and worker machines Tested creating a cluster: ``` - apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: AWSMachineTemplate metadata: name: aws-quick-start-control-plane-pgg9l namespace: default spec: template: spec: iamInstanceProfile: custom-control-plane.cluster-api-provider-aws.sigs.k8s.io instanceType: m5.xlarge - apiVersion: infrastructure.cluster.x-k8s.io/v1beta2 kind: AWSMachineTemplate name: aws-quick-start-md-0-infra-jkwdz namespace: default spec: template: spec: iamInstanceProfile: custom-nodes.cluster-api-provider-aws.sigs.k8s.io instanceType: m5.2xlarge ``` --------- Signed-off-by: Dimitri Koshkin <[email protected]> Co-authored-by: Shalin Patel <[email protected]>
1 parent fa8e744 commit 572735b

File tree

17 files changed

+593
-71
lines changed

17 files changed

+593
-71
lines changed

api/v1alpha1/aws_node_types.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,30 @@ package v1alpha1
55

66
import clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
77

8-
type AWSNodeSpec struct{}
8+
type AWSNodeSpec struct {
9+
// +optional
10+
IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
11+
}
912

1013
func (AWSNodeSpec) VariableSchema() clusterv1.VariableSchema {
1114
return clusterv1.VariableSchema{
1215
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
1316
Description: "AWS Node configuration",
1417
Type: "object",
15-
Properties: map[string]clusterv1.JSONSchemaProps{},
18+
Properties: map[string]clusterv1.JSONSchemaProps{
19+
"iamInstanceProfile": IAMInstanceProfile("").VariableSchema().OpenAPIV3Schema,
20+
},
21+
},
22+
}
23+
}
24+
25+
type IAMInstanceProfile string
26+
27+
func (IAMInstanceProfile) VariableSchema() clusterv1.VariableSchema {
28+
return clusterv1.VariableSchema{
29+
OpenAPIV3Schema: clusterv1.JSONSchemaProps{
30+
Type: "string",
31+
Description: "The IAM instance profile to use for the cluster Machines",
1632
},
1733
}
1834
}

api/v1alpha1/zz_generated.deepcopy.go

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

common/pkg/testutils/capitest/request/items.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import (
1414
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
1515

1616
capav1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
17+
capdv1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
1718
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/testutils/capitest/serializer"
19+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
1820
)
1921

2022
const (
@@ -140,3 +142,95 @@ func NewAWSClusterTemplateRequestItem(
140142
uid,
141143
)
142144
}
145+
146+
func NewCPDockerMachineTemplateRequestItem(
147+
uid types.UID,
148+
) runtimehooksv1.GeneratePatchesRequestItem {
149+
return NewRequestItem(
150+
&capdv1.DockerMachineTemplate{
151+
TypeMeta: metav1.TypeMeta{
152+
APIVersion: capdv1.GroupVersion.String(),
153+
Kind: "DockerMachineTemplate",
154+
},
155+
ObjectMeta: metav1.ObjectMeta{
156+
Name: "docker-machine-template",
157+
Namespace: "docker-cluster",
158+
},
159+
},
160+
&runtimehooksv1.HolderReference{
161+
APIVersion: controlplanev1.GroupVersion.String(),
162+
Kind: "KubeadmControlPlane",
163+
FieldPath: "spec.machineTemplate.infrastructureRef",
164+
},
165+
uid,
166+
)
167+
}
168+
169+
func NewWorkerDockerMachineTemplateRequestItem(
170+
uid types.UID,
171+
) runtimehooksv1.GeneratePatchesRequestItem {
172+
return NewRequestItem(
173+
&capdv1.DockerMachineTemplate{
174+
TypeMeta: metav1.TypeMeta{
175+
APIVersion: capdv1.GroupVersion.String(),
176+
Kind: "DockerMachineTemplate",
177+
},
178+
ObjectMeta: metav1.ObjectMeta{
179+
Name: "docker-machine-template",
180+
Namespace: "docker-cluster",
181+
},
182+
},
183+
&runtimehooksv1.HolderReference{
184+
APIVersion: clusterv1.GroupVersion.String(),
185+
Kind: "MachineDeployment",
186+
FieldPath: "spec.template.spec.infrastructureRef",
187+
},
188+
uid,
189+
)
190+
}
191+
192+
func NewCPAWSMachineTemplateRequestItem(
193+
uid types.UID,
194+
) runtimehooksv1.GeneratePatchesRequestItem {
195+
return NewRequestItem(
196+
&capav1.AWSMachineTemplate{
197+
TypeMeta: metav1.TypeMeta{
198+
APIVersion: capav1.GroupVersion.String(),
199+
Kind: "AWSMachineTemplate",
200+
},
201+
ObjectMeta: metav1.ObjectMeta{
202+
Name: "aws-machine-template",
203+
Namespace: "aws-cluster",
204+
},
205+
},
206+
&runtimehooksv1.HolderReference{
207+
APIVersion: controlplanev1.GroupVersion.String(),
208+
Kind: "KubeadmControlPlane",
209+
FieldPath: "spec.machineTemplate.infrastructureRef",
210+
},
211+
uid,
212+
)
213+
}
214+
215+
func NewWorkerAWSMachineTemplateRequestItem(
216+
uid types.UID,
217+
) runtimehooksv1.GeneratePatchesRequestItem {
218+
return NewRequestItem(
219+
&capav1.AWSMachineTemplate{
220+
TypeMeta: metav1.TypeMeta{
221+
APIVersion: capav1.GroupVersion.String(),
222+
Kind: "AWSMachineTemplate",
223+
},
224+
ObjectMeta: metav1.ObjectMeta{
225+
Name: "aws-machine-template",
226+
Namespace: "aws-cluster",
227+
},
228+
},
229+
&runtimehooksv1.HolderReference{
230+
APIVersion: clusterv1.GroupVersion.String(),
231+
Kind: "MachineDeployment",
232+
FieldPath: "spec.template.spec.infrastructureRef",
233+
},
234+
uid,
235+
)
236+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
+++
2+
title = "IAM Instance Profile"
3+
+++
4+
5+
The IAM instance profile customization allows the user to specify the profile to use for control-plane
6+
and worker Machines.
7+
8+
This customization will be available when the
9+
[provider-specific cluster configuration patch]({{< ref "..">}}) is included in the `ClusterClass`.
10+
11+
## Example
12+
13+
To specify the IAM instance profile, use the following configuration:
14+
15+
```yaml
16+
apiVersion: cluster.x-k8s.io/v1beta1
17+
kind: Cluster
18+
metadata:
19+
name: <NAME>
20+
spec:
21+
topology:
22+
variables:
23+
- name: clusterConfig
24+
value:
25+
controlPlane:
26+
aws:
27+
iamInstanceProfile: custom-control-plane.cluster-api-provider-aws.sigs.k8s.io
28+
- name: workerConfig
29+
value:
30+
aws:
31+
iamInstanceProfile: custom-nodes.cluster-api-provider-aws.sigs.k8s.io
32+
```
33+
34+
Applying this configuration will result in the following value being set:
35+
36+
- control-plane `AWSMachineTemplate`:
37+
38+
- ```yaml
39+
spec:
40+
template:
41+
spec:
42+
iamInstanceProfile: custom-control-plane.cluster-api-provider-aws.sigs.k8s.io
43+
```
44+
45+
- worker `AWSMachineTemplate`:
46+
47+
- ```yaml
48+
spec:
49+
template:
50+
spec:
51+
iamInstanceProfile: custom-nodes.cluster-api-provider-aws.sigs.k8s.io
52+
```

pkg/handlers/aws/clusterconfig/variables_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,19 @@ func TestVariableValidation(t *testing.T) {
2828
},
2929
},
3030
},
31+
capitest.VariableTestDef{
32+
Name: "specified IAM instance profile",
33+
Vals: v1alpha1.ClusterConfigSpec{
34+
ControlPlane: &v1alpha1.NodeConfigSpec{
35+
AWS: &v1alpha1.AWSNodeSpec{
36+
IAMInstanceProfile: ptr.To(
37+
v1alpha1.IAMInstanceProfile(
38+
"control-plane.cluster-api-provider-aws.sigs.k8s.io",
39+
),
40+
),
41+
},
42+
},
43+
},
44+
},
3145
)
3246
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package iaminstanceprofile
5+
6+
import (
7+
"context"
8+
_ "embed"
9+
10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
11+
"k8s.io/apimachinery/pkg/runtime"
12+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
13+
ctrl "sigs.k8s.io/controller-runtime"
14+
"sigs.k8s.io/controller-runtime/pkg/client"
15+
16+
"github.com/d2iq-labs/capi-runtime-extensions/api/v1alpha1"
17+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/apis"
18+
commonhandlers "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers"
19+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
20+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches"
21+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches/selectors"
22+
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
23+
capav1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
24+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers"
25+
awsclusterconfig "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/aws/clusterconfig"
26+
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/clusterconfig"
27+
)
28+
29+
const (
30+
// ControlPlaneHandlerNamePatch is the name of the inject handler.
31+
ControlPlaneHandlerNamePatch = "AWSIAMInstanceProfileControlPlanePatch"
32+
)
33+
34+
type awsIAMInstanceProfileControlPlanePatchHandler struct {
35+
variableName string
36+
variableFieldPath []string
37+
}
38+
39+
var (
40+
_ commonhandlers.Named = &awsIAMInstanceProfileControlPlanePatchHandler{}
41+
_ mutation.GeneratePatches = &awsIAMInstanceProfileControlPlanePatchHandler{}
42+
_ mutation.MetaMutator = &awsIAMInstanceProfileControlPlanePatchHandler{}
43+
)
44+
45+
func NewControlPlaneMetaPatch() *awsIAMInstanceProfileControlPlanePatchHandler {
46+
return newAWSIAMInstanceProfileControlPlanePatchHandler(
47+
clusterconfig.MetaVariableName,
48+
clusterconfig.MetaControlPlaneConfigName,
49+
awsclusterconfig.AWSVariableName,
50+
VariableName,
51+
)
52+
}
53+
54+
func newAWSIAMInstanceProfileControlPlanePatchHandler(
55+
variableName string,
56+
variableFieldPath ...string,
57+
) *awsIAMInstanceProfileControlPlanePatchHandler {
58+
return &awsIAMInstanceProfileControlPlanePatchHandler{
59+
variableName: variableName,
60+
variableFieldPath: variableFieldPath,
61+
}
62+
}
63+
64+
func (h *awsIAMInstanceProfileControlPlanePatchHandler) Name() string {
65+
return ControlPlaneHandlerNamePatch
66+
}
67+
68+
func (h *awsIAMInstanceProfileControlPlanePatchHandler) 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+
iamInstanceProfileVar, found, err := variables.Get[v1alpha1.IAMInstanceProfile](
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("AWS IAM instance profile variable for control-plane not defined")
89+
return nil
90+
}
91+
92+
log = log.WithValues(
93+
"variableName",
94+
h.variableName,
95+
"variableFieldPath",
96+
h.variableFieldPath,
97+
"variableValue",
98+
iamInstanceProfileVar,
99+
)
100+
101+
return patches.Generate(
102+
obj,
103+
vars,
104+
&holderRef,
105+
selectors.InfrastructureControlPlaneMachines(
106+
"v1beta2",
107+
"AWSMachineTemplate",
108+
),
109+
log,
110+
func(obj *capav1.AWSMachineTemplate) error {
111+
log.WithValues(
112+
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
113+
"patchedObjectName", client.ObjectKeyFromObject(obj),
114+
).Info("setting IAM instance profile in control plane AWSMachineTemplate spec")
115+
116+
obj.Spec.Template.Spec.IAMInstanceProfile = string(iamInstanceProfileVar)
117+
118+
return nil
119+
},
120+
)
121+
}
122+
123+
func (h *awsIAMInstanceProfileControlPlanePatchHandler) GeneratePatches(
124+
ctx context.Context,
125+
req *runtimehooksv1.GeneratePatchesRequest,
126+
resp *runtimehooksv1.GeneratePatchesResponse,
127+
) {
128+
handlers.GeneratePatches(ctx, req, resp, apis.CAPADecoder(), h.Mutate)
129+
}

0 commit comments

Comments
 (0)