Skip to content

Commit c64b93d

Browse files
committed
Implement changes in the structure of the OAuth Cleanup tests
1 parent c1d6867 commit c64b93d

File tree

1 file changed

+158
-91
lines changed

1 file changed

+158
-91
lines changed

components/odh-notebook-controller/controllers/notebook_controller_test.go

Lines changed: 158 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,114 +1023,112 @@ var _ = Describe("The Openshift Notebook controller", func() {
10231023
)
10241024

10251025
var (
1026-
notebook *nbv1.Notebook
1027-
oauthClient *oauthv1.OAuthClient
1028-
oauthClientName string
1029-
ctx context.Context
1026+
notebook *nbv1.Notebook
1027+
ctx context.Context
1028+
notebookKey types.NamespacedName
10301029
)
10311030

1032-
// Setup for all tests in this context
1033-
BeforeEach(func() {
1034-
ctx = context.Background()
1035-
notebook = createNotebook(Name, Namespace)
1036-
oauthClientName = fmt.Sprintf("%s-%s-%s", Name, Namespace, "oauth-client")
1037-
1038-
oauthClient = &oauthv1.OAuthClient{
1039-
ObjectMeta: metav1.ObjectMeta{
1040-
Name: oauthClientName,
1041-
},
1042-
RedirectURIs: []string{"https://www.kubeflow.org/"},
1043-
GrantMethod: oauthv1.GrantHandlerAuto,
1044-
}
1045-
})
1031+
// Initialize context and keys once
1032+
ctx = context.Background()
1033+
notebookKey = types.NamespacedName{Name: Name, Namespace: Namespace}
10461034

1047-
// Clean up resources after each test
1048-
AfterEach(func() {
1049-
nbToCleanup := &nbv1.Notebook{}
1050-
err := cli.Get(ctx, types.NamespacedName{Name: Name, Namespace: Namespace}, nbToCleanup)
1051-
if err == nil {
1052-
// Remove finalizers to allow deletion
1053-
nbToCleanup.Finalizers = nil
1054-
_ = cli.Update(ctx, nbToCleanup)
1055-
_ = cli.Delete(ctx, nbToCleanup)
1056-
}
1057-
1058-
oauthClientToCleanup := &oauthv1.OAuthClient{}
1059-
err = cli.Get(ctx, types.NamespacedName{Name: oauthClientName}, oauthClientToCleanup)
1060-
if err == nil {
1061-
_ = cli.Delete(ctx, oauthClientToCleanup)
1062-
}
1063-
})
1035+
// Create notebook once for all tests - WITH OAUTH ENABLED
1036+
notebook = createNotebookWithOAuth(Name, Namespace)
10641037

1065-
It("Should add a finalizer when a Notebook has been created", func() {
1038+
It("Should create a Notebook CR successfully", func() {
10661039
By("Creating a new Notebook")
10671040
Expect(cli.Create(ctx, notebook)).Should(Succeed())
10681041

1069-
By("Creating an OAuthClient")
1070-
err := cli.Create(ctx, oauthClient)
1071-
if err != nil {
1072-
GinkgoT().Logf("OAuthClient creation result: %v", err)
1073-
}
1074-
1075-
By("Adding the finalizer to the Notebook")
1076-
key := types.NamespacedName{Name: Name, Namespace: Namespace}
1077-
Expect(cli.Get(ctx, key, notebook)).Should(Succeed())
1078-
1079-
notebook.Finalizers = append(notebook.Finalizers, Finalizer)
1080-
Expect(cli.Update(ctx, notebook)).Should(Succeed())
1042+
// Wait for the Reconciler to create the route, or else the OAuth reconciler
1043+
// cannot create the OAuthClient object
1044+
time.Sleep(3 * time.Second)
1045+
})
10811046

1082-
By("Verifying the finalizer is added to the Notebook")
1083-
Expect(cli.Get(ctx, key, notebook)).Should(Succeed())
1084-
Expect(notebook.Finalizers).To(ContainElement(Finalizer))
1047+
It("Should have finalizer set by controller or webhook", func() {
1048+
By("Waiting for controller to add the finalizer")
1049+
Eventually(func() []string {
1050+
var updated nbv1.Notebook
1051+
err := cli.Get(ctx, notebookKey, &updated)
1052+
if err != nil {
1053+
return nil
1054+
}
1055+
return updated.Finalizers
1056+
}, duration, interval).Should(ContainElement(Finalizer),
1057+
"Expected finalizer '%s' to be added by controller", Finalizer)
10851058
})
10861059

1087-
It("Should delete the OAuthClient when the Notebook is deleted", func() {
1088-
By("Creating a Notebook with finalizer")
1089-
notebook.Finalizers = []string{Finalizer}
1090-
Expect(cli.Create(ctx, notebook)).Should(Succeed())
1060+
It("Should create OAuthClient for the Notebook CR", func() {
1061+
By("Ensuring finalizer exists first")
1062+
Eventually(func() []string {
1063+
var updated nbv1.Notebook
1064+
cli.Get(ctx, notebookKey, &updated)
1065+
return updated.Finalizers
1066+
}, duration, interval).Should(ContainElement(Finalizer))
1067+
1068+
By("Waiting for controller to create OAuthClient")
1069+
oauthClientKey := types.NamespacedName{Name: Name + "-" + Namespace + "-oauth-client"}
1070+
createdOAuthClient := &oauthv1.OAuthClient{}
1071+
Eventually(func() error {
1072+
return cli.Get(ctx, oauthClientKey, createdOAuthClient)
1073+
}, time.Second*90, time.Second*3).Should(Succeed(),
1074+
"Expected OAuthClient to be created by odh-notebook-controller")
1075+
1076+
By("Verifying OAuthClient has proper labels")
1077+
Expect(createdOAuthClient.Labels).Should(
1078+
HaveKeyWithValue("notebook-owner", Name),
1079+
"OAuthClient should have labels linking it to the notebook")
1080+
})
10911081

1092-
By("Creating an OAuthClient")
1093-
Expect(cli.Create(ctx, oauthClient)).Should(Succeed())
1082+
It("Should delete OAuthClient when Notebook is deleted", func() {
1083+
By("Ensuring prerequisite resources exist")
1084+
Eventually(func() []string {
1085+
var updated nbv1.Notebook
1086+
cli.Get(ctx, notebookKey, &updated)
1087+
return updated.Finalizers
1088+
}, duration, interval).Should(ContainElement(Finalizer))
10941089

1095-
By("Requesting deletion of the Notebook")
1096-
Expect(cli.Delete(ctx, notebook)).Should(Succeed())
1090+
oauthClientKey := types.NamespacedName{Name: Name + "-" + Namespace + "-oauth-client"}
1091+
Eventually(func() error {
1092+
return cli.Get(ctx, oauthClientKey, &oauthv1.OAuthClient{})
1093+
}, duration, interval).Should(Succeed())
10971094

1098-
By("Checking if the controller deletes the OAuthClient")
1099-
oauthClientKey := types.NamespacedName{Name: oauthClientName}
1095+
By("Deleting the notebook")
1096+
var notebookToDelete nbv1.Notebook
1097+
Expect(cli.Get(ctx, notebookKey, &notebookToDelete)).Should(Succeed())
1098+
Expect(cli.Delete(ctx, &notebookToDelete)).Should(Succeed())
11001099

1101-
// First verify that the OAuthClient exists initially
1102-
Expect(cli.Get(ctx, oauthClientKey, oauthClient)).Should(Succeed())
1100+
By("Verifying notebook is marked for deletion but persists due to finalizer")
1101+
Eventually(func() bool {
1102+
var updated nbv1.Notebook
1103+
err := cli.Get(ctx, notebookKey, &updated)
1104+
return err == nil && updated.DeletionTimestamp != nil
1105+
}, duration, interval).Should(BeTrue(),
1106+
"Notebook should be marked for deletion but persist due to finalizer")
11031107

1104-
// Log the notebook state for debugging
1105-
key := types.NamespacedName{Name: notebook.Name, Namespace: notebook.Namespace}
1106-
nb := &nbv1.Notebook{}
1107-
if err := cli.Get(ctx, key, nb); err == nil {
1108-
hasTimestamp := "no"
1109-
if nb.DeletionTimestamp != nil {
1110-
hasTimestamp = "yes"
1111-
}
1112-
GinkgoT().Logf("Notebook state: exists=true, has deletion timestamp=%s, finalizers=%v",
1113-
hasTimestamp, nb.Finalizers)
1114-
} else {
1115-
GinkgoT().Logf("Notebook state: exists=false, error=%v", err)
1116-
}
1108+
By("Verifying controller deletes the OAuthClient")
1109+
Eventually(func() error {
1110+
var oauth oauthv1.OAuthClient
1111+
return cli.Get(ctx, oauthClientKey, &oauth)
1112+
}, time.Second*90, time.Second*3).Should(
1113+
MatchError(ContainSubstring("not found")),
1114+
"Expected OAuthClient to be deleted by odh-notebook-controller during finalizer processing")
1115+
})
11171116

1118-
// Wait for the controller to potentially delete the OAuthClient
1119-
// without any manual intervention
1120-
time.Sleep(5 * time.Second)
1121-
1122-
// Check and log the final state
1123-
client := &oauthv1.OAuthClient{}
1124-
err := cli.Get(ctx, oauthClientKey, client)
1125-
if apierrors.IsNotFound(err) {
1126-
GinkgoT().Logf("OAuthClient was successfully deleted by the controller")
1127-
} else if err != nil {
1128-
GinkgoT().Logf("Error checking OAuthClient: %v", err)
1129-
} else {
1130-
GinkgoT().Logf("OAuthClient still exists, which suggests the controller isn't handling deletion in the test environment")
1131-
}
1117+
It("Should remove finalizer and delete Notebook after OAuthClient cleanup", func() {
1118+
By("Verifying OAuthClient was deleted in previous test")
1119+
oauthClientKey := types.NamespacedName{Name: Name + "-" + Namespace + "-oauth-client"}
1120+
Eventually(func() error {
1121+
var oauth oauthv1.OAuthClient
1122+
return cli.Get(ctx, oauthClientKey, &oauth)
1123+
}, time.Second*30).Should(MatchError(ContainSubstring("not found")))
11321124

1133-
// No assertion here - we're just observing behavior
1125+
By("Verifying finalizer is removed and notebook is deleted")
1126+
Eventually(func() error {
1127+
var updated nbv1.Notebook
1128+
return cli.Get(ctx, notebookKey, &updated)
1129+
}, time.Second*60, time.Second*2).Should(
1130+
MatchError(ContainSubstring("not found")),
1131+
"Expected Notebook to be fully deleted after finalizer removal")
11341132
})
11351133
})
11361134

@@ -1466,6 +1464,75 @@ func createNotebook(name, namespace string) *nbv1.Notebook {
14661464
}
14671465
}
14681466

1467+
func createNotebookWithOAuth(name, namespace string) *nbv1.Notebook {
1468+
return &nbv1.Notebook{
1469+
ObjectMeta: metav1.ObjectMeta{
1470+
Name: name,
1471+
Namespace: namespace,
1472+
Labels: map[string]string{
1473+
"app.kubernetes.io/instance": name,
1474+
},
1475+
Annotations: map[string]string{
1476+
"notebooks.opendatahub.io/inject-oauth": "true",
1477+
"notebooks.opendatahub.io/foo": "bar",
1478+
"notebooks.opendatahub.io/oauth-logout-url": "https://example.notebook-url/notebook/" + namespace + "/" + name,
1479+
"kubeflow-resource-stopped": "odh-notebook-controller-lock",
1480+
},
1481+
},
1482+
Spec: nbv1.NotebookSpec{
1483+
Template: nbv1.NotebookTemplateSpec{
1484+
Spec: corev1.PodSpec{
1485+
ServiceAccountName: name,
1486+
Containers: []corev1.Container{
1487+
{
1488+
Name: name,
1489+
Image: "registry.redhat.io/ubi8/ubi:latest",
1490+
},
1491+
createOAuthContainer(name, namespace),
1492+
},
1493+
Volumes: []corev1.Volume{
1494+
{
1495+
Name: "notebook-data",
1496+
VolumeSource: corev1.VolumeSource{
1497+
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
1498+
ClaimName: name + "-data",
1499+
},
1500+
},
1501+
},
1502+
{
1503+
Name: "oauth-config",
1504+
VolumeSource: corev1.VolumeSource{
1505+
Secret: &corev1.SecretVolumeSource{
1506+
SecretName: name + "-oauth-config",
1507+
DefaultMode: ptr.To[int32](420),
1508+
},
1509+
},
1510+
},
1511+
{
1512+
Name: "oauth-client",
1513+
VolumeSource: corev1.VolumeSource{
1514+
Secret: &corev1.SecretVolumeSource{
1515+
SecretName: name + "-oauth-client",
1516+
DefaultMode: ptr.To[int32](420),
1517+
},
1518+
},
1519+
},
1520+
{
1521+
Name: "tls-certificates",
1522+
VolumeSource: corev1.VolumeSource{
1523+
Secret: &corev1.SecretVolumeSource{
1524+
SecretName: name + "-tls",
1525+
DefaultMode: ptr.To[int32](420),
1526+
},
1527+
},
1528+
},
1529+
},
1530+
},
1531+
},
1532+
},
1533+
}
1534+
}
1535+
14691536
func getRouteFromList(route *routev1.Route, notebook *nbv1.Notebook, name, namespace string) (*routev1.Route, error) {
14701537
routeList := &routev1.RouteList{}
14711538
opts := []client.ListOption{

0 commit comments

Comments
 (0)