-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new API to allow services to generate MariaDBAccount
- Loading branch information
Showing
10 changed files
with
940 additions
and
141 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,330 @@ | ||
/* | ||
Copyright 2023 Red Hat | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package helpers | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" | ||
"k8s.io/apimachinery/pkg/types" | ||
) | ||
|
||
// populateHarness describes a function that will insert suite-appropriate | ||
// data into a MariaDBTestHarness instance | ||
type populateHarness func(*MariaDBTestHarness) | ||
|
||
// establishesCR describes a test function that can fully set up a particular | ||
// controller's "Reconciliation Successful" state for a given kind of CR. | ||
type establishesCR func(types.NamespacedName) | ||
|
||
// updatesAccountName describes a test function that can change the | ||
// "databaseAccount" or similar member of an already-reconciled CR to a new | ||
// one, which is expected to kick off a username/password rotation sequence. | ||
type updatesAccountName func(types.NamespacedName) | ||
|
||
// deletesCr describes a test function that will delete the CR that was | ||
// created by an establishesCR function | ||
type deletesCR func() | ||
|
||
// MariaDBTestHarness describes the parameters for running a series | ||
// of Ginkgo tests which exercise a controller's ability to correctly | ||
// work with MariaDBDatabase / MariaDBAccount APIs. | ||
type MariaDBTestHarness struct { | ||
Namespace string | ||
DatabaseName string | ||
FinalizerName string | ||
MariaDBHelper *TestHelper | ||
Timeout time.Duration | ||
Interval time.Duration | ||
} | ||
|
||
// PopulateHarness receives named arguments to place within a | ||
// MariaDBTestHarness instance. | ||
func (harness *MariaDBTestHarness) PopulateHarness( | ||
namespace string, | ||
databaseName string, | ||
finalizerName string, | ||
mariadb *TestHelper, | ||
timeout time.Duration, | ||
interval time.Duration, | ||
) { | ||
harness.Namespace = namespace | ||
harness.DatabaseName = databaseName | ||
harness.FinalizerName = finalizerName | ||
harness.MariaDBHelper = mariadb | ||
harness.Timeout = timeout | ||
harness.Interval = interval | ||
} | ||
|
||
// MariaDBAccountSuiteTests runs MariaDBAccount suite tests. these are | ||
// pre-packaged ginkgo tests that exercise standard account create / update | ||
// patterns that should be common to all controllers that work with | ||
// MariaDBDatabase and MariaDBAccount CRs. | ||
func MariaDBAccountSuiteTests( | ||
description string, | ||
provideHarness populateHarness, | ||
crSetup establishesCR, | ||
updateAccount updatesAccountName, | ||
crDelete deletesCR, | ||
) { | ||
|
||
var harness *MariaDBTestHarness | ||
|
||
BeforeEach(func() { | ||
harness = &MariaDBTestHarness{} | ||
provideHarness(harness) | ||
}) | ||
|
||
When(fmt.Sprintf("The %s service is being configured to run", description), func() { | ||
It("Uses a pre-existing MariaDBAccount and sets a finalizer", func() { | ||
|
||
mariadb := harness.MariaDBHelper | ||
k8sClient := mariadb.K8sClient | ||
|
||
accountName := types.NamespacedName{ | ||
Name: "some-mariadb-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
// create MariaDBAccount first | ||
acc, accSecret := mariadb.CreateMariaDBAccountAndSecret(accountName, mariadbv1.MariaDBAccountSpec{}) | ||
DeferCleanup(k8sClient.Delete, mariadb.Ctx, accSecret) | ||
DeferCleanup(k8sClient.Delete, mariadb.Ctx, acc) | ||
|
||
// then create the CR | ||
crSetup(accountName) | ||
|
||
mariadb.Logger.Info(fmt.Sprintf("Service should fully configure on MariaDBAccount %s", accountName)) | ||
|
||
// now wait for the account to have the finalizer and the | ||
// database name | ||
|
||
Eventually(func() []string { | ||
mariadbAccount := mariadb.GetMariaDBAccount(accountName) | ||
return mariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
// CreateOrPatchDBByName will add a label referring to the database | ||
Eventually(func() string { | ||
mariadbAccount := mariadb.GetMariaDBAccount(accountName) | ||
return mariadbAccount.Labels["mariaDBDatabaseName"] | ||
}, harness.Timeout, harness.Interval).Should(Equal(harness.DatabaseName)) | ||
|
||
}) | ||
|
||
It("Ensures a MariaDBAccount is created if not present and sets a finalizer", func() { | ||
mariadb := harness.MariaDBHelper | ||
|
||
accountName := types.NamespacedName{ | ||
Name: "some-mariadb-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
// here, dont create a mariadbaccount. right now CRs should | ||
// generate this if not exists using EnsureMariaDBAccount | ||
|
||
// then create the CR | ||
crSetup(accountName) | ||
|
||
mariadb.Logger.Info(fmt.Sprintf("Service should fully configure on MariaDBAccount %s", accountName)) | ||
|
||
// now wait for the account to have the finalizer and the | ||
// database name | ||
|
||
Eventually(func() []string { | ||
mariadbAccount := mariadb.GetMariaDBAccount(accountName) | ||
return mariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
// CreateOrPatchDBByName will add a label referring to the database | ||
Eventually(func() string { | ||
mariadbAccount := mariadb.GetMariaDBAccount(accountName) | ||
return mariadbAccount.Labels["mariaDBDatabaseName"] | ||
}, harness.Timeout, harness.Interval).Should(Equal(harness.DatabaseName)) | ||
|
||
}) | ||
}) | ||
|
||
When(fmt.Sprintf("The %s service is fully running", description), func() { | ||
// get service fully complete with a mariadbaccount | ||
BeforeEach(func() { | ||
mariadb := harness.MariaDBHelper | ||
|
||
oldAccountName := types.NamespacedName{ | ||
Name: "some-old-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
// create the CR with old account | ||
crSetup(oldAccountName) | ||
|
||
// also simulate that it got completed | ||
mariadb.SimulateMariaDBAccountCompleted(oldAccountName) | ||
|
||
mariadb.Logger.Info(fmt.Sprintf("Service should fully configure on MariaDBAccount %s", oldAccountName)) | ||
|
||
// finalizer is attached to old account | ||
Eventually(func() []string { | ||
oldMariadbAccount := mariadb.GetMariaDBAccount(oldAccountName) | ||
return oldMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
}) | ||
It("should ensure a new MariaDBAccount exists when accountname is changed", func() { | ||
mariadb := harness.MariaDBHelper | ||
|
||
oldAccountName := types.NamespacedName{ | ||
Name: "some-old-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
newAccountName := types.NamespacedName{ | ||
Name: "some-new-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
mariadb.Logger.Info("About to update account from some-old-account to some-new-account") | ||
|
||
updateAccount(newAccountName) | ||
|
||
// new account is (eventually) created | ||
_ = mariadb.GetMariaDBAccount(newAccountName) | ||
|
||
// dont simuluate MariaDBAccount being created. it's not done yet | ||
|
||
mariadb.Logger.Info( | ||
fmt.Sprintf("Service should have ensured MariaDBAccount %s exists but should remain running on %s", | ||
newAccountName, oldAccountName), | ||
) | ||
|
||
// finalizer is attached to new account | ||
Eventually(func() []string { | ||
newMariadbAccount := mariadb.GetMariaDBAccount(newAccountName) | ||
return newMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
// old account retains the finalizer because we did not yet | ||
// complete the new MariaDBAccount | ||
Eventually(func() []string { | ||
oldMariadbAccount := mariadb.GetMariaDBAccount(oldAccountName) | ||
return oldMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
}) | ||
|
||
It("should move the finalizer to a new MariaDBAccount when create is complete", func() { | ||
mariadb := harness.MariaDBHelper | ||
|
||
oldAccountName := types.NamespacedName{ | ||
Name: "some-old-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
newAccountName := types.NamespacedName{ | ||
Name: "some-new-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
updateAccount(newAccountName) | ||
|
||
// new account is (eventually) created | ||
_ = mariadb.GetMariaDBAccount(newAccountName) | ||
|
||
// also simulate that it got completed | ||
mariadb.SimulateMariaDBAccountCompleted(newAccountName) | ||
|
||
mariadb.Logger.Info( | ||
fmt.Sprintf("Service should move to run fully off MariaDBAccount %s and remove finalizer from %s", | ||
newAccountName, oldAccountName), | ||
) | ||
|
||
// finalizer is attached to new account | ||
Eventually(func() []string { | ||
newMariadbAccount := mariadb.GetMariaDBAccount(newAccountName) | ||
return newMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
// CreateOrPatchDBByName will add a label referring to the database | ||
Eventually(func() string { | ||
mariadbAccount := mariadb.GetMariaDBAccount(newAccountName) | ||
return mariadbAccount.Labels["mariaDBDatabaseName"] | ||
}, harness.Timeout, harness.Interval).Should(Equal(harness.DatabaseName)) | ||
|
||
// finalizer removed from old account | ||
Eventually(func() []string { | ||
oldMariadbAccount := mariadb.GetMariaDBAccount(oldAccountName) | ||
return oldMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).ShouldNot(ContainElement(harness.FinalizerName)) | ||
}) | ||
|
||
It("should remove the finalizer from all associated MariaDBAccount objects regardless of status when deleted", func() { | ||
mariadb := harness.MariaDBHelper | ||
|
||
oldAccountName := types.NamespacedName{ | ||
Name: "some-old-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
newAccountName := types.NamespacedName{ | ||
Name: "some-new-account", | ||
Namespace: harness.Namespace, | ||
} | ||
|
||
mariadb.Logger.Info("About to update account from some-old-account to some-new-account") | ||
|
||
updateAccount(newAccountName) | ||
|
||
// new account is (eventually) created | ||
_ = mariadb.GetMariaDBAccount(newAccountName) | ||
|
||
// dont simuluate MariaDBAccount being created, so that finalizer is | ||
// on both | ||
|
||
mariadb.Logger.Info( | ||
fmt.Sprintf("Service should have ensured MariaDBAccount %s exists but should remain running on %s", | ||
newAccountName, oldAccountName), | ||
) | ||
|
||
// as before, both accounts have a finalizer | ||
Eventually(func() []string { | ||
newMariadbAccount := mariadb.GetMariaDBAccount(newAccountName) | ||
return newMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
Eventually(func() []string { | ||
oldMariadbAccount := mariadb.GetMariaDBAccount(oldAccountName) | ||
return oldMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).Should(ContainElement(harness.FinalizerName)) | ||
|
||
// now delete the CR | ||
crDelete() | ||
|
||
// finalizer is removed from both as part of the delete | ||
// process | ||
Eventually(func() []string { | ||
newMariadbAccount := mariadb.GetMariaDBAccount(newAccountName) | ||
return newMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).ShouldNot(ContainElement(harness.FinalizerName)) | ||
|
||
Eventually(func() []string { | ||
oldMariadbAccount := mariadb.GetMariaDBAccount(oldAccountName) | ||
return oldMariadbAccount.Finalizers | ||
}, harness.Timeout, harness.Interval).ShouldNot(ContainElement(harness.FinalizerName)) | ||
|
||
}) | ||
}) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.