-
Notifications
You must be signed in to change notification settings - Fork 578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🌱Add initial Rosa machine pool integration tests #5214
base: main
Are you sure you want to change the base?
🌱Add initial Rosa machine pool integration tests #5214
Conversation
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Welcome @PanSpagetka! |
Hi @PanSpagetka. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
9e2fe4e
to
2ce8f3d
Compare
2ce8f3d
to
abce607
Compare
f2c32f1
to
abd21bc
Compare
@nrb would you add ok-to-test |
main.go
Outdated
@@ -238,6 +239,8 @@ func main() { | |||
WatchFilterValue: watchFilterValue, | |||
WaitInfraPeriod: waitInfraPeriod, | |||
Endpoints: awsServiceEndpoints, | |||
NewOCMClient: rosa.NewOCMClient, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a good idea to create the clients here in the main . why do you need to do that ? for integration test you may just mock the clients.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to expose and init the clients in main. We can init the clients (sts and ocm) internally in the struct and regards the integration test you can mock it similar to this here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I moved the initialization to SetupWithManager
that seems to me as the only ROSAMachinePoolReconciler
method where it fits. I am using same mechanism to create the mock implementation as the STS api.
pkg/rosa/idps.go
Outdated
@@ -4,7 +4,6 @@ import ( | |||
"fmt" | |||
|
|||
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" | |||
"github.com/openshift/rosa/pkg/ocm" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using the github.com/openshift/rosa/pkg/ocm in order to avoid duplicate the effort of creating a lib that communicate with OCM. Please keep using it for this first integration test iteration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use github.com/openshift/rosa/pkg/ocm
directly here, because it doesn't expose interface that we could mock. So I had to create mockable interface at our side to be able to mock the ocm calls.
The guys that are developing github.com/openshift/rosa/pkg/ocm
are planning to create (and I hope also expose) OCM calls as interface to increase the testability of OCM code. So we could get rid of this in the future. But I am not sure how long will it take them to do it.
pkg/rosa/idps.go
Outdated
@@ -14,7 +13,7 @@ const ( | |||
|
|||
// CreateAdminUserIfNotExist creates a new admin user withe username/password in the cluster if username doesn't already exist. | |||
// the user is granted admin privileges by being added to a special IDP called `cluster-admin` which will be created if it doesn't already exist. | |||
func CreateAdminUserIfNotExist(client *ocm.Client, clusterID, username, password string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using the github.com/openshift/rosa/pkg/ocm in order to avoid duplicate the effort of creating a lib that communicate with OCM. Please keep using it for this first integration test iteration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, just github duplication
/ok-to-test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add the skeleton for RosaControlPlane_controller integration test as well, it is important as the RosaMachinePool integration test
main.go
Outdated
@@ -238,6 +239,8 @@ func main() { | |||
WatchFilterValue: watchFilterValue, | |||
WaitInfraPeriod: waitInfraPeriod, | |||
Endpoints: awsServiceEndpoints, | |||
NewOCMClient: rosa.NewOCMClient, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to expose and init the clients in main. We can init the clients (sts and ocm) internally in the struct and regards the integration test you can mock it similar to this here
pkg/rosa/client.go
Outdated
token, url, err := ocmCredentials(ctx, rosaScope) | ||
if err != nil { | ||
return nil, err | ||
return ocmclient{}, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil
pkg/rosa/client.go
Outdated
} | ||
|
||
// NewMockOCMClient creates a new empty ocm.Client without any real connection. | ||
func NewMockOCMClient(ctx context.Context, rosaScope *scope.ROSAControlPlaneScope) (OCMClient, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for function params. in fact it not a function just variable
c := ocmclient{ ocmClient: ocm.Client{}, }
2cbbf46
to
cdc81e8
Compare
/test pull-cluster-api-provider-aws-test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments and please add test for rosacontrolplane_controller.go as well.
@@ -203,7 +211,7 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc | |||
} | |||
} | |||
|
|||
ocmClient, err := rosa.NewOCMClient(ctx, rosaScope) | |||
ocmClient, err := r.NewOCMClient(ctx, rosaScope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check for nil, r.NewOCMClient could be nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you forget this, if r.NewOCMClient != nil
@@ -186,7 +194,7 @@ func (r *ROSAMachinePoolReconciler) reconcileNormal(ctx context.Context, | |||
} | |||
} | |||
|
|||
ocmClient, err := rosa.NewOCMClient(ctx, rosaControlPlaneScope) | |||
ocmClient, err := r.NewOCMClient(ctx, rosaControlPlaneScope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same, check for nil
Template: clusterv1.MachineTemplateSpec{ | ||
Spec: clusterv1.MachineSpec{ | ||
ClusterName: ownerCluster.Name, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add the infrastructureRef pointing to RosaMachinePool to have proper test,
Kind: "ROSAMachinePool", | ||
APIVersion: expinfrav1.GroupVersion.String(), | ||
}, | ||
Spec: expinfrav1.RosaMachinePoolSpec{}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should at least set the version, otherwise it should fail
|
||
result, err := r.Reconcile(ctx, req) | ||
|
||
g.Expect(err).ToNot(HaveOccurred()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add more validations, check for the RosaMachinePool.status
defer teardown() | ||
|
||
deleteTime := metav1.NewTime(time.Now().Add(5 * time.Second)) | ||
rosaMachinePool.ObjectMeta.Finalizers = []string{"finalizer-rosa"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what are you testing here, but finalizer should be added by the RosaMachinePool controller
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure? I think it should be removed on delete https://github.com/kubernetes-sigs/cluster-api-provider-aws/blob/main/exp/controllers/rosamachinepool_controller.go#L318
|
||
result, err := r.Reconcile(ctx, req) | ||
g.Expect(err).ToNot(HaveOccurred()) | ||
g.Expect(result).To(Equal(ctrl.Result{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to validate if the RosaMachinePool deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am testing that DeleteNodePool
. It seems that reconcileDelete
doesn't modify the ROSAMachinePool
object directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metadata.deletionTimeStamp should be created and then the finalizer should be removed. try to Get the rosamachinepool and it should gives you error not exist. if you have issue most likely in node delete here
pkg/rosa/client.go
Outdated
@@ -20,16 +22,142 @@ const ( | |||
ocmAPIURLKey = "ocmApiUrl" | |||
) | |||
|
|||
type ocmclient struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OCMClient not ocmclient and please move the OCMClient struct, interface and funcs to another file ex; ocmclient.go
pkg/rosa/idps.go
Outdated
@@ -14,7 +13,7 @@ const ( | |||
|
|||
// CreateAdminUserIfNotExist creates a new admin user withe username/password in the cluster if username doesn't already exist. | |||
// the user is granted admin privileges by being added to a special IDP called `cluster-admin` which will be created if it doesn't already exist. | |||
func CreateAdminUserIfNotExist(client *ocm.Client, clusterID, username, password string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, just github duplication
cdc81e8
to
23e5a17
Compare
975b9c4
to
ee2cdfd
Compare
df4b31b
to
8dd9c18
Compare
|
||
result, err := r.Reconcile(ctx, req) | ||
g.Expect(err).ToNot(HaveOccurred()) | ||
g.Expect(result).To(Equal(ctrl.Result{})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metadata.deletionTimeStamp should be created and then the finalizer should be removed. try to Get the rosamachinepool and it should gives you error not exist. if you have issue most likely in node delete here
pkg/rosa/client.go
Outdated
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope" | ||
) | ||
|
||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to move this part to the new ocmClinet file. to avoid conflict and rebase another effort in progress to change that PR
59c2caf
to
0034cfe
Compare
59adac6
to
55d1d29
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we almost there :) , few comments and please run make lint-fix
before pushing your changes to fix all the golang-ci job issue
@@ -203,7 +211,7 @@ func (r *ROSAControlPlaneReconciler) reconcileNormal(ctx context.Context, rosaSc | |||
} | |||
} | |||
|
|||
ocmClient, err := rosa.NewOCMClient(ctx, rosaScope) | |||
ocmClient, err := r.NewOCMClient(ctx, rosaScope) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you forget this, if r.NewOCMClient != nil
@@ -424,14 +432,16 @@ func (r *ROSAControlPlaneReconciler) reconcileClusterVersion(rosaScope *scope.RO | |||
return nil | |||
} | |||
|
|||
scheduledUpgrade, err := rosa.CheckExistingScheduledUpgrade(ocmClient, cluster) | |||
c := ocmClient.(*ocm.Client) | |||
scheduledUpgrade, err := rosa.CheckExistingScheduledUpgrade(c, cluster) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better naming; rosaOCMClient := ocmClient.(*ocm.Client)
OR scheduledUpgrade, err := rosa.CheckExistingScheduledUpgrade(ocmClient.(*ocm.Client) , cluster)
if err != nil { | ||
return fmt.Errorf("failed to get existing scheduled upgrades: %w", err) | ||
} | ||
|
||
if scheduledUpgrade == nil { | ||
ack := (rosaScope.ControlPlane.Spec.VersionGate == rosacontrolplanev1.Acknowledge || rosaScope.ControlPlane.Spec.VersionGate == rosacontrolplanev1.AlwaysAcknowledge) | ||
scheduledUpgrade, err = rosa.ScheduleControlPlaneUpgrade(ocmClient, cluster, version, time.Now(), ack) | ||
c := ocmClient.(*ocm.Client) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -334,7 +340,8 @@ func (r *ROSAMachinePoolReconciler) reconcileMachinePoolVersion(machinePoolScope | |||
} | |||
|
|||
if scheduledUpgrade == nil { | |||
scheduledUpgrade, err = rosa.ScheduleNodePoolUpgrade(ocmClient, clusterID, nodePool, version, time.Now()) | |||
c := ocmClient.(*ocm.Client) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
// This is set by CAPI MachinePool reconcile | ||
test.old.OwnerReferences = []metav1.OwnerReference{ | ||
{ | ||
Name: ownerMachinePool(i).Name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually in k8s project we use the rand lib to generate a random string. If you can change it will be better otherwise add TODO note to change that.
InstanceType: "m5.large", | ||
}, | ||
} | ||
oc := ownerCluster(9) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here you are passing 9 to be similar to the rosaMachinePool naming, its better to use the rand lib generate random string and pass it to all the test CRs
g.Expect(err).NotTo(HaveOccurred()) | ||
return nodePool, true, nil | ||
}).Times(1) | ||
m.DeleteNodePool("rosa-control-plane-9", "node-pool-1").DoAndReturn(func(clusterId string, nodePoolID string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is this name "rosa-control-plane-9"
come from ? if it is the cp CR then better is cp.Name
|
||
cpPh, err := patch.NewHelper(cp, testEnv) | ||
cp.Status.Ready = true | ||
cp.Status.ID = "rosa-control-plane-9" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"rosa-control-plane-9" is repeated many places in the code please define var OR ref to it from RosaControlPlane CR.
|
||
machinePoolScope.Close() | ||
time.Sleep(50 * time.Millisecond) | ||
m := &expinfrav1.ROSAMachinePool{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better naming rosaMachinePool := &expinfrav1.ROSAMachinePool{}
m := &expinfrav1.ROSAMachinePool{} | ||
key := client.ObjectKey{Name: mp.Name, Namespace: ns.Name} | ||
err4 := testEnv.Get(ctx, key, m) | ||
g.Expect(err4).ToNot(HaveOccurred()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this, After deleting the RosaMachinePool we expect to have error IsNotFound Please check if the error is IsNotFound error using the API mentioned not any other error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In https://github.com/kubernetes-sigs/cluster-api-provider-aws/blob/main/exp/controllers/rosamachinepool_controller.go#L295 the only function that might delete the CR is DeleteNodePool
that I am mocking. I can mock it in a way that it deletes the machinePool CR, but is that right? Does calling ocm actually delete the CR?
55d1d29
to
e027cf5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Robin, looks good as initial test-cases, will add more test-cases later.
What type of PR is this?
Adding tests. I am not sure what kind should apply so I am not applying any.,
What this PR does / why we need it:
Adding basic integration tests for
ROSAMachinePoolReconciler
. One test case for creating new machine pool and for deleting.To be able to mock OCM and STS calls I had to do small refactoring.
Checklist:
Release note: