pkg/controllers/secret_controller.go (102 lines of code) (raw):

// Copyright (c) 2021, 2023, Oracle and/or its affiliates. // // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ package controllers import ( "context" v1 "github.com/mysql/ndb-operator/pkg/apis/ndbcontroller/v1" "github.com/mysql/ndb-operator/pkg/resources" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" klog "k8s.io/klog/v2" ) type DefaultSecretControlInterface interface { IsControlledBy(ctx context.Context, secretName string, ndb *v1.NdbCluster) bool Delete(ctx context.Context, namespace, secretName string) error ExtractPassword(ctx context.Context, namespace, name string) (string, error) } // secretDefaults implements the default methods and fields for all secret types type secretDefaults struct { client kubernetes.Interface } // secretInterface returns a typed/core/v1.SecretInterface func (sd *secretDefaults) secretInterface(namespace string) typedcorev1.SecretInterface { return sd.client.CoreV1().Secrets(namespace) } // IsControlledBy returns if the given secret is owned by the NdbCluster object func (sd *secretDefaults) IsControlledBy(ctx context.Context, secretName string, nc *v1.NdbCluster) bool { secret, err := sd.secretInterface(nc.Namespace).Get(ctx, secretName, metav1.GetOptions{}) if err != nil { klog.Errorf("Failed to retrieve Secret %q : %s", secretName, err) return false } return metav1.IsControlledBy(secret, nc) } // Delete deletes the secret from the namespace func (sd *secretDefaults) Delete(ctx context.Context, namespace, secretName string) error { return sd.secretInterface(namespace).Delete(ctx, secretName, metav1.DeleteOptions{}) } // ExtractPassword extracts the password from the given secret func (sd *secretDefaults) ExtractPassword(ctx context.Context, namespace, name string) (string, error) { // Check if the secret exists secret, err := sd.secretInterface(namespace).Get(ctx, name, metav1.GetOptions{}) if err != nil { // Secret does not exist klog.Errorf("Failed to retrieve Secret %q : %s", name, err) return "", err } return string(secret.Data[corev1.BasicAuthPasswordKey]), nil } // NewTDESecretInterface creates and returns a new DefaultSecretControlInterface func NewTDESecretInterface(client kubernetes.Interface) DefaultSecretControlInterface { return &secretDefaults{ client: client, } } type MySQLUserPasswordSecretControlInterface interface { DefaultSecretControlInterface EnsureMySQLRootPassword(ctx context.Context, ndb *v1.NdbCluster) (*corev1.Secret, error) EnsureNDBOperatorPassword(ctx context.Context, nc *v1.NdbCluster) (*corev1.Secret, error) } // mysqlUserPasswordSecrets implements MySQLUserPasswordSecretControlInterface and // can handle a password required for the MySQL user accounts. type mysqlUserPasswordSecrets struct { secretDefaults } // NewMySQLUserPasswordSecretInterface creates and returns a new MySQLUserPasswordSecretControlInterface func NewMySQLUserPasswordSecretInterface(client kubernetes.Interface) MySQLUserPasswordSecretControlInterface { return &mysqlUserPasswordSecrets{ secretDefaults{ client: client, }, } } // EnsureMySQLRootPassword checks if the MySQL root user secret exists // and creates a new one if it doesn't exist already func (mups *mysqlUserPasswordSecrets) EnsureMySQLRootPassword(ctx context.Context, ndb *v1.NdbCluster) (*corev1.Secret, error) { // Check if the root secret exists secretName, customSecret := resources.GetMySQLRootPasswordSecretName(ndb) secret, err := mups.secretInterface(ndb.Namespace).Get(ctx, secretName, metav1.GetOptions{}) if err == nil { // Secret exists return secret, nil } if !errors.IsNotFound(err) { // Error retrieving the secret klog.Errorf("Failed to retrieve secret %s : %v", secretName, err) return nil, err } // Secret not found if customSecret { // Secret specified in the spec doesn't exist klog.Errorf("MySQL root password Secret specified in the Ndb Spec doesn't exist : %v", err) return nil, err } // Secret not found and not a custom secret - create a new one secret = resources.NewMySQLRootPasswordSecret(ndb) secret, err = mups.secretInterface(ndb.Namespace).Create(ctx, secret, metav1.CreateOptions{}) if err != nil { klog.Errorf("Failed to create secret %s : %v", secretName, err) } return secret, err } // EnsureNDBOperatorPassword checks if the MySQL ndb-operator user secret exists // and creates a new one if it doesn't exist already func (mups *mysqlUserPasswordSecrets) EnsureNDBOperatorPassword( ctx context.Context, nc *v1.NdbCluster) (*corev1.Secret, error) { // Check if the ndb-operator secret exists secretName := resources.GetMySQLNDBOperatorPasswordSecretName(nc) secret, err := mups.secretInterface(nc.Namespace).Get(ctx, secretName, metav1.GetOptions{}) if err == nil { // Secret exists return secret, nil } if !errors.IsNotFound(err) { // Error retrieving the secret klog.Errorf("Failed to retrieve secret %s : %v", secretName, err) return nil, err } // Secret not found create a new one secret = resources.NewMySQLNDBOperatorPasswordSecret(nc) secret, err = mups.secretInterface(nc.Namespace).Create(ctx, secret, metav1.CreateOptions{}) if err != nil { klog.Errorf("Failed to create secret %s : %v", secretName, err) } klog.Errorf("successfully created secret %s", secretName) return secret, err }