Skip to content

Commit

Permalink
simplify implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nakamasato committed Aug 21, 2022
1 parent 662cba9 commit b5fa53c
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 211 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ IMG ?= ghcr.io/nakamasato/mysql-operator:latest
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false"
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.21
ENVTEST_K8S_VERSION = 1.24

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ limitations under the License.
*/

// Package v1alpha1 contains API Schema definitions for the mysql v1alpha1 API group
//+kubebuilder:object:generate=true
//+groupName=mysql.nakamasato.com
// +kubebuilder:object:generate=true
// +groupName=mysql.nakamasato.com
package v1alpha1

import (
Expand Down
5 changes: 2 additions & 3 deletions controllers/mysql_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

"github.com/go-logr/logr"
mysqlv1alpha1 "github.com/nakamasato/mysql-operator/api/v1alpha1"
)

Expand Down Expand Up @@ -67,7 +66,7 @@ func (r *MySQLReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
}

// Get referenced number
referencedNum, err := r.countReferencesByMySQLUser(ctx, log, mysql)
referencedNum, err := r.countReferencesByMySQLUser(ctx, mysql)
if err != nil {
log.Error(err, "[countReferences] Failed get referencedNum")
return ctrl.Result{}, err
Expand Down Expand Up @@ -96,7 +95,7 @@ func (r *MySQLReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

func (r *MySQLReconciler) countReferencesByMySQLUser(ctx context.Context, log logr.Logger, mysql *mysqlv1alpha1.MySQL) (int, error) {
func (r *MySQLReconciler) countReferencesByMySQLUser(ctx context.Context, mysql *mysqlv1alpha1.MySQL) (int, error) {
// 1. Get the referenced MySQLUser instances.
// 2. Return the number of referencing MySQLUser.
mysqlUserList := &mysqlv1alpha1.MySQLUserList{}
Expand Down
60 changes: 30 additions & 30 deletions controllers/mysqluser_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"context"
"strings"

"github.com/redhat-cop/operator-utils/pkg/util"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -31,7 +30,6 @@ import (

"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

"github.com/go-logr/logr"
_ "github.com/go-sql-driver/mysql"

mysqlv1alpha1 "github.com/nakamasato/mysql-operator/api/v1alpha1"
Expand All @@ -51,8 +49,7 @@ const (

// MySQLUserReconciler reconciles a MySQLUser object
type MySQLUserReconciler struct {
util.ReconcilerBase
Log logr.Logger
client.Client
Scheme *runtime.Scheme
MySQLClientFactory mysqlinternal.MySQLClientFactory
}
Expand All @@ -77,7 +74,7 @@ func (r *MySQLUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (

// Fetch MySQLUser
mysqlUser := &mysqlv1alpha1.MySQLUser{}
err := r.GetClient().Get(ctx, req.NamespacedName, mysqlUser)
err := r.Get(ctx, req.NamespacedName, mysqlUser)
if err != nil {
if errors.IsNotFound(err) {
log.Info("[FetchMySQLUser] Not found", "req.NamespacedName", req.NamespacedName)
Expand All @@ -94,24 +91,23 @@ func (r *MySQLUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// Fetch MySQL
mysql := &mysqlv1alpha1.MySQL{}
var mysqlNamespacedName = client.ObjectKey{Namespace: req.Namespace, Name: mysqlUser.Spec.MysqlName}
if err := r.GetClient().Get(ctx, mysqlNamespacedName, mysql); err != nil {
if err := r.Get(ctx, mysqlNamespacedName, mysql); err != nil {
log.Error(err, "[FetchMySQL] Failed")
mysqlUser.Status.Phase = mysqlUserPhaseNotReady
mysqlUser.Status.Reason = mysqlUserReasonMySQLFetchFailed
// return ctrl.Result{}, client.IgnoreNotFound(err)
return r.ManageError(ctx, mysqlUser, err)
return ctrl.Result{}, client.IgnoreNotFound(err)
}
log.Info("[FetchMySQL] Found")

// SetOwnerReference if not exists
if !r.ifOwnerReferencesContains(mysqlUser.ObjectMeta.OwnerReferences, mysql) {
err := controllerutil.SetControllerReference(mysql, mysqlUser, r.Scheme)
if err != nil {
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err //requeue
}
err = r.GetClient().Update(ctx, mysqlUser)
err = r.Update(ctx, mysqlUser)
if err != nil {
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err //requeue
}
}

Expand All @@ -125,16 +121,18 @@ func (r *MySQLUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
if err != nil {
mysqlUser.Status.Phase = mysqlUserPhaseNotReady
mysqlUser.Status.Reason = mysqlUserReasonMySQLConnectionFailed
r.Status().Update(ctx, mysqlUser)
log.Error(err, "[MySQLClient] Failed to create")
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
log.Info("[MySQLClient] Ping")
err = mysqlClient.Ping()
if err != nil {
mysqlUser.Status.Phase = mysqlUserPhaseNotReady
mysqlUser.Status.Reason = mysqlUserReasonMySQLConnectionFailed
log.Error(err, "[MySQLClient] Failed to connect to MySQL", "mysqlName", mysqlName)
return r.ManageError(ctx, mysqlUser, err) // requeue
r.Status().Update(ctx, mysqlUser)
return ctrl.Result{}, err // requeue
}
log.Info("[MySQLClient] Successfully connected")
defer mysqlClient.Close()
Expand All @@ -146,45 +144,44 @@ func (r *MySQLUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// Run finalization logic for mysqlUserFinalizer. If the
// finalization logic fails, don't remove the finalizer so
// that we can retry during the next reconciliation.
if err := r.finalizeMySQLUser(log, mysqlUser, mysql); err != nil {
if err := r.finalizeMySQLUser(ctx, mysqlUser, mysql); err != nil {
// return ctrl.Result{}, err
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
// Remove mysqlUserFinalizer. Once all finalizers have been
// removed, the object will be deleted.
controllerutil.RemoveFinalizer(mysqlUser, mysqlUserFinalizer)
err := r.GetClient().Update(ctx, mysqlUser)
err := r.Update(ctx, mysqlUser)
if err != nil {
// return ctrl.Result{}, err
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
return ctrl.Result{}, nil
}
// return ctrl.Result{}, err
return r.ManageSuccess(ctx, mysqlUser) // should return success when not having the finalizer
return ctrl.Result{}, nil // should return success when not having the finalizer
}

// Add finalizer for this CR
if !controllerutil.ContainsFinalizer(mysqlUser, mysqlUserFinalizer) {
controllerutil.AddFinalizer(mysqlUser, mysqlUserFinalizer)
err = r.GetClient().Update(ctx, mysqlUser)
err = r.Update(ctx, mysqlUser)
if err != nil {
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
}

// Get password from Secret if exists. Otherwise, generate new one.
secretName := getSecretName(mysqlName, mysqlUserName)
secret := &v1.Secret{}
err = r.GetClient().Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: secretName}, secret)
err = r.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: secretName}, secret)
var password string
if err != nil {
if errors.IsNotFound(err) { // Secret doesn't exists -> generate password
log.Info("[password] Generate new password for Secret", "secretName", secretName)
password = utils.GenerateRandomString(16)
} else {
log.Error(err, "[password] Failed to get Secret", "secretName", secretName)
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
} else { // exists -> get password from Secret
password = string(secret.Data["password"])
Expand All @@ -194,22 +191,23 @@ func (r *MySQLUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
err = mysqlClient.Exec("CREATE USER IF NOT EXISTS '" + mysqlUserName + "'@'" + mysqlUser.Spec.Host + "' IDENTIFIED BY '" + password + "';")
if err != nil {
log.Error(err, "[MySQL] Failed to create MySQL user.", "mysqlName", mysqlName, "mysqlUserName", mysqlUserName)
return r.ManageError(ctx, mysqlUser, err) // requeue
return ctrl.Result{}, err // requeue
}
log.Info("[MySQL] Created or updated", "name", mysqlUserName, "mysqlUser.Namespace", mysqlUser.Namespace)
metrics.MysqlUserCreatedTotal.Increment()
mysqlUser.Status.Phase = mysqlUserPhaseReady
mysqlUser.Status.Reason = "mysql user are successfully created. Secret is being created."

err = r.createSecret(ctx, log, password, secretName, mysqlUser.Namespace, mysqlUser)
err = r.createSecret(ctx, password, secretName, mysqlUser.Namespace, mysqlUser)
// TODO: #35 add test if mysql user is successfully created but secret is failed to create
if err != nil {
return r.ManageError(ctx, mysqlUser, err)
return ctrl.Result{}, err
}
mysqlUser.Status.Phase = mysqlUserPhaseReady
mysqlUser.Status.Reason = mysqlUserReasonCompleted
r.Status().Update(ctx, mysqlUser)

return r.ManageSuccess(ctx, mysqlUser)
return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
Expand All @@ -219,10 +217,11 @@ func (r *MySQLUserReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

func (r *MySQLUserReconciler) finalizeMySQLUser(log logr.Logger, mysqlUser *mysqlv1alpha1.MySQLUser, mysql *mysqlv1alpha1.MySQL) error {
func (r *MySQLUserReconciler) finalizeMySQLUser(ctx context.Context, mysqlUser *mysqlv1alpha1.MySQLUser, mysql *mysqlv1alpha1.MySQL) error {
// 1. Get the referenced MySQL instance.
// 2. Connect to MySQL.
// 3. Delete the MySQL user.
log := log.FromContext(ctx)

cfg := mysqlinternal.MySQLConfig{
AdminUser: mysql.Spec.AdminUser,
Expand Down Expand Up @@ -256,7 +255,8 @@ func getSecretName(mysqlName string, mysqlUserName string) string {
return strings.Join(str, "-")
}

func (r *MySQLUserReconciler) createSecret(ctx context.Context, log logr.Logger, password string, secretName string, namespace string, mysqlUser *mysqlv1alpha1.MySQLUser) error {
func (r *MySQLUserReconciler) createSecret(ctx context.Context, password string, secretName string, namespace string, mysqlUser *mysqlv1alpha1.MySQLUser) error {
log := log.FromContext(ctx)
data := make(map[string][]byte)
data["password"] = []byte(password)
secret := &v1.Secret{
Expand All @@ -270,7 +270,7 @@ func (r *MySQLUserReconciler) createSecret(ctx context.Context, log logr.Logger,
log.Error(err, "Failed to SetControllerReference for Secret.")
return err
}
if _, err := ctrl.CreateOrUpdate(ctx, r.GetClient(), secret, func() error {
if _, err := ctrl.CreateOrUpdate(ctx, r.Client, secret, func() error {
secret.Data = data
log.Info("Successfully created Secret.")
return nil
Expand Down
19 changes: 2 additions & 17 deletions controllers/mysqluser_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"time"

. "github.com/onsi/ginkgo"
"github.com/redhat-cop/operator-utils/pkg/util"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand All @@ -32,14 +31,7 @@ var _ = Describe("MySQLUser controller", func() {
Expect(err).ToNot(HaveOccurred())

err = (&MySQLUserReconciler{
ReconcilerBase: util.NewReconcilerBase(
k8sManager.GetClient(),
k8sManager.GetScheme(),
k8sManager.GetConfig(),
k8sManager.GetEventRecorderFor("mysqluser_controller"),
k8sManager.GetAPIReader(),
),
Log: nil,
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
MySQLClientFactory: NewFakeMySQLClient,
}).SetupWithManager(k8sManager)
Expand Down Expand Up @@ -191,14 +183,7 @@ var _ = Describe("MySQLUser controller", func() {
Expect(err).ToNot(HaveOccurred())

err = (&MySQLUserReconciler{
ReconcilerBase: util.NewReconcilerBase(
k8sManager.GetClient(),
k8sManager.GetScheme(),
k8sManager.GetConfig(),
k8sManager.GetEventRecorderFor("mysqluser_controller"),
k8sManager.GetAPIReader(),
),
Log: nil,
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
MySQLClientFactory: NewMySQLClient, // real mysql client
}).SetupWithManager(k8sManager)
Expand Down
10 changes: 0 additions & 10 deletions e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)

const (
Expand Down Expand Up @@ -352,15 +351,6 @@ func newMySQLDeployment() *appsv1.Deployment {
Value: "password",
},
},
ReadinessProbe: &corev1.Probe{
Handler: corev1.Handler{
TCPSocket: &corev1.TCPSocketAction{
Port: intstr.FromInt(3306),
},
},
InitialDelaySeconds: 5,
PeriodSeconds: 10,
},
}},
},
},
Expand Down
26 changes: 7 additions & 19 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ module github.com/nakamasato/mysql-operator
go 1.18

require (
github.com/go-logr/logr v1.2.0
github.com/go-sql-driver/mysql v1.6.0
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.20.0
github.com/prometheus/client_golang v1.13.0
github.com/redhat-cop/operator-utils v1.3.3
k8s.io/api v0.24.3
k8s.io/apimachinery v0.24.3
k8s.io/client-go v0.24.3
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
sigs.k8s.io/controller-runtime v0.10.0
sigs.k8s.io/controller-runtime v0.12.3
)

require (
Expand All @@ -24,10 +22,6 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/BurntSushi/toml v0.4.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/beorn7/perks v1.0.1 // indirect
Expand All @@ -36,8 +30,9 @@ require (
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/zapr v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/go-logr/logr v1.2.0 // indirect
github.com/go-logr/zapr v1.2.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
Expand All @@ -48,15 +43,11 @@ require (
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/huandu/xstrings v1.3.1 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
Expand All @@ -65,12 +56,10 @@ require (
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.0 // indirect
go.uber.org/zap v1.19.1 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
Expand All @@ -85,11 +74,10 @@ require (
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.22.1 // indirect
k8s.io/component-base v0.22.3 // indirect
k8s.io/apiextensions-apiserver v0.24.2 // indirect
k8s.io/component-base v0.24.2 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
k8s.io/kubectl v0.22.3 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
Expand Down
Loading

0 comments on commit b5fa53c

Please sign in to comment.