From e8ecfb877ab222b1490b58164febf646a1ef1229 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 11 Oct 2019 14:54:26 +1100 Subject: [PATCH 01/27] add tests for controller with mock --- api/v1/sqldatabase_types.go | 1 - api/v1/sqlserver_types.go | 1 - controllers/sqlaction_controller.go | 11 +- controllers/sqldatabase_controller.go | 37 +++-- controllers/sqldatabase_controller_test.go | 132 ++++++++++++++++++ controllers/sqlfirewallrule_controller.go | 15 +- controllers/sqlserver_controller.go | 29 ++-- controllers/sqlserver_controller_test.go | 119 ++++++++++++++++ controllers/suite_test.go | 28 +++- main.go | 38 ++--- .../sqlclient/endtoend_test.go | 15 +- .../sqlclient/sqlclient_godsk.go | 96 ++++++------- .../sqlclient/sqlclient_gosdk_mock.go | 115 +++++++++++++++ .../sqlclient/sqlclient_manager.go | 26 ++++ 14 files changed, 550 insertions(+), 113 deletions(-) create mode 100644 controllers/sqldatabase_controller_test.go create mode 100644 controllers/sqlserver_controller_test.go create mode 100644 pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go create mode 100644 pkg/resourcemanager/sqlclient/sqlclient_manager.go diff --git a/api/v1/sqldatabase_types.go b/api/v1/sqldatabase_types.go index 19ce0cdaf88..85a430b9c96 100644 --- a/api/v1/sqldatabase_types.go +++ b/api/v1/sqldatabase_types.go @@ -41,7 +41,6 @@ type SqlDatabaseStatus struct { } // +kubebuilder:object:root=true -// +kubebuilder:subresource:status // SqlDatabase is the Schema for the sqldatabases API type SqlDatabase struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1/sqlserver_types.go b/api/v1/sqlserver_types.go index 586840a19ad..fb277dff24f 100644 --- a/api/v1/sqlserver_types.go +++ b/api/v1/sqlserver_types.go @@ -41,7 +41,6 @@ type SqlServerStatus struct { } // +kubebuilder:object:root=true -// +kubebuilder:subresource:status // SqlServer is the Schema for the sqlservers API type SqlServer struct { metav1.TypeMeta `json:",inline"` diff --git a/controllers/sqlaction_controller.go b/controllers/sqlaction_controller.go index 4d187038610..101e4e5af9a 100644 --- a/controllers/sqlaction_controller.go +++ b/controllers/sqlaction_controller.go @@ -46,9 +46,10 @@ const sqlActionFinalizerName = "sqlaction.finalizers.azure.com" // SqlActionReconciler reconciles a SqlAction object type SqlActionReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + SQLManager sql.SQLManager } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=sqlactions,verbs=get;list;watch;create;update;patch;delete @@ -126,7 +127,7 @@ func (r *SqlActionReconciler) reconcileExternal(instance *azurev1.SqlAction) err } // Get the Sql Server instance that corresponds to the Server name in the spec for this action - server, err := sdkClient.GetServer() + server, err := r.SQLManager.GetServer(sdkClient) if err != nil { if strings.Contains(err.Error(), "ResourceGroupNotFound") { r.Recorder.Event(instance, "Warning", "Failed", "Unable to get instance of SqlServer: Resource group not found") @@ -162,7 +163,7 @@ func (r *SqlActionReconciler) reconcileExternal(instance *azurev1.SqlAction) err newPassword, _ := generateRandomPassword(passwordLength) sqlServerProperties.AdministratorLoginPassword = to.StringPtr(newPassword) - if _, err := sdkClient.CreateOrUpdateSQLServer(sqlServerProperties); err != nil { + if _, err := r.SQLManager.CreateOrUpdateSQLServer(sdkClient, sqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { r.Recorder.Event(instance, "Warning", "Failed", "Unable to provision or update instance") return errhelp.NewAzureError(err) diff --git a/controllers/sqldatabase_controller.go b/controllers/sqldatabase_controller.go index a68b8440b1b..4e434a61601 100644 --- a/controllers/sqldatabase_controller.go +++ b/controllers/sqldatabase_controller.go @@ -26,12 +26,12 @@ import ( //"github.com/Azure/go-autorest/autorest/to" "github.com/go-logr/logr" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "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/controller/controllerutil" azurev1 "github.com/Azure/azure-service-operator/api/v1" ) @@ -41,9 +41,10 @@ const SQLDatabaseFinalizerName = "sqldatabase.finalizers.azure.com" // SqlDatabaseReconciler reconciles a SqlDatabase object type SqlDatabaseReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + SQLManager sql.SQLManager } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=sqldatabases,verbs=get;list;watch;create;update;patch;delete @@ -150,10 +151,20 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1.SqlDatabase) r.Recorder.Event(instance, "Warning", "Failed", "Unable to get owner instance of SqlServer") } else { r.Recorder.Event(instance, "Normal", "OwnerAssign", "Got owner instance of Sql Server and assigning controller reference now") - innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) - if innerErr != nil { - r.Recorder.Event(instance, "Warning", "Failed", "Unable to set controller reference to SqlServer") + // innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) + + // if innerErr != nil { + // r.Recorder.Event(instance, "Warning", "Failed", "Unable to set controller reference to SqlServer") + // } + references := []metav1.OwnerReference{ + metav1.OwnerReference{ + APIVersion: "v1", + Kind: "SqlServer", + Name: ownerInstance.GetName(), + UID: ownerInstance.GetUID(), + }, } + instance.ObjectMeta.SetOwnerReferences(references) r.Recorder.Event(instance, "Normal", "OwnerAssign", "Owner instance assigned successfully") } @@ -162,12 +173,12 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1.SqlDatabase) r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } - _, err = sdkClient.CreateOrUpdateDB(sqlDatabaseProperties) + _, err = r.SQLManager.CreateOrUpdateDB(sdkClient, sqlDatabaseProperties) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") instance.Status.Provisioning = true - if errup := r.Status().Update(ctx, instance); errup != nil { + if errup := r.Update(ctx, instance); errup != nil { r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } } @@ -175,7 +186,7 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1.SqlDatabase) return errhelp.NewAzureError(err) } - _, err = sdkClient.GetDB(dbName) + _, err = r.SQLManager.GetDB(sdkClient, dbName) if err != nil { return errhelp.NewAzureError(err) } @@ -183,7 +194,7 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1.SqlDatabase) instance.Status.Provisioning = false instance.Status.Provisioned = true - if err = r.Status().Update(ctx, instance); err != nil { + if err = r.Update(ctx, instance); err != nil { r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } @@ -198,7 +209,7 @@ func (r *SqlDatabaseReconciler) deleteExternal(instance *azurev1.SqlDatabase) er dbName := instance.ObjectMeta.Name // create the Go SDK client with relevant info - sdk := sql.GoSDKClient{ + sdkClient := sql.GoSDKClient{ Ctx: ctx, ResourceGroupName: groupName, ServerName: server, @@ -206,7 +217,7 @@ func (r *SqlDatabaseReconciler) deleteExternal(instance *azurev1.SqlDatabase) er } r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/database/%s"+groupName, server, dbName)) - _, err := sdk.DeleteDB(dbName) + _, err := r.SQLManager.DeleteDB(sdkClient, dbName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, "Warning", "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/sqldatabase_controller_test.go b/controllers/sqldatabase_controller_test.go new file mode 100644 index 00000000000..419cdf4d2fc --- /dev/null +++ b/controllers/sqldatabase_controller_test.go @@ -0,0 +1,132 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + "fmt" + "strings" + "time" + + azurev1 "github.com/Azure/azure-service-operator/api/v1" + + helpers "github.com/Azure/azure-service-operator/pkg/helpers" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("SqlDatabase Controller", func() { + + const timeout = time.Second * 240 + var rgName string + var rgLocation string + var sqlName string + + BeforeEach(func() { + // Add any setup steps that needs to be executed before each test + rgName = tc.resourceGroupName + rgLocation = tc.resourceGroupLocation + }) + + AfterEach(func() { + // Add any teardown steps that needs to be executed after each test + }) + + // Add Tests for OpenAPI validation (or additonal CRD features) specified in + // your API definition. + // Avoid adding tests for vanilla CRUD operations because they would + // test Kubernetes API server, which isn't the goal here. + + Context("Create and Delete", func() { + It("should create and delete sql database in k8s", func() { + + sqlServerName := "t-sqlserver-dev-" + helpers.RandomString(10) + sqlDatabaseName := "t-sqldatabase-dev-" + helpers.RandomString(10) + + var err error + + // Create the SqlServer object and expect the Reconcile to be created + sqlServerInstance := &azurev1.SqlServer{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlServerName, + Namespace: "default", + }, + Spec: azurev1.SqlServerSpec{ + Location: rgLocation, + ResourceGroup: rgName, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlServerInstance) + Expect(err).NotTo(HaveOccurred()) + + // Create the SqlDatabase object and expect the Reconcile to be created + sqlDatabaseInstance := &azurev1.SqlDatabase{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlDatabaseName, + Namespace: "default", + }, + Spec: azurev1.SqlDatabaseSpec{ + Location: rgLocation, + ResourceGroup: rgName, + Server: sqlName, + Edition: 0, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlDatabaseInstance) + Expect(apierrors.IsInvalid(err)).To(Equal(false)) + Expect(err).NotTo(HaveOccurred()) + + sqlDatabaseNamespacedName := types.NamespacedName{Name: sqlDatabaseName, Namespace: "default"} + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return helpers.HasFinalizer(sqlDatabaseInstance, SQLDatabaseFinalizerName) + }, timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return sqlDatabaseInstance.IsSubmitted() + }, timeout, + ).Should(BeTrue()) + + err = tc.k8sClient.Delete(context.Background(), sqlDatabaseInstance) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return helpers.IsBeingDeleted(sqlDatabaseInstance) + }, timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + err := tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + if err == nil { + err = fmt.Errorf("") + } + return strings.Contains(err.Error(), "not found") + }, timeout, + ).Should(BeTrue()) + + }) + }) +}) diff --git a/controllers/sqlfirewallrule_controller.go b/controllers/sqlfirewallrule_controller.go index 3f421a1304f..b85c15278ad 100644 --- a/controllers/sqlfirewallrule_controller.go +++ b/controllers/sqlfirewallrule_controller.go @@ -39,9 +39,10 @@ const SQLFirewallRuleFinalizerName = "sqlfirewallrule.finalizers.azure.com" // SqlFirewallRuleReconciler reconciles a SqlFirewallRule object type SqlFirewallRuleReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + SQLManager sql.SQLManager } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=sqlfirewallrules,verbs=get;list;watch;create;update;patch;delete @@ -154,7 +155,7 @@ func (r *SqlFirewallRuleReconciler) reconcileExternal(instance *azurev1.SqlFirew r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } - _, err = sdkClient.CreateOrUpdateSQLFirewallRule(ruleName, startIP, endIP) + _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(sdkClient, ruleName, startIP, endIP) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -167,7 +168,7 @@ func (r *SqlFirewallRuleReconciler) reconcileExternal(instance *azurev1.SqlFirew return errhelp.NewAzureError(err) } - _, err = sdkClient.GetSQLFirewallRule(ruleName) + _, err = r.SQLManager.GetSQLFirewallRule(sdkClient, ruleName) if err != nil { return errhelp.NewAzureError(err) } @@ -189,14 +190,14 @@ func (r *SqlFirewallRuleReconciler) deleteExternal(instance *azurev1.SqlFirewall ruleName := instance.ObjectMeta.Name // create the Go SDK client with relevant info - sdk := sql.GoSDKClient{ + sdkClient := sql.GoSDKClient{ Ctx: ctx, ResourceGroupName: groupName, ServerName: server, } r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/firewallrule/%s"+groupName, server, ruleName)) - err := sdk.DeleteSQLFirewallRule(ruleName) + err := r.SQLManager.DeleteSQLFirewallRule(sdkClient, ruleName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, "Warning", "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/sqlserver_controller.go b/controllers/sqlserver_controller.go index 59920312be8..93942a4e468 100644 --- a/controllers/sqlserver_controller.go +++ b/controllers/sqlserver_controller.go @@ -43,9 +43,10 @@ import ( // SqlServerReconciler reconciles a SqlServer object type SqlServerReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + SQLManager sql.SQLManager } // Constants @@ -203,12 +204,12 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1.SqlServer) err // create the sql server instance.Status.Provisioning = true - if _, err := sdkClient.CreateOrUpdateSQLServer(sqlServerProperties); err != nil { + if _, err := r.SQLManager.CreateOrUpdateSQLServer(sdkClient, sqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { instance.Status.Message = fmt.Sprintf("CreateOrUpdateSQLServer not complete: %v", err) // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } @@ -220,17 +221,17 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1.SqlServer) err instance.Status.Message = "Successfully Submitted to Azure" // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } } _, createOrUpdateSecretErr := controllerutil.CreateOrUpdate(context.Background(), r.Client, secret, func() error { - r.Log.Info("Creating or updating secret with SQL Server credentials") - innerErr := controllerutil.SetControllerReference(instance, secret, r.Scheme) - if innerErr != nil { - return innerErr - } + r.Log.Info("mutating secret bundle") + // innerErr := controllerutil.SetControllerReference(instance, secret, r.Scheme) + // if innerErr != nil { + // return innerErr + // } return nil }) if createOrUpdateSecretErr != nil { @@ -238,7 +239,7 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1.SqlServer) err } // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, "Warning", "Failed", "Unable to update instance") } @@ -258,7 +259,7 @@ func (r *SqlServerReconciler) verifyExternal(instance *azurev1.SqlServer) error Location: location, } - serv, err := sdkClient.GetServer() + serv, err := r.SQLManager.GetServer(sdkClient) if err != nil { azerr := errhelp.NewAzureError(err).(*errhelp.AzureError) if azerr.Type != errhelp.ResourceNotFound { @@ -300,7 +301,7 @@ func (r *SqlServerReconciler) deleteExternal(instance *azurev1.SqlServer) error Location: location, } - _, err := sdkClient.DeleteSQLServer() + _, err := r.SQLManager.DeleteSQLServer(sdkClient) if err != nil { instance.Status.Message = fmt.Sprintf("Couldn't delete resource in Azure: %v", err) r.Recorder.Event(instance, "Warning", "Failed", "Couldn't delete resouce in azure") diff --git a/controllers/sqlserver_controller_test.go b/controllers/sqlserver_controller_test.go new file mode 100644 index 00000000000..495ebf58ff9 --- /dev/null +++ b/controllers/sqlserver_controller_test.go @@ -0,0 +1,119 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + "fmt" + "strings" + "time" + + azurev1 "github.com/Azure/azure-service-operator/api/v1" + + helpers "github.com/Azure/azure-service-operator/pkg/helpers" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("SqlServer Controller", func() { + + const timeout = time.Second * 240 + var rgName string + var rgLocation string + + BeforeEach(func() { + // Add any setup steps that needs to be executed before each test + rgName = tc.resourceGroupName + rgLocation = tc.resourceGroupLocation + }) + + AfterEach(func() { + // Add any teardown steps that needs to be executed after each test + }) + + // Add Tests for OpenAPI validation (or additonal CRD features) specified in + // your API definition. + // Avoid adding tests for vanilla CRUD operations because they would + // test Kubernetes API server, which isn't the goal here. + + Context("Create and Delete", func() { + It("should create and delete sql server in k8s", func() { + sqlServerName := "t-sqlserver-dev-" + helpers.RandomString(10) + + var err error + + // Create the SqlServer object and expect the Reconcile to be created + sqlServerInstance := &azurev1.SqlServer{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlServerName, + Namespace: "default", + }, + Spec: azurev1.SqlServerSpec{ + Location: rgLocation, + ResourceGroup: rgName, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlServerInstance) + Expect(apierrors.IsInvalid(err)).To(Equal(false)) + Expect(err).NotTo(HaveOccurred()) + + sqlServerNamespacedName := types.NamespacedName{Name: sqlServerName, Namespace: "default"} + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return helpers.HasFinalizer(sqlServerInstance, SQLServerFinalizerName) + }, timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return sqlServerInstance.IsSubmitted() + }, timeout, + ).Should(BeTrue()) + + //verify secret exists in k8s + // secret := &v1.Secret{} + // err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) + // Expect(err).NotTo(HaveOccurred()) + // Expect(secret.ObjectMeta.Name).To(Equal(sqlServerName)) + // Expect(secret.ObjectMeta.Namespace).To(Equal(sqlServerInstance.Namespace)) + + err = tc.k8sClient.Delete(context.Background(), sqlServerInstance) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return helpers.IsBeingDeleted(sqlServerInstance) + }, timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + err := tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + if err == nil { + err = fmt.Errorf("") + } + return strings.Contains(err.Error(), "not found") + }, timeout, + ).Should(BeTrue()) + + }) + }) +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 39bf07e3393..fed104be320 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -18,14 +18,15 @@ package controllers import ( "context" "fmt" - "github.com/Azure/azure-service-operator/pkg/helpers" - "k8s.io/client-go/rest" "log" "os" "path/filepath" "testing" "time" + "github.com/Azure/azure-service-operator/pkg/helpers" + "k8s.io/client-go/rest" + azurev1 "github.com/Azure/azure-service-operator/api/v1" resourcemanagerconfig "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" resourcemanagereventhub "github.com/Azure/azure-service-operator/pkg/resourcemanager/eventhubs" @@ -37,6 +38,8 @@ import ( resourcegroupsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" resourcemanagerstorages "github.com/Azure/azure-service-operator/pkg/resourcemanager/storages" + resourcemanagersql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -139,17 +142,22 @@ var _ = BeforeSuite(func() { var eventHubManagers resourcemanagereventhub.EventHubManagers var storageManagers resourcemanagerstorages.StorageManagers var keyVaultManager resourcemanagerkeyvaults.KeyVaultManager + var sqlManager resourcemanagersql.SQLManager + //using mock for sql controller tests irrespective of the flag, as the end to end tests cover azure tests and it saves time + sqlManager = &resourcemanagersql.MockSqlManager{} if os.Getenv("TEST_CONTROLLER_WITH_MOCKS") == "false" { resourceGroupManager = resourcegroupsresourcemanager.AzureResourceGroupManager eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager + //sqlManager = resourcemanagersql.AzureSQLManager timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} + //sqlManager = &resourcemanagersql.MockSqlManager{} timeout = time.Second * 5 } @@ -194,6 +202,22 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + err = (&SqlServerReconciler{ + Client: k8sManager.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlServer"), + Recorder: k8sManager.GetEventRecorderFor("SqlServer-controller"), + SQLManager: sqlManager, + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + err = (&SqlDatabaseReconciler{ + Client: k8sManager.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlDatabase"), + Recorder: k8sManager.GetEventRecorderFor("SqlDatabase-controller"), + SQLManager: sqlManager, + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + go func() { err = k8sManager.Start(ctrl.SetupSignalHandler()) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index ae2751444c0..924619713d9 100644 --- a/main.go +++ b/main.go @@ -28,6 +28,7 @@ import ( resourcemanagereventhub "github.com/Azure/azure-service-operator/pkg/resourcemanager/eventhubs" resourcemanagerkeyvault "github.com/Azure/azure-service-operator/pkg/resourcemanager/keyvaults" resourcemanagerresourcegroup "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" + resourcemanagersql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" resourcemanagerstorage "github.com/Azure/azure-service-operator/pkg/resourcemanager/storages" kscheme "k8s.io/client-go/kubernetes/scheme" @@ -85,6 +86,7 @@ func main() { eventhubManagers := resourcemanagereventhub.AzureEventHubManagers storageManagers := resourcemanagerstorage.AzureStorageManagers keyVaultManager := resourcemanagerkeyvault.AzureKeyVaultManager + sqlManager := resourcemanagersql.AzureSQLManager err = (&controllers.StorageReconciler{ Client: mgr.GetClient(), @@ -173,37 +175,41 @@ func main() { } if err = (&controllers.SqlServerReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlServer"), - Recorder: mgr.GetEventRecorderFor("SqlServer-controller"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlServer"), + Recorder: mgr.GetEventRecorderFor("SqlServer-controller"), + Scheme: mgr.GetScheme(), + SQLManager: sqlManager, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SqlServer") os.Exit(1) } if err = (&controllers.SqlDatabaseReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlDatabase"), - Recorder: mgr.GetEventRecorderFor("SqlDatabase-controller"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlDatabase"), + Recorder: mgr.GetEventRecorderFor("SqlDatabase-controller"), + Scheme: mgr.GetScheme(), + SQLManager: sqlManager, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SqlDatabase") os.Exit(1) } if err = (&controllers.SqlFirewallRuleReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlFirewallRule"), - Recorder: mgr.GetEventRecorderFor("SqlFirewallRule-controller"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlFirewallRule"), + Recorder: mgr.GetEventRecorderFor("SqlFirewallRule-controller"), + Scheme: mgr.GetScheme(), + SQLManager: sqlManager, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SqlFirewallRule") os.Exit(1) } if err = (&controllers.SqlActionReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlAction"), - Recorder: mgr.GetEventRecorderFor("SqlAction-controller"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlAction"), + Recorder: mgr.GetEventRecorderFor("SqlAction-controller"), + Scheme: mgr.GetScheme(), + SQLManager: sqlManager, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SqlAction") os.Exit(1) diff --git a/pkg/resourcemanager/sqlclient/endtoend_test.go b/pkg/resourcemanager/sqlclient/endtoend_test.go index 108ec11b692..b43e6a18edb 100644 --- a/pkg/resourcemanager/sqlclient/endtoend_test.go +++ b/pkg/resourcemanager/sqlclient/endtoend_test.go @@ -35,7 +35,8 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { } // create the Go SDK client with relevant info - sdk := GoSDKClient{ + manager := AzureSQLManager + sdkClient := GoSDKClient{ Ctx: ctx, ResourceGroupName: groupName, ServerName: generateName("sqlsrvtest"), @@ -51,7 +52,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // wait for server to be created, then only proceed once activated for { time.Sleep(time.Second) - server, err := sdk.CreateOrUpdateSQLServer(sqlServerProperties) + server, err := manager.CreateOrUpdateSQLServer(sdkClient, sqlServerProperties) if err == nil { if *server.State == "Ready" { util.PrintAndLog("sql server ready") @@ -81,7 +82,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // wait for db to be created, then only proceed once activated for { time.Sleep(time.Second) - future, err := sdk.CreateOrUpdateDB(sqlDBProperties) + future, err := manager.CreateOrUpdateDB(sdkClient, sqlDBProperties) if err == nil { db, err := future.Result(getGoDbClient()) if err == nil { @@ -107,7 +108,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // create a firewall rule util.PrintAndLog("creating firewall rule...") - _, err = sdk.CreateOrUpdateSQLFirewallRule("test-rule1", "1.1.1.1", "2.2.2.2") + _, err = manager.CreateOrUpdateSQLFirewallRule(sdkClient, "test-rule1", "1.1.1.1", "2.2.2.2") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot create firewall rule: %v", err)) t.FailNow() @@ -117,7 +118,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete firewall rule util.PrintAndLog("deleting firewall rule...") - err = sdk.DeleteSQLFirewallRule("test-rule1") + err = manager.DeleteSQLFirewallRule(sdkClient, "test-rule1") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot delete firewall rule: %v", err)) t.FailNow() @@ -126,7 +127,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the DB time.Sleep(time.Second) - response, err := sdk.DeleteDB("sqldatabase-sample") + response, err := manager.DeleteDB(sdkClient, "sqldatabase-sample") if err == nil { if response.StatusCode == 200 { util.PrintAndLog("db deleted") @@ -138,7 +139,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the server time.Sleep(time.Second) - response, err = sdk.DeleteSQLServer() + response, err = manager.DeleteSQLServer(sdkClient) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("sql server deleted") diff --git a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go index 32dba6cdf94..8156c14d68b 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go @@ -12,6 +12,8 @@ import ( const typeOfService = "Microsoft.Sql/servers" +type azureSqlManager struct{} + // getGoServersClient retrieves a ServersClient func getGoServersClient() sql.ServersClient { serversClient := sql.NewServersClient(config.SubscriptionID()) @@ -40,17 +42,17 @@ func getGoFirewallClient() sql.FirewallRulesClient { } // CreateOrUpdateSQLServer creates a SQL server in Azure -func (sdk GoSDKClient) CreateOrUpdateSQLServer(properties SQLServerProperties) (result sql.Server, err error) { +func (*azureSqlManager) CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) { serversClient := getGoServersClient() serverProp := SQLServerPropertiesToServer(properties) // issue the creation future, err := serversClient.CreateOrUpdate( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, sql.Server{ - Location: to.StringPtr(sdk.Location), + Location: to.StringPtr(sdkClient.Location), ServerProperties: &serverProp, }) if err != nil { @@ -63,19 +65,19 @@ func (sdk GoSDKClient) CreateOrUpdateSQLServer(properties SQLServerProperties) ( // CreateOrUpdateSQLFirewallRule creates or updates a firewall rule // based on code from: https://github.com/Azure-Samples/azure-sdk-for-go-samples/blob/master/sql/sql.go#L111 // to allow allow Azure services to connect example: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure#manage-firewall-rules-using-azure-cli -func (sdk GoSDKClient) CreateOrUpdateSQLFirewallRule(ruleName string, startIP string, endIP string) (result bool, err error) { +func (manager *azureSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer() + server, err := manager.GetServer(sdkClient) if err != nil || *server.State != "Ready" { return false, err } firewallClient := getGoFirewallClient() _, err = firewallClient.CreateOrUpdate( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, ruleName, sql.FirewallRule{ FirewallRuleProperties: &sql.FirewallRuleProperties{ @@ -93,48 +95,48 @@ func (sdk GoSDKClient) CreateOrUpdateSQLFirewallRule(ruleName string, startIP st } // CreateOrUpdateDB creates or updates a DB in Azure -func (sdk GoSDKClient) CreateOrUpdateDB(properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { +func (manager *azureSqlManager) CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { dbClient := getGoDbClient() dbProp := SQLDatabasePropertiesToDatabase(properties) return dbClient.CreateOrUpdate( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, properties.DatabaseName, sql.Database{ - Location: to.StringPtr(sdk.Location), + Location: to.StringPtr(sdkClient.Location), DatabaseProperties: &dbProp, }) } // GetSQLFirewallRule returns a firewall rule -func (sdk GoSDKClient) GetSQLFirewallRule(ruleName string) (result sql.FirewallRule, err error) { +func (manager *azureSqlManager) GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { firewallClient := getGoFirewallClient() return firewallClient.Get( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, ruleName, ) } // GetDB retrieves a database -func (sdk GoSDKClient) GetDB(databaseName string) (sql.Database, error) { +func (manager *azureSqlManager) GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) { dbClient := getGoDbClient() return dbClient.Get( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, databaseName, "serviceTierAdvisors, transparentDataEncryption", ) } // DeleteDB deletes a DB -func (sdk GoSDKClient) DeleteDB(databaseName string) (result autorest.Response, err error) { +func (manager *azureSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -142,22 +144,22 @@ func (sdk GoSDKClient) DeleteDB(databaseName string) (result autorest.Response, } // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer() + server, err := manager.GetServer(sdkClient) if err != nil || *server.State != "Ready" { return result, nil } // check to see if the db exists, if it doesn't then short-circuit - _, err = sdk.GetDB(databaseName) + _, err = manager.GetDB(sdkClient, databaseName) if err != nil { return result, nil } dbClient := getGoDbClient() result, err = dbClient.Delete( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, databaseName, ) @@ -165,25 +167,25 @@ func (sdk GoSDKClient) DeleteDB(databaseName string) (result autorest.Response, } // DeleteSQLFirewallRule deletes a firewall rule -func (sdk GoSDKClient) DeleteSQLFirewallRule(ruleName string) (err error) { +func (manager *azureSqlManager) DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer() + server, err := manager.GetServer(sdkClient) if err != nil || *server.State != "Ready" { return nil } // check to see if the rule exists, if it doesn't then short-circuit - _, err = sdk.GetSQLFirewallRule(ruleName) + _, err = manager.GetSQLFirewallRule(sdkClient, ruleName) if err != nil { return nil } firewallClient := getGoFirewallClient() _, err = firewallClient.Delete( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, ruleName, ) @@ -191,7 +193,7 @@ func (sdk GoSDKClient) DeleteSQLFirewallRule(ruleName string) (err error) { } // DeleteSQLServer deletes a SQL server -func (sdk GoSDKClient) DeleteSQLServer() (result autorest.Response, err error) { +func (manager *azureSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -199,16 +201,16 @@ func (sdk GoSDKClient) DeleteSQLServer() (result autorest.Response, err error) { } // check to see if the server exists, if it doesn't then short-circuit - _, err = sdk.GetServer() + _, err = manager.GetServer(sdkClient) if err != nil { return result, nil } serversClient := getGoServersClient() future, err := serversClient.Delete( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, ) if err != nil { return result, err @@ -218,13 +220,13 @@ func (sdk GoSDKClient) DeleteSQLServer() (result autorest.Response, err error) { } // CheckNameAvailability determines whether a SQL resource can be created with the specified name -func (sdk GoSDKClient) CheckNameAvailability() (result AvailabilityResponse, err error) { +func (manager *azureSqlManager) CheckNameAvailability(sdkClient GoSDKClient) (result AvailabilityResponse, err error) { serversClient := getGoServersClient() response, err := serversClient.CheckNameAvailability( - sdk.Ctx, + sdkClient.Ctx, sql.CheckNameAvailabilityRequest{ - Name: to.StringPtr(sdk.ServerName), + Name: to.StringPtr(sdkClient.ServerName), Type: to.StringPtr(typeOfService), }, ) @@ -236,12 +238,12 @@ func (sdk GoSDKClient) CheckNameAvailability() (result AvailabilityResponse, err } // GetServer returns a SQL server -func (sdk GoSDKClient) GetServer() (result sql.Server, err error) { +func (manager *azureSqlManager) GetServer(sdkClient GoSDKClient) (result sql.Server, err error) { serversClient := getGoServersClient() return serversClient.Get( - sdk.Ctx, - sdk.ResourceGroupName, - sdk.ServerName, + sdkClient.Ctx, + sdkClient.ResourceGroupName, + sdkClient.ServerName, ) } diff --git a/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go b/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go new file mode 100644 index 00000000000..fde93859403 --- /dev/null +++ b/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go @@ -0,0 +1,115 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlclient + +import ( + "net/http" + + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + helpers "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/helpers" + "github.com/Azure/go-autorest/autorest" +) + +// MockSqlManager struct +type MockSqlManager struct { + sqlServer sql.Server + sqlDatabase sql.Database + sqlFirewallRule sql.FirewallRule + sqlDatabasesCreateOrUpdateFuture sql.DatabasesCreateOrUpdateFuture +} + +// CreateOrUpdateSQLServer creates a new sql server +func (manager *MockSqlManager) CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) { + var sqlServer = sql.Server{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlServer = sqlServer + + return sqlServer, nil +} + +//DeleteSQLServer return StatusOK +func (manager *MockSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) { + + return helpers.GetRestResponse(http.StatusOK), nil +} + +//GetServer get server +func (manager *MockSqlManager) GetServer(sdkClient GoSDKClient) (result sql.Server, err error) { + + state := "Ready" + serverProperties := sql.ServerProperties{State: &state} + var sqlServer = sql.Server{ + Response: helpers.GetRestResponse(http.StatusCreated), + ServerProperties: &serverProperties, + } + + manager.sqlServer = sqlServer + + return sqlServer, nil +} + +//CreateOrUpdateSQLFirewallRule create or +func (manager *MockSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { + + return true, nil +} + +//DeleteSQLFirewallRule delete sql firewall +func (manager *MockSqlManager) DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) { + return nil +} + +//DeleteDB delete database +func (manager *MockSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) { + + return helpers.GetRestResponse(http.StatusOK), nil +} + +//GetSQLFirewallRule get sql firewall rule +func (manager *MockSqlManager) GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { + + var sqlFirewallRule = sql.FirewallRule{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlFirewallRule = sqlFirewallRule + + return sqlFirewallRule, nil +} + +//GetDB get database +func (manager *MockSqlManager) GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) { + + var sqlDatabase = sql.Database{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlDatabase = sqlDatabase + + return sqlDatabase, nil +} + +//CreateOrUpdateDB create or update DB +func (manager *MockSqlManager) CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { + + var sqlDatabasesCreateOrUpdateFuture = sql.DatabasesCreateOrUpdateFuture{} + manager.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture + + return sqlDatabasesCreateOrUpdateFuture, nil +} diff --git a/pkg/resourcemanager/sqlclient/sqlclient_manager.go b/pkg/resourcemanager/sqlclient/sqlclient_manager.go new file mode 100644 index 00000000000..159d8f0a0ea --- /dev/null +++ b/pkg/resourcemanager/sqlclient/sqlclient_manager.go @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package sqlclient + +import ( + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + "github.com/Azure/go-autorest/autorest" +) + +var AzureSQLManager SQLManager = &azureSqlManager{} + +// SQLManager interface +type SQLManager interface { + CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) + DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) + GetServer(sdkClient GoSDKClient) (result sql.Server, err error) + DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) + DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) + GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) + GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) + CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) + CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) +} From 3e6fe19712fd406daa5a3e3b0223bd664f74cf3e Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 11 Oct 2019 15:50:40 +1100 Subject: [PATCH 02/27] add package --- controllers/sqldatabase_controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/sqldatabase_controller.go b/controllers/sqldatabase_controller.go index 9b2b863f5a6..025759af6ae 100644 --- a/controllers/sqldatabase_controller.go +++ b/controllers/sqldatabase_controller.go @@ -32,6 +32,7 @@ import ( "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/controller/controllerutil" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" ) From 485deb57f284054b5e9f6ae19d0c0e18ad28f8ce Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 11 Oct 2019 16:18:04 +1100 Subject: [PATCH 03/27] update api version in tests --- controllers/sqldatabase_controller_test.go | 10 +++++----- controllers/sqlserver_controller_test.go | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/controllers/sqldatabase_controller_test.go b/controllers/sqldatabase_controller_test.go index 419cdf4d2fc..74bf3850b15 100644 --- a/controllers/sqldatabase_controller_test.go +++ b/controllers/sqldatabase_controller_test.go @@ -22,7 +22,7 @@ import ( "strings" "time" - azurev1 "github.com/Azure/azure-service-operator/api/v1" + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" helpers "github.com/Azure/azure-service-operator/pkg/helpers" . "github.com/onsi/ginkgo" @@ -63,12 +63,12 @@ var _ = Describe("SqlDatabase Controller", func() { var err error // Create the SqlServer object and expect the Reconcile to be created - sqlServerInstance := &azurev1.SqlServer{ + sqlServerInstance := &azurev1alpha1.SqlServer{ ObjectMeta: metav1.ObjectMeta{ Name: sqlServerName, Namespace: "default", }, - Spec: azurev1.SqlServerSpec{ + Spec: azurev1alpha1.SqlServerSpec{ Location: rgLocation, ResourceGroup: rgName, }, @@ -78,12 +78,12 @@ var _ = Describe("SqlDatabase Controller", func() { Expect(err).NotTo(HaveOccurred()) // Create the SqlDatabase object and expect the Reconcile to be created - sqlDatabaseInstance := &azurev1.SqlDatabase{ + sqlDatabaseInstance := &azurev1alpha1.SqlDatabase{ ObjectMeta: metav1.ObjectMeta{ Name: sqlDatabaseName, Namespace: "default", }, - Spec: azurev1.SqlDatabaseSpec{ + Spec: azurev1alpha1.SqlDatabaseSpec{ Location: rgLocation, ResourceGroup: rgName, Server: sqlName, diff --git a/controllers/sqlserver_controller_test.go b/controllers/sqlserver_controller_test.go index 495ebf58ff9..f1c00df89b0 100644 --- a/controllers/sqlserver_controller_test.go +++ b/controllers/sqlserver_controller_test.go @@ -22,7 +22,7 @@ import ( "strings" "time" - azurev1 "github.com/Azure/azure-service-operator/api/v1" + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" helpers "github.com/Azure/azure-service-operator/pkg/helpers" . "github.com/onsi/ginkgo" @@ -60,12 +60,12 @@ var _ = Describe("SqlServer Controller", func() { var err error // Create the SqlServer object and expect the Reconcile to be created - sqlServerInstance := &azurev1.SqlServer{ + sqlServerInstance := &azurev1alpha1.SqlServer{ ObjectMeta: metav1.ObjectMeta{ Name: sqlServerName, Namespace: "default", }, - Spec: azurev1.SqlServerSpec{ + Spec: azurev1alpha1.SqlServerSpec{ Location: rgLocation, ResourceGroup: rgName, }, From 6f593de8de29a5bb924a9adaef35ecc6d8886fd3 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 11 Oct 2019 16:49:25 +1100 Subject: [PATCH 04/27] remove status update instance directly --- controllers/sqldatabase_controller.go | 22 ++++++++++++++++------ controllers/sqlserver_controller.go | 10 +++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/controllers/sqldatabase_controller.go b/controllers/sqldatabase_controller.go index 025759af6ae..2a98018aa2c 100644 --- a/controllers/sqldatabase_controller.go +++ b/controllers/sqldatabase_controller.go @@ -27,12 +27,12 @@ import ( //"github.com/Azure/go-autorest/autorest/to" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "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/controller/controllerutil" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" ) @@ -152,10 +152,20 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.SqlDat r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get owner instance of SqlServer") } else { r.Recorder.Event(instance, corev1.EventTypeNormal, "OwnerAssign", "Got owner instance of Sql Server and assigning controller reference now") - innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) - if innerErr != nil { - r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to set controller reference to SqlServer") + // innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) + // if innerErr != nil { + // r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to set controller reference to SqlServer") + // } + references := []metav1.OwnerReference{ + metav1.OwnerReference{ + APIVersion: "v1", + Kind: "SqlServer", + Name: ownerInstance.GetName(), + UID: ownerInstance.GetUID(), + }, } + instance.ObjectMeta.SetOwnerReferences(references) + r.Recorder.Event(instance, corev1.EventTypeNormal, "OwnerAssign", "Owner instance assigned successfully") } @@ -169,7 +179,7 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.SqlDat if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") instance.Status.Provisioning = true - if errup := r.Status().Update(ctx, instance); errup != nil { + if errup := r.Update(ctx, instance); errup != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } } @@ -185,7 +195,7 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.SqlDat instance.Status.Provisioning = false instance.Status.Provisioned = true - if err = r.Status().Update(ctx, instance); err != nil { + if err = r.Update(ctx, instance); err != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } diff --git a/controllers/sqlserver_controller.go b/controllers/sqlserver_controller.go index e617babb8a2..238a0eceb81 100644 --- a/controllers/sqlserver_controller.go +++ b/controllers/sqlserver_controller.go @@ -209,7 +209,7 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1alpha1.SqlServe instance.Status.Message = fmt.Sprintf("CreateOrUpdateSQLServer not complete: %v", err) // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -221,7 +221,7 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1alpha1.SqlServe instance.Status.Message = "Successfully Submitted to Azure" // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } } @@ -239,7 +239,7 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1alpha1.SqlServe } // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -280,7 +280,7 @@ func (r *SqlServerReconciler) verifyExternal(instance *azurev1alpha1.SqlServer) } // write information back to instance - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") return updateerr } @@ -305,7 +305,7 @@ func (r *SqlServerReconciler) deleteExternal(instance *azurev1alpha1.SqlServer) if err != nil { instance.Status.Message = fmt.Sprintf("Couldn't delete resource in Azure: %v", err) r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Couldn't delete resouce in azure") - if updateerr := r.Status().Update(ctx, instance); updateerr != nil { + if updateerr := r.Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } return errhelp.NewAzureError(err) From 7a78216cf3626cafc7b7daa7ff86420c2faa6123 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 14 Oct 2019 11:03:57 +1100 Subject: [PATCH 05/27] fix controllerutil crash in tests and move mock --- controllers/sqldatabase_controller.go | 18 +-- controllers/sqlserver_controller.go | 8 +- controllers/sqlserver_controller_test.go | 11 +- controllers/suite_test.go | 9 +- .../mock/sqlclient/sqlclient_gosdk.go | 116 ++++++++++++++++++ 5 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go diff --git a/controllers/sqldatabase_controller.go b/controllers/sqldatabase_controller.go index 2a98018aa2c..efae3449332 100644 --- a/controllers/sqldatabase_controller.go +++ b/controllers/sqldatabase_controller.go @@ -27,12 +27,12 @@ import ( //"github.com/Azure/go-autorest/autorest/to" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "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/controller/controllerutil" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" ) @@ -152,20 +152,10 @@ func (r *SqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.SqlDat r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get owner instance of SqlServer") } else { r.Recorder.Event(instance, corev1.EventTypeNormal, "OwnerAssign", "Got owner instance of Sql Server and assigning controller reference now") - // innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) - // if innerErr != nil { - // r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to set controller reference to SqlServer") - // } - references := []metav1.OwnerReference{ - metav1.OwnerReference{ - APIVersion: "v1", - Kind: "SqlServer", - Name: ownerInstance.GetName(), - UID: ownerInstance.GetUID(), - }, + innerErr := controllerutil.SetControllerReference(&ownerInstance, instance, r.Scheme) + if innerErr != nil { + r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to set controller reference to SqlServer") } - instance.ObjectMeta.SetOwnerReferences(references) - r.Recorder.Event(instance, corev1.EventTypeNormal, "OwnerAssign", "Owner instance assigned successfully") } diff --git a/controllers/sqlserver_controller.go b/controllers/sqlserver_controller.go index 238a0eceb81..e1c900d0fd5 100644 --- a/controllers/sqlserver_controller.go +++ b/controllers/sqlserver_controller.go @@ -228,10 +228,10 @@ func (r *SqlServerReconciler) reconcileExternal(instance *azurev1alpha1.SqlServe _, createOrUpdateSecretErr := controllerutil.CreateOrUpdate(context.Background(), r.Client, secret, func() error { r.Log.Info("mutating secret bundle") - // innerErr := controllerutil.SetControllerReference(instance, secret, r.Scheme) - // if innerErr != nil { - // return innerErr - // } + innerErr := controllerutil.SetControllerReference(instance, secret, r.Scheme) + if innerErr != nil { + return innerErr + } return nil }) if createOrUpdateSecretErr != nil { diff --git a/controllers/sqlserver_controller_test.go b/controllers/sqlserver_controller_test.go index f1c00df89b0..0d25220d72e 100644 --- a/controllers/sqlserver_controller_test.go +++ b/controllers/sqlserver_controller_test.go @@ -27,6 +27,7 @@ import ( helpers "github.com/Azure/azure-service-operator/pkg/helpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + v1 "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" @@ -90,11 +91,11 @@ var _ = Describe("SqlServer Controller", func() { ).Should(BeTrue()) //verify secret exists in k8s - // secret := &v1.Secret{} - // err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) - // Expect(err).NotTo(HaveOccurred()) - // Expect(secret.ObjectMeta.Name).To(Equal(sqlServerName)) - // Expect(secret.ObjectMeta.Namespace).To(Equal(sqlServerInstance.Namespace)) + secret := &v1.Secret{} + err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) + Expect(err).NotTo(HaveOccurred()) + Expect(secret.ObjectMeta.Name).To(Equal(sqlServerName)) + Expect(secret.ObjectMeta.Namespace).To(Equal(sqlServerInstance.Namespace)) err = tc.k8sClient.Delete(context.Background(), sqlServerInstance) Expect(err).NotTo(HaveOccurred()) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 368fc58d8b0..c34b189965a 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -37,6 +37,7 @@ import ( resourcegroupsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" resourcemanagerstorages "github.com/Azure/azure-service-operator/pkg/resourcemanager/storages" + resourcemanagersqlmock "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/sqlclient" resourcemanagersql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" . "github.com/onsi/ginkgo" @@ -144,8 +145,8 @@ var _ = BeforeSuite(func() { var storageManagers resourcemanagerstorages.StorageManagers var keyVaultManager resourcemanagerkeyvaults.KeyVaultManager var sqlManager resourcemanagersql.SQLManager - //using mock for sql controller tests irrespective of the flag, as the end to end tests cover azure tests and it saves time - sqlManager = &resourcemanagersql.MockSqlManager{} + + sqlManager = &resourcemanagersqlmock.MockSqlManager{} if os.Getenv("TEST_CONTROLLER_WITH_MOCKS") == "false" { resourceGroupManager = resourcegroupsresourcemanager.AzureResourceGroupManager eventHubManagers = resourcemanagereventhub.AzureEventHubManagers @@ -158,7 +159,7 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - //sqlManager = &resourcemanagersql.MockSqlManager{} + //sqlManager = &resourcemanagersqlmock.MockSqlManager{} timeout = time.Second * 5 } @@ -207,6 +208,7 @@ var _ = BeforeSuite(func() { Client: k8sManager.GetClient(), Log: ctrl.Log.WithName("controllers").WithName("SqlServer"), Recorder: k8sManager.GetEventRecorderFor("SqlServer-controller"), + Scheme: scheme.Scheme, SQLManager: sqlManager, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) @@ -215,6 +217,7 @@ var _ = BeforeSuite(func() { Client: k8sManager.GetClient(), Log: ctrl.Log.WithName("controllers").WithName("SqlDatabase"), Recorder: k8sManager.GetEventRecorderFor("SqlDatabase-controller"), + Scheme: scheme.Scheme, SQLManager: sqlManager, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go new file mode 100644 index 00000000000..2c590a7941b --- /dev/null +++ b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go @@ -0,0 +1,116 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlclient + +import ( + "net/http" + + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + helpers "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/helpers" + sqlclient "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" + "github.com/Azure/go-autorest/autorest" +) + +// MockSqlManager struct +type MockSqlManager struct { + sqlServer sql.Server + sqlDatabase sql.Database + sqlFirewallRule sql.FirewallRule + sqlDatabasesCreateOrUpdateFuture sql.DatabasesCreateOrUpdateFuture +} + +// CreateOrUpdateSQLServer creates a new sql server +func (manager *MockSqlManager) CreateOrUpdateSQLServer(sdkClient sqlclient.GoSDKClient, properties sqlclient.SQLServerProperties) (result sql.Server, err error) { + var sqlServer = sql.Server{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlServer = sqlServer + + return sqlServer, nil +} + +//DeleteSQLServer return StatusOK +func (manager *MockSqlManager) DeleteSQLServer(sdkClient sqlclient.GoSDKClient) (result autorest.Response, err error) { + + return helpers.GetRestResponse(http.StatusOK), nil +} + +//GetServer get server +func (manager *MockSqlManager) GetServer(sdkClient sqlclient.GoSDKClient) (result sql.Server, err error) { + + state := "Ready" + serverProperties := sql.ServerProperties{State: &state} + var sqlServer = sql.Server{ + Response: helpers.GetRestResponse(http.StatusCreated), + ServerProperties: &serverProperties, + } + + manager.sqlServer = sqlServer + + return sqlServer, nil +} + +//CreateOrUpdateSQLFirewallRule create or +func (manager *MockSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { + + return true, nil +} + +//DeleteSQLFirewallRule delete sql firewall +func (manager *MockSqlManager) DeleteSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string) (err error) { + return nil +} + +//DeleteDB delete database +func (manager *MockSqlManager) DeleteDB(sdkClient sqlclient.GoSDKClient, databaseName string) (result autorest.Response, err error) { + + return helpers.GetRestResponse(http.StatusOK), nil +} + +//GetSQLFirewallRule get sql firewall rule +func (manager *MockSqlManager) GetSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { + + var sqlFirewallRule = sql.FirewallRule{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlFirewallRule = sqlFirewallRule + + return sqlFirewallRule, nil +} + +//GetDB get database +func (manager *MockSqlManager) GetDB(sdkClient sqlclient.GoSDKClient, databaseName string) (sql.Database, error) { + + var sqlDatabase = sql.Database{ + Response: helpers.GetRestResponse(http.StatusCreated), + } + + manager.sqlDatabase = sqlDatabase + + return sqlDatabase, nil +} + +//CreateOrUpdateDB create or update DB +func (manager *MockSqlManager) CreateOrUpdateDB(sdkClient sqlclient.GoSDKClient, properties sqlclient.SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { + + var sqlDatabasesCreateOrUpdateFuture = sql.DatabasesCreateOrUpdateFuture{} + manager.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture + + return sqlDatabasesCreateOrUpdateFuture, nil +} From c02963f123f8fef70c28f66f61a64ca56f1e2031 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 14 Oct 2019 12:10:07 +1100 Subject: [PATCH 06/27] update to run mock and azure based on flag --- controllers/suite_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index c34b189965a..19ca71fadc4 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -37,9 +37,10 @@ import ( resourcegroupsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/resourcegroups" resourcemanagerstorages "github.com/Azure/azure-service-operator/pkg/resourcemanager/storages" - resourcemanagersqlmock "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/sqlclient" resourcemanagersql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" + resourcemanagersqlmock "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/sqlclient" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -77,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - t.Parallel() + //t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, @@ -146,20 +147,19 @@ var _ = BeforeSuite(func() { var keyVaultManager resourcemanagerkeyvaults.KeyVaultManager var sqlManager resourcemanagersql.SQLManager - sqlManager = &resourcemanagersqlmock.MockSqlManager{} if os.Getenv("TEST_CONTROLLER_WITH_MOCKS") == "false" { resourceGroupManager = resourcegroupsresourcemanager.AzureResourceGroupManager eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - //sqlManager = resourcemanagersql.AzureSQLManager + sqlManager = resourcemanagersql.AzureSQLManager timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - //sqlManager = &resourcemanagersqlmock.MockSqlManager{} + sqlManager = &resourcemanagersqlmock.MockSqlManager{} timeout = time.Second * 5 } From 81597ec671c5c3f1415a727f52776f7e4deea49b Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 14 Oct 2019 14:18:09 +1100 Subject: [PATCH 07/27] enable tests to run in parallel --- controllers/suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index dd7ce09eb6b..9a3dca83020 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - //t.Parallel() + t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, From e2e213bd31aa2d7a494ca6447236e34a36511e34 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 14 Oct 2019 15:59:29 +1100 Subject: [PATCH 08/27] increase timeout --- controllers/sqldatabase_controller_test.go | 2 +- controllers/suite_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/sqldatabase_controller_test.go b/controllers/sqldatabase_controller_test.go index 74bf3850b15..200e0bc669e 100644 --- a/controllers/sqldatabase_controller_test.go +++ b/controllers/sqldatabase_controller_test.go @@ -34,7 +34,7 @@ import ( var _ = Describe("SqlDatabase Controller", func() { - const timeout = time.Second * 240 + const timeout = time.Second * 360 var rgName string var rgLocation string var sqlName string diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 9a3dca83020..b812d69d234 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -153,7 +153,7 @@ var _ = BeforeSuite(func() { storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager sqlManager = resourcemanagersql.AzureSQLManager - timeout = time.Second * 120 + timeout = time.Second * 240 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers From 55bf533a415a260c2ca2cfabde2f7029db6dfd55 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 14 Oct 2019 17:30:01 +1100 Subject: [PATCH 09/27] run sql controller with mock always --- controllers/sqldatabase_controller_test.go | 2 +- controllers/suite_test.go | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/controllers/sqldatabase_controller_test.go b/controllers/sqldatabase_controller_test.go index 200e0bc669e..74bf3850b15 100644 --- a/controllers/sqldatabase_controller_test.go +++ b/controllers/sqldatabase_controller_test.go @@ -34,7 +34,7 @@ import ( var _ = Describe("SqlDatabase Controller", func() { - const timeout = time.Second * 360 + const timeout = time.Second * 240 var rgName string var rgLocation string var sqlName string diff --git a/controllers/suite_test.go b/controllers/suite_test.go index b812d69d234..d0c760a3a4b 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -152,16 +152,17 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - sqlManager = resourcemanagersql.AzureSQLManager - timeout = time.Second * 240 + //sqlManager = resourcemanagersql.AzureSQLManager + timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - sqlManager = &resourcemanagersqlmock.MockSqlManager{} + //sqlManager = &resourcemanagersqlmock.MockSqlManager{} timeout = time.Second * 5 } + sqlManager = &resourcemanagersqlmock.MockSqlManager{} err = (&KeyVaultReconciler{ Client: k8sManager.GetClient(), From 5756c4d065c9f0a8cf1cee646d8c1fa7b23f83c4 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 10:53:28 +1100 Subject: [PATCH 10/27] rename test files --- ...r_test.go => azuresqldatabase_controller_test.go} | 12 +++++------- ...ler_test.go => azuresqlserver_controller_test.go} | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) rename controllers/{sqldatabase_controller_test.go => azuresqldatabase_controller_test.go} (96%) rename controllers/{sqlserver_controller_test.go => azuresqlserver_controller_test.go} (95%) diff --git a/controllers/sqldatabase_controller_test.go b/controllers/azuresqldatabase_controller_test.go similarity index 96% rename from controllers/sqldatabase_controller_test.go rename to controllers/azuresqldatabase_controller_test.go index 582dcdfe5fc..ca428dada96 100644 --- a/controllers/sqldatabase_controller_test.go +++ b/controllers/azuresqldatabase_controller_test.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "strings" - "time" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" @@ -32,9 +31,8 @@ import ( "k8s.io/apimachinery/pkg/types" ) -var _ = Describe("SqlDatabase Controller", func() { +var _ = Describe("AzureSqlDatabase Controller", func() { - const timeout = time.Second * 240 var rgName string var rgLocation string var sqlName string @@ -100,13 +98,13 @@ var _ = Describe("SqlDatabase Controller", func() { Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) return helpers.HasFinalizer(sqlDatabaseInstance, azureSQLDatabaseFinalizerName) - }, timeout, + }, tc.timeout, ).Should(BeTrue()) Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) return sqlDatabaseInstance.IsSubmitted() - }, timeout, + }, tc.timeout, ).Should(BeTrue()) err = tc.k8sClient.Delete(context.Background(), sqlDatabaseInstance) @@ -115,7 +113,7 @@ var _ = Describe("SqlDatabase Controller", func() { Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) return helpers.IsBeingDeleted(sqlDatabaseInstance) - }, timeout, + }, tc.timeout, ).Should(BeTrue()) Eventually(func() bool { @@ -124,7 +122,7 @@ var _ = Describe("SqlDatabase Controller", func() { err = fmt.Errorf("") } return strings.Contains(err.Error(), "not found") - }, timeout, + }, tc.timeout, ).Should(BeTrue()) }) diff --git a/controllers/sqlserver_controller_test.go b/controllers/azuresqlserver_controller_test.go similarity index 95% rename from controllers/sqlserver_controller_test.go rename to controllers/azuresqlserver_controller_test.go index f92f6902cae..35dd06eaf94 100644 --- a/controllers/sqlserver_controller_test.go +++ b/controllers/azuresqlserver_controller_test.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "strings" - "time" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" @@ -33,9 +32,8 @@ import ( "k8s.io/apimachinery/pkg/types" ) -var _ = Describe("SqlServer Controller", func() { +var _ = Describe("AzureSqlServer Controller", func() { - const timeout = time.Second * 240 var rgName string var rgLocation string @@ -81,13 +79,13 @@ var _ = Describe("SqlServer Controller", func() { Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) return helpers.HasFinalizer(sqlServerInstance, AzureSQLServerFinalizerName) - }, timeout, + }, tc.timeout, ).Should(BeTrue()) Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) return sqlServerInstance.IsSubmitted() - }, timeout, + }, tc.timeout, ).Should(BeTrue()) //verify secret exists in k8s @@ -103,7 +101,7 @@ var _ = Describe("SqlServer Controller", func() { Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) return helpers.IsBeingDeleted(sqlServerInstance) - }, timeout, + }, tc.timeout, ).Should(BeTrue()) Eventually(func() bool { @@ -112,7 +110,7 @@ var _ = Describe("SqlServer Controller", func() { err = fmt.Errorf("") } return strings.Contains(err.Error(), "not found") - }, timeout, + }, tc.timeout, ).Should(BeTrue()) }) From 3372db898077a3de56ef18969ccebe8db43dafdc Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 12:47:08 +1100 Subject: [PATCH 11/27] run sql with mock always --- api/v1alpha1/azuresqldatabase_types.go | 1 - api/v1alpha1/azuresqlserver_types.go | 1 - controllers/suite_test.go | 18 +-- .../sqlclient/sqlclient_gosdk_mock.go | 115 ------------------ 4 files changed, 9 insertions(+), 126 deletions(-) delete mode 100644 pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go diff --git a/api/v1alpha1/azuresqldatabase_types.go b/api/v1alpha1/azuresqldatabase_types.go index 52d2cecd358..e7a10971959 100644 --- a/api/v1alpha1/azuresqldatabase_types.go +++ b/api/v1alpha1/azuresqldatabase_types.go @@ -41,7 +41,6 @@ type AzureSqlDatabaseStatus struct { } // +kubebuilder:object:root=true -// +kubebuilder:subresource:status // AzureSqlDatabase is the Schema for the azuresqldatabases API type AzureSqlDatabase struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1alpha1/azuresqlserver_types.go b/api/v1alpha1/azuresqlserver_types.go index aa8cae11e4b..f8a0dd05906 100644 --- a/api/v1alpha1/azuresqlserver_types.go +++ b/api/v1alpha1/azuresqlserver_types.go @@ -41,7 +41,6 @@ type AzureSqlServerStatus struct { } // +kubebuilder:object:root=true -// +kubebuilder:subresource:status // AzureSqlServer is the Schema for the azuresqlservers API type AzureSqlServer struct { metav1.TypeMeta `json:",inline"` diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 5ad809b6a20..6d4573800c9 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - t.Parallel() + //t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, @@ -152,17 +152,17 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - sqlManager = resourcemanagersql.AzureSQLManager + //sqlManager = resourcemanagersql.AzureSQLManager timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - sqlManager = &resourcemanagersqlmock.MockSqlManager{} - timeout = time.Second * 5 + //sqlManager = &resourcemanagersqlmock.MockSqlManager{} + timeout = time.Second * 60 } - //sqlManager = &resourcemanagersqlmock.MockSqlManager{} + sqlManager = &resourcemanagersqlmock.MockSqlManager{} err = (&KeyVaultReconciler{ Client: k8sManager.GetClient(), @@ -207,8 +207,8 @@ var _ = BeforeSuite(func() { err = (&AzureSqlServerReconciler{ Client: k8sManager.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlServer"), - Recorder: k8sManager.GetEventRecorderFor("SqlServer-controller"), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlServer"), + Recorder: k8sManager.GetEventRecorderFor("AzureSqlServer-controller"), Scheme: scheme.Scheme, SQLManager: sqlManager, }).SetupWithManager(k8sManager) @@ -216,8 +216,8 @@ var _ = BeforeSuite(func() { err = (&AzureSqlDatabaseReconciler{ Client: k8sManager.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlDatabase"), - Recorder: k8sManager.GetEventRecorderFor("SqlDatabase-controller"), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), + Recorder: k8sManager.GetEventRecorderFor("AzureSqlDatabase-controller"), Scheme: scheme.Scheme, SQLManager: sqlManager, }).SetupWithManager(k8sManager) diff --git a/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go b/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go deleted file mode 100644 index fde93859403..00000000000 --- a/pkg/resourcemanager/sqlclient/sqlclient_gosdk_mock.go +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright 2019 microsoft. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package sqlclient - -import ( - "net/http" - - "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" - helpers "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/helpers" - "github.com/Azure/go-autorest/autorest" -) - -// MockSqlManager struct -type MockSqlManager struct { - sqlServer sql.Server - sqlDatabase sql.Database - sqlFirewallRule sql.FirewallRule - sqlDatabasesCreateOrUpdateFuture sql.DatabasesCreateOrUpdateFuture -} - -// CreateOrUpdateSQLServer creates a new sql server -func (manager *MockSqlManager) CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) { - var sqlServer = sql.Server{ - Response: helpers.GetRestResponse(http.StatusCreated), - } - - manager.sqlServer = sqlServer - - return sqlServer, nil -} - -//DeleteSQLServer return StatusOK -func (manager *MockSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) { - - return helpers.GetRestResponse(http.StatusOK), nil -} - -//GetServer get server -func (manager *MockSqlManager) GetServer(sdkClient GoSDKClient) (result sql.Server, err error) { - - state := "Ready" - serverProperties := sql.ServerProperties{State: &state} - var sqlServer = sql.Server{ - Response: helpers.GetRestResponse(http.StatusCreated), - ServerProperties: &serverProperties, - } - - manager.sqlServer = sqlServer - - return sqlServer, nil -} - -//CreateOrUpdateSQLFirewallRule create or -func (manager *MockSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { - - return true, nil -} - -//DeleteSQLFirewallRule delete sql firewall -func (manager *MockSqlManager) DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) { - return nil -} - -//DeleteDB delete database -func (manager *MockSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) { - - return helpers.GetRestResponse(http.StatusOK), nil -} - -//GetSQLFirewallRule get sql firewall rule -func (manager *MockSqlManager) GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { - - var sqlFirewallRule = sql.FirewallRule{ - Response: helpers.GetRestResponse(http.StatusCreated), - } - - manager.sqlFirewallRule = sqlFirewallRule - - return sqlFirewallRule, nil -} - -//GetDB get database -func (manager *MockSqlManager) GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) { - - var sqlDatabase = sql.Database{ - Response: helpers.GetRestResponse(http.StatusCreated), - } - - manager.sqlDatabase = sqlDatabase - - return sqlDatabase, nil -} - -//CreateOrUpdateDB create or update DB -func (manager *MockSqlManager) CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { - - var sqlDatabasesCreateOrUpdateFuture = sql.DatabasesCreateOrUpdateFuture{} - manager.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture - - return sqlDatabasesCreateOrUpdateFuture, nil -} From 90aef7d63d936dd824057eba04057218a8c59289 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 13:05:26 +1100 Subject: [PATCH 12/27] update test --- controllers/azuresqlserver_controller_test.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/controllers/azuresqlserver_controller_test.go b/controllers/azuresqlserver_controller_test.go index 35dd06eaf94..9c6c28e79c0 100644 --- a/controllers/azuresqlserver_controller_test.go +++ b/controllers/azuresqlserver_controller_test.go @@ -90,10 +90,16 @@ var _ = Describe("AzureSqlServer Controller", func() { //verify secret exists in k8s secret := &v1.Secret{} - err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) - Expect(err).NotTo(HaveOccurred()) - Expect(secret.ObjectMeta.Name).To(Equal(sqlServerName)) - Expect(secret.ObjectMeta.Namespace).To(Equal(sqlServerInstance.Namespace)) + Eventually(func() bool { + err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) + if err == nil { + if (secret.ObjectMeta.Name == sqlServerName) && (secret.ObjectMeta.Namespace == sqlServerInstance.Namespace) { + return true + } + } + return false + }, tc.timeout, + ).Should(BeTrue()) err = tc.k8sClient.Delete(context.Background(), sqlServerInstance) Expect(err).NotTo(HaveOccurred()) From e49f9ebe00e813a926e6c3bb393990df808e2097 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 15:59:47 +1100 Subject: [PATCH 13/27] enable parallel tests --- controllers/suite_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 6d4573800c9..c098c7487d1 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - //t.Parallel() + t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, @@ -152,17 +152,17 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - //sqlManager = resourcemanagersql.AzureSQLManager + sqlManager = resourcemanagersql.AzureSQLManager timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - //sqlManager = &resourcemanagersqlmock.MockSqlManager{} + sqlManager = &resourcemanagersqlmock.MockSqlManager{} timeout = time.Second * 60 } - sqlManager = &resourcemanagersqlmock.MockSqlManager{} + //sqlManager = &resourcemanagersqlmock.MockSqlManager{} err = (&KeyVaultReconciler{ Client: k8sManager.GetClient(), From 2f31e9fd7253c0d4d9bd8622364042142fdf0752 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 16:19:33 +1100 Subject: [PATCH 14/27] run sql using mock --- controllers/suite_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index c098c7487d1..71333a6630a 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -152,17 +152,17 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - sqlManager = resourcemanagersql.AzureSQLManager + //sqlManager = resourcemanagersql.AzureSQLManager timeout = time.Second * 120 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - sqlManager = &resourcemanagersqlmock.MockSqlManager{} + //sqlManager = &resourcemanagersqlmock.MockSqlManager{} timeout = time.Second * 60 } - //sqlManager = &resourcemanagersqlmock.MockSqlManager{} + sqlManager = &resourcemanagersqlmock.MockSqlManager{} err = (&KeyVaultReconciler{ Client: k8sManager.GetClient(), From 4a429eb4457e9c28abc65a1ea3d97f9d49093493 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 15 Oct 2019 16:39:37 +1100 Subject: [PATCH 15/27] disable tests running in parallel --- controllers/suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 71333a6630a..6d4573800c9 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - t.Parallel() + //t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, From 64e1aca88dd9cfde603d2a5991b587e45a88e355 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 21 Oct 2019 08:31:17 +1100 Subject: [PATCH 16/27] remove tests and add status subresource back --- api/v1alpha1/azuresqldatabase_types.go | 1 + api/v1alpha1/azuresqlserver_types.go | 1 + .../azuresqldatabase_controller_test.go | 130 ------------------ controllers/azuresqlserver_controller_test.go | 124 ----------------- 4 files changed, 2 insertions(+), 254 deletions(-) delete mode 100644 controllers/azuresqldatabase_controller_test.go delete mode 100644 controllers/azuresqlserver_controller_test.go diff --git a/api/v1alpha1/azuresqldatabase_types.go b/api/v1alpha1/azuresqldatabase_types.go index e7a10971959..52d2cecd358 100644 --- a/api/v1alpha1/azuresqldatabase_types.go +++ b/api/v1alpha1/azuresqldatabase_types.go @@ -41,6 +41,7 @@ type AzureSqlDatabaseStatus struct { } // +kubebuilder:object:root=true +// +kubebuilder:subresource:status // AzureSqlDatabase is the Schema for the azuresqldatabases API type AzureSqlDatabase struct { metav1.TypeMeta `json:",inline"` diff --git a/api/v1alpha1/azuresqlserver_types.go b/api/v1alpha1/azuresqlserver_types.go index f8a0dd05906..aa8cae11e4b 100644 --- a/api/v1alpha1/azuresqlserver_types.go +++ b/api/v1alpha1/azuresqlserver_types.go @@ -41,6 +41,7 @@ type AzureSqlServerStatus struct { } // +kubebuilder:object:root=true +// +kubebuilder:subresource:status // AzureSqlServer is the Schema for the azuresqlservers API type AzureSqlServer struct { metav1.TypeMeta `json:",inline"` diff --git a/controllers/azuresqldatabase_controller_test.go b/controllers/azuresqldatabase_controller_test.go deleted file mode 100644 index ca428dada96..00000000000 --- a/controllers/azuresqldatabase_controller_test.go +++ /dev/null @@ -1,130 +0,0 @@ -/* -Copyright 2019 microsoft. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controllers - -import ( - "context" - "fmt" - "strings" - - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" - - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -var _ = Describe("AzureSqlDatabase Controller", func() { - - var rgName string - var rgLocation string - var sqlName string - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - rgName = tc.resourceGroupName - rgLocation = tc.resourceGroupLocation - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - - Context("Create and Delete", func() { - It("should create and delete sql database in k8s", func() { - - sqlServerName := "t-sqlserver-dev-" + helpers.RandomString(10) - sqlDatabaseName := "t-sqldatabase-dev-" + helpers.RandomString(10) - - var err error - - // Create the SqlServer object and expect the Reconcile to be created - sqlServerInstance := &azurev1alpha1.AzureSqlServer{ - ObjectMeta: metav1.ObjectMeta{ - Name: sqlServerName, - Namespace: "default", - }, - Spec: azurev1alpha1.AzureSqlServerSpec{ - Location: rgLocation, - ResourceGroup: rgName, - }, - } - - err = tc.k8sClient.Create(context.Background(), sqlServerInstance) - Expect(err).NotTo(HaveOccurred()) - - // Create the SqlDatabase object and expect the Reconcile to be created - sqlDatabaseInstance := &azurev1alpha1.AzureSqlDatabase{ - ObjectMeta: metav1.ObjectMeta{ - Name: sqlDatabaseName, - Namespace: "default", - }, - Spec: azurev1alpha1.AzureSqlDatabaseSpec{ - Location: rgLocation, - ResourceGroup: rgName, - Server: sqlName, - Edition: 0, - }, - } - - err = tc.k8sClient.Create(context.Background(), sqlDatabaseInstance) - Expect(apierrors.IsInvalid(err)).To(Equal(false)) - Expect(err).NotTo(HaveOccurred()) - - sqlDatabaseNamespacedName := types.NamespacedName{Name: sqlDatabaseName, Namespace: "default"} - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) - return helpers.HasFinalizer(sqlDatabaseInstance, azureSQLDatabaseFinalizerName) - }, tc.timeout, - ).Should(BeTrue()) - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) - return sqlDatabaseInstance.IsSubmitted() - }, tc.timeout, - ).Should(BeTrue()) - - err = tc.k8sClient.Delete(context.Background(), sqlDatabaseInstance) - Expect(err).NotTo(HaveOccurred()) - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) - return helpers.IsBeingDeleted(sqlDatabaseInstance) - }, tc.timeout, - ).Should(BeTrue()) - - Eventually(func() bool { - err := tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) - if err == nil { - err = fmt.Errorf("") - } - return strings.Contains(err.Error(), "not found") - }, tc.timeout, - ).Should(BeTrue()) - - }) - }) -}) diff --git a/controllers/azuresqlserver_controller_test.go b/controllers/azuresqlserver_controller_test.go deleted file mode 100644 index 9c6c28e79c0..00000000000 --- a/controllers/azuresqlserver_controller_test.go +++ /dev/null @@ -1,124 +0,0 @@ -/* -Copyright 2019 microsoft. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package controllers - -import ( - "context" - "fmt" - "strings" - - azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" - - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - v1 "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" -) - -var _ = Describe("AzureSqlServer Controller", func() { - - var rgName string - var rgLocation string - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - rgName = tc.resourceGroupName - rgLocation = tc.resourceGroupLocation - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - - Context("Create and Delete", func() { - It("should create and delete sql server in k8s", func() { - sqlServerName := "t-sqlserver-dev-" + helpers.RandomString(10) - - var err error - - // Create the SqlServer object and expect the Reconcile to be created - sqlServerInstance := &azurev1alpha1.AzureSqlServer{ - ObjectMeta: metav1.ObjectMeta{ - Name: sqlServerName, - Namespace: "default", - }, - Spec: azurev1alpha1.AzureSqlServerSpec{ - Location: rgLocation, - ResourceGroup: rgName, - }, - } - - err = tc.k8sClient.Create(context.Background(), sqlServerInstance) - Expect(apierrors.IsInvalid(err)).To(Equal(false)) - Expect(err).NotTo(HaveOccurred()) - - sqlServerNamespacedName := types.NamespacedName{Name: sqlServerName, Namespace: "default"} - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) - return helpers.HasFinalizer(sqlServerInstance, AzureSQLServerFinalizerName) - }, tc.timeout, - ).Should(BeTrue()) - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) - return sqlServerInstance.IsSubmitted() - }, tc.timeout, - ).Should(BeTrue()) - - //verify secret exists in k8s - secret := &v1.Secret{} - Eventually(func() bool { - err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) - if err == nil { - if (secret.ObjectMeta.Name == sqlServerName) && (secret.ObjectMeta.Namespace == sqlServerInstance.Namespace) { - return true - } - } - return false - }, tc.timeout, - ).Should(BeTrue()) - - err = tc.k8sClient.Delete(context.Background(), sqlServerInstance) - Expect(err).NotTo(HaveOccurred()) - - Eventually(func() bool { - _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) - return helpers.IsBeingDeleted(sqlServerInstance) - }, tc.timeout, - ).Should(BeTrue()) - - Eventually(func() bool { - err := tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) - if err == nil { - err = fmt.Errorf("") - } - return strings.Contains(err.Error(), "not found") - }, tc.timeout, - ).Should(BeTrue()) - - }) - }) -}) From 06b4059373353b421ac5a6cfb67b6b7ae0b2935a Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 22 Oct 2019 10:22:41 +1100 Subject: [PATCH 17/27] add interface methods --- pkg/resourcemanager/sqlclient/sqlclient_manager.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/resourcemanager/sqlclient/sqlclient_manager.go b/pkg/resourcemanager/sqlclient/sqlclient_manager.go index 159d8f0a0ea..40bdfb30da5 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_manager.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_manager.go @@ -18,6 +18,8 @@ type SQLManager interface { DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) GetServer(sdkClient GoSDKClient) (result sql.Server, err error) DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) + CreateOrUpdateFailoverGroup(sdkClient GoSDKClient, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) + DeleteFailoverGroup(sdkClient GoSDKClient, failoverGroupName string) (result autorest.Response, err error) DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) From d3dba00af7664f039edc96cb04c116b5a09e3046 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Tue, 22 Oct 2019 10:56:10 +1100 Subject: [PATCH 18/27] update status --- controllers/azuresqldatabase_controller.go | 10 +++++----- controllers/azuresqlserver_controller.go | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index dbeaebc2795..c3134b93ec6 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -73,7 +73,7 @@ func (r *AzureSqlDatabaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e } helpers.RemoveFinalizer(&instance, azureSQLDatabaseFinalizerName) - if err := r.Update(context.Background(), &instance); err != nil { + if err := r.Status().Update(context.Background(), &instance); err != nil { return ctrl.Result{}, err } } @@ -160,7 +160,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A } // write information back to instance - if updateerr := r.Update(ctx, instance); updateerr != nil { + if updateerr := r.Status().Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -169,7 +169,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") instance.Status.Provisioning = true - if errup := r.Update(ctx, instance); errup != nil { + if errup := r.Status().Update(ctx, instance); errup != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } } @@ -185,7 +185,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A instance.Status.Provisioning = false instance.Status.Provisioned = true - if err = r.Update(ctx, instance); err != nil { + if err = r.Status().Update(ctx, instance); err != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -224,7 +224,7 @@ func (r *AzureSqlDatabaseReconciler) deleteExternal(instance *azurev1alpha1.Azur func (r *AzureSqlDatabaseReconciler) addFinalizer(instance *azurev1alpha1.AzureSqlDatabase) error { helpers.AddFinalizer(instance, azureSQLDatabaseFinalizerName) - err := r.Update(context.Background(), instance) + err := r.Status().Update(context.Background(), instance) if err != nil { return fmt.Errorf("failed to update finalizer: %v", err) } diff --git a/controllers/azuresqlserver_controller.go b/controllers/azuresqlserver_controller.go index 9c03b8d7c9a..bc8374321dd 100644 --- a/controllers/azuresqlserver_controller.go +++ b/controllers/azuresqlserver_controller.go @@ -99,7 +99,7 @@ func (r *AzureSqlServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err } helpers.RemoveFinalizer(&instance, AzureSQLServerFinalizerName) - if err := r.Update(context.Background(), &instance); err != nil { + if err := r.Status().Update(context.Background(), &instance); err != nil { return ctrl.Result{}, err } } @@ -231,7 +231,7 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu } // write information back to instance - if err := r.Update(ctx, instance); err != nil { + if err := r.Status().Update(ctx, instance); err != nil { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -270,7 +270,7 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu } // write information back to instance - if updateerr := r.Update(ctx, instance); updateerr != nil { + if updateerr := r.Status().Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } @@ -312,7 +312,7 @@ func (r *AzureSqlServerReconciler) verifyExternal(instance *azurev1alpha1.AzureS } // write information back to instance - if updateerr := r.Update(ctx, instance); updateerr != nil { + if updateerr := r.Status().Update(ctx, instance); updateerr != nil { r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") return updateerr } From 8a4f788100fc3a1a164a837681907576fe7e1ce9 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Wed, 23 Oct 2019 16:46:42 +1100 Subject: [PATCH 19/27] refactor gosdkclient --- controllers/azuresqlaction_controller.go | 12 +- controllers/azuresqldatabase_controller.go | 21 +-- .../azuresqlfirewallrule_controller.go | 19 +-- controllers/azuresqlserver_controller.go | 27 +--- controllers/suite_test.go | 3 +- main.go | 2 +- .../mock/sqlclient/sqlclient_gosdk.go | 39 ++--- .../sqlclient/endtoend_test.go | 38 ++--- pkg/resourcemanager/sqlclient/gosdkclient.go | 6 - .../sqlclient/sqlclient_godsk.go | 140 +++++++++--------- .../sqlclient/sqlclient_manager.go | 26 ++-- 11 files changed, 131 insertions(+), 202 deletions(-) diff --git a/controllers/azuresqlaction_controller.go b/controllers/azuresqlaction_controller.go index 7ebf8c4152b..6d21bf192fd 100644 --- a/controllers/azuresqlaction_controller.go +++ b/controllers/azuresqlaction_controller.go @@ -121,12 +121,6 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: serverName, - } - //get owner instance of AzureSqlServer r.Recorder.Event(instance, corev1.EventTypeNormal, "UpdatingOwner", "Updating owner AzureSqlServer instance") var ownerInstance azurev1alpha1.AzureSqlServer @@ -150,7 +144,7 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu } // Get the Sql Server instance that corresponds to the Server name in the spec for this action - server, err := r.SQLManager.GetServer(sdkClient) + server, err := r.SQLManager.GetServer(ctx, groupName, "", serverName) if err != nil { if strings.Contains(err.Error(), "ResourceGroupNotFound") { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get instance of AzureSqlServer: Resource group not found") @@ -173,8 +167,6 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu } } - sdkClient.Location = *server.Location - // rollcreds action if strings.ToLower(instance.Spec.ActionName) == "rollcreds" { azureSqlServerProperties := sql.SQLServerProperties{ @@ -186,7 +178,7 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu newPassword, _ := generateRandomPassword(passwordLength) azureSqlServerProperties.AdministratorLoginPassword = to.StringPtr(newPassword) - if _, err := r.SQLManager.CreateOrUpdateSQLServer(sdkClient, azureSqlServerProperties); err != nil { + if _, err := r.SQLManager.CreateOrUpdateSQLServer(ctx, groupName, *server.Location, serverName, azureSqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to provision or update instance") return errhelp.NewAzureError(err) diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index c3134b93ec6..229e5380a06 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -127,13 +127,6 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A dbName := instance.ObjectMeta.Name dbEdition := instance.Spec.Edition - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: server, - Location: location, - } - azureSqlDatabaseProperties := sql.SQLDatabaseProperties{ DatabaseName: dbName, Edition: dbEdition, @@ -164,7 +157,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } - _, err = r.SQLManager.CreateOrUpdateDB(sdkClient, azureSqlDatabaseProperties) + _, err = r.SQLManager.CreateOrUpdateDB(ctx, groupName, location, server, azureSqlDatabaseProperties) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -177,7 +170,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetDB(sdkClient, dbName) + _, err = r.SQLManager.GetDB(ctx, groupName, location, server, dbName) if err != nil { return errhelp.NewAzureError(err) } @@ -199,16 +192,8 @@ func (r *AzureSqlDatabaseReconciler) deleteExternal(instance *azurev1alpha1.Azur server := instance.Spec.Server dbName := instance.ObjectMeta.Name - // create the Go SDK client with relevant info - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: server, - Location: location, - } - r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/database/%s"+groupName, server, dbName)) - _, err := r.SQLManager.DeleteDB(sdkClient, dbName) + _, err := r.SQLManager.DeleteDB(ctx, groupName, location, server, dbName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, corev1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlfirewallrule_controller.go b/controllers/azuresqlfirewallrule_controller.go index 9907f215c40..b88bef51a2f 100644 --- a/controllers/azuresqlfirewallrule_controller.go +++ b/controllers/azuresqlfirewallrule_controller.go @@ -143,12 +143,6 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph startIP := instance.Spec.StartIPAddress endIP := instance.Spec.EndIPAddress - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: server, - } - r.Log.Info("Calling createorupdate Azure SQL firewall rule") //get owner instance of AzureSqlServer @@ -182,7 +176,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } - _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(sdkClient, ruleName, startIP, endIP) + _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(ctx, groupName, "", server, ruleName, startIP, endIP) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -192,7 +186,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetSQLFirewallRule(sdkClient, ruleName) + _, err = r.SQLManager.GetSQLFirewallRule(ctx, groupName, "", server, ruleName) if err != nil { return errhelp.NewAzureError(err) } @@ -209,15 +203,8 @@ func (r *AzureSqlFirewallRuleReconciler) deleteExternal(instance *azurev1alpha1. server := instance.Spec.Server ruleName := instance.ObjectMeta.Name - // create the Go SDK client with relevant info - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: server, - } - r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/firewallrule/%s"+groupName, server, ruleName)) - err := r.SQLManager.DeleteSQLFirewallRule(sdkClient, ruleName) + err := r.SQLManager.DeleteSQLFirewallRule(ctx, groupName, "", server, ruleName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, v1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlserver_controller.go b/controllers/azuresqlserver_controller.go index bc8374321dd..97942ee9e5e 100644 --- a/controllers/azuresqlserver_controller.go +++ b/controllers/azuresqlserver_controller.go @@ -204,13 +204,6 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: name, - Location: location, - } - //get owner instance of ResourceGroup r.Recorder.Event(instance, corev1.EventTypeNormal, "UpdatingOwner", "Updating owner ResourceGroup instance") var ownerInstance azurev1alpha1.ResourceGroup @@ -244,7 +237,7 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu // create the sql server instance.Status.Provisioning = true - if _, err := r.SQLManager.CreateOrUpdateSQLServer(sdkClient, azureSqlServerProperties); err != nil { + if _, err := r.SQLManager.CreateOrUpdateSQLServer(ctx, groupName, location, name, azureSqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { msg := fmt.Sprintf("CreateOrUpdateSQLServer not complete: %v", err) instance.Status.Message = msg @@ -283,14 +276,7 @@ func (r *AzureSqlServerReconciler) verifyExternal(instance *azurev1alpha1.AzureS name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: name, - Location: location, - } - - serv, err := r.SQLManager.GetServer(sdkClient) + serv, err := r.SQLManager.GetServer(ctx, groupName, location, name) if err != nil { azerr := errhelp.NewAzureError(err).(*errhelp.AzureError) if azerr.Type != errhelp.ResourceNotFound { @@ -326,14 +312,7 @@ func (r *AzureSqlServerReconciler) deleteExternal(instance *azurev1alpha1.AzureS groupName := instance.Spec.ResourceGroup location := instance.Spec.Location - sdkClient := sql.GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: name, - Location: location, - } - - _, err := r.SQLManager.DeleteSQLServer(sdkClient) + _, err := r.SQLManager.DeleteSQLServer(ctx, groupName, location, name) if err != nil { msg := fmt.Sprintf("Couldn't delete resource in Azure: %v", err) instance.Status.Message = msg diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 979f28f9a56..7fa1a5fe14b 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -152,15 +152,16 @@ var _ = BeforeSuite(func() { eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager + sqlManager = &resourcemanagersql.GoSDKClient{} timeout = time.Second * 320 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} + sqlManager = &resourcemanagersqlmock.MockGoSDKClient{} timeout = time.Second * 20 } - sqlManager = &resourcemanagersqlmock.MockSqlManager{} err = (&KeyVaultReconciler{ Client: k8sManager.GetClient(), diff --git a/main.go b/main.go index bc45be0027a..948dab74798 100644 --- a/main.go +++ b/main.go @@ -85,7 +85,7 @@ func main() { eventhubManagers := resourcemanagereventhub.AzureEventHubManagers storageManagers := resourcemanagerstorage.AzureStorageManagers keyVaultManager := resourcemanagerkeyvault.AzureKeyVaultManager - sqlManager := resourcemanagersql.AzureSQLManager + sqlManager := resourcemanagersql.GoSDKClient{} err = (&controllers.StorageReconciler{ Client: mgr.GetClient(), diff --git a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go index 196d1fdef47..beb02258063 100644 --- a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go +++ b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go @@ -17,6 +17,7 @@ limitations under the License. package sqlclient import ( + "context" "net/http" "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" @@ -25,8 +26,8 @@ import ( "github.com/Azure/go-autorest/autorest" ) -// MockSqlManager struct -type MockSqlManager struct { +// MockGoSDKClient struct +type MockGoSDKClient struct { sqlServer sql.Server sqlDatabase sql.Database sqlFirewallRule sql.FirewallRule @@ -35,24 +36,24 @@ type MockSqlManager struct { } // CreateOrUpdateSQLServer creates a new sql server -func (manager *MockSqlManager) CreateOrUpdateSQLServer(sdkClient sqlclient.GoSDKClient, properties sqlclient.SQLServerProperties) (result sql.Server, err error) { +func (sdk *MockGoSDKClient) CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties sqlclient.SQLServerProperties) (result sql.Server, err error) { var sqlServer = sql.Server{ Response: helpers.GetRestResponse(http.StatusCreated), } - manager.sqlServer = sqlServer + sdk.sqlServer = sqlServer return sqlServer, nil } //DeleteSQLServer return StatusOK -func (manager *MockSqlManager) DeleteSQLServer(sdkClient sqlclient.GoSDKClient) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } //GetServer get server -func (manager *MockSqlManager) GetServer(sdkClient sqlclient.GoSDKClient) (result sql.Server, err error) { +func (sdk *MockGoSDKClient) GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) { state := "Ready" serverProperties := sql.ServerProperties{State: &state} @@ -61,73 +62,73 @@ func (manager *MockSqlManager) GetServer(sdkClient sqlclient.GoSDKClient) (resul ServerProperties: &serverProperties, } - manager.sqlServer = sqlServer + sdk.sqlServer = sqlServer return sqlServer, nil } //CreateOrUpdateSQLFirewallRule create or -func (manager *MockSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { +func (sdk *MockGoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { return true, nil } //DeleteSQLFirewallRule delete sql firewall -func (manager *MockSqlManager) DeleteSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string) (err error) { +func (sdk *MockGoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) { return nil } //DeleteDB delete database -func (manager *MockSqlManager) DeleteDB(sdkClient sqlclient.GoSDKClient, databaseName string) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } //GetSQLFirewallRule get sql firewall rule -func (manager *MockSqlManager) GetSQLFirewallRule(sdkClient sqlclient.GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { +func (sdk *MockGoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) { var sqlFirewallRule = sql.FirewallRule{ Response: helpers.GetRestResponse(http.StatusCreated), } - manager.sqlFirewallRule = sqlFirewallRule + sdk.sqlFirewallRule = sqlFirewallRule return sqlFirewallRule, nil } //GetDB get database -func (manager *MockSqlManager) GetDB(sdkClient sqlclient.GoSDKClient, databaseName string) (sql.Database, error) { +func (sdk *MockGoSDKClient) GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) { var sqlDatabase = sql.Database{ Response: helpers.GetRestResponse(http.StatusCreated), } - manager.sqlDatabase = sqlDatabase + sdk.sqlDatabase = sqlDatabase return sqlDatabase, nil } //CreateOrUpdateDB create or update DB -func (manager *MockSqlManager) CreateOrUpdateDB(sdkClient sqlclient.GoSDKClient, properties sqlclient.SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { +func (sdk *MockGoSDKClient) CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties sqlclient.SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { var sqlDatabasesCreateOrUpdateFuture = sql.DatabasesCreateOrUpdateFuture{} - manager.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture + sdk.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture return sqlDatabasesCreateOrUpdateFuture, nil } //CreateOrUpdateFailoverGroup create or update failover group -func (manager *MockSqlManager) CreateOrUpdateFailoverGroup(sdkClient sqlclient.GoSDKClient, failovergroupname string, properties sqlclient.SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { +func (sdk *MockGoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties sqlclient.SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { var sqlFailoverGroupsCreateOrUpdateFuture = sql.FailoverGroupsCreateOrUpdateFuture{} - manager.sqlFailoverGroupsCreateOrUpdateFuture = sqlFailoverGroupsCreateOrUpdateFuture + sdk.sqlFailoverGroupsCreateOrUpdateFuture = sqlFailoverGroupsCreateOrUpdateFuture return sqlFailoverGroupsCreateOrUpdateFuture, nil } //DeleteFailoverGroup delete fail over group -func (manager *MockSqlManager) DeleteFailoverGroup(sdkClient sqlclient.GoSDKClient, failoverGroupName string) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } diff --git a/pkg/resourcemanager/sqlclient/endtoend_test.go b/pkg/resourcemanager/sqlclient/endtoend_test.go index c0d2a50e893..41ea5dc7eb4 100644 --- a/pkg/resourcemanager/sqlclient/endtoend_test.go +++ b/pkg/resourcemanager/sqlclient/endtoend_test.go @@ -36,13 +36,10 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { } // create the Go SDK client with relevant info - manager := AzureSQLManager - sdkClient := GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: generateName("sqlsrvtest"), - Location: "eastus2", - } + sdk := GoSDKClient{} + + location := "eastus2" + serverName := generateName("sqlsrvtest") // create the server sqlServerProperties := SQLServerProperties{ @@ -53,7 +50,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // wait for server to be created, then only proceed once activated for { time.Sleep(time.Second) - server, err := manager.CreateOrUpdateSQLServer(sdkClient, sqlServerProperties) + server, err := sdk.CreateOrUpdateSQLServer(ctx, groupName, location, serverName, sqlServerProperties) if err == nil { if *server.State == "Ready" { util.PrintAndLog("sql server ready") @@ -83,7 +80,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // wait for db to be created, then only proceed once activated for { time.Sleep(time.Second) - future, err := manager.CreateOrUpdateDB(sdkClient, sqlDBProperties) + future, err := sdk.CreateOrUpdateDB(ctx, groupName, location, serverName, sqlDBProperties) if err == nil { db, err := future.Result(getGoDbClient()) if err == nil { @@ -109,7 +106,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // create a firewall rule util.PrintAndLog("creating firewall rule...") - _, err = manager.CreateOrUpdateSQLFirewallRule(sdkClient, "test-rule1", "1.1.1.1", "2.2.2.2") + _, err = sdk.CreateOrUpdateSQLFirewallRule(ctx, groupName, location, serverName, "test-rule1", "1.1.1.1", "2.2.2.2") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot create firewall rule: %v", err)) t.FailNow() @@ -122,12 +119,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // create secondary SQL server // create the Go SDK client with relevant info secSrvName := generateName("sqlsrvsecondary") - sdk2 := GoSDKClient{ - Ctx: ctx, - ResourceGroupName: groupName, - ServerName: secSrvName, - Location: "westus", - } + secLocation := "westus" // create the server sqlServerProperties = SQLServerProperties{ @@ -138,7 +130,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // wait for server to be created, then only proceed once activated for { time.Sleep(time.Second) - server, err := manager.CreateOrUpdateSQLServer(sdk2, sqlServerProperties) + server, err := sdk.CreateOrUpdateSQLServer(ctx, groupName, secLocation, secSrvName, sqlServerProperties) if err == nil { if *server.State == "Ready" { util.PrintAndLog("sql server ready") @@ -171,7 +163,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { failoverGroupName := generateName("failovergroup") for { time.Sleep(time.Second) - _, err := manager.CreateOrUpdateFailoverGroup(sdk2, failoverGroupName, sqlFailoverGroupProperties) + _, err := sdk.CreateOrUpdateFailoverGroup(ctx, groupName, secLocation, secSrvName, failoverGroupName, sqlFailoverGroupProperties) if err == nil { util.PrintAndLog(fmt.Sprintf("failover group created successfully %s", failoverGroupName)) break @@ -189,7 +181,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete firewall rule util.PrintAndLog("deleting firewall rule...") - err = manager.DeleteSQLFirewallRule(sdkClient, "test-rule1") + err = sdk.DeleteSQLFirewallRule(ctx, groupName, location, serverName, "test-rule1") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot delete firewall rule: %v", err)) t.FailNow() @@ -198,7 +190,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the failover group util.PrintAndLog("deleting failover group...") - response, err := manager.DeleteFailoverGroup(sdk2, failoverGroupName) + response, err := sdk.DeleteFailoverGroup(ctx, groupName, secLocation, secSrvName, failoverGroupName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("failover group deleted") @@ -210,7 +202,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the DB time.Sleep(time.Second) - response, err = manager.DeleteDB(sdk2, "sqldatabase-sample") + response, err = sdk.DeleteDB(ctx, groupName, secLocation, secSrvName, "sqldatabase-sample") if err == nil { if response.StatusCode == 200 { util.PrintAndLog("db deleted") @@ -222,7 +214,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the server time.Sleep(time.Second) - response, err = manager.DeleteSQLServer(sdkClient) + response, err = sdk.DeleteSQLServer(ctx, groupName, location, serverName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("sql server deleted") @@ -239,7 +231,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the secondary server time.Sleep(time.Second) - response, err = manager.DeleteSQLServer(sdk2) + response, err = sdk.DeleteSQLServer(ctx, groupName, secLocation, secSrvName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("sql server deleted") diff --git a/pkg/resourcemanager/sqlclient/gosdkclient.go b/pkg/resourcemanager/sqlclient/gosdkclient.go index f5ddbb84e62..f9ffea06e71 100644 --- a/pkg/resourcemanager/sqlclient/gosdkclient.go +++ b/pkg/resourcemanager/sqlclient/gosdkclient.go @@ -5,12 +5,6 @@ package sqlclient -import "context" - // GoSDKClient is used to pass information to an implemetation of the ResourceClient interface that wraps calls to the Go SDK for Azure. type GoSDKClient struct { - Ctx context.Context - ResourceGroupName string - ServerName string - Location string } diff --git a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go index 0b598560002..76f1bd2db46 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go @@ -13,8 +13,6 @@ import ( const typeOfService = "Microsoft.Sql/servers" -type azureSqlManager struct{} - // getGoServersClient retrieves a ServersClient func getGoServersClient() sql.ServersClient { serversClient := sql.NewServersClient(config.SubscriptionID()) @@ -52,17 +50,17 @@ func getGoFailoverGroupsClient() sql.FailoverGroupsClient { } // CreateOrUpdateSQLServer creates a SQL server in Azure -func (*azureSqlManager) CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) { +func (sdk GoSDKClient) CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLServerProperties) (result sql.Server, err error) { serversClient := getGoServersClient() serverProp := SQLServerPropertiesToServer(properties) // issue the creation future, err := serversClient.CreateOrUpdate( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, sql.Server{ - Location: to.StringPtr(sdkClient.Location), + Location: to.StringPtr(location), ServerProperties: &serverProp, }) if err != nil { @@ -75,19 +73,19 @@ func (*azureSqlManager) CreateOrUpdateSQLServer(sdkClient GoSDKClient, propertie // CreateOrUpdateSQLFirewallRule creates or updates a firewall rule // based on code from: https://github.com/Azure-Samples/azure-sdk-for-go-samples/blob/master/sql/sql.go#L111 // to allow allow Azure services to connect example: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure#manage-firewall-rules-using-azure-cli -func (manager *azureSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) { +func (sdk GoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := manager.GetServer(sdkClient) + server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) if err != nil || *server.State != "Ready" { return false, err } firewallClient := getGoFirewallClient() _, err = firewallClient.CreateOrUpdate( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, ruleName, sql.FirewallRule{ FirewallRuleProperties: &sql.FirewallRuleProperties{ @@ -105,34 +103,34 @@ func (manager *azureSqlManager) CreateOrUpdateSQLFirewallRule(sdkClient GoSDKCli } // CreateOrUpdateDB creates or updates a DB in Azure -func (manager *azureSqlManager) CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { +func (sdk GoSDKClient) CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { dbClient := getGoDbClient() dbProp := SQLDatabasePropertiesToDatabase(properties) return dbClient.CreateOrUpdate( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, properties.DatabaseName, sql.Database{ - Location: to.StringPtr(sdkClient.Location), + Location: to.StringPtr(location), DatabaseProperties: &dbProp, }) } // CreateOrUpdateFailoverGroup creates a failover group -func (manager *azureSqlManager) CreateOrUpdateFailoverGroup(sdkClient GoSDKClient, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { +func (sdk GoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { failoverGroupsClient := getGoFailoverGroupsClient() // Construct a PartnerInfo object from the server name // Get resource ID from the servername to use - secServerSDKClient := GoSDKClient{ - Ctx: context.Background(), - ResourceGroupName: properties.SecondaryServerResourceGroup, - ServerName: properties.SecondaryServerName, - Location: "", // We dont get the location from the user for the secondary server as it is not required - } - server, err := manager.GetServer(secServerSDKClient) + // secServerSDKClient := GoSDKClient{ + // Ctx: ctx, + // ResourceGroupName: properties.SecondaryServerResourceGroup, + // ServerName: properties.SecondaryServerName, + // Location: "", // We dont get the location from the user for the secondary server as it is not required + // } + server, err := sdk.GetServer(ctx, properties.SecondaryServerResourceGroup, "", properties.SecondaryServerName) if err != nil { return result, nil } @@ -149,7 +147,7 @@ func (manager *azureSqlManager) CreateOrUpdateFailoverGroup(sdkClient GoSDKClien // Parse the Databases in the Databaselist and form array of Resource IDs for _, each := range properties.DatabaseList { - database, err := manager.GetDB(sdkClient, each) + database, err := sdk.GetDB(ctx, resourceGroupName, location, serverName, each) if err != nil { return result, err } @@ -171,41 +169,41 @@ func (manager *azureSqlManager) CreateOrUpdateFailoverGroup(sdkClient GoSDKClien } return failoverGroupsClient.CreateOrUpdate( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, failovergroupname, failoverGroup) } // GetSQLFirewallRule returns a firewall rule -func (manager *azureSqlManager) GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) { +func (sdk GoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) { firewallClient := getGoFirewallClient() return firewallClient.Get( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, ruleName, ) } // GetDB retrieves a database -func (manager *azureSqlManager) GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) { +func (sdk GoSDKClient) GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) { dbClient := getGoDbClient() return dbClient.Get( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, databaseName, "serviceTierAdvisors, transparentDataEncryption", ) } // DeleteDB deletes a DB -func (manager *azureSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -213,22 +211,22 @@ func (manager *azureSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName str } // check to see if the server exists, if it doesn't then short-circuit - server, err := manager.GetServer(sdkClient) + server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) if err != nil || *server.State != "Ready" { return result, nil } // check to see if the db exists, if it doesn't then short-circuit - _, err = manager.GetDB(sdkClient, databaseName) + _, err = sdk.GetDB(ctx, resourceGroupName, location, serverName, databaseName) if err != nil { return result, nil } dbClient := getGoDbClient() result, err = dbClient.Delete( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, databaseName, ) @@ -236,25 +234,25 @@ func (manager *azureSqlManager) DeleteDB(sdkClient GoSDKClient, databaseName str } // DeleteSQLFirewallRule deletes a firewall rule -func (manager *azureSqlManager) DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) { +func (sdk GoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := manager.GetServer(sdkClient) + server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) if err != nil || *server.State != "Ready" { return nil } // check to see if the rule exists, if it doesn't then short-circuit - _, err = manager.GetSQLFirewallRule(sdkClient, ruleName) + _, err = sdk.GetSQLFirewallRule(ctx, resourceGroupName, location, serverName, ruleName) if err != nil { return nil } firewallClient := getGoFirewallClient() _, err = firewallClient.Delete( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, ruleName, ) @@ -262,7 +260,7 @@ func (manager *azureSqlManager) DeleteSQLFirewallRule(sdkClient GoSDKClient, rul } // DeleteSQLServer deletes a SQL server -func (manager *azureSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -270,16 +268,16 @@ func (manager *azureSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result a } // check to see if the server exists, if it doesn't then short-circuit - _, err = manager.GetServer(sdkClient) + _, err = sdk.GetServer(ctx, resourceGroupName, location, serverName) if err != nil { return result, nil } serversClient := getGoServersClient() future, err := serversClient.Delete( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, ) if err != nil { return result, err @@ -289,19 +287,19 @@ func (manager *azureSqlManager) DeleteSQLServer(sdkClient GoSDKClient) (result a } // GetFailoverGroup retrieves a failover group -func (manager *azureSqlManager) GetFailoverGroup(sdkClient GoSDKClient, failovergroupname string) (sql.FailoverGroup, error) { +func (sdk GoSDKClient) GetFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string) (sql.FailoverGroup, error) { failoverGroupsClient := getGoFailoverGroupsClient() return failoverGroupsClient.Get( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, failovergroupname, ) } // DeleteFailoverGroup deletes a failover group -func (manager *azureSqlManager) DeleteFailoverGroup(sdkClient GoSDKClient, failoverGroupName string) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ @@ -310,22 +308,22 @@ func (manager *azureSqlManager) DeleteFailoverGroup(sdkClient GoSDKClient, failo } // check to see if the server exists, if it doesn't then short-circuit - _, err = manager.GetServer(sdkClient) + _, err = sdk.GetServer(ctx, resourceGroupName, location, serverName) if err != nil { return result, nil } // check to see if the failover group exists, if it doesn't then short-circuit - _, err = manager.GetFailoverGroup(sdkClient, failoverGroupName) + _, err = sdk.GetFailoverGroup(ctx, resourceGroupName, location, serverName, failoverGroupName) if err != nil { return result, nil } failoverGroupsClient := getGoFailoverGroupsClient() future, err := failoverGroupsClient.Delete( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, failoverGroupName, ) if err != nil { @@ -336,13 +334,13 @@ func (manager *azureSqlManager) DeleteFailoverGroup(sdkClient GoSDKClient, failo } // CheckNameAvailability determines whether a SQL resource can be created with the specified name -func (manager *azureSqlManager) CheckNameAvailability(sdkClient GoSDKClient) (result AvailabilityResponse, err error) { +func (sdk GoSDKClient) CheckNameAvailability(ctx context.Context, resourceGroupName string, location string, serverName string) (result AvailabilityResponse, err error) { serversClient := getGoServersClient() response, err := serversClient.CheckNameAvailability( - sdkClient.Ctx, + ctx, sql.CheckNameAvailabilityRequest{ - Name: to.StringPtr(sdkClient.ServerName), + Name: to.StringPtr(serverName), Type: to.StringPtr(typeOfService), }, ) @@ -354,12 +352,12 @@ func (manager *azureSqlManager) CheckNameAvailability(sdkClient GoSDKClient) (re } // GetServer returns a SQL server -func (manager *azureSqlManager) GetServer(sdkClient GoSDKClient) (result sql.Server, err error) { +func (sdk GoSDKClient) GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) { serversClient := getGoServersClient() return serversClient.Get( - sdkClient.Ctx, - sdkClient.ResourceGroupName, - sdkClient.ServerName, + ctx, + resourceGroupName, + serverName, ) } diff --git a/pkg/resourcemanager/sqlclient/sqlclient_manager.go b/pkg/resourcemanager/sqlclient/sqlclient_manager.go index 40bdfb30da5..fbac368611b 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_manager.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_manager.go @@ -6,23 +6,23 @@ package sqlclient import ( + "context" + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" "github.com/Azure/go-autorest/autorest" ) -var AzureSQLManager SQLManager = &azureSqlManager{} - // SQLManager interface type SQLManager interface { - CreateOrUpdateSQLServer(sdkClient GoSDKClient, properties SQLServerProperties) (result sql.Server, err error) - DeleteSQLServer(sdkClient GoSDKClient) (result autorest.Response, err error) - GetServer(sdkClient GoSDKClient) (result sql.Server, err error) - DeleteSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (err error) - CreateOrUpdateFailoverGroup(sdkClient GoSDKClient, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) - DeleteFailoverGroup(sdkClient GoSDKClient, failoverGroupName string) (result autorest.Response, err error) - DeleteDB(sdkClient GoSDKClient, databaseName string) (result autorest.Response, err error) - GetSQLFirewallRule(sdkClient GoSDKClient, ruleName string) (result sql.FirewallRule, err error) - GetDB(sdkClient GoSDKClient, databaseName string) (sql.Database, error) - CreateOrUpdateDB(sdkClient GoSDKClient, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) - CreateOrUpdateSQLFirewallRule(sdkClient GoSDKClient, ruleName string, startIP string, endIP string) (result bool, err error) + CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLServerProperties) (result sql.Server, err error) + DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) + GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) + DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) + CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) + DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) + DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) + GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) + GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) + CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) + CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) } From 5dd33bdab810589f2b2dbe707e28449950bc6ec9 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Thu, 24 Oct 2019 09:42:17 +1100 Subject: [PATCH 20/27] refactor sqlclient gosdk --- controllers/azuresqlaction_controller.go | 2 +- controllers/azuresqldatabase_controller.go | 5 +- .../azuresqlfirewallrule_controller.go | 6 +-- controllers/azuresqlserver_controller.go | 6 +-- .../mock/sqlclient/sqlclient_gosdk.go | 19 ++++--- .../sqlclient/endtoend_test.go | 14 +++--- .../sqlclient/sqlclient_godsk.go | 49 +++++++++---------- .../sqlclient/sqlclient_manager.go | 18 +++---- 8 files changed, 55 insertions(+), 64 deletions(-) diff --git a/controllers/azuresqlaction_controller.go b/controllers/azuresqlaction_controller.go index 6d21bf192fd..9dc62985790 100644 --- a/controllers/azuresqlaction_controller.go +++ b/controllers/azuresqlaction_controller.go @@ -144,7 +144,7 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu } // Get the Sql Server instance that corresponds to the Server name in the spec for this action - server, err := r.SQLManager.GetServer(ctx, groupName, "", serverName) + server, err := r.SQLManager.GetServer(ctx, groupName, serverName) if err != nil { if strings.Contains(err.Error(), "ResourceGroupNotFound") { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get instance of AzureSqlServer: Resource group not found") diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index 229e5380a06..627bcdce413 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -170,7 +170,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetDB(ctx, groupName, location, server, dbName) + _, err = r.SQLManager.GetDB(ctx, groupName, server, dbName) if err != nil { return errhelp.NewAzureError(err) } @@ -187,13 +187,12 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A func (r *AzureSqlDatabaseReconciler) deleteExternal(instance *azurev1alpha1.AzureSqlDatabase) error { ctx := context.Background() - location := instance.Spec.Location groupName := instance.Spec.ResourceGroup server := instance.Spec.Server dbName := instance.ObjectMeta.Name r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/database/%s"+groupName, server, dbName)) - _, err := r.SQLManager.DeleteDB(ctx, groupName, location, server, dbName) + _, err := r.SQLManager.DeleteDB(ctx, groupName, server, dbName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, corev1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlfirewallrule_controller.go b/controllers/azuresqlfirewallrule_controller.go index b88bef51a2f..eda3ad09f47 100644 --- a/controllers/azuresqlfirewallrule_controller.go +++ b/controllers/azuresqlfirewallrule_controller.go @@ -176,7 +176,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } - _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(ctx, groupName, "", server, ruleName, startIP, endIP) + _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(ctx, groupName, server, ruleName, startIP, endIP) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -186,7 +186,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetSQLFirewallRule(ctx, groupName, "", server, ruleName) + _, err = r.SQLManager.GetSQLFirewallRule(ctx, groupName, server, ruleName) if err != nil { return errhelp.NewAzureError(err) } @@ -204,7 +204,7 @@ func (r *AzureSqlFirewallRuleReconciler) deleteExternal(instance *azurev1alpha1. ruleName := instance.ObjectMeta.Name r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/firewallrule/%s"+groupName, server, ruleName)) - err := r.SQLManager.DeleteSQLFirewallRule(ctx, groupName, "", server, ruleName) + err := r.SQLManager.DeleteSQLFirewallRule(ctx, groupName, server, ruleName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, v1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlserver_controller.go b/controllers/azuresqlserver_controller.go index 97942ee9e5e..45ecee71348 100644 --- a/controllers/azuresqlserver_controller.go +++ b/controllers/azuresqlserver_controller.go @@ -272,11 +272,10 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu func (r *AzureSqlServerReconciler) verifyExternal(instance *azurev1alpha1.AzureSqlServer) error { ctx := context.Background() - location := instance.Spec.Location name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - serv, err := r.SQLManager.GetServer(ctx, groupName, location, name) + serv, err := r.SQLManager.GetServer(ctx, groupName, name) if err != nil { azerr := errhelp.NewAzureError(err).(*errhelp.AzureError) if azerr.Type != errhelp.ResourceNotFound { @@ -310,9 +309,8 @@ func (r *AzureSqlServerReconciler) deleteExternal(instance *azurev1alpha1.AzureS ctx := context.Background() name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - location := instance.Spec.Location - _, err := r.SQLManager.DeleteSQLServer(ctx, groupName, location, name) + _, err := r.SQLManager.DeleteSQLServer(ctx, groupName, name) if err != nil { msg := fmt.Sprintf("Couldn't delete resource in Azure: %v", err) instance.Status.Message = msg diff --git a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go index beb02258063..4e245c4eeb4 100644 --- a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go +++ b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go @@ -47,13 +47,13 @@ func (sdk *MockGoSDKClient) CreateOrUpdateSQLServer(ctx context.Context, resourc } //DeleteSQLServer return StatusOK -func (sdk *MockGoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } //GetServer get server -func (sdk *MockGoSDKClient) GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) { +func (sdk *MockGoSDKClient) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) { state := "Ready" serverProperties := sql.ServerProperties{State: &state} @@ -68,24 +68,24 @@ func (sdk *MockGoSDKClient) GetServer(ctx context.Context, resourceGroupName str } //CreateOrUpdateSQLFirewallRule create or -func (sdk *MockGoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { +func (sdk *MockGoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { return true, nil } //DeleteSQLFirewallRule delete sql firewall -func (sdk *MockGoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) { +func (sdk *MockGoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) { return nil } //DeleteDB delete database -func (sdk *MockGoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } //GetSQLFirewallRule get sql firewall rule -func (sdk *MockGoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) { +func (sdk *MockGoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) { var sqlFirewallRule = sql.FirewallRule{ Response: helpers.GetRestResponse(http.StatusCreated), @@ -97,7 +97,7 @@ func (sdk *MockGoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGrou } //GetDB get database -func (sdk *MockGoSDKClient) GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) { +func (sdk *MockGoSDKClient) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) { var sqlDatabase = sql.Database{ Response: helpers.GetRestResponse(http.StatusCreated), @@ -112,13 +112,12 @@ func (sdk *MockGoSDKClient) GetDB(ctx context.Context, resourceGroupName string, func (sdk *MockGoSDKClient) CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties sqlclient.SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) { var sqlDatabasesCreateOrUpdateFuture = sql.DatabasesCreateOrUpdateFuture{} - sdk.sqlDatabasesCreateOrUpdateFuture = sqlDatabasesCreateOrUpdateFuture return sqlDatabasesCreateOrUpdateFuture, nil } //CreateOrUpdateFailoverGroup create or update failover group -func (sdk *MockGoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties sqlclient.SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { +func (sdk *MockGoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties sqlclient.SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { var sqlFailoverGroupsCreateOrUpdateFuture = sql.FailoverGroupsCreateOrUpdateFuture{} sdk.sqlFailoverGroupsCreateOrUpdateFuture = sqlFailoverGroupsCreateOrUpdateFuture @@ -128,7 +127,7 @@ func (sdk *MockGoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, res } //DeleteFailoverGroup delete fail over group -func (sdk *MockGoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) { +func (sdk *MockGoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) { return helpers.GetRestResponse(http.StatusOK), nil } diff --git a/pkg/resourcemanager/sqlclient/endtoend_test.go b/pkg/resourcemanager/sqlclient/endtoend_test.go index 41ea5dc7eb4..e810b6b4bb6 100644 --- a/pkg/resourcemanager/sqlclient/endtoend_test.go +++ b/pkg/resourcemanager/sqlclient/endtoend_test.go @@ -106,7 +106,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // create a firewall rule util.PrintAndLog("creating firewall rule...") - _, err = sdk.CreateOrUpdateSQLFirewallRule(ctx, groupName, location, serverName, "test-rule1", "1.1.1.1", "2.2.2.2") + _, err = sdk.CreateOrUpdateSQLFirewallRule(ctx, groupName, serverName, "test-rule1", "1.1.1.1", "2.2.2.2") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot create firewall rule: %v", err)) t.FailNow() @@ -163,7 +163,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { failoverGroupName := generateName("failovergroup") for { time.Sleep(time.Second) - _, err := sdk.CreateOrUpdateFailoverGroup(ctx, groupName, secLocation, secSrvName, failoverGroupName, sqlFailoverGroupProperties) + _, err := sdk.CreateOrUpdateFailoverGroup(ctx, groupName, secSrvName, failoverGroupName, sqlFailoverGroupProperties) if err == nil { util.PrintAndLog(fmt.Sprintf("failover group created successfully %s", failoverGroupName)) break @@ -181,7 +181,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete firewall rule util.PrintAndLog("deleting firewall rule...") - err = sdk.DeleteSQLFirewallRule(ctx, groupName, location, serverName, "test-rule1") + err = sdk.DeleteSQLFirewallRule(ctx, groupName, serverName, "test-rule1") if err != nil { util.PrintAndLog(fmt.Sprintf("cannot delete firewall rule: %v", err)) t.FailNow() @@ -190,7 +190,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the failover group util.PrintAndLog("deleting failover group...") - response, err := sdk.DeleteFailoverGroup(ctx, groupName, secLocation, secSrvName, failoverGroupName) + response, err := sdk.DeleteFailoverGroup(ctx, groupName, secSrvName, failoverGroupName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("failover group deleted") @@ -202,7 +202,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the DB time.Sleep(time.Second) - response, err = sdk.DeleteDB(ctx, groupName, secLocation, secSrvName, "sqldatabase-sample") + response, err = sdk.DeleteDB(ctx, groupName, secSrvName, "sqldatabase-sample") if err == nil { if response.StatusCode == 200 { util.PrintAndLog("db deleted") @@ -214,7 +214,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the server time.Sleep(time.Second) - response, err = sdk.DeleteSQLServer(ctx, groupName, location, serverName) + response, err = sdk.DeleteSQLServer(ctx, groupName, serverName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("sql server deleted") @@ -231,7 +231,7 @@ func TestCreateOrUpdateSQLServer(t *testing.T) { // delete the secondary server time.Sleep(time.Second) - response, err = sdk.DeleteSQLServer(ctx, groupName, secLocation, secSrvName) + response, err = sdk.DeleteSQLServer(ctx, groupName, secSrvName) if err == nil { if response.StatusCode == 200 { util.PrintAndLog("sql server deleted") diff --git a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go index 76f1bd2db46..e8f957b4614 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_godsk.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_godsk.go @@ -73,10 +73,10 @@ func (sdk GoSDKClient) CreateOrUpdateSQLServer(ctx context.Context, resourceGrou // CreateOrUpdateSQLFirewallRule creates or updates a firewall rule // based on code from: https://github.com/Azure-Samples/azure-sdk-for-go-samples/blob/master/sql/sql.go#L111 // to allow allow Azure services to connect example: https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure#manage-firewall-rules-using-azure-cli -func (sdk GoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { +func (sdk GoSDKClient) CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) + server, err := sdk.GetServer(ctx, resourceGroupName, serverName) if err != nil || *server.State != "Ready" { return false, err } @@ -119,18 +119,13 @@ func (sdk GoSDKClient) CreateOrUpdateDB(ctx context.Context, resourceGroupName s } // CreateOrUpdateFailoverGroup creates a failover group -func (sdk GoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { +func (sdk GoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { failoverGroupsClient := getGoFailoverGroupsClient() // Construct a PartnerInfo object from the server name // Get resource ID from the servername to use - // secServerSDKClient := GoSDKClient{ - // Ctx: ctx, - // ResourceGroupName: properties.SecondaryServerResourceGroup, - // ServerName: properties.SecondaryServerName, - // Location: "", // We dont get the location from the user for the secondary server as it is not required - // } - server, err := sdk.GetServer(ctx, properties.SecondaryServerResourceGroup, "", properties.SecondaryServerName) + + server, err := sdk.GetServer(ctx, properties.SecondaryServerResourceGroup, properties.SecondaryServerName) if err != nil { return result, nil } @@ -147,7 +142,7 @@ func (sdk GoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resource // Parse the Databases in the Databaselist and form array of Resource IDs for _, each := range properties.DatabaseList { - database, err := sdk.GetDB(ctx, resourceGroupName, location, serverName, each) + database, err := sdk.GetDB(ctx, resourceGroupName, serverName, each) if err != nil { return result, err } @@ -178,7 +173,7 @@ func (sdk GoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resource } // GetSQLFirewallRule returns a firewall rule -func (sdk GoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) { +func (sdk GoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) { firewallClient := getGoFirewallClient() return firewallClient.Get( @@ -190,7 +185,7 @@ func (sdk GoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGroupName } // GetDB retrieves a database -func (sdk GoSDKClient) GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) { +func (sdk GoSDKClient) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) { dbClient := getGoDbClient() return dbClient.Get( @@ -203,7 +198,7 @@ func (sdk GoSDKClient) GetDB(ctx context.Context, resourceGroupName string, loca } // DeleteDB deletes a DB -func (sdk GoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -211,13 +206,13 @@ func (sdk GoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, l } // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) + server, err := sdk.GetServer(ctx, resourceGroupName, serverName) if err != nil || *server.State != "Ready" { return result, nil } // check to see if the db exists, if it doesn't then short-circuit - _, err = sdk.GetDB(ctx, resourceGroupName, location, serverName, databaseName) + _, err = sdk.GetDB(ctx, resourceGroupName, serverName, databaseName) if err != nil { return result, nil } @@ -234,16 +229,16 @@ func (sdk GoSDKClient) DeleteDB(ctx context.Context, resourceGroupName string, l } // DeleteSQLFirewallRule deletes a firewall rule -func (sdk GoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) { +func (sdk GoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) { // check to see if the server exists, if it doesn't then short-circuit - server, err := sdk.GetServer(ctx, resourceGroupName, location, serverName) + server, err := sdk.GetServer(ctx, resourceGroupName, serverName) if err != nil || *server.State != "Ready" { return nil } // check to see if the rule exists, if it doesn't then short-circuit - _, err = sdk.GetSQLFirewallRule(ctx, resourceGroupName, location, serverName, ruleName) + _, err = sdk.GetSQLFirewallRule(ctx, resourceGroupName, serverName, ruleName) if err != nil { return nil } @@ -260,7 +255,7 @@ func (sdk GoSDKClient) DeleteSQLFirewallRule(ctx context.Context, resourceGroupN } // DeleteSQLServer deletes a SQL server -func (sdk GoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ StatusCode: 200, @@ -268,7 +263,7 @@ func (sdk GoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName st } // check to see if the server exists, if it doesn't then short-circuit - _, err = sdk.GetServer(ctx, resourceGroupName, location, serverName) + _, err = sdk.GetServer(ctx, resourceGroupName, serverName) if err != nil { return result, nil } @@ -287,7 +282,7 @@ func (sdk GoSDKClient) DeleteSQLServer(ctx context.Context, resourceGroupName st } // GetFailoverGroup retrieves a failover group -func (sdk GoSDKClient) GetFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string) (sql.FailoverGroup, error) { +func (sdk GoSDKClient) GetFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string) (sql.FailoverGroup, error) { failoverGroupsClient := getGoFailoverGroupsClient() return failoverGroupsClient.Get( @@ -299,7 +294,7 @@ func (sdk GoSDKClient) GetFailoverGroup(ctx context.Context, resourceGroupName s } // DeleteFailoverGroup deletes a failover group -func (sdk GoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) { +func (sdk GoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) { result = autorest.Response{ Response: &http.Response{ @@ -308,13 +303,13 @@ func (sdk GoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupNam } // check to see if the server exists, if it doesn't then short-circuit - _, err = sdk.GetServer(ctx, resourceGroupName, location, serverName) + _, err = sdk.GetServer(ctx, resourceGroupName, serverName) if err != nil { return result, nil } // check to see if the failover group exists, if it doesn't then short-circuit - _, err = sdk.GetFailoverGroup(ctx, resourceGroupName, location, serverName, failoverGroupName) + _, err = sdk.GetFailoverGroup(ctx, resourceGroupName, serverName, failoverGroupName) if err != nil { return result, nil } @@ -334,7 +329,7 @@ func (sdk GoSDKClient) DeleteFailoverGroup(ctx context.Context, resourceGroupNam } // CheckNameAvailability determines whether a SQL resource can be created with the specified name -func (sdk GoSDKClient) CheckNameAvailability(ctx context.Context, resourceGroupName string, location string, serverName string) (result AvailabilityResponse, err error) { +func (sdk GoSDKClient) CheckNameAvailability(ctx context.Context, resourceGroupName string, serverName string) (result AvailabilityResponse, err error) { serversClient := getGoServersClient() response, err := serversClient.CheckNameAvailability( @@ -352,7 +347,7 @@ func (sdk GoSDKClient) CheckNameAvailability(ctx context.Context, resourceGroupN } // GetServer returns a SQL server -func (sdk GoSDKClient) GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) { +func (sdk GoSDKClient) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) { serversClient := getGoServersClient() return serversClient.Get( diff --git a/pkg/resourcemanager/sqlclient/sqlclient_manager.go b/pkg/resourcemanager/sqlclient/sqlclient_manager.go index fbac368611b..02f00e4fb6e 100644 --- a/pkg/resourcemanager/sqlclient/sqlclient_manager.go +++ b/pkg/resourcemanager/sqlclient/sqlclient_manager.go @@ -15,14 +15,14 @@ import ( // SQLManager interface type SQLManager interface { CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLServerProperties) (result sql.Server, err error) - DeleteSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result autorest.Response, err error) - GetServer(ctx context.Context, resourceGroupName string, location string, serverName string) (result sql.Server, err error) - DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (err error) - CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) - DeleteFailoverGroup(ctx context.Context, resourceGroupName string, location string, serverName string, failoverGroupName string) (result autorest.Response, err error) - DeleteDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (result autorest.Response, err error) - GetSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string) (result sql.FirewallRule, err error) - GetDB(ctx context.Context, resourceGroupName string, location string, serverName string, databaseName string) (sql.Database, error) + DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) + GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) + DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) + CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) + DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) + DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) + GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) + GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) - CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, location string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) + CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) } From f777198026ee7dab7eb7e077d7e561b0af2d9004 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Thu, 24 Oct 2019 10:55:20 +1100 Subject: [PATCH 21/27] use resourceclient --- controllers/azuresqlaction_controller.go | 12 +++--- controllers/azuresqldatabase_controller.go | 14 +++---- .../azuresqlfirewallrule_controller.go | 14 +++---- controllers/azuresqlserver_controller.go | 14 +++---- controllers/suite_test.go | 26 ++++++------ main.go | 42 +++++++++---------- .../sqlclient/resourceclient.go | 25 +++++------ 7 files changed, 74 insertions(+), 73 deletions(-) diff --git a/controllers/azuresqlaction_controller.go b/controllers/azuresqlaction_controller.go index 9dc62985790..e562b032cb2 100644 --- a/controllers/azuresqlaction_controller.go +++ b/controllers/azuresqlaction_controller.go @@ -47,10 +47,10 @@ const AzureSqlActionFinalizerName = "azuresqlaction.finalizers.azure.com" // AzureSqlActionReconciler reconciles a AzureSqlAction object type AzureSqlActionReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme - SQLManager sql.SQLManager + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + ResourceClient sql.ResourceClient } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=azuresqlactions,verbs=get;list;watch;create;update;patch;delete @@ -144,7 +144,7 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu } // Get the Sql Server instance that corresponds to the Server name in the spec for this action - server, err := r.SQLManager.GetServer(ctx, groupName, serverName) + server, err := r.ResourceClient.GetServer(ctx, groupName, serverName) if err != nil { if strings.Contains(err.Error(), "ResourceGroupNotFound") { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get instance of AzureSqlServer: Resource group not found") @@ -178,7 +178,7 @@ func (r *AzureSqlActionReconciler) reconcileExternal(instance *azurev1alpha1.Azu newPassword, _ := generateRandomPassword(passwordLength) azureSqlServerProperties.AdministratorLoginPassword = to.StringPtr(newPassword) - if _, err := r.SQLManager.CreateOrUpdateSQLServer(ctx, groupName, *server.Location, serverName, azureSqlServerProperties); err != nil { + if _, err := r.ResourceClient.CreateOrUpdateSQLServer(ctx, groupName, *server.Location, serverName, azureSqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to provision or update instance") return errhelp.NewAzureError(err) diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index 627bcdce413..e784de67f51 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -42,10 +42,10 @@ const azureSQLDatabaseFinalizerName = "azuresqldatabase.finalizers.azure.com" // AzureSqlDatabaseReconciler reconciles a AzureSqlDatabase object type AzureSqlDatabaseReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme - SQLManager sql.SQLManager + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + ResourceClient sql.ResourceClient } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=azuresqldatabases,verbs=get;list;watch;create;update;patch;delete @@ -157,7 +157,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") } - _, err = r.SQLManager.CreateOrUpdateDB(ctx, groupName, location, server, azureSqlDatabaseProperties) + _, err = r.ResourceClient.CreateOrUpdateDB(ctx, groupName, location, server, azureSqlDatabaseProperties) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -170,7 +170,7 @@ func (r *AzureSqlDatabaseReconciler) reconcileExternal(instance *azurev1alpha1.A return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetDB(ctx, groupName, server, dbName) + _, err = r.ResourceClient.GetDB(ctx, groupName, server, dbName) if err != nil { return errhelp.NewAzureError(err) } @@ -192,7 +192,7 @@ func (r *AzureSqlDatabaseReconciler) deleteExternal(instance *azurev1alpha1.Azur dbName := instance.ObjectMeta.Name r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/database/%s"+groupName, server, dbName)) - _, err := r.SQLManager.DeleteDB(ctx, groupName, server, dbName) + _, err := r.ResourceClient.DeleteDB(ctx, groupName, server, dbName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, corev1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlfirewallrule_controller.go b/controllers/azuresqlfirewallrule_controller.go index eda3ad09f47..9f1e60bb0e2 100644 --- a/controllers/azuresqlfirewallrule_controller.go +++ b/controllers/azuresqlfirewallrule_controller.go @@ -40,10 +40,10 @@ const azureSQLFirewallRuleFinalizerName = "azuresqlfirewallrule.finalizers.azure // AzureSqlFirewallRuleReconciler reconciles a AzureSqlFirewallRule object type AzureSqlFirewallRuleReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme - SQLManager sql.SQLManager + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + ResourceClient sql.ResourceClient } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=azuresqlfirewallrules,verbs=get;list;watch;create;update;patch;delete @@ -176,7 +176,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph r.Recorder.Event(instance, v1.EventTypeWarning, "Failed", "Unable to update instance") } - _, err = r.SQLManager.CreateOrUpdateSQLFirewallRule(ctx, groupName, server, ruleName, startIP, endIP) + _, err = r.ResourceClient.CreateOrUpdateSQLFirewallRule(ctx, groupName, server, ruleName, startIP, endIP) if err != nil { if errhelp.IsAsynchronousOperationNotComplete(err) || errhelp.IsGroupNotFound(err) { r.Log.Info("Async operation not complete or group not found") @@ -186,7 +186,7 @@ func (r *AzureSqlFirewallRuleReconciler) reconcileExternal(instance *azurev1alph return errhelp.NewAzureError(err) } - _, err = r.SQLManager.GetSQLFirewallRule(ctx, groupName, server, ruleName) + _, err = r.ResourceClient.GetSQLFirewallRule(ctx, groupName, server, ruleName) if err != nil { return errhelp.NewAzureError(err) } @@ -204,7 +204,7 @@ func (r *AzureSqlFirewallRuleReconciler) deleteExternal(instance *azurev1alpha1. ruleName := instance.ObjectMeta.Name r.Log.Info(fmt.Sprintf("deleting external resource: group/%s/server/%s/firewallrule/%s"+groupName, server, ruleName)) - err := r.SQLManager.DeleteSQLFirewallRule(ctx, groupName, server, ruleName) + err := r.ResourceClient.DeleteSQLFirewallRule(ctx, groupName, server, ruleName) if err != nil { if errhelp.IsStatusCode204(err) { r.Recorder.Event(instance, v1.EventTypeWarning, "DoesNotExist", "Resource to delete does not exist") diff --git a/controllers/azuresqlserver_controller.go b/controllers/azuresqlserver_controller.go index 45ecee71348..fbce84339e3 100644 --- a/controllers/azuresqlserver_controller.go +++ b/controllers/azuresqlserver_controller.go @@ -44,10 +44,10 @@ import ( // AzureSqlServerReconciler reconciles an AzureSqlServer object type AzureSqlServerReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme - SQLManager sql.SQLManager + Log logr.Logger + Recorder record.EventRecorder + Scheme *runtime.Scheme + ResourceClient sql.ResourceClient } // Constants @@ -237,7 +237,7 @@ func (r *AzureSqlServerReconciler) reconcileExternal(instance *azurev1alpha1.Azu // create the sql server instance.Status.Provisioning = true - if _, err := r.SQLManager.CreateOrUpdateSQLServer(ctx, groupName, location, name, azureSqlServerProperties); err != nil { + if _, err := r.ResourceClient.CreateOrUpdateSQLServer(ctx, groupName, location, name, azureSqlServerProperties); err != nil { if !strings.Contains(err.Error(), "not complete") { msg := fmt.Sprintf("CreateOrUpdateSQLServer not complete: %v", err) instance.Status.Message = msg @@ -275,7 +275,7 @@ func (r *AzureSqlServerReconciler) verifyExternal(instance *azurev1alpha1.AzureS name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - serv, err := r.SQLManager.GetServer(ctx, groupName, name) + serv, err := r.ResourceClient.GetServer(ctx, groupName, name) if err != nil { azerr := errhelp.NewAzureError(err).(*errhelp.AzureError) if azerr.Type != errhelp.ResourceNotFound { @@ -310,7 +310,7 @@ func (r *AzureSqlServerReconciler) deleteExternal(instance *azurev1alpha1.AzureS name := instance.ObjectMeta.Name groupName := instance.Spec.ResourceGroup - _, err := r.SQLManager.DeleteSQLServer(ctx, groupName, name) + _, err := r.ResourceClient.DeleteSQLServer(ctx, groupName, name) if err != nil { msg := fmt.Sprintf("Couldn't delete resource in Azure: %v", err) instance.Status.Message = msg diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 7fa1a5fe14b..62fb2a8a5db 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -145,21 +145,21 @@ var _ = BeforeSuite(func() { var eventHubManagers resourcemanagereventhub.EventHubManagers var storageManagers resourcemanagerstorages.StorageManagers var keyVaultManager resourcemanagerkeyvaults.KeyVaultManager - var sqlManager resourcemanagersql.SQLManager + var resourceClient resourcemanagersql.ResourceClient if os.Getenv("TEST_CONTROLLER_WITH_MOCKS") == "false" { resourceGroupManager = resourcegroupsresourcemanager.AzureResourceGroupManager eventHubManagers = resourcemanagereventhub.AzureEventHubManagers storageManagers = resourcemanagerstorages.AzureStorageManagers keyVaultManager = resourcemanagerkeyvaults.AzureKeyVaultManager - sqlManager = &resourcemanagersql.GoSDKClient{} + resourceClient = &resourcemanagersql.GoSDKClient{} timeout = time.Second * 320 } else { resourceGroupManager = &resourcegroupsresourcemanagermock.MockResourceGroupManager{} eventHubManagers = resourcemanagereventhubmock.MockEventHubManagers storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} - sqlManager = &resourcemanagersqlmock.MockGoSDKClient{} + resourceClient = &resourcemanagersqlmock.MockGoSDKClient{} timeout = time.Second * 20 } @@ -205,20 +205,20 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) err = (&AzureSqlServerReconciler{ - Client: k8sManager.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlServer"), - Recorder: k8sManager.GetEventRecorderFor("AzureSqlServer-controller"), - Scheme: scheme.Scheme, - SQLManager: sqlManager, + Client: k8sManager.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlServer"), + Recorder: k8sManager.GetEventRecorderFor("AzureSqlServer-controller"), + Scheme: scheme.Scheme, + ResourceClient: resourceClient, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) err = (&AzureSqlDatabaseReconciler{ - Client: k8sManager.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), - Recorder: k8sManager.GetEventRecorderFor("AzureSqlDatabase-controller"), - Scheme: scheme.Scheme, - SQLManager: sqlManager, + Client: k8sManager.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), + Recorder: k8sManager.GetEventRecorderFor("AzureSqlDatabase-controller"), + Scheme: scheme.Scheme, + ResourceClient: resourceClient, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index 948dab74798..346522393e6 100644 --- a/main.go +++ b/main.go @@ -85,7 +85,7 @@ func main() { eventhubManagers := resourcemanagereventhub.AzureEventHubManagers storageManagers := resourcemanagerstorage.AzureStorageManagers keyVaultManager := resourcemanagerkeyvault.AzureKeyVaultManager - sqlManager := resourcemanagersql.GoSDKClient{} + resourceClient := resourcemanagersql.GoSDKClient{} err = (&controllers.StorageReconciler{ Client: mgr.GetClient(), @@ -174,41 +174,41 @@ func main() { } if err = (&controllers.AzureSqlServerReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlServer"), - Recorder: mgr.GetEventRecorderFor("AzureSqlServer-controller"), - Scheme: mgr.GetScheme(), - SQLManager: sqlManager, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlServer"), + Recorder: mgr.GetEventRecorderFor("AzureSqlServer-controller"), + Scheme: mgr.GetScheme(), + ResourceClient: resourceClient, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "AzureSqlServer") os.Exit(1) } if err = (&controllers.AzureSqlDatabaseReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), - Recorder: mgr.GetEventRecorderFor("AzureSqlDatabase-controller"), - Scheme: mgr.GetScheme(), - SQLManager: sqlManager, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), + Recorder: mgr.GetEventRecorderFor("AzureSqlDatabase-controller"), + Scheme: mgr.GetScheme(), + ResourceClient: resourceClient, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "AzureSqlDatabase") os.Exit(1) } if err = (&controllers.AzureSqlFirewallRuleReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("SqlFirewallRule"), - Recorder: mgr.GetEventRecorderFor("SqlFirewallRule-controller"), - Scheme: mgr.GetScheme(), - SQLManager: sqlManager, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("SqlFirewallRule"), + Recorder: mgr.GetEventRecorderFor("SqlFirewallRule-controller"), + Scheme: mgr.GetScheme(), + ResourceClient: resourceClient, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "SqlFirewallRule") os.Exit(1) } if err = (&controllers.AzureSqlActionReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlAction"), - Recorder: mgr.GetEventRecorderFor("AzureSqlAction-controller"), - Scheme: mgr.GetScheme(), - SQLManager: sqlManager, + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("AzureSqlAction"), + Recorder: mgr.GetEventRecorderFor("AzureSqlAction-controller"), + Scheme: mgr.GetScheme(), + ResourceClient: resourceClient, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "AzureSqlAction") os.Exit(1) diff --git a/pkg/resourcemanager/sqlclient/resourceclient.go b/pkg/resourcemanager/sqlclient/resourceclient.go index 9cb308a736e..c8b5521a799 100644 --- a/pkg/resourcemanager/sqlclient/resourceclient.go +++ b/pkg/resourcemanager/sqlclient/resourceclient.go @@ -6,22 +6,23 @@ package sqlclient import ( + "context" + "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" "github.com/Azure/go-autorest/autorest" ) // ResourceClient contains the helper functions for interacting with SQL servers / databases type ResourceClient interface { - CreateOrUpdateSQLServer(properties SQLServerProperties) (result sql.Server, err error) - CreateOrUpdateSQLFirewallRule(ruleName string, startIP string, endIP string) (result bool, err error) - CreateOrUpdateDB(properties SQLDatabaseProperties) (result sql.Database, err error) - CreateOrUpdateFailoverGroup(failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroup, err error) - GetServer() (result sql.Server, err error) - GetSQLFirewallRule(ruleName string) (result sql.FirewallRule, err error) - GetDB(databaseName string) (sql.Database, error) - DeleteDB(databaseName string) (result autorest.Response, err error) - DeleteSQLFirewallRule(ruleName string) (err error) - DeleteSQLServer() (result autorest.Response, err error) - DeleteFailoverGroup(failoverGroupName string) - CheckNameAvailability() (result AvailabilityResponse, err error) + CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLServerProperties) (result sql.Server, err error) + DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) + GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) + DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) + CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) + DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) + DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) + GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) + GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) + CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) + CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) } From f59f811536c97bb7314bf63cf8d6c8185fae0a89 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Thu, 24 Oct 2019 12:31:41 +1100 Subject: [PATCH 22/27] remove redundant file --- .../mock/sqlclient/sqlclient_gosdk.go | 20 ++++++------- .../sqlclient/sqlclient_manager.go | 28 ------------------- 2 files changed, 10 insertions(+), 38 deletions(-) delete mode 100644 pkg/resourcemanager/sqlclient/sqlclient_manager.go diff --git a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go index 4e245c4eeb4..36645c1d59f 100644 --- a/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go +++ b/pkg/resourcemanager/mock/sqlclient/sqlclient_gosdk.go @@ -28,11 +28,11 @@ import ( // MockGoSDKClient struct type MockGoSDKClient struct { - sqlServer sql.Server - sqlDatabase sql.Database - sqlFirewallRule sql.FirewallRule - sqlDatabasesCreateOrUpdateFuture sql.DatabasesCreateOrUpdateFuture - sqlFailoverGroupsCreateOrUpdateFuture sql.FailoverGroupsCreateOrUpdateFuture + Server sql.Server + Database sql.Database + FirewallRule sql.FirewallRule + DatabasesCreateOrUpdateFuture sql.DatabasesCreateOrUpdateFuture + FailoverGroupsCreateOrUpdateFuture sql.FailoverGroupsCreateOrUpdateFuture } // CreateOrUpdateSQLServer creates a new sql server @@ -41,7 +41,7 @@ func (sdk *MockGoSDKClient) CreateOrUpdateSQLServer(ctx context.Context, resourc Response: helpers.GetRestResponse(http.StatusCreated), } - sdk.sqlServer = sqlServer + sdk.Server = sqlServer return sqlServer, nil } @@ -62,7 +62,7 @@ func (sdk *MockGoSDKClient) GetServer(ctx context.Context, resourceGroupName str ServerProperties: &serverProperties, } - sdk.sqlServer = sqlServer + sdk.Server = sqlServer return sqlServer, nil } @@ -91,7 +91,7 @@ func (sdk *MockGoSDKClient) GetSQLFirewallRule(ctx context.Context, resourceGrou Response: helpers.GetRestResponse(http.StatusCreated), } - sdk.sqlFirewallRule = sqlFirewallRule + sdk.FirewallRule = sqlFirewallRule return sqlFirewallRule, nil } @@ -103,7 +103,7 @@ func (sdk *MockGoSDKClient) GetDB(ctx context.Context, resourceGroupName string, Response: helpers.GetRestResponse(http.StatusCreated), } - sdk.sqlDatabase = sqlDatabase + sdk.Database = sqlDatabase return sqlDatabase, nil } @@ -120,7 +120,7 @@ func (sdk *MockGoSDKClient) CreateOrUpdateDB(ctx context.Context, resourceGroupN func (sdk *MockGoSDKClient) CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties sqlclient.SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) { var sqlFailoverGroupsCreateOrUpdateFuture = sql.FailoverGroupsCreateOrUpdateFuture{} - sdk.sqlFailoverGroupsCreateOrUpdateFuture = sqlFailoverGroupsCreateOrUpdateFuture + sdk.FailoverGroupsCreateOrUpdateFuture = sqlFailoverGroupsCreateOrUpdateFuture return sqlFailoverGroupsCreateOrUpdateFuture, nil diff --git a/pkg/resourcemanager/sqlclient/sqlclient_manager.go b/pkg/resourcemanager/sqlclient/sqlclient_manager.go deleted file mode 100644 index 02f00e4fb6e..00000000000 --- a/pkg/resourcemanager/sqlclient/sqlclient_manager.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft and contributors. All rights reserved. -// -// This source code is licensed under the MIT license found in the -// LICENSE file in the root directory of this source tree. - -package sqlclient - -import ( - "context" - - "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" - "github.com/Azure/go-autorest/autorest" -) - -// SQLManager interface -type SQLManager interface { - CreateOrUpdateSQLServer(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLServerProperties) (result sql.Server, err error) - DeleteSQLServer(ctx context.Context, resourceGroupName string, serverName string) (result autorest.Response, err error) - GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) - DeleteSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (err error) - CreateOrUpdateFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failovergroupname string, properties SQLFailoverGroupProperties) (result sql.FailoverGroupsCreateOrUpdateFuture, err error) - DeleteFailoverGroup(ctx context.Context, resourceGroupName string, serverName string, failoverGroupName string) (result autorest.Response, err error) - DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) - GetSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string) (result sql.FirewallRule, err error) - GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) - CreateOrUpdateDB(ctx context.Context, resourceGroupName string, location string, serverName string, properties SQLDatabaseProperties) (sql.DatabasesCreateOrUpdateFuture, error) - CreateOrUpdateSQLFirewallRule(ctx context.Context, resourceGroupName string, serverName string, ruleName string, startIP string, endIP string) (result bool, err error) -} From 77c8ae591480f5b730f8a11a8a7d50e7c6b34251 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Thu, 24 Oct 2019 13:04:33 +1100 Subject: [PATCH 23/27] enable parallel tests --- controllers/suite_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 62fb2a8a5db..3854374b0b6 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - //t.Parallel() + t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, @@ -160,7 +160,7 @@ var _ = BeforeSuite(func() { storageManagers = resourcemanagerstoragesmock.MockStorageManagers keyVaultManager = &resourcemanagerkeyvaultsmock.MockKeyVaultManager{} resourceClient = &resourcemanagersqlmock.MockGoSDKClient{} - timeout = time.Second * 20 + timeout = time.Second * 60 } err = (&KeyVaultReconciler{ From 30885351f197240e81314f35a0ed4b9bb4a25f28 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 25 Oct 2019 13:21:57 +1100 Subject: [PATCH 24/27] add tests and fix issues --- Makefile | 4 +- api/v1alpha1/azuresqldatabase_types.go | 9 ++ controllers/azuresqldatabase_controller.go | 27 ++-- .../azuresqldatabase_controller_finalizer.go | 36 ++++++ .../azuresqldatabase_controller_test.go | 120 ++++++++++++++++++ controllers/azuresqlserver_controller_test.go | 113 +++++++++++++++++ 6 files changed, 291 insertions(+), 18 deletions(-) create mode 100644 controllers/azuresqldatabase_controller_finalizer.go create mode 100644 controllers/azuresqldatabase_controller_test.go create mode 100644 controllers/azuresqlserver_controller_test.go diff --git a/Makefile b/Makefile index 5d8d9e48bd6..fec9e27faf0 100644 --- a/Makefile +++ b/Makefile @@ -34,13 +34,13 @@ api-test: generate fmt vet manifests # Run tests test: generate fmt vet manifests - TEST_USE_EXISTING_CLUSTER=false TEST_CONTROLLER_WITH_MOCKS=true go test -v -coverprofile=coverage.txt -covermode count ./api/... ./controllers/... ./pkg/resourcemanager/eventhubs/... ./pkg/resourcemanager/resourcegroups/... ./pkg/resourcemanager/storages/... 2>&1 | tee testlogs.txt + TEST_USE_EXISTING_CLUSTER=false TEST_CONTROLLER_WITH_MOCKS=true REQUEUE_AFTER=20 go test -v -coverprofile=coverage.txt -covermode count ./api/... ./controllers/... ./pkg/resourcemanager/eventhubs/... ./pkg/resourcemanager/resourcegroups/... ./pkg/resourcemanager/storages/... 2>&1 | tee testlogs.txt go-junit-report < testlogs.txt > report.xml go tool cover -html=coverage.txt -o cover.html # Run tests with existing cluster test-existing: generate fmt vet manifests - TEST_USE_EXISTING_CLUSTER=true TEST_CONTROLLER_WITH_MOCKS=false go test -v -coverprofile=coverage-existing.txt -covermode count ./api/... ./controllers/... ./pkg/resourcemanager/eventhubs/... ./pkg/resourcemanager/resourcegroups/... ./pkg/resourcemanager/storages/... 2>&1 | tee testlogs-existing.txt + TEST_USE_EXISTING_CLUSTER=true TEST_CONTROLLER_WITH_MOCKS=false REQUEUE_AFTER=20 go test -v -coverprofile=coverage-existing.txt -covermode count ./api/... ./controllers/... ./pkg/resourcemanager/eventhubs/... ./pkg/resourcemanager/resourcegroups/... ./pkg/resourcemanager/storages/... 2>&1 | tee testlogs-existing.txt go-junit-report < testlogs-existing.txt > report-existing.xml go tool cover -html=coverage-existing.txt -o cover-existing.html diff --git a/api/v1alpha1/azuresqldatabase_types.go b/api/v1alpha1/azuresqldatabase_types.go index 52d2cecd358..2918bd14bf0 100644 --- a/api/v1alpha1/azuresqldatabase_types.go +++ b/api/v1alpha1/azuresqldatabase_types.go @@ -16,6 +16,7 @@ limitations under the License. package v1alpha1 import ( + helpers "github.com/Azure/azure-service-operator/pkg/helpers" sql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -67,3 +68,11 @@ func init() { func (s *AzureSqlDatabase) IsSubmitted() bool { return s.Status.Provisioned } + +func (s *AzureSqlDatabase) HasFinalizer(finalizerName string) bool { + return helpers.ContainsString(s.ObjectMeta.Finalizers, finalizerName) +} + +func (s *AzureSqlDatabase) IsBeingDeleted() bool { + return !s.ObjectMeta.DeletionTimestamp.IsZero() +} diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index e784de67f51..3977875d428 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -18,6 +18,8 @@ package controllers import ( "context" "fmt" + "os" + "strconv" "time" "github.com/Azure/azure-service-operator/pkg/errhelp" @@ -37,8 +39,6 @@ import ( azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" ) -const azureSQLDatabaseFinalizerName = "azuresqldatabase.finalizers.azure.com" - // AzureSqlDatabaseReconciler reconciles a AzureSqlDatabase object type AzureSqlDatabaseReconciler struct { client.Client @@ -66,13 +66,13 @@ func (r *AzureSqlDatabaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e } if helpers.IsBeingDeleted(&instance) { - if helpers.HasFinalizer(&instance, azureSQLDatabaseFinalizerName) { + if helpers.HasFinalizer(&instance, AzureSQLDatabaseFinalizerName) { if err := r.deleteExternal(&instance); err != nil { log.Info("Delete AzureSqlDatabase failed with ", "err", err.Error()) return ctrl.Result{}, err } - helpers.RemoveFinalizer(&instance, azureSQLDatabaseFinalizerName) + helpers.RemoveFinalizer(&instance, AzureSQLDatabaseFinalizerName) if err := r.Status().Update(context.Background(), &instance); err != nil { return ctrl.Result{}, err } @@ -80,13 +80,18 @@ func (r *AzureSqlDatabaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e return ctrl.Result{}, nil } - if !helpers.HasFinalizer(&instance, azureSQLDatabaseFinalizerName) { + if !instance.HasFinalizer(AzureSQLDatabaseFinalizerName) { if err := r.addFinalizer(&instance); err != nil { log.Info("Adding AzureSqlDatabase finalizer failed with ", "error", err.Error()) return ctrl.Result{}, err } } + requeueAfter, err := strconv.Atoi(os.Getenv("REQUEUE_AFTER")) + if err != nil { + requeueAfter = 30 + } + if !instance.IsSubmitted() { r.Recorder.Event(&instance, corev1.EventTypeNormal, "Submitting", "starting resource reconciliation for AzureSqlDatabase") if err := r.reconcileExternal(&instance); err != nil { @@ -100,7 +105,7 @@ func (r *AzureSqlDatabaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e if azerr, ok := err.(*errhelp.AzureError); ok { if helpers.ContainsString(catch, azerr.Type) { log.Info("Got ignorable error", "type", azerr.Type) - return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil + return ctrl.Result{Requeue: true, RequeueAfter: time.Duration(requeueAfter) * time.Second}, nil } } return ctrl.Result{}, fmt.Errorf("error reconciling azure sql database in azure: %v", err) @@ -205,13 +210,3 @@ func (r *AzureSqlDatabaseReconciler) deleteExternal(instance *azurev1alpha1.Azur r.Recorder.Event(instance, corev1.EventTypeNormal, "Deleted", dbName+" deleted") return nil } - -func (r *AzureSqlDatabaseReconciler) addFinalizer(instance *azurev1alpha1.AzureSqlDatabase) error { - helpers.AddFinalizer(instance, azureSQLDatabaseFinalizerName) - err := r.Status().Update(context.Background(), instance) - if err != nil { - return fmt.Errorf("failed to update finalizer: %v", err) - } - r.Recorder.Event(instance, corev1.EventTypeNormal, "Updated", fmt.Sprintf("finalizer %s added", azureSQLDatabaseFinalizerName)) - return nil -} diff --git a/controllers/azuresqldatabase_controller_finalizer.go b/controllers/azuresqldatabase_controller_finalizer.go new file mode 100644 index 00000000000..0925ceac3ba --- /dev/null +++ b/controllers/azuresqldatabase_controller_finalizer.go @@ -0,0 +1,36 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + "fmt" + + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + helpers "github.com/Azure/azure-service-operator/pkg/helpers" +) + +const AzureSQLDatabaseFinalizerName = "azuresqldatabase.finalizers.azure.com" + +func (r *AzureSqlDatabaseReconciler) addFinalizer(instance *azurev1alpha1.AzureSqlDatabase) error { + helpers.AddFinalizer(instance, AzureSQLDatabaseFinalizerName) + if updateerr := r.Update(context.Background(), instance); updateerr != nil { + r.Recorder.Event(instance, "Warning", "Failed", "Failed to update finalizer") + } + r.Recorder.Event(instance, "Normal", "Updated", fmt.Sprintf("finalizer %s added", AzureSQLDatabaseFinalizerName)) + return nil +} diff --git a/controllers/azuresqldatabase_controller_test.go b/controllers/azuresqldatabase_controller_test.go new file mode 100644 index 00000000000..3209d2e1cc1 --- /dev/null +++ b/controllers/azuresqldatabase_controller_test.go @@ -0,0 +1,120 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + + helpers "github.com/Azure/azure-service-operator/pkg/helpers" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("AzureSqlDatabase Controller", func() { + + var rgName string + var rgLocation string + //var sqlName string + + BeforeEach(func() { + // Add any setup steps that needs to be executed before each test + rgName = tc.resourceGroupName + rgLocation = tc.resourceGroupLocation + }) + + AfterEach(func() { + // Add any teardown steps that needs to be executed after each test + }) + + // Add Tests for OpenAPI validation (or additonal CRD features) specified in + // your API definition. + // Avoid adding tests for vanilla CRUD operations because they would + // test Kubernetes API server, which isn't the goal here. + + Context("Create and Delete", func() { + It("should create and delete sql database in k8s", func() { + + randomName := helpers.RandomString(10) + sqlServerName := "t-sqlserver-dev-" + randomName + sqlDatabaseName := "t-sqldatabase-dev-" + randomName + + var err error + + // Create the SqlServer object and expect the Reconcile to be created + sqlServerInstance := &azurev1alpha1.AzureSqlServer{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlServerName, + Namespace: "default", + }, + Spec: azurev1alpha1.AzureSqlServerSpec{ + Location: rgLocation, + ResourceGroup: rgName, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlServerInstance) + Expect(err).NotTo(HaveOccurred()) + + // Create the SqlDatabase object and expect the Reconcile to be created + sqlDatabaseInstance := &azurev1alpha1.AzureSqlDatabase{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlDatabaseName, + Namespace: "default", + }, + Spec: azurev1alpha1.AzureSqlDatabaseSpec{ + Location: rgLocation, + ResourceGroup: rgName, + Server: sqlServerName, + Edition: 0, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlDatabaseInstance) + Expect(apierrors.IsInvalid(err)).To(Equal(false)) + Expect(err).NotTo(HaveOccurred()) + + sqlDatabaseNamespacedName := types.NamespacedName{Name: sqlDatabaseName, Namespace: "default"} + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return helpers.HasFinalizer(sqlDatabaseInstance, AzureSQLDatabaseFinalizerName) + }, tc.timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return sqlDatabaseInstance.IsSubmitted() + }, tc.timeout, + ).Should(BeTrue()) + + err = tc.k8sClient.Delete(context.Background(), sqlDatabaseInstance) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) + return helpers.IsBeingDeleted(sqlDatabaseInstance) + }, tc.timeout, + ).Should(BeTrue()) + + }) + }) +}) diff --git a/controllers/azuresqlserver_controller_test.go b/controllers/azuresqlserver_controller_test.go new file mode 100644 index 00000000000..04ad68072e6 --- /dev/null +++ b/controllers/azuresqlserver_controller_test.go @@ -0,0 +1,113 @@ +/* +Copyright 2019 microsoft. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controllers + +import ( + "context" + + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + + helpers "github.com/Azure/azure-service-operator/pkg/helpers" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + v1 "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" +) + +var _ = Describe("AzureSqlServer Controller", func() { + + var rgName string + var rgLocation string + + BeforeEach(func() { + // Add any setup steps that needs to be executed before each test + rgName = tc.resourceGroupName + rgLocation = tc.resourceGroupLocation + }) + + AfterEach(func() { + // Add any teardown steps that needs to be executed after each test + }) + + // Add Tests for OpenAPI validation (or additonal CRD features) specified in + // your API definition. + // Avoid adding tests for vanilla CRUD operations because they would + // test Kubernetes API server, which isn't the goal here. + + Context("Create and Delete", func() { + It("should create and delete sql server in k8s", func() { + sqlServerName := "t-sqlserver-dev-" + helpers.RandomString(10) + + var err error + + // Create the SqlServer object and expect the Reconcile to be created + sqlServerInstance := &azurev1alpha1.AzureSqlServer{ + ObjectMeta: metav1.ObjectMeta{ + Name: sqlServerName, + Namespace: "default", + }, + Spec: azurev1alpha1.AzureSqlServerSpec{ + Location: rgLocation, + ResourceGroup: rgName, + }, + } + + err = tc.k8sClient.Create(context.Background(), sqlServerInstance) + Expect(apierrors.IsInvalid(err)).To(Equal(false)) + Expect(err).NotTo(HaveOccurred()) + + sqlServerNamespacedName := types.NamespacedName{Name: sqlServerName, Namespace: "default"} + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return helpers.HasFinalizer(sqlServerInstance, AzureSQLServerFinalizerName) + }, tc.timeout, + ).Should(BeTrue()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return sqlServerInstance.IsSubmitted() + }, tc.timeout, + ).Should(BeTrue()) + + //verify secret exists in k8s + secret := &v1.Secret{} + Eventually(func() bool { + err = tc.k8sClient.Get(context.Background(), types.NamespacedName{Name: sqlServerName, Namespace: sqlServerInstance.Namespace}, secret) + if err == nil { + if (secret.ObjectMeta.Name == sqlServerName) && (secret.ObjectMeta.Namespace == sqlServerInstance.Namespace) { + return true + } + } + return false + }, tc.timeout, + ).Should(BeTrue()) + + err = tc.k8sClient.Delete(context.Background(), sqlServerInstance) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() bool { + _ = tc.k8sClient.Get(context.Background(), sqlServerNamespacedName, sqlServerInstance) + return helpers.IsBeingDeleted(sqlServerInstance) + }, tc.timeout, + ).Should(BeTrue()) + + }) + }) +}) From c441016e45b584cee616242fad363381c0114cbb Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 25 Oct 2019 14:47:30 +1100 Subject: [PATCH 25/27] disable parallel tests --- controllers/suite_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 3854374b0b6..64b3ec4082b 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -78,7 +78,7 @@ type testContext struct { var tc testContext func TestAPIs(t *testing.T) { - t.Parallel() + //t.Parallel() RegisterFailHandler(Fail) RunSpecsWithDefaultAndCustomReporters(t, From 11ac8150b954e9bb5279c830cae0dcf55f5a24b4 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Fri, 25 Oct 2019 15:20:12 +1100 Subject: [PATCH 26/27] use requeue_after env variable --- controllers/eventhub_controller.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/controllers/eventhub_controller.go b/controllers/eventhub_controller.go index 1931dfca8cd..cf41d7e62fc 100644 --- a/controllers/eventhub_controller.go +++ b/controllers/eventhub_controller.go @@ -19,6 +19,8 @@ import ( "context" "fmt" "net/http" + "os" + "strconv" "time" "github.com/Azure/azure-service-operator/pkg/resourcemanager/config" @@ -89,6 +91,11 @@ func (r *EventhubReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, nil } + requeueAfter, err := strconv.Atoi(os.Getenv("REQUEUE_AFTER")) + if err != nil { + requeueAfter = 30 + } + if !instance.IsSubmitted() { err := r.reconcileExternal(&instance) if err != nil { @@ -100,7 +107,7 @@ func (r *EventhubReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { if azerr, ok := err.(*errhelp.AzureError); ok { if helpers.ContainsString(catch, azerr.Type) { log.Info("Got ignorable error", "type", azerr.Type) - return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil + return ctrl.Result{Requeue: true, RequeueAfter: time.Duration(requeueAfter) * time.Second}, nil } } From 52a13d6fc58d81cd6dc02b8f07fb10194151da78 Mon Sep 17 00:00:00 2001 From: Priya Kumaran Date: Mon, 28 Oct 2019 09:06:06 +1100 Subject: [PATCH 27/27] make requeue time configurablle in eh ns --- controllers/eventhubnamespace_controller.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/controllers/eventhubnamespace_controller.go b/controllers/eventhubnamespace_controller.go index aa18e040efb..3d15ae7218c 100644 --- a/controllers/eventhubnamespace_controller.go +++ b/controllers/eventhubnamespace_controller.go @@ -18,6 +18,8 @@ package controllers import ( "context" "fmt" + "os" + "strconv" "time" azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" @@ -26,13 +28,13 @@ import ( eventhubsresourcemanager "github.com/Azure/azure-service-operator/pkg/resourcemanager/eventhubs" "github.com/go-logr/logr" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "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/reconcile" - v1 "k8s.io/api/core/v1" ) // EventhubNamespaceReconciler reconciles a EventhubNamespace object @@ -75,6 +77,11 @@ func (r *EventhubNamespaceReconciler) Reconcile(req ctrl.Request) (ctrl.Result, return ctrl.Result{}, nil } + requeueAfter, err := strconv.Atoi(os.Getenv("REQUEUE_AFTER")) + if err != nil { + requeueAfter = 30 + } + if !instance.IsSubmitted() { err := r.reconcileExternal(&instance) if err != nil { @@ -84,7 +91,7 @@ func (r *EventhubNamespaceReconciler) Reconcile(req ctrl.Request) (ctrl.Result, } if helpers.ContainsString(catch, err.(*errhelp.AzureError).Type) { log.Info("Got ignorable error", "type", err.(*errhelp.AzureError).Type) - return ctrl.Result{Requeue: true, RequeueAfter: 30 * time.Second}, nil + return ctrl.Result{Requeue: true, RequeueAfter: time.Duration(requeueAfter) * time.Second}, nil } return ctrl.Result{}, fmt.Errorf("error when creating resource in azure: %v", err)