diff --git a/api/v1alpha1/azuresqldatabase_types.go b/api/v1alpha1/azuresqldatabase_types.go index 543b051aca1..7f45f1a8fc1 100644 --- a/api/v1alpha1/azuresqldatabase_types.go +++ b/api/v1alpha1/azuresqldatabase_types.go @@ -17,20 +17,22 @@ 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" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +// DBEdition - wraps: https://godoc.org/github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql#DatabaseEdition +type DBEdition byte + // AzureSqlDatabaseSpec defines the desired state of AzureSqlDatabase type AzureSqlDatabaseSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - Location string `json:"location"` - ResourceGroup string `json:"resourcegroup,omitempty"` - Server string `json:"server"` - Edition sql.DBEdition `json:"edition"` + Location string `json:"location"` + ResourceGroup string `json:"resourcegroup,omitempty"` + Server string `json:"server"` + Edition DBEdition `json:"edition"` } // +kubebuilder:object:root=true diff --git a/api/v1alpha1/azuresqlfailovergroup_types.go b/api/v1alpha1/azuresqlfailovergroup_types.go index f3d70182a06..4667ea9ac42 100644 --- a/api/v1alpha1/azuresqlfailovergroup_types.go +++ b/api/v1alpha1/azuresqlfailovergroup_types.go @@ -16,23 +16,25 @@ limitations under the License. package v1alpha1 import ( - sql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +// ReadWriteEndpointFailoverPolicy - wraps https://godoc.org/github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql#ReadWriteEndpointFailoverPolicy +type ReadWriteEndpointFailoverPolicy string + // AzureSqlFailoverGroupSpec defines the desired state of AzureSqlFailoverGroup type AzureSqlFailoverGroupSpec struct { // Important: Run "make" to regenerate code after modifying this file - Location string `json:"location"` - ResourceGroup string `json:"resourcegroup,omitempty"` - Server string `json:"server"` - FailoverPolicy sql.ReadWriteEndpointFailoverPolicy `json:"failoverpolicy"` - FailoverGracePeriod int32 `json:"failovergraceperiod"` - SecondaryServerName string `json:"secondaryserver"` - SecondaryServerResourceGroup string `json:"secondaryserverresourcegroup"` - DatabaseList []string `json:"databaselist"` + Location string `json:"location"` + ResourceGroup string `json:"resourcegroup,omitempty"` + Server string `json:"server"` + FailoverPolicy ReadWriteEndpointFailoverPolicy `json:"failoverpolicy"` + FailoverGracePeriod int32 `json:"failovergraceperiod"` + SecondaryServerName string `json:"secondaryserver"` + SecondaryServerResourceGroup string `json:"secondaryserverresourcegroup"` + DatabaseList []string `json:"databaselist"` } // AzureSqlFailoverGroupStatus defines the observed state of AzureSqlFailoverGroup diff --git a/controllers/azuresqldatabase_controller.go b/controllers/azuresqldatabase_controller.go index 3436deb160f..07833b20b90 100644 --- a/controllers/azuresqldatabase_controller.go +++ b/controllers/azuresqldatabase_controller.go @@ -16,196 +16,29 @@ limitations under the License. package controllers import ( - "context" - "fmt" - "os" - "strconv" - "time" - - "github.com/Azure/azure-service-operator/pkg/errhelp" - helpers "github.com/Azure/azure-service-operator/pkg/helpers" - sql "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" - //"github.com/Azure/go-autorest/autorest/to" - "github.com/go-logr/logr" - corev1 "k8s.io/api/core/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" ) -// AzureSqlDatabaseReconciler reconciles a AzureSqlDatabase object +// AzureSqlDbReconciler reconciles a AzureSqlDatabase object type AzureSqlDatabaseReconciler struct { client.Client - Log logr.Logger - Recorder record.EventRecorder - Scheme *runtime.Scheme - AzureSqlDbManager sql.SqlDbManager + Reconciler *AsyncReconciler } // +kubebuilder:rbac:groups=azure.microsoft.com,resources=azuresqldatabases,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=azure.microsoft.com,resources=azuresqldatabases/status,verbs=get;update;patch +// Reconcile function does the main reconciliation loop of the operator func (r *AzureSqlDatabaseReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - ctx := context.Background() - log := r.Log.WithValues("azuresqldatabase", req.NamespacedName) - - var instance azurev1alpha1.AzureSqlDatabase - - if err := r.Get(ctx, req.NamespacedName, &instance); err != nil { - log.Info("Unable to retrieve azure-sql-database resource", "err", err.Error()) - // we'll ignore not-found errors, since they can't be fixed by an immediate - // requeue (we'll need to wait for a new notification), and we can get them - // on deleted requests. - return ctrl.Result{}, client.IgnoreNotFound(err) - } - - defer func() { - if !helpers.IsBeingDeleted(&instance) { - if err := r.Status().Update(ctx, &instance); err != nil { - r.Recorder.Event(&instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") - } - } - }() - - if helpers.IsBeingDeleted(&instance) { - if helpers.HasFinalizer(&instance, AzureSQLDatabaseFinalizerName) { - if err := r.deleteExternal(ctx, &instance); err != nil { - log.Info("Delete AzureSqlDatabase failed with ", "err", err.Error()) - return ctrl.Result{}, err - } - - helpers.RemoveFinalizer(&instance, AzureSQLDatabaseFinalizerName) - if err := r.Update(context.Background(), &instance); err != nil { - return ctrl.Result{}, err - } - } - return ctrl.Result{}, nil - } - - 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(ctx, &instance); err != nil { - - catch := []string{ - errhelp.ParentNotFoundErrorCode, - errhelp.ResourceGroupNotFoundErrorCode, - errhelp.NotFoundErrorCode, - errhelp.AsyncOpIncompleteError, - } - azerr := errhelp.NewAzureErrorAzureError(err) - if helpers.ContainsString(catch, azerr.Type) { - log.Info("Got ignorable error", "type", azerr.Type) - 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) - } - return ctrl.Result{}, nil - } - - r.Recorder.Event(&instance, corev1.EventTypeNormal, "Provisioned", "azuresqldatabase "+instance.ObjectMeta.Name+" provisioned ") - - return ctrl.Result{}, nil + return r.Reconciler.Reconcile(req, &azurev1alpha1.AzureSqlDatabase{}) } +// SetupWithManager function sets up the functions with the controller func (r *AzureSqlDatabaseReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&azurev1alpha1.AzureSqlDatabase{}). Complete(r) } - -func (r *AzureSqlDatabaseReconciler) reconcileExternal(ctx context.Context, instance *azurev1alpha1.AzureSqlDatabase) error { - location := instance.Spec.Location - groupName := instance.Spec.ResourceGroup - server := instance.Spec.Server - dbName := instance.ObjectMeta.Name - dbEdition := instance.Spec.Edition - - azureSqlDatabaseProperties := sql.SQLDatabaseProperties{ - DatabaseName: dbName, - Edition: dbEdition, - } - - r.Log.Info("Calling createorupdate") - - //get owner instance of AzureSqlServer - r.Recorder.Event(instance, corev1.EventTypeNormal, "UpdatingOwner", "Updating owner AzureSqlServer instance") - var ownerInstance azurev1alpha1.AzureSqlServer - azureSqlServerNamespacedName := types.NamespacedName{Name: server, Namespace: instance.Namespace} - - err := r.Get(ctx, azureSqlServerNamespacedName, &ownerInstance) - if err != nil { - //log error and kill it, as the parent might not exist in the cluster. It could have been created elsewhere or through the portal directly - r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to get owner instance of AzureSqlServer") - } 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 AzureSqlServer") - } - r.Recorder.Event(instance, corev1.EventTypeNormal, "OwnerAssign", "Owner instance assigned successfully") - } - - // write information back to instance - if updateerr := r.Update(ctx, instance); updateerr != nil { - r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Unable to update instance") - } - - _, err = r.AzureSqlDbManager.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") - instance.Status.Provisioning = true - } - - return err - } - - _, err = r.AzureSqlDbManager.GetDB(ctx, groupName, server, dbName) - if err != nil { - return err - } - - instance.Status.Provisioning = false - instance.Status.Provisioned = true - - return nil -} - -func (r *AzureSqlDatabaseReconciler) deleteExternal(ctx context.Context, instance *azurev1alpha1.AzureSqlDatabase) error { - 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.AzureSqlDbManager.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") - return nil - } - - r.Recorder.Event(instance, corev1.EventTypeWarning, "Failed", "Couldn't delete resouce in azure") - return err - } - r.Recorder.Event(instance, corev1.EventTypeNormal, "Deleted", dbName+" deleted") - return nil -} diff --git a/controllers/azuresqldatabase_controller_finalizer.go b/controllers/azuresqldatabase_controller_finalizer.go deleted file mode 100644 index 0925ceac3ba..00000000000 --- a/controllers/azuresqldatabase_controller_finalizer.go +++ /dev/null @@ -1,36 +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" - - 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 index 82e5bf2f618..6fd6cdf81b3 100644 --- a/controllers/azuresqldatabase_controller_test.go +++ b/controllers/azuresqldatabase_controller_test.go @@ -127,7 +127,7 @@ var _ = Describe("AzureSqlDatabase Controller", func() { Eventually(func() bool { _ = tc.k8sClient.Get(context.Background(), sqlDatabaseNamespacedName, sqlDatabaseInstance) - return helpers.HasFinalizer(sqlDatabaseInstance, AzureSQLDatabaseFinalizerName) + return helpers.HasFinalizer(sqlDatabaseInstance, finalizerName) }, tc.timeout, tc.retry, ).Should(BeTrue()) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index b52868e3822..a9f033b1aa1 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -264,11 +264,16 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) err = (&AzureSqlDatabaseReconciler{ - Client: k8sManager.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("AzureSqlDatabase"), - Recorder: k8sManager.GetEventRecorderFor("AzureSqlDatabase-controller"), - Scheme: scheme.Scheme, - AzureSqlDbManager: sqlDbManager, + Reconciler: &AsyncReconciler{ + Client: k8sManager.GetClient(), + AzureClient: sqlDbManager, + Telemetry: telemetry.InitializePrometheusDefault( + ctrl.Log.WithName("controllers").WithName("AzureSqlDb"), + "AzureSqlDb", + ), + Recorder: k8sManager.GetEventRecorderFor("AzureSqlDb-controller"), + Scheme: scheme.Scheme, + }, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index 827dc0e25e1..d5cce5c0768 100644 --- a/main.go +++ b/main.go @@ -92,7 +92,7 @@ func main() { storageManagers := resourcemanagerstorage.AzureStorageManagers keyVaultManager := resourcemanagerkeyvault.AzureKeyVaultManager sqlServerManager := resourcemanagersql.NewAzureSqlServerManager(ctrl.Log.WithName("sqlservermanager").WithName("AzureSqlServer")) - sqlDBManager := resourcemanagersql.NewAzureSqlDbManager(ctrl.Log.WithName("sqldbmanager").WithName("AzureSqlDb")) + sqlDbManager := resourcemanagersql.NewAzureSqlDbManager(ctrl.Log.WithName("sqldbmanager").WithName("AzureSqlDb")) sqlFirewallRuleManager := resourcemanagersql.NewAzureSqlFirewallRuleManager(ctrl.Log.WithName("sqlfirewallrulemanager").WithName("AzureSqlFirewallRule")) sqlFailoverGroupManager := resourcemanagersql.NewAzureSqlFailoverGroupManager(ctrl.Log.WithName("sqlfailovergroupmanager").WithName("AzureSqlFailoverGroup")) sqlUserManager := resourcemanagersql.NewAzureSqlUserManager(ctrl.Log.WithName("sqlusermanager").WithName("AzureSqlUser")) @@ -215,16 +215,25 @@ func main() { 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(), - AzureSqlDbManager: sqlDBManager, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "AzureSqlDatabase") + + /* Azure Sql Database */ + err = (&controllers.AzureSqlDatabaseReconciler{ + Reconciler: &controllers.AsyncReconciler{ + Client: mgr.GetClient(), + AzureClient: sqlDbManager, + Telemetry: telemetry.InitializePrometheusDefault( + ctrl.Log.WithName("controllers").WithName("AzureSqlDb"), + "AzureSqlDb", + ), + Recorder: mgr.GetEventRecorderFor("AzureSqlDb-controller"), + Scheme: scheme, + }, + }).SetupWithManager(mgr) + if err != nil { + setupLog.Error(err, "unable to create controller", "controller", "AzureSqlDb") os.Exit(1) } + if err = (&controllers.AzureSqlFirewallRuleReconciler{ Client: mgr.GetClient(), Telemetry: telemetry.InitializePrometheusDefault( diff --git a/pkg/resourcemanager/mock/sql/azuresqldb.go b/pkg/resourcemanager/mock/sql/azuresqldb.go index 4f34cac0501..7624cb0ec42 100644 --- a/pkg/resourcemanager/mock/sql/azuresqldb.go +++ b/pkg/resourcemanager/mock/sql/azuresqldb.go @@ -8,14 +8,18 @@ package sql import ( "context" "errors" + "fmt" "net/http" "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/to" + "k8s.io/apimachinery/pkg/runtime" "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/pkg/resourcemanager" "github.com/Azure/azure-service-operator/pkg/resourcemanager/mock/helpers" - sqlclient "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" + "github.com/Azure/azure-service-operator/pkg/resourcemanager/sqlclient" ) type MockSqlDbManager struct { @@ -101,3 +105,61 @@ func (manager *MockSqlDbManager) DeleteDB(ctx context.Context, resourceGroupName return helpers.GetRestResponse(http.StatusOK), nil } + +func (db *MockSqlDbManager) Ensure(ctx context.Context, obj runtime.Object) (bool, error) { + instance, err := db.convert(obj) + if err != nil { + return false, err + } + + location := instance.Spec.Location + groupName := instance.Spec.ResourceGroup + server := instance.Spec.Server + dbName := instance.ObjectMeta.Name + dbEdition := instance.Spec.Edition + + azureSqlDatabaseProperties := sqlclient.SQLDatabaseProperties{ + DatabaseName: dbName, + Edition: dbEdition, + } + + _, err = db.CreateOrUpdateDB(ctx, groupName, location, server, azureSqlDatabaseProperties) + if err != nil { + return false, err + } + + instance.Status.Provisioning = true + instance.Status.Provisioned = true + + return true, nil +} + +func (db *MockSqlDbManager) Delete(ctx context.Context, obj runtime.Object) (bool, error) { + instance, err := db.convert(obj) + if err != nil { + return false, err + } + + groupName := instance.Spec.ResourceGroup + server := instance.Spec.Server + dbName := instance.ObjectMeta.Name + + _, err = db.DeleteDB(ctx, groupName, server, dbName) + if err != nil { + return false, err + } + + return false, nil +} + +func (g *MockSqlDbManager) GetParents(obj runtime.Object) ([]resourcemanager.KubeParent, error) { + return nil, nil +} + +func (*MockSqlDbManager) convert(obj runtime.Object) (*azurev1alpha1.AzureSqlDatabase, error) { + local, ok := obj.(*azurev1alpha1.AzureSqlDatabase) + if !ok { + return nil, fmt.Errorf("failed type assertion on kind: %s", obj.GetObjectKind().GroupVersionKind().String()) + } + return local, nil +} diff --git a/pkg/resourcemanager/sqlclient/azuresqldb_manager.go b/pkg/resourcemanager/sqlclient/azuresqldb_manager.go index d709da7ccb4..ffe112a277f 100644 --- a/pkg/resourcemanager/sqlclient/azuresqldb_manager.go +++ b/pkg/resourcemanager/sqlclient/azuresqldb_manager.go @@ -9,6 +9,7 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + "github.com/Azure/azure-service-operator/pkg/resourcemanager" "github.com/Azure/go-autorest/autorest" "github.com/go-logr/logr" ) @@ -22,4 +23,5 @@ type SqlDbManager interface { DeleteDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (result autorest.Response, err error) GetDB(ctx context.Context, resourceGroupName string, serverName string, databaseName string) (sql.Database, error) GetServer(ctx context.Context, resourceGroupName string, serverName string) (result sql.Server, err error) + resourcemanager.ARMClient } diff --git a/pkg/resourcemanager/sqlclient/azuresqldb_reconcile.go b/pkg/resourcemanager/sqlclient/azuresqldb_reconcile.go new file mode 100644 index 00000000000..66c190cac37 --- /dev/null +++ b/pkg/resourcemanager/sqlclient/azuresqldb_reconcile.go @@ -0,0 +1,125 @@ +/* +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 ( + "context" + "fmt" + + azurev1alpha1 "github.com/Azure/azure-service-operator/api/v1alpha1" + "github.com/Azure/azure-service-operator/pkg/errhelp" + "github.com/Azure/azure-service-operator/pkg/helpers" + "github.com/Azure/azure-service-operator/pkg/resourcemanager" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" +) + +// Ensure creates an AzureSqlDb +func (db *AzureSqlDbManager) Ensure(ctx context.Context, obj runtime.Object) (bool, error) { + + instance, err := db.convert(obj) + if err != nil { + return false, err + } + + location := instance.Spec.Location + groupName := instance.Spec.ResourceGroup + server := instance.Spec.Server + dbName := instance.ObjectMeta.Name + dbEdition := instance.Spec.Edition + + azureSqlDatabaseProperties := SQLDatabaseProperties{ + DatabaseName: dbName, + Edition: dbEdition, + } + + instance.Status.Provisioning = true + + _, err = db.CreateOrUpdateDB(ctx, groupName, location, server, azureSqlDatabaseProperties) + if err != nil { + catch := []string{ + errhelp.ResourceGroupNotFoundErrorCode, + errhelp.AsyncOpIncompleteError, + } + azerr := errhelp.NewAzureErrorAzureError(err) + if helpers.ContainsString(catch, azerr.Type) { + return false, nil + } + + return true, fmt.Errorf("AzureSqlDb CreateOrUpdate error %v", err) + } + + resp, err := db.GetDB(ctx, groupName, server, dbName) + if err != nil { + return true, fmt.Errorf("AzureSqlDb GetDB error %v", err) + } + + instance.Status.Provisioning = false + instance.Status.Provisioned = true + instance.Status.State = string(*resp.Status) + instance.Status.Message = "Success" + + return true, nil +} + +// Delete drops a AzureSqlDb +func (db *AzureSqlDbManager) Delete(ctx context.Context, obj runtime.Object) (bool, error) { + instance, err := db.convert(obj) + if err != nil { + return false, err + } + + groupName := instance.Spec.ResourceGroup + server := instance.Spec.Server + dbName := instance.ObjectMeta.Name + + _, err = db.DeleteDB(ctx, groupName, server, dbName) + if err != nil { + if errhelp.IsStatusCode204(err) { + // Database does not exist + return false, nil + } + + return true, fmt.Errorf("AzureSqlDb delete error %v", err) + } + + return true, nil +} + +// GetParents returns the parents of AzureSqlDatabase +func (db *AzureSqlDbManager) GetParents(obj runtime.Object) ([]resourcemanager.KubeParent, error) { + instance, err := db.convert(obj) + if err != nil { + return nil, err + } + + rgKey := types.NamespacedName{Name: instance.Spec.ResourceGroup, Namespace: instance.Namespace} + key := types.NamespacedName{Name: instance.Spec.Server, Namespace: instance.Namespace} + + return []resourcemanager.KubeParent{ + {Key: key, Target: &azurev1alpha1.AzureSqlServer{}}, + {Key: rgKey, Target: &azurev1alpha1.ResourceGroup{}}, + }, nil +} + +func (*AzureSqlDbManager) convert(obj runtime.Object) (*azurev1alpha1.AzureSqlDatabase, error) { + local, ok := obj.(*azurev1alpha1.AzureSqlDatabase) + if !ok { + return nil, fmt.Errorf("failed type assertion on kind: %s", obj.GetObjectKind().GroupVersionKind().String()) + } + return local, nil +} diff --git a/pkg/resourcemanager/sqlclient/sqlproperties.go b/pkg/resourcemanager/sqlclient/sqlproperties.go index 61722a6cd42..425fa6d086d 100644 --- a/pkg/resourcemanager/sqlclient/sqlproperties.go +++ b/pkg/resourcemanager/sqlclient/sqlproperties.go @@ -7,10 +7,11 @@ package sqlclient import ( "github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql" + "github.com/Azure/azure-service-operator/api/v1alpha1" ) -// DBEdition - wraps: https://godoc.org/github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql#DatabaseEdition -type DBEdition byte +type DBEdition = v1alpha1.DBEdition +type ReadWriteEndpointFailoverPolicy = v1alpha1.ReadWriteEndpointFailoverPolicy const ( // Basic ... @@ -43,9 +44,6 @@ const ( Web DBEdition = 13 ) -// ReadWriteEndpointFailoverPolicy - wraps https://godoc.org/github.com/Azure/azure-sdk-for-go/services/preview/sql/mgmt/2015-05-01-preview/sql#ReadWriteEndpointFailoverPolicy -type ReadWriteEndpointFailoverPolicy string - const ( // Automatic ... Automatic ReadWriteEndpointFailoverPolicy = "Automatic"