Skip to content
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

controllers: refactor devdb to reuse for atlas_migration #169

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions controllers/atlasmigration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ type (
}
)

func NewAtlasMigrationReconciler(mgr Manager, execPath string) *AtlasMigrationReconciler {
func NewAtlasMigrationReconciler(mgr Manager, execPath string, _ bool) *AtlasMigrationReconciler {
return &AtlasMigrationReconciler{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
Expand Down Expand Up @@ -219,8 +219,8 @@ func (r *AtlasMigrationReconciler) watchRefs(res *dbv1alpha1.AtlasMigration) {
}

// Reconcile the given AtlasMigration resource.
func (r *AtlasMigrationReconciler) reconcile(ctx context.Context, dir, envName string) (_ *dbv1alpha1.AtlasMigrationStatus, _ error) {
c, err := atlas.NewClient(dir, r.execPath)
func (r *AtlasMigrationReconciler) reconcile(ctx context.Context, wd, envName string) (_ *dbv1alpha1.AtlasMigrationStatus, _ error) {
c, err := atlas.NewClient(wd, r.execPath)
if err != nil {
return nil, err
}
Expand Down
11 changes: 6 additions & 5 deletions controllers/atlasschema_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type (
configMapWatcher *watch.ResourceWatcher
secretWatcher *watch.ResourceWatcher
recorder record.EventRecorder
prewarmDevDB bool
devDB *devDBReconciler
}
// managedData contains information about the managed database and its desired state.
managedData struct {
Expand All @@ -78,14 +78,15 @@ type (
const sqlLimitSize = 1024

func NewAtlasSchemaReconciler(mgr Manager, execPath string, prewarmDevDB bool) *AtlasSchemaReconciler {
r := mgr.GetEventRecorderFor("atlasschema-controller")
return &AtlasSchemaReconciler{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
execPath: execPath,
configMapWatcher: watch.New(),
secretWatcher: watch.New(),
recorder: mgr.GetEventRecorderFor("atlasschema-controller"),
prewarmDevDB: prewarmDevDB,
recorder: r,
devDB: newDevDB(mgr, r, prewarmDevDB),
}
}

Expand All @@ -111,7 +112,7 @@ func (r *AtlasSchemaReconciler) Reconcile(ctx context.Context, req ctrl.Request)
r.watchRefs(res)
// Clean up any resources created by the controller after the reconciler is successful.
if res.IsReady() {
r.cleanUp(ctx, res)
r.devDB.cleanUp(ctx, res)
}
}()
// When the resource is first created, create the "Ready" condition.
Expand Down Expand Up @@ -145,7 +146,7 @@ func (r *AtlasSchemaReconciler) Reconcile(ctx context.Context, req ctrl.Request)
if data.DevURL == "" {
// The user has not specified an URL for dev-db,
// spin up a dev-db and get the connection string.
data.DevURL, err = r.devURL(ctx, res, *data.URL)
data.DevURL, err = r.devDB.devURL(ctx, res, *data.URL)
if err != nil {
res.SetNotReady("GettingDevDB", err.Error())
return result(err)
Expand Down
13 changes: 8 additions & 5 deletions controllers/atlasschema_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

const (
Expand Down Expand Up @@ -111,9 +110,7 @@ func TestReconcile_Reconcile(t *testing.T) {
ObjectMeta: meta,
Spec: dbv1alpha1.AtlasSchemaSpec{},
}
h, reconcile := newRunner(func(mgr Manager, name string) reconcile.Reconciler {
return NewAtlasSchemaReconciler(mgr, name, true)
}, func(cb *fake.ClientBuilder) {
h, reconcile := newRunner(NewAtlasSchemaReconciler, func(cb *fake.ClientBuilder) {
cb.WithObjects(obj)
})
assert := func(except ctrl.Result, ready bool, reason, msg string) {
Expand Down Expand Up @@ -567,6 +564,7 @@ func newTest(t *testing.T) *test {
}
execPath, err := exec.LookPath("atlas")
require.NoError(t, err)
r := record.NewFakeRecorder(100)
return &test{
T: t,
k8s: m,
Expand All @@ -576,7 +574,12 @@ func newTest(t *testing.T) *test {
execPath: execPath,
configMapWatcher: watch.New(),
secretWatcher: watch.New(),
recorder: record.NewFakeRecorder(100),
recorder: r,
devDB: &devDBReconciler{
Client: m,
scheme: scheme,
recorder: r,
},
},
}
}
Expand Down
56 changes: 41 additions & 15 deletions controllers/devdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ import (
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/tools/record"
"k8s.io/utils/pointer"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

dbv1alpha1 "github.com/ariga/atlas-operator/api/v1alpha1"
)

const (
Expand All @@ -44,12 +45,40 @@ const (
hostReplace = "REPLACE_HOST"
)

type (
// TODO: Refactor this to a separate controller
devDBReconciler struct {
client.Client
scheme *runtime.Scheme
recorder record.EventRecorder
prewarm bool
}
resourceOwner interface {
metav1.Object
runtime.Object
}
)

func newDevDB(mgr Manager, r record.EventRecorder, prewarm bool) *devDBReconciler {
if r == nil {
// Only create a new recorder if it is not provided.
// This keep the controller from creating multiple recorders.
r = mgr.GetEventRecorderFor("devdb")
}
return &devDBReconciler{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
recorder: r,
prewarm: prewarm,
}
}

// cleanUp clean up any resources created by the controller
func (r *AtlasSchemaReconciler) cleanUp(ctx context.Context, sc *dbv1alpha1.AtlasSchema) {
func (r *devDBReconciler) cleanUp(ctx context.Context, sc resourceOwner) {
// If prewarmDevDB is false, scale down the deployment to 0
if !r.prewarmDevDB {
if !r.prewarm {
deploy := &appsv1.Deployment{}
key := nameDevDB(sc.ObjectMeta)
key := nameDevDB(sc)
err := r.Get(ctx, key, deploy)
if err != nil {
r.recorder.Eventf(sc, corev1.EventTypeWarning, "CleanUpDevDB", "Error getting devDB deployment: %v", err)
Expand All @@ -61,11 +90,10 @@ func (r *AtlasSchemaReconciler) cleanUp(ctx context.Context, sc *dbv1alpha1.Atla
}
return
}

// delete pods to clean up
pods := &corev1.PodList{}
err := r.List(ctx, pods, client.MatchingLabels(map[string]string{
labelInstance: nameDevDB(sc.ObjectMeta).Name,
labelInstance: nameDevDB(sc).Name,
}))
if err != nil {
r.recorder.Eventf(sc, corev1.EventTypeWarning, "CleanUpDevDB", "Error listing devDB pods: %v", err)
Expand All @@ -79,27 +107,26 @@ func (r *AtlasSchemaReconciler) cleanUp(ctx context.Context, sc *dbv1alpha1.Atla

// devURL returns the URL of the dev database for the given target URL.
// It creates a dev database if it does not exist.
func (r *AtlasSchemaReconciler) devURL(ctx context.Context, sc *dbv1alpha1.AtlasSchema, targetURL url.URL) (string, error) {
func (r *devDBReconciler) devURL(ctx context.Context, sc resourceOwner, targetURL url.URL) (string, error) {
drv := driver(targetURL.Scheme)
if drv == "sqlite" {
return "sqlite://db?mode=memory", nil
}
// make sure we have a dev db running
key := nameDevDB(sc.ObjectMeta)
key := nameDevDB(sc)
deploy := &appsv1.Deployment{}
switch err := r.Get(ctx, key, deploy); {
case err == nil:
// The dev database already exists,
// If it is scaled down, scale it up.
if deploy.Spec.Replicas == nil || *deploy.Spec.Replicas == 0 {
*deploy.Spec.Replicas = int32(1)
deploy.Spec.Replicas = pointer.Int32(1)
if err := r.Update(ctx, deploy); err != nil {
return "", transient(err)
}
r.recorder.Eventf(sc, corev1.EventTypeNormal, "ScaledUpDevDB", "Scaled up dev database deployment: %s", deploy.Name)
return "", transientAfter(errors.New("waiting for dev database to be ready"), 15*time.Second)
}

case apierrors.IsNotFound(err):
// The dev database does not exist, create it.
deploy, err := deploymentDevDB(key, drv, isSchemaBound(drv, &targetURL))
Expand All @@ -114,7 +141,6 @@ func (r *AtlasSchemaReconciler) devURL(ctx context.Context, sc *dbv1alpha1.Atlas
return "", transientAfter(errors.New("waiting for dev database to be ready"), 15*time.Second)
default:
// An error occurred while getting the dev database,
sc.SetNotReady("GettingDevDB", err.Error())
return "", err
}
pods := &corev1.PodList{}
Expand Down Expand Up @@ -205,10 +231,10 @@ func deploymentDevDB(name types.NamespacedName, drv string, schemaBound bool) (*
}

// nameDevDB returns the namespaced name of the dev database.
func nameDevDB(owner metav1.ObjectMeta) types.NamespacedName {
func nameDevDB(owner metav1.Object) types.NamespacedName {
return types.NamespacedName{
Name: fmt.Sprintf("%s-atlas-dev-db", owner.Name),
Namespace: owner.Namespace,
Name: fmt.Sprintf("%s-atlas-dev-db", owner.GetName()),
Namespace: owner.GetNamespace(),
}
}

Expand Down
4 changes: 2 additions & 2 deletions controllers/testhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type (
)

// newRunner returns a runner that can be used to test a reconcile.Reconciler.
func newRunner[T reconcile.Reconciler](fn func(Manager, string) T, modify func(*fake.ClientBuilder)) (*helper, runner) {
func newRunner[T reconcile.Reconciler](fn func(Manager, string, bool) T, modify func(*fake.ClientBuilder)) (*helper, runner) {
execPath, err := exec.LookPath("atlas")
if err != nil {
panic(err)
Expand All @@ -64,7 +64,7 @@ func newRunner[T reconcile.Reconciler](fn func(Manager, string) T, modify func(*
client: c,
recorder: r,
scheme: scheme,
}, execPath)
}, execPath, true)
h := &helper{client: c, recorder: r}
return h, func(obj client.Object, fn check) {
fn(a.Reconcile(context.Background(), request(obj)))
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "AtlasSchema")
os.Exit(1)
}
if err = controllers.NewAtlasMigrationReconciler(mgr, execPath).
if err = controllers.NewAtlasMigrationReconciler(mgr, execPath, prewarmDevDB).
SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "AtlasMigration")
os.Exit(1)
Expand Down
Loading