Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
MDBF-378: create Secrets for stateless application
- It works with creating the secret for root and user can edit the secret which is visible after minikube restart (don't know how to solve dynamically)
- It is not relying on tweak with status variable .status.SecretSet (that was set in CreateRootSecret() and checked in reconciliation loop in order to create the desired secret).
- This patch should be updated for statefull app
  • Loading branch information
an3l committed Jun 16, 2022
1 parent 8a43a6e commit 11a4261
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 10 deletions.
5 changes: 3 additions & 2 deletions api/v1alpha1/mariadb_types.go
Expand Up @@ -43,8 +43,8 @@ type MariaDBSpec struct {
// +kubebuilder:validation:Required
Database string `json:"database"`

// Root user password
// +kubebuilder:validation:Required
// Root user password (if set will be used, else root secret will be created)
// +optional
Rootpwd string `json:"rootpwd"`

// Image name with version
Expand Down Expand Up @@ -90,6 +90,7 @@ type MariaDBStatus struct {
// +kubebuilder:default="NOT STARTED"

ShowState string `json:"showState"`
SecretSet int32 `json:"secretSet"`
}

//+kubebuilder:object:root=true
Expand Down
8 changes: 6 additions & 2 deletions config/crd/bases/mariak8g.mariadb.org_mariadbs.yaml
Expand Up @@ -81,7 +81,8 @@ spec:
maximum: 4
type: integer
rootpwd:
description: Root user password
description: Root user password (if set will be used, else root secret
will be created)
type: string
username:
description: Database additional user details (base64 encoded)
Expand All @@ -90,7 +91,6 @@ spec:
- dataStoragePath
- database
- password
- rootpwd
- username
type: object
status:
Expand All @@ -106,13 +106,17 @@ spec:
type: integer
lastMessage:
type: string
secretSet:
format: int32
type: integer
showState:
default: NOT STARTED
type: string
required:
- dbState
- desiredReplicas
- lastMessage
- secretSet
type: object
type: object
served: true
Expand Down
2 changes: 1 addition & 1 deletion config/samples/mariak8g_v1alpha1_mariadb.yaml
Expand Up @@ -7,10 +7,10 @@ spec:
dataStoragePath: "/tmp/datadir"
database: "testDB-operator"
password: "my_cool_secret"
rootpwd: "my-secret-pw"
username: "example-user"

# Optional fields
replicas: 2
#rootpwd: "my-secret-pw"
imageVersion: "10.6"
image: "quay.io/mariadb-foundation/mariadb-devel:10.5"
49 changes: 46 additions & 3 deletions controllers/mariadb_controller.go
Expand Up @@ -23,6 +23,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -67,7 +68,41 @@ func (r *MariaDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
log.Error(err, "unable to fetch MariaDB")
return ctrl_res, err
}
// Second call function to reconcile all resources

applyOpts := []client.PatchOption{client.ForceOwnership, client.FieldOwner("mariadb-controller")}

// Check if secret exists (one cannot specify plain text rootpwd)
var root_secret *corev1.Secret = nil
if err := r.Get(ctx, req.NamespacedName, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: app.Name + "-secret",
Namespace: app.Namespace,
},
}); err != nil && errors.IsNotFound(err) {
log.Info("Root secret doesn't exist, let me creat it:...")
// Create root secret if not exist root password
var err error
root_secret, err = r.reconcile_root_secret(ctx, app, log)
err = r.Client.Create(ctx, root_secret)
if err != nil {
log.Error(err, " failed to reconcile root secret!")
return ctrl_res, err
}

// Secret created successfully - requeue after 5 minutes
log.Info("Secret Created successfully, RequeueAfter 5 sec")
return ctrl.Result{RequeueAfter: 5}, nil
}

// This part is needed to be outside of reconciliation because of need to edit the secrets
if root_secret != nil {
err1 := r.Patch(ctx, root_secret, client.Apply, applyOpts...)
if err1 != nil {
return ctrl_res, err1
}
}

// Create the deployment
deployment, err := r.reconcile_deployment(ctx, app, log)
if err != nil {
log.Error(err, " failed to reconcile deployments!")
Expand All @@ -81,8 +116,6 @@ func (r *MariaDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl_res, err
}

applyOpts := []client.PatchOption{client.ForceOwnership, client.FieldOwner("mariadb-controller")}

err = r.Patch(ctx, &deployment, client.Apply, applyOpts...)
if err != nil {
return ctrl_res, err
Expand All @@ -108,6 +141,16 @@ func (r *MariaDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
Custom function used to be called in reconciliation loop
--------------------------------------------------------
*/
func (r *MariaDBReconciler) reconcile_root_secret(
ctx context.Context,
app mariak8gv1alpha1.MariaDB,
log logr.Logger,
) (*corev1.Secret, error) {
// If not create the secret with password `mysecret`
root_secret, err_secret := k8s.CreateRootSecret(&app, "mysecret")
return &root_secret, err_secret
}

func (r *MariaDBReconciler) reconcile_deployment(
ctx context.Context,
app mariak8gv1alpha1.MariaDB,
Expand Down
31 changes: 29 additions & 2 deletions pkg/k8s/stateless.go
Expand Up @@ -42,8 +42,19 @@ func DesiredDeployment(database mariak8gv1alpha1.MariaDB) (appsv1.Deployment, er
Image: mariaImage,
Env: []corev1.EnvVar{
{Name: "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD", Value: "0"},
// root password should be set from secret - test
{Name: "MARIADB_ROOT_PASSWORD", Value: database.Spec.Rootpwd},
// ValueFrom cannot be used if Value is non empty
{
Name: "MARIADB_ROOT_PASSWORD",
Value: database.Spec.Rootpwd,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: database.Name + "-secret",
},
Key: "mariadb-root-password",
},
},
},
{Name: "MARIADB_USER", Value: database.Spec.Username},
{Name: "MARIADB_PASSWORD", Value: database.Spec.Password},
{Name: "MARIADB_DATABASE", Value: database.Spec.Database},
Expand Down Expand Up @@ -80,3 +91,19 @@ func DesiredService(database mariak8gv1alpha1.MariaDB) (corev1.Service, error) {

return svc, nil
}

func CreateRootSecret(database *mariak8gv1alpha1.MariaDB, secretPassword string) (corev1.Secret, error) {
rootSecret := corev1.Secret{
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String(), Kind: "Secret"},
ObjectMeta: metav1.ObjectMeta{
Name: database.Name + "-secret",
Namespace: database.Namespace,
},
Type: "Opaque", // default
Data: map[string][]byte{
"mariadb-root-password": []byte(secretPassword),
},
}

return rootSecret, nil
}

0 comments on commit 11a4261

Please sign in to comment.