diff --git a/exp/api/v1beta2/rosamachinepool_webhook.go b/exp/api/v1beta2/rosamachinepool_webhook.go index d4fdaf00a5..adceed12bc 100644 --- a/exp/api/v1beta2/rosamachinepool_webhook.go +++ b/exp/api/v1beta2/rosamachinepool_webhook.go @@ -1,6 +1,8 @@ package v1beta2 import ( + "fmt" + "github.com/blang/semver" "github.com/google/go-cmp/cmp" "github.com/pkg/errors" @@ -31,6 +33,7 @@ var _ webhook.Validator = &ROSAMachinePool{} // ValidateCreate implements admission.Validator. func (r *ROSAMachinePool) ValidateCreate() (warnings admission.Warnings, err error) { var allErrs field.ErrorList + fmt.Println("VALIDTAE CREATE") if err := r.validateVersion(); err != nil { allErrs = append(allErrs, err) @@ -43,6 +46,8 @@ func (r *ROSAMachinePool) ValidateCreate() (warnings admission.Warnings, err err allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...) if len(allErrs) == 0 { + fmt.Println("VALIDTAE CREATE FINE") + return nil, nil } @@ -55,6 +60,7 @@ func (r *ROSAMachinePool) ValidateCreate() (warnings admission.Warnings, err err // ValidateUpdate implements admission.Validator. func (r *ROSAMachinePool) ValidateUpdate(old runtime.Object) (warnings admission.Warnings, err error) { + fmt.Println("VALIDTAE UPDATE") oldPool, ok := old.(*ROSAMachinePool) if !ok { return nil, apierrors.NewInvalid(GroupVersion.WithKind("ROSAMachinePool").GroupKind(), r.Name, field.ErrorList{ diff --git a/exp/controllers/rosamachinepool_controller.go b/exp/controllers/rosamachinepool_controller.go index 7fad8a9aec..7559e117e3 100644 --- a/exp/controllers/rosamachinepool_controller.go +++ b/exp/controllers/rosamachinepool_controller.go @@ -135,6 +135,7 @@ func (r *ROSAMachinePoolReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } + fmt.Println("CLIENT:", &r.Client) machinePoolScope, err := scope.NewRosaMachinePoolScope(scope.RosaMachinePoolScopeParams{ Client: r.Client, ControllerName: "rosamachinepool", @@ -168,11 +169,36 @@ func (r *ROSAMachinePoolReconciler) Reconcile(ctx context.Context, req ctrl.Requ } defer func() { + fmt.Println("DEFER") conditions.SetSummary(machinePoolScope.RosaMachinePool, conditions.WithConditions(expinfrav1.RosaMachinePoolReadyCondition), conditions.WithStepCounter()) - - if err := machinePoolScope.Close(); err != nil && reterr == nil { - reterr = err + fmt.Println("DEFER") + + // patchHelper, err := patch.NewHelper(machinePoolScope.RosaMachinePool, r.Client) + // if err != nil { + // fmt.Println("ERROR when creatin helper") + // } + + failureMessage := "fail blabla" + machinePoolScope.RosaMachinePool.Status.FailureMessage = &failureMessage + // err = patchHelper.Patch( + // ctx, + // // context.TODO(), + // machinePoolScope.RosaMachinePool, + // patch.WithOwnedConditions{Conditions: []clusterv1.ConditionType{ + // expinfrav1.RosaMachinePoolReadyCondition, + // }}) + // r.Client.Ge + + err = r.Client.Status().Patch(ctx, machinePoolScope.RosaMachinePool, client.MergeFrom(machinePoolScope.RosaMachinePool)) + if err != nil { + fmt.Println("ERR WHEN PATCHING", err) } + + // if err := machinePoolScope.Close(); err != nil && reterr == nil { + // fmt.Println("DEFER", err) + + // reterr = err + // } }() if !rosaMachinePool.ObjectMeta.DeletionTimestamp.IsZero() { @@ -201,14 +227,34 @@ func (r *ROSAMachinePoolReconciler) reconcileNormal(ctx context.Context, } failureMessage, err := validateMachinePoolSpec(machinePoolScope) + fmt.Println("VALIDATION", failureMessage, err) + if err != nil { return ctrl.Result{}, fmt.Errorf("failed to validate ROSAMachinePool.spec: %w", err) } if failureMessage != nil { - machinePoolScope.RosaMachinePool.Status.FailureMessage = failureMessage + fmt.Println("FAIL", machinePoolScope.RosaMachinePool.Name) + + // machinePoolScope.RosaMachinePool.Status.FailureMessage = failureMessage + // conditions.MarkFalse(machinePoolScope.RosaMachinePool, + // expinfrav1.RosaMachinePoolReadyCondition, + // expinfrav1.RosaMachinePoolReconciliationFailedReason, + // clusterv1.ConditionSeverityError, + // "failed to create ROSAMachinePool: %s", *failureMessage) + // machinePoolScope.Close() + // annotations.AddAnnotations(machinePoolScope.RosaMachinePool, map[string]string{ + // clusterv1.ReplicasManagedByAnnotation: "rosa", + // }) + // if err := machinePoolScope.PatchRosaMachinePoolObject(ctx); err != nil { + // fmt.Println("ERRRRR PatchRosaMachinePoolObject", err.Error()) + // return ctrl.Result{}, err + // } + // machinePoolScope.Patch(ctx, machinePoolScope.RosaMachinePool) + // r.Status().Update(ctx, machinePoolScope.RosaMachinePool) // dont' requeue because input is invalid and manual intervention is needed. return ctrl.Result{}, nil } + fmt.Println("CCCCC") machinePoolScope.RosaMachinePool.Status.FailureMessage = nil rosaMachinePool := machinePoolScope.RosaMachinePool @@ -225,11 +271,14 @@ func (r *ROSAMachinePoolReconciler) reconcileNormal(ctx context.Context, } nodePool, found, err := ocmClient.GetNodePool(machinePoolScope.ControlPlane.Status.ID, rosaMachinePool.Spec.NodePoolName) + fmt.Println("DDDDD", nodePool, found, err) + if err != nil { return ctrl.Result{}, err } if found { + fmt.Println("FOUND") if rosaMachinePool.Spec.AvailabilityZone == "" { // reflect the current AvailabilityZone in the spec if not set. rosaMachinePool.Spec.AvailabilityZone = nodePool.AvailabilityZone() @@ -280,6 +329,8 @@ func (r *ROSAMachinePoolReconciler) reconcileNormal(ctx context.Context, return ctrl.Result{RequeueAfter: time.Second * 60}, nil } + fmt.Println("EEEEEE ") + npBuilder := nodePoolBuilder(rosaMachinePool.Spec, machinePool.Spec) nodePoolSpec, err := npBuilder.Build() if err != nil { @@ -297,6 +348,7 @@ func (r *ROSAMachinePoolReconciler) reconcileNormal(ctx context.Context, } machinePoolScope.RosaMachinePool.Status.ID = nodePool.ID() + fmt.Println("BBBB") return ctrl.Result{}, nil } diff --git a/exp/controllers/rosamachinepool_controller_test.go b/exp/controllers/rosamachinepool_controller_test.go index 5a978b5801..6fc0b51a38 100644 --- a/exp/controllers/rosamachinepool_controller_test.go +++ b/exp/controllers/rosamachinepool_controller_test.go @@ -2,6 +2,7 @@ package controllers import ( "context" + "fmt" "testing" "time" @@ -31,6 +32,7 @@ import ( "sigs.k8s.io/cluster-api-provider-aws/v2/test/mocks" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" expclusterv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" + "sigs.k8s.io/cluster-api/util/patch" ) func TestNodePoolToRosaMachinePoolSpec(t *testing.T) { @@ -104,6 +106,7 @@ func TestRosaMachinePoolReconcile(t *testing.T) { recorder = record.NewFakeRecorder(10) ctx = context.TODO() scheme = runtime.NewScheme() + // scheme = testEnv.Scheme() ns, err = testEnv.CreateNamespace(ctx, "test-namespace") g.Expect(err).To(BeNil()) @@ -174,12 +177,18 @@ func TestRosaMachinePoolReconcile(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "rosa-machinepool", Namespace: ns.Name, + UID: "rosa-machinepool-1", }, TypeMeta: metav1.TypeMeta{ Kind: "ROSAMachinePool", APIVersion: expinfrav1.GroupVersion.String(), }, - Spec: expinfrav1.RosaMachinePoolSpec{}, + Spec: expinfrav1.RosaMachinePoolSpec{ + NodePoolName: "test-nodepool", + Version: "4.14.5", + Subnet: "subnet-id", + InstanceType: "m5.large", + }, } ownerMachinePool = &expclusterv1.MachinePool{ @@ -220,7 +229,7 @@ func TestRosaMachinePoolReconcile(t *testing.T) { }, } - objects = []client.Object{secret, ownerCluster, ownerMachinePool} + objects = []client.Object{secret, ownerCluster, ownerMachinePool, rosaMachinePool} for _, obj := range objects { createObject(g, obj, ns.Name) @@ -235,6 +244,7 @@ func TestRosaMachinePoolReconcile(t *testing.T) { } t.Run("Reconcile create node pool", func(t *testing.T) { + fmt.Println("START test") setup(t) defer teardown() ocmMock = mocks.NewMockOCMClient(mockCtrl) @@ -243,12 +253,40 @@ func TestRosaMachinePoolReconcile(t *testing.T) { return nil, false, nil }).Times(1) m.CreateNodePool(gomock.Any(), gomock.Any()).DoAndReturn(func(clusterId string, nodePool *cmv1.NodePool) (*cmv1.NodePool, error) { + fmt.Println("NODE POOL", nodePool.ID()) return nodePool, nil }).Times(1) } expect(ocmMock.EXPECT()) + fmt.Println("REC", scheme.Recognizes(rosaMachinePool.GroupVersionKind())) + fmt.Println("REC", scheme.Recognizes(ownerCluster.GroupVersionKind())) + c := fake.NewClientBuilder().WithScheme(scheme).WithObjects(rosaMachinePool, ownerCluster, ownerMachinePool, rosaControlPlane, secret).Build() + + // failureMessage := "fail blabla" + // rosaMachinePool.Status.FailureMessage = &failureMessage + + // err = c.Status().Patch(ctx, rosaMachinePool, client.MergeFrom(rosaMachinePool)) + // err = c.Status().Patch(ctx, ownerMachinePool, client.MergeFrom(ownerMachinePool)) + g.Expect(err).NotTo(HaveOccurred()) + mpPh, err := patch.NewHelper(rosaMachinePool, testEnv) + + rosaMachinePool.Status.Ready = true + l := map[string]string{"key": "value"} + rosaMachinePool.SetLabels(l) + + err = mpPh.Patch(ctx, rosaMachinePool, patch.WithOwnedConditions{Conditions: []clusterv1.ConditionType{ + expinfrav1.RosaMachinePoolReadyCondition, + }}) + + m := &expinfrav1.ROSAMachinePool{} + key := client.ObjectKey{Name: rosaMachinePool.Name, Namespace: ns.Name} + c.Get(ctx, key, m) + fmt.Println("ROSAMACHINEPOOL:", m.Name, m.Status, m.Namespace, m.Labels) + + g.Expect(err).NotTo(HaveOccurred()) + stsMock := mock_stsiface.NewMockSTSAPI(mockCtrl) stsMock.EXPECT().GetCallerIdentity(gomock.Any()).Times(1) @@ -266,10 +304,15 @@ func TestRosaMachinePoolReconcile(t *testing.T) { req := ctrl.Request{} req.NamespacedName = types.NamespacedName{Name: "rosa-machinepool", Namespace: ns.Name} - result, err := r.Reconcile(ctx, req) + g.Expect(r.Endpoints).To(Equal("a")) + // result, err := r.Reconcile(ctx, req) + // key := client.ObjectKey{Name: ownerMachinePool.Name, Namespace: ns.Name} + + g.Expect(m.Status).To(Equal(map[string]string{"cluster.x-k8s.io/replicas-managed-by": "rosa"})) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(result).To(Equal(ctrl.Result{})) + + // g.Expect(result).To(Equal(ctrl.Result{})) }) // t.Run("Reconcile delete", func(t *testing.T) { diff --git a/exp/controllers/suite_test.go b/exp/controllers/suite_test.go index 5f7ded08c8..c8b88aef4f 100644 --- a/exp/controllers/suite_test.go +++ b/exp/controllers/suite_test.go @@ -21,12 +21,14 @@ import ( "path" "testing" + corev1 "k8s.io/api/core/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" // +kubebuilder:scaffold:imports infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" + rosacontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/v2/controlplane/rosa/api/v1beta2" expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2" "sigs.k8s.io/cluster-api-provider-aws/v2/test/helpers" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -52,6 +54,8 @@ func setup() { utilruntime.Must(clusterv1.AddToScheme(scheme.Scheme)) utilruntime.Must(expinfrav1.AddToScheme(scheme.Scheme)) utilruntime.Must(expclusterv1.AddToScheme(scheme.Scheme)) + utilruntime.Must(corev1.AddToScheme(scheme.Scheme)) + utilruntime.Must(rosacontrolplanev1.AddToScheme(scheme.Scheme)) testEnvConfig := helpers.NewTestEnvironmentConfiguration([]string{ path.Join("config", "crd", "bases"), }, @@ -76,6 +80,12 @@ func setup() { if err := (&expinfrav1.AWSManagedMachinePool{}).SetupWebhookWithManager(testEnv); err != nil { panic(fmt.Sprintf("Unable to setup AWSManagedMachinePool webhook: %v", err)) } + if err := (&expinfrav1.ROSAMachinePool{}).SetupWebhookWithManager(testEnv); err != nil { + panic(fmt.Sprintf("Unable to setup ROSAMachinePool webhook: %v", err)) + } + if err := (&rosacontrolplanev1.ROSAControlPlane{}).SetupWebhookWithManager(testEnv); err != nil { + panic(fmt.Sprintf("Unable to setup ROSAMachinePool webhook: %v", err)) + } go func() { fmt.Println("Starting the manager") if err := testEnv.StartManager(ctx); err != nil { diff --git a/pkg/cloud/scope/rosamachinepool.go b/pkg/cloud/scope/rosamachinepool.go index 00d480ca3e..fd294f3427 100644 --- a/pkg/cloud/scope/rosamachinepool.go +++ b/pkg/cloud/scope/rosamachinepool.go @@ -18,6 +18,7 @@ package scope import ( "context" + "fmt" awsclient "github.com/aws/aws-sdk-go/aws/client" "github.com/pkg/errors" @@ -66,6 +67,8 @@ func NewRosaMachinePoolScope(params RosaMachinePoolScopeParams) (*RosaMachinePoo params.Logger = logger.NewLogger(log) } + fmt.Println("CLIENT:", ¶ms.Client) + ammpHelper, err := patch.NewHelper(params.RosaMachinePool, params.Client) if err != nil { return nil, errors.Wrap(err, "failed to init RosaMachinePool patch helper") @@ -76,8 +79,9 @@ func NewRosaMachinePoolScope(params RosaMachinePoolScopeParams) (*RosaMachinePoo } scope := &RosaMachinePoolScope{ - Logger: *params.Logger, - Client: params.Client, + Logger: *params.Logger, + Client: params.Client, + // issue here for tests? patchHelper: ammpHelper, capiMachinePoolPatchHelper: mpHelper, @@ -227,6 +231,13 @@ func (s *RosaMachinePoolScope) PatchCAPIMachinePoolObject(ctx context.Context) e ) } +func (s *RosaMachinePoolScope) PatchRosaMachinePoolObject(ctx context.Context) error { + return s.patchHelper.Patch( + ctx, + s.RosaMachinePool, + ) +} + // Close closes the current scope persisting the control plane configuration and status. func (s *RosaMachinePoolScope) Close() error { return s.PatchObject()