Skip to content

Commit 79bdbab

Browse files
committed
Fix RosaControlPlane sync defaulet RosaMachinePool
Signed-off-by: serngawy <[email protected]>
1 parent 645f38e commit 79bdbab

File tree

10 files changed

+717
-61
lines changed

10 files changed

+717
-61
lines changed

config/rbac/role.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ rules:
8383
- machinepools
8484
- machinepools/status
8585
verbs:
86+
- create
8687
- get
8788
- list
8889
- patch
@@ -161,7 +162,6 @@ rules:
161162
- awsmanagedclusters
162163
- awsmanagedmachinepools
163164
- rosaclusters
164-
- rosamachinepools
165165
verbs:
166166
- delete
167167
- get
@@ -175,7 +175,6 @@ rules:
175175
- awsclusters/status
176176
- awsfargateprofiles/status
177177
- rosaclusters/status
178-
- rosamachinepools/status
179178
verbs:
180179
- get
181180
- patch
@@ -197,6 +196,7 @@ rules:
197196
- infrastructure.cluster.x-k8s.io
198197
resources:
199198
- awsmachines
199+
- rosamachinepools
200200
verbs:
201201
- create
202202
- delete
@@ -211,3 +211,14 @@ rules:
211211
- rosamachinepools/finalizers
212212
verbs:
213213
- update
214+
- apiGroups:
215+
- infrastructure.cluster.x-k8s.io
216+
resources:
217+
- rosamachinepools/status
218+
verbs:
219+
- create
220+
- get
221+
- list
222+
- patch
223+
- update
224+
- watch

controllers/rosacluster_controller.go

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,15 @@ import (
2121
"fmt"
2222

2323
"github.com/pkg/errors"
24+
corev1 "k8s.io/api/core/v1"
2425
apierrors "k8s.io/apimachinery/pkg/api/errors"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/runtime"
2528
"k8s.io/apimachinery/pkg/types"
29+
kerrors "k8s.io/apimachinery/pkg/util/errors"
2630
"k8s.io/client-go/tools/record"
2731
"k8s.io/klog/v2"
32+
"k8s.io/utils/ptr"
2833
ctrl "sigs.k8s.io/controller-runtime"
2934
"sigs.k8s.io/controller-runtime/pkg/client"
3035
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -35,9 +40,15 @@ import (
3540
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
3641
rosacontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/rosa/api/v1beta2"
3742
expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2"
43+
"sigs.k8s.io/cluster-api-provider-aws/v2/exp/utils"
44+
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud"
45+
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
46+
stsservice "sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services/sts"
3847
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger"
48+
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/rosa"
3949
"sigs.k8s.io/cluster-api-provider-aws/v2/util/paused"
4050
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
51+
expclusterv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
4152
"sigs.k8s.io/cluster-api/util"
4253
"sigs.k8s.io/cluster-api/util/patch"
4354
"sigs.k8s.io/cluster-api/util/predicates"
@@ -48,16 +59,20 @@ type ROSAClusterReconciler struct {
4859
client.Client
4960
Recorder record.EventRecorder
5061
WatchFilterValue string
62+
NewStsClient func(cloud.ScopeUsage, cloud.Session, logger.Wrapper, runtime.Object) stsservice.STSClient
63+
NewOCMClient func(ctx context.Context, rosaScope *scope.ROSAControlPlaneScope) (rosa.OCMClient, error)
5164
}
5265

5366
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=rosaclusters,verbs=get;list;watch;update;patch;delete
5467
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=rosaclusters/status,verbs=get;update;patch
5568
// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=rosacontrolplanes;rosacontrolplanes/status,verbs=get;list;watch
5669
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch
70+
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinepools;machinepools/status,verbs=get;list;watch;create
71+
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=rosamachinepools;rosamachinepools/status,verbs=get;list;watch;create
5772
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch;delete
5873

5974
func (r *ROSAClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) {
60-
log := ctrl.LoggerFrom(ctx)
75+
log := logger.FromContext(ctx)
6176
log.Info("Reconciling ROSACluster")
6277

6378
// Fetch the ROSACluster instance
@@ -70,11 +85,17 @@ func (r *ROSAClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
7085
return reconcile.Result{}, err
7186
}
7287

88+
if !rosaCluster.DeletionTimestamp.IsZero() {
89+
log.Info("Deleting ROSACluster.")
90+
return reconcile.Result{}, nil
91+
}
92+
7393
// Fetch the Cluster.
7494
cluster, err := util.GetOwnerCluster(ctx, r.Client, rosaCluster.ObjectMeta)
7595
if err != nil {
7696
return reconcile.Result{}, err
7797
}
98+
7899
if cluster == nil {
79100
log.Info("Cluster Controller has not yet set OwnerRef")
80101
return reconcile.Result{}, nil
@@ -111,13 +132,122 @@ func (r *ROSAClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
111132
return reconcile.Result{}, fmt.Errorf("failed to patch ROSACluster: %w", err)
112133
}
113134

135+
if controlPlane.Status.Ready {
136+
// List the ROSA-HCP nodePools and ROSA MachinePools
137+
rosaScope, err := scope.NewROSAControlPlaneScope(scope.ROSAControlPlaneScopeParams{
138+
Client: r.Client,
139+
Cluster: cluster,
140+
ControlPlane: controlPlane,
141+
ControllerName: "",
142+
Logger: log,
143+
NewStsClient: r.NewStsClient,
144+
})
145+
if err != nil {
146+
return ctrl.Result{}, fmt.Errorf("failed to create rosa controlplane scope: %w", err)
147+
}
148+
149+
if r.NewOCMClient == nil {
150+
return ctrl.Result{}, fmt.Errorf("failed to create OCM client: NewOCMClient is nil")
151+
}
152+
153+
ocmClient, err := r.NewOCMClient(ctx, rosaScope)
154+
if err != nil || ocmClient == nil {
155+
return ctrl.Result{}, fmt.Errorf("failed to create OCM client: %w", err)
156+
}
157+
158+
nodePools, err := ocmClient.GetNodePools(rosaScope.ControlPlane.Status.ID)
159+
if err != nil {
160+
return ctrl.Result{}, fmt.Errorf("failed to get nodePools: %w", err)
161+
}
162+
163+
rosaMPNames, err := r.getRosaMachinePoolNames(ctx, cluster)
164+
if err != nil {
165+
return ctrl.Result{}, fmt.Errorf("failed to get Rosa machinePool names: %w", err)
166+
}
167+
168+
var errs []error
169+
for _, nodePool := range nodePools {
170+
// continue if nodePool is not in ready state.
171+
if !rosa.IsNodePoolReady(nodePool) {
172+
continue
173+
}
174+
// continue if nodePool exist
175+
if rosaMPNames[nodePool.ID()] {
176+
continue
177+
}
178+
179+
// create RosaMachinePool
180+
rosaMPSpec := utils.NodePoolToRosaMachinePoolSpec(nodePool)
181+
rosaMachinePool := &expinfrav1.ROSAMachinePool{
182+
TypeMeta: metav1.TypeMeta{
183+
APIVersion: expinfrav1.GroupVersion.String(),
184+
Kind: "ROSAMachinePool",
185+
},
186+
ObjectMeta: metav1.ObjectMeta{
187+
Name: nodePool.ID(),
188+
Namespace: controlPlane.Namespace,
189+
Labels: map[string]string{
190+
clusterv1.ClusterNameLabel: cluster.Name,
191+
},
192+
},
193+
Spec: rosaMPSpec,
194+
}
195+
log.Info(fmt.Sprintf("Create ROSAMachinePool %s", rosaMachinePool.Name))
196+
if err = r.Client.Create(ctx, rosaMachinePool); err != nil {
197+
errs = append(errs, err)
198+
}
199+
200+
// create MachinePool
201+
machinePool := &expclusterv1.MachinePool{
202+
TypeMeta: metav1.TypeMeta{
203+
APIVersion: expclusterv1.GroupVersion.String(),
204+
Kind: "MachinePool",
205+
},
206+
ObjectMeta: metav1.ObjectMeta{
207+
Name: nodePool.ID(),
208+
Namespace: cluster.Namespace,
209+
Labels: map[string]string{
210+
clusterv1.ClusterNameLabel: cluster.Name,
211+
},
212+
},
213+
Spec: expclusterv1.MachinePoolSpec{
214+
ClusterName: cluster.Name,
215+
Replicas: ptr.To(int32(1)),
216+
Template: clusterv1.MachineTemplateSpec{
217+
Spec: clusterv1.MachineSpec{
218+
ClusterName: cluster.Name,
219+
Bootstrap: clusterv1.Bootstrap{
220+
DataSecretName: ptr.To(string("")),
221+
},
222+
InfrastructureRef: corev1.ObjectReference{
223+
APIVersion: expinfrav1.GroupVersion.String(),
224+
Kind: "ROSAMachinePool",
225+
Name: rosaMachinePool.Name,
226+
},
227+
},
228+
},
229+
},
230+
}
231+
log.Info(fmt.Sprintf("Create MachinePool %s", machinePool.Name))
232+
if err = r.Client.Create(ctx, machinePool); err != nil {
233+
errs = append(errs, err)
234+
}
235+
}
236+
237+
if len(errs) > 0 {
238+
return ctrl.Result{}, kerrors.NewAggregate(errs)
239+
}
240+
}
241+
114242
log.Info("Successfully reconciled ROSACluster")
115243

116244
return reconcile.Result{}, nil
117245
}
118246

119247
func (r *ROSAClusterReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
120248
log := logger.FromContext(ctx)
249+
r.NewOCMClient = rosa.NewWrappedOCMClient
250+
r.NewStsClient = scope.NewSTSClient
121251

122252
rosaCluster := &expinfrav1.ROSACluster{}
123253

@@ -196,3 +326,26 @@ func (r *ROSAClusterReconciler) rosaControlPlaneToManagedCluster(log *logger.Log
196326
}
197327
}
198328
}
329+
330+
// GetRosMachinePools get map of RosaMachinePool names associatd with the cluster.
331+
func (r *ROSAClusterReconciler) getRosaMachinePoolNames(ctx context.Context, cluster *clusterv1.Cluster) (map[string]bool, error) {
332+
selectors := []client.ListOption{
333+
client.InNamespace(cluster.GetNamespace()),
334+
client.MatchingLabels{
335+
clusterv1.ClusterNameLabel: cluster.GetName(),
336+
},
337+
}
338+
339+
rosaMachinePoolList := &expinfrav1.ROSAMachinePoolList{}
340+
err := r.Client.List(ctx, rosaMachinePoolList, selectors...)
341+
if err != nil {
342+
return nil, err
343+
}
344+
345+
rosaMPNames := make(map[string]bool)
346+
for _, rosaMP := range rosaMachinePoolList.Items {
347+
rosaMPNames[rosaMP.Spec.NodePoolName] = true
348+
}
349+
350+
return rosaMPNames, nil
351+
}

0 commit comments

Comments
 (0)