mirror of
https://github.com/clastix/kamaji.git
synced 2026-03-03 18:21:17 +00:00
251 lines
7.2 KiB
Go
251 lines
7.2 KiB
Go
// Copyright 2022 Clastix Labs
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package resources
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
|
|
|
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
|
"github.com/clastix/kamaji/internal/sql"
|
|
)
|
|
|
|
const (
|
|
secretHashLabelKey = "component.kamaji.clastix.io/secret-hash"
|
|
)
|
|
|
|
type sqlSetupResource struct {
|
|
schema string
|
|
user string
|
|
password string
|
|
}
|
|
|
|
type SQLSetup struct {
|
|
resource sqlSetupResource
|
|
Client client.Client
|
|
DBConnection sql.DBConnection
|
|
Name string
|
|
}
|
|
|
|
func (r *SQLSetup) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
|
if tenantControlPlane.Status.Storage.KineMySQL == nil {
|
|
return true
|
|
}
|
|
|
|
return tenantControlPlane.Status.Storage.KineMySQL.Setup.Schema != r.resource.schema ||
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.User != r.resource.user ||
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.SQLConfigResourceVersion != tenantControlPlane.Status.Storage.KineMySQL.Config.ResourceVersion
|
|
}
|
|
|
|
func (r *SQLSetup) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
|
return false
|
|
}
|
|
|
|
func (r *SQLSetup) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (r *SQLSetup) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
secret := &corev1.Secret{}
|
|
namespacedName := types.NamespacedName{
|
|
Namespace: tenantControlPlane.GetNamespace(),
|
|
Name: tenantControlPlane.Status.Storage.KineMySQL.Config.SecretName,
|
|
}
|
|
if err := r.Client.Get(ctx, namespacedName, secret); err != nil {
|
|
return err
|
|
}
|
|
|
|
r.resource = sqlSetupResource{
|
|
schema: string(secret.Data["MYSQL_SCHEMA"]),
|
|
user: string(secret.Data["MYSQL_USER"]),
|
|
password: string(secret.Data["MYSQL_PASSWORD"]),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *SQLSetup) GetClient() client.Client {
|
|
return r.Client
|
|
}
|
|
|
|
func (r *SQLSetup) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
if tenantControlPlane.Status.Storage.KineMySQL.Setup.SQLConfigResourceVersion != "" &&
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.SQLConfigResourceVersion != tenantControlPlane.Status.Storage.KineMySQL.Config.ResourceVersion {
|
|
if err := r.Delete(ctx, tenantControlPlane); err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
return controllerutil.OperationResultUpdated, nil
|
|
}
|
|
|
|
reconcilationResult := controllerutil.OperationResultNone
|
|
var operationResult controllerutil.OperationResult
|
|
var err error
|
|
|
|
operationResult, err = r.createDB(ctx, tenantControlPlane)
|
|
if err != nil {
|
|
return reconcilationResult, err
|
|
}
|
|
reconcilationResult = updateOperationResult(reconcilationResult, operationResult)
|
|
|
|
operationResult, err = r.createUser(ctx, tenantControlPlane)
|
|
if err != nil {
|
|
return reconcilationResult, err
|
|
}
|
|
reconcilationResult = updateOperationResult(reconcilationResult, operationResult)
|
|
|
|
operationResult, err = r.createGrantPrivileges(ctx, tenantControlPlane)
|
|
if err != nil {
|
|
return reconcilationResult, err
|
|
}
|
|
reconcilationResult = updateOperationResult(reconcilationResult, operationResult)
|
|
|
|
return reconcilationResult, nil
|
|
}
|
|
|
|
func (r *SQLSetup) GetName() string {
|
|
return r.Name
|
|
}
|
|
|
|
func (r *SQLSetup) Delete(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
if err := r.Define(ctx, tenantControlPlane); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := r.revokeGrantPrivileges(ctx, tenantControlPlane); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := r.deleteDB(ctx, tenantControlPlane); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := r.deleteUser(ctx, tenantControlPlane); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *SQLSetup) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
if tenantControlPlane.Status.Storage.KineMySQL == nil {
|
|
return fmt.Errorf("sql configuration is not ready")
|
|
}
|
|
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.Schema = r.resource.schema
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.User = r.resource.user
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.LastUpdate = metav1.Now()
|
|
tenantControlPlane.Status.Storage.KineMySQL.Setup.SQLConfigResourceVersion = tenantControlPlane.Status.Storage.KineMySQL.Config.ResourceVersion
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *SQLSetup) createDB(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
exists, err := r.DBConnection.DBExists(ctx, r.resource.schema)
|
|
if err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
if exists {
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
|
|
if err := r.DBConnection.CreateDB(ctx, r.resource.schema); err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
return controllerutil.OperationResultCreated, nil
|
|
}
|
|
|
|
func (r *SQLSetup) deleteDB(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
exists, err := r.DBConnection.DBExists(ctx, r.resource.schema)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
if err := r.DBConnection.DeleteDB(ctx, r.resource.schema); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *SQLSetup) createUser(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
exists, err := r.DBConnection.UserExists(ctx, r.resource.user)
|
|
if err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
if exists {
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
|
|
if err := r.DBConnection.CreateUser(ctx, r.resource.user, r.resource.password); err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
return controllerutil.OperationResultCreated, nil
|
|
}
|
|
|
|
func (r *SQLSetup) deleteUser(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
exists, err := r.DBConnection.UserExists(ctx, r.resource.user)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
if err := r.DBConnection.DeleteUser(ctx, r.resource.user); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *SQLSetup) createGrantPrivileges(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
exists, err := r.DBConnection.GrantPrivilegesExists(ctx, r.resource.user, r.resource.schema)
|
|
if err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
if exists {
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
|
|
if err := r.DBConnection.GrantPrivileges(ctx, r.resource.user, r.resource.schema); err != nil {
|
|
return controllerutil.OperationResultNone, err
|
|
}
|
|
|
|
return controllerutil.OperationResultCreated, nil
|
|
}
|
|
|
|
func (r *SQLSetup) revokeGrantPrivileges(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
exists, err := r.DBConnection.GrantPrivilegesExists(ctx, r.resource.user, r.resource.schema)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
if err := r.DBConnection.RevokePrivileges(ctx, r.resource.user, r.resource.schema); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|