diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 224c4fb..b211bdb 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -4,6 +4,13 @@ kind: ClusterRole metadata: name: manager-role rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - crd.lagoon.sh resources: diff --git a/internal/controller/databasemongodbprovider_controller.go b/internal/controller/databasemongodbprovider_controller.go index 6800181..b16a6d6 100644 --- a/internal/controller/databasemongodbprovider_controller.go +++ b/internal/controller/databasemongodbprovider_controller.go @@ -20,6 +20,7 @@ import ( "context" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -30,9 +31,11 @@ import ( // DatabaseMongoDBProviderReconciler reconciles a DatabaseMongoDBProvider object type DatabaseMongoDBProviderReconciler struct { client.Client - Scheme *runtime.Scheme + Scheme *runtime.Scheme + Recoder record.EventRecorder } +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemongodbproviders,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemongodbproviders/status,verbs=get;update;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemongodbproviders/finalizers,verbs=update @@ -56,6 +59,7 @@ func (r *DatabaseMongoDBProviderReconciler) Reconcile(ctx context.Context, req c // SetupWithManager sets up the controller with the Manager. func (r *DatabaseMongoDBProviderReconciler) SetupWithManager(mgr ctrl.Manager) error { + r.Recoder = mgr.GetEventRecorderFor("databasemongodbprovider_controller") return ctrl.NewControllerManagedBy(mgr). For(&crdv1alpha1.DatabaseMongoDBProvider{}). Complete(r) diff --git a/internal/controller/databasemongodbprovider_controller_test.go b/internal/controller/databasemongodbprovider_controller_test.go index dc2a490..7bf93a5 100644 --- a/internal/controller/databasemongodbprovider_controller_test.go +++ b/internal/controller/databasemongodbprovider_controller_test.go @@ -24,6 +24,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/reconcile" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -106,9 +107,11 @@ var _ = Describe("DatabaseMongoDBProvider Controller", func() { }) It("should successfully reconcile the resource", func() { By("Reconciling the created resource") + fakeRecorder := record.NewFakeRecorder(1) controllerReconciler := &DatabaseMongoDBProviderReconciler{ - Client: k8sClient, - Scheme: k8sClient.Scheme(), + Client: k8sClient, + Scheme: k8sClient.Scheme(), + Recoder: fakeRecorder, } _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ diff --git a/internal/controller/databasemysqlprovider_controller.go b/internal/controller/databasemysqlprovider_controller.go index 2fe51b7..0c5571c 100644 --- a/internal/controller/databasemysqlprovider_controller.go +++ b/internal/controller/databasemysqlprovider_controller.go @@ -34,7 +34,7 @@ import ( "github.com/prometheus/client_golang/prometheus" crdv1alpha1 "github.com/uselagoon/dbaas-controller/api/v1alpha1" - "github.com/uselagoon/dbaas-controller/internal/mysql" + "github.com/uselagoon/dbaas-controller/internal/database/mysql" ) const databaseMySQLProviderFinalizer = "databasemysqlprovider.crd.lagoon.sh/finalizer" @@ -81,10 +81,12 @@ var ( // DatabaseMySQLProviderReconciler reconciles a DatabaseMySQLProvider object type DatabaseMySQLProviderReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder + Scheme *runtime.Scheme + Recorder record.EventRecorder + MySQLClient mysql.MySQLInterface } +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemysqlproviders,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemysqlproviders/status,verbs=get;update;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasemysqlproviders/finalizers,verbs=update @@ -174,10 +176,10 @@ func (r *DatabaseMySQLProviderReconciler) Reconcile(ctx context.Context, req ctr for _, conn := range mySQLConns { // make a ping to the database to check if it's up and running and we can connect to it // if not, we should return an error and set the status to 0 - if err := mysql.Ping(ctx, conn.getDSN()); err != nil { + if err := r.MySQLClient.Ping(ctx, conn.getDSN()); err != nil { return r.handleError(ctx, instance, "db-ping", err) } - version, err := mysql.Version(ctx, conn.getDSN()) + version, err := r.MySQLClient.Version(ctx, conn.getDSN()) if err != nil { return r.handleError(ctx, instance, "db-version", err) } diff --git a/internal/controller/databasemysqlprovider_controller_test.go b/internal/controller/databasemysqlprovider_controller_test.go index a9d1ee6..6baf48a 100644 --- a/internal/controller/databasemysqlprovider_controller_test.go +++ b/internal/controller/databasemysqlprovider_controller_test.go @@ -24,11 +24,13 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/reconcile" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" crdv1alpha1 "github.com/uselagoon/dbaas-controller/api/v1alpha1" + "github.com/uselagoon/dbaas-controller/internal/database/mysql" ) var _ = Describe("DatabaseMySQLProvider Controller", func() { @@ -105,9 +107,12 @@ var _ = Describe("DatabaseMySQLProvider Controller", func() { }) It("should successfully reconcile the resource", func() { By("Reconciling the created resource") + fakeRecorder := record.NewFakeRecorder(1) controllerReconciler := &DatabaseMySQLProviderReconciler{ - Client: k8sClient, - Scheme: k8sClient.Scheme(), + Client: k8sClient, + Scheme: k8sClient.Scheme(), + Recorder: fakeRecorder, + MySQLClient: &mysql.MockMySQLer{}, } _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ diff --git a/internal/controller/databasepostgresqlprovider_controller.go b/internal/controller/databasepostgresqlprovider_controller.go index 38a1fac..8b58d24 100644 --- a/internal/controller/databasepostgresqlprovider_controller.go +++ b/internal/controller/databasepostgresqlprovider_controller.go @@ -20,6 +20,7 @@ import ( "context" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" @@ -30,9 +31,11 @@ import ( // DatabasePostgreSQLProviderReconciler reconciles a DatabasePostgreSQLProvider object type DatabasePostgreSQLProviderReconciler struct { client.Client - Scheme *runtime.Scheme + Scheme *runtime.Scheme + Recorder record.EventRecorder } +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasepostgresqlproviders,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasepostgresqlproviders/status,verbs=get;update;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databasepostgresqlproviders/finalizers,verbs=update @@ -56,6 +59,7 @@ func (r *DatabasePostgreSQLProviderReconciler) Reconcile(ctx context.Context, re // SetupWithManager sets up the controller with the Manager. func (r *DatabasePostgreSQLProviderReconciler) SetupWithManager(mgr ctrl.Manager) error { + r.Recorder = mgr.GetEventRecorderFor("databasepostgresqlprovider_controller") return ctrl.NewControllerManagedBy(mgr). For(&crdv1alpha1.DatabasePostgreSQLProvider{}). Complete(r) diff --git a/internal/controller/databasepostgresqlprovider_controller_test.go b/internal/controller/databasepostgresqlprovider_controller_test.go index dd14c24..6ef1bb4 100644 --- a/internal/controller/databasepostgresqlprovider_controller_test.go +++ b/internal/controller/databasepostgresqlprovider_controller_test.go @@ -24,6 +24,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/reconcile" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -104,9 +105,11 @@ var _ = Describe("DatabasePostgreSQLProvider Controller", func() { }) It("should successfully reconcile the resource", func() { By("Reconciling the created resource") + fakeRecorder := record.NewFakeRecorder(1) controllerReconciler := &DatabasePostgreSQLProviderReconciler{ - Client: k8sClient, - Scheme: k8sClient.Scheme(), + Client: k8sClient, + Scheme: k8sClient.Scheme(), + Recorder: fakeRecorder, } _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ diff --git a/internal/controller/databaserequest_controller.go b/internal/controller/databaserequest_controller.go index 7ab8ae2..3eee625 100644 --- a/internal/controller/databaserequest_controller.go +++ b/internal/controller/databaserequest_controller.go @@ -75,6 +75,7 @@ type DatabaseRequestReconciler struct { Recorder record.EventRecorder } +//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databaserequests,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databaserequests/status,verbs=get;update;patch //+kubebuilder:rbac:groups=crd.lagoon.sh,resources=databaserequests/finalizers,verbs=update @@ -83,7 +84,7 @@ type DatabaseRequestReconciler struct { func (r *DatabaseRequestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { logger := log.FromContext(ctx).WithName("databaserequest_controller") logger.Info("Reconciling DatabaseRequest") - promDatabaseRequestReconcileCounter.WithLabelValues(req.Name, req.Namespace, "reconciled").Inc() + promDatabaseRequestReconcileCounter.WithLabelValues(req.Name, req.Namespace).Inc() databaseRequest := &crdv1alpha1.DatabaseRequest{} if err := r.Get(ctx, req.NamespacedName, databaseRequest); err != nil { diff --git a/internal/controller/databaserequest_controller_test.go b/internal/controller/databaserequest_controller_test.go index b2a6bb2..9885a18 100644 --- a/internal/controller/databaserequest_controller_test.go +++ b/internal/controller/databaserequest_controller_test.go @@ -23,6 +23,7 @@ import ( . "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/reconcile" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -71,9 +72,11 @@ var _ = Describe("DatabaseRequest Controller", func() { }) It("should successfully reconcile the resource", func() { By("Reconciling the created resource") + fakeRecoder := record.NewFakeRecorder(1) controllerReconciler := &DatabaseRequestReconciler{ - Client: k8sClient, - Scheme: k8sClient.Scheme(), + Client: k8sClient, + Scheme: k8sClient.Scheme(), + Recorder: fakeRecoder, } _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ diff --git a/internal/database/mysql/mock.go b/internal/database/mysql/mock.go new file mode 100644 index 0000000..8235b31 --- /dev/null +++ b/internal/database/mysql/mock.go @@ -0,0 +1,19 @@ +package mysql + +import "context" + +var _ MySQLInterface = (*MockMySQLer)(nil) + +type MockMySQLer struct{} + +func (mi *MockMySQLer) Ping(ctx context.Context, dsn string) error { + return nil +} + +func (mi *MockMySQLer) Version(ctx context.Context, dsn string) (string, error) { + return "5.7.34", nil +} + +func (mi *MockMySQLer) CreateDatabase(ctx context.Context, dsn, databaseName, userName, password string) error { + return nil +} diff --git a/internal/mysql/mysql.go b/internal/database/mysql/mysql.go similarity index 81% rename from internal/mysql/mysql.go rename to internal/database/mysql/mysql.go index 8b69b3d..2098aff 100644 --- a/internal/mysql/mysql.go +++ b/internal/database/mysql/mysql.go @@ -10,8 +10,20 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" ) +// MySQLInterface is the interface for the MySQL database +type MySQLInterface interface { + // Ping pings the MySQL database + Ping(ctx context.Context, dsn string) error + // Version returns the version of the MySQL database + Version(ctx context.Context, dsn string) (string, error) + // CreateDatabase creates a database in the MySQL database if it does not exist. + CreateDatabase(ctx context.Context, dsn, databaseName, userName, password string) error +} + +type MySQLerImpl struct{} + // Ping pings the MySQL database -func Ping(ctx context.Context, dsn string) error { +func (mi *MySQLerImpl) Ping(ctx context.Context, dsn string) error { log.FromContext(ctx).Info("Pinging MySQL database") db, err := sql.Open("mysql", dsn) if err != nil { @@ -27,7 +39,7 @@ func Ping(ctx context.Context, dsn string) error { } // Version returns the version of the MySQL database -func Version(ctx context.Context, dsn string) (string, error) { +func (mi *MySQLerImpl) Version(ctx context.Context, dsn string) (string, error) { log.FromContext(ctx).Info("Getting MySQL database version") db, err := sql.Open("mysql", dsn) if err != nil { @@ -47,7 +59,7 @@ func Version(ctx context.Context, dsn string) (string, error) { // CreateDatabase creates a database in the MySQL database if it does not exist. // It also creates a user and grants the user permissions on the database. // This function is idempotent and can be called multiple times without side effects. -func CreateDatabase(ctx context.Context, dsn, databaseName, userName, password string) error { +func (mi *MySQLerImpl) CreateDatabase(ctx context.Context, dsn, databaseName, userName, password string) error { log.FromContext(ctx).Info("Creating MySQL database") // Connect to the database server db, err := sql.Open("mysql", dsn)