Kubernetes RabbitMQ operator, forked https://github.com/tekliner/rabbitmq-operator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

185 lines
6.8 KiB

package rabbitmq
import (
"context"
"encoding/base64"
"math/rand"
"github.com/go-logr/logr"
rabbitmqv1 "github.com/tekliner/rabbitmq-operator/pkg/apis/rabbitmq/v1"
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/types"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
func secretEncode(plaintextSecret string) string {
return base64.StdEncoding.EncodeToString([]byte(plaintextSecret))
}
func secretDecode(encodedSecret []byte) (string, error) {
decoded, err := base64.StdEncoding.DecodeString(string(encodedSecret))
return string(decoded), err
}
func (r *ReconcileRabbitmq) getSecret(name string, namespace string) (corev1.Secret, error) {
secretObj := corev1.Secret{}
err := r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: namespace}, &secretObj)
return secretObj, err
}
func (r *ReconcileRabbitmq) getSecretData(reqLogger logr.Logger, secretNamespace string, secretName string, secretDataField string) (string, error) {
secretObj := corev1.Secret{}
reqLogger.Info("Get secret request", "secret namespace", secretNamespace, "secret name", secretName, "secret data field", secretDataField)
secretObj, err := r.getSecret(secretName, secretNamespace)
if err != nil {
reqLogger.Info("Get secret request ERROR", "secret namespace", secretNamespace, "secret name", secretName, "secret data field", secretDataField)
return "", err
}
return string(secretObj.Data[secretDataField]), nil
}
func (r *ReconcileRabbitmq) reconcileSecrets(reqLogger logr.Logger, cr *rabbitmqv1.Rabbitmq) (secretResouces, error) {
var secretNames secretResouces
// standart resource names
secretNames.ServiceAccount = cr.Name + "-service-account"
secretNames.Credentials = cr.Name + "-credentials"
/////////////////////////////////////////////////////////////////
// SERVICE ACCOUNT SECRET, CREATING ONCE AT RABBIT INSTALL
/////////////////////////////////////////////////////////////////
// check existance of linked or standart service account secret
createServiceAccount := false
if cr.Spec.RabbitmqSecretServiceAccount != "" {
secretNames.ServiceAccount = cr.Spec.RabbitmqSecretServiceAccount
secretSAResource := &corev1.Secret{}
err := r.client.Get(context.TODO(), types.NamespacedName{Name: secretNames.ServiceAccount, Namespace: cr.Namespace}, secretSAResource)
if err != nil && apierrors.IsNotFound(err) {
// not found! create new service account
reqLogger.Info("Service Account: linked resource not found, operator will create new")
createServiceAccount = true
} else if err != nil {
// happend something else, do nothing
reqLogger.Info("Service Account linked: error happend", err)
return secretResouces{}, err
}
} else {
// link empty, search standart service account secret
reqLogger.Info("Service Account: search for standart resource")
secretSAResource := &corev1.Secret{}
err := r.client.Get(context.TODO(), types.NamespacedName{Name: secretNames.ServiceAccount, Namespace: cr.Namespace}, secretSAResource)
if err != nil && apierrors.IsNotFound(err) {
// not found! create new service account
reqLogger.Info("Service Account: standart resource not found, operator will create new")
createServiceAccount = true
} else if err != nil {
// happend something else, do nothing
reqLogger.Info("Service Account standart: error happend", err)
return secretResouces{}, err
}
}
// create service account with standart name
if createServiceAccount {
reqLogger.Info("Creating new service account secret", "Namespace", cr.Namespace, "Name", secretNames.ServiceAccount)
secretSAResource := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretNames.ServiceAccount,
Namespace: cr.Namespace,
Labels: returnLabels(cr),
},
Data: map[string][]byte{
"username": []byte("sa"),
"password": []byte(randomString(30)),
"cookie": []byte(randomString(30)),
},
}
if err := controllerutil.SetControllerReference(cr, secretSAResource, r.scheme); err != nil {
return secretResouces{}, err
}
err := r.client.Create(context.TODO(), secretSAResource)
if err != nil {
return secretResouces{}, err
}
}
/////////////////////////////////////////////////////////////////
// USER CREDENTIALS SECRET
/////////////////////////////////////////////////////////////////
// check existance of linked or standart credentials secret
// if resource found remove make lists to add, change or remove users
createCredentialsSecret := false
secretCredResource := &corev1.Secret{}
if cr.Spec.RabbitmqSecretCredentials != "" {
// try to find secret under name from CRD
err := r.client.Get(context.TODO(), types.NamespacedName{Name: cr.Spec.RabbitmqSecretCredentials, Namespace: cr.Namespace}, secretCredResource)
if err != nil && apierrors.IsNotFound(err) {
// not found! create new service account
reqLogger.Info("User credentials: linked resource not found, operator will create new")
createCredentialsSecret = true
} else if err != nil {
// happend something else, do nothing
reqLogger.Info("User credentials: error happend", err)
return secretResouces{}, err
}
secretNames.Credentials = cr.Spec.RabbitmqSecretCredentials
} else {
// link empty, search standart credentials secret name
reqLogger.Info("User credentials: search for standart resource")
err := r.client.Get(context.TODO(), types.NamespacedName{Name: secretNames.Credentials, Namespace: cr.Namespace}, secretCredResource)
if err != nil && apierrors.IsNotFound(err) {
// not found! create new service account
reqLogger.Info("User credentials: standart resource not found, operator will create new")
createCredentialsSecret = true
} else if err != nil {
// happend something else, do nothing
reqLogger.Info("User credentials standart: error happend", err)
return secretResouces{}, err
}
}
// create credentials secret
if createCredentialsSecret {
reqLogger.Info("Creating new user credentials secret", "Namespace", cr.Namespace, "Name", secretNames.Credentials)
secretCredResourceNew := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretNames.Credentials,
Namespace: cr.Namespace,
Labels: returnLabels(cr),
},
Data: map[string][]byte{},
}
if err := controllerutil.SetControllerReference(cr, secretCredResourceNew, r.scheme); err != nil {
return secretResouces{}, err
}
err := r.client.Create(context.TODO(), secretCredResourceNew)
if err != nil {
return secretResouces{}, err
}
}
return secretNames, nil
}
func randomString(l int) string {
var letterRunes = []rune("ABCDEFGHIJKLMNOabcdefghijklmn67890PQRSTUVWXYZ12345opqrstuvwxyz")
b := make([]rune, l)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}