Skip to content

Commit

Permalink
Check Name Availability/Validation for SQL Resources (#245)
Browse files Browse the repository at this point in the history
* adding CheckNameAvailablity to sqlclient go sdk

* adding checkname call in controller

* cleaning, commments, etc

* fixing instance and params

* fixing gerserver to match rest of interface

* fixing fcn comment

* adding error check

* Rearranging vars

* adding msg and reconcile loop stop

* making global var

* making type of service const

* removing unnecessary log

* changing statement to check boolean instead of string contents

* fixing log
  • Loading branch information
melonrush13 authored Oct 2, 2019
1 parent f6b9b03 commit becb841
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
23 changes: 22 additions & 1 deletion controllers/sqlserver_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ type SqlServerReconciler struct {
func (r *SqlServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
ctx := context.Background()
log := r.Log.WithValues("sqlserver", req.NamespacedName)

var instance azurev1.SqlServer

if err := r.Get(ctx, req.NamespacedName, &instance); err != nil {
Expand All @@ -64,6 +63,17 @@ func (r *SqlServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

location := instance.Spec.Location
name := instance.ObjectMeta.Name
groupName := instance.Spec.ResourceGroup

sdkClient := sql.GoSDKClient{
Ctx: ctx,
ResourceGroupName: groupName,
ServerName: name,
Location: location,
}

if helpers.IsBeingDeleted(&instance) {
if helpers.HasFinalizer(&instance, SQLServerFinalizerName) {
if err := r.deleteExternal(&instance); err != nil {
Expand Down Expand Up @@ -96,6 +106,17 @@ func (r *SqlServerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
}
}

availableResp, err := sdkClient.CheckNameAvailability()
if err != nil {
log.Info("error validating name")
return ctrl.Result{}, err
}
if !availableResp.Available {
log.Info("Servername is invalid or not available")
r.Recorder.Event(&instance, "Warning", "Failed", "Servername is invalid")
return ctrl.Result{Requeue: false}, fmt.Errorf("Servername invalid %s", availableResp.Name)
}

if !instance.IsSubmitted() {
r.Recorder.Event(&instance, "Normal", "Submitting", "starting resource reconciliation")
if err := r.reconcileExternal(&instance); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion pkg/resourcemanager/sqlclient/resourceclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ type ResourceClient interface {
DeleteDB(databaseName string) (result autorest.Response, err error)
DeleteSQLServer() (result autorest.Response, err error)
DeleteSQLFirewallRule(ruleName string) (err error)
}
GetServer() (result sql.Server, err error)
IsAsyncNotCompleted(err error) (result bool)
CheckNameAvailability() (result AvailabilityResponse, err error)
}
42 changes: 42 additions & 0 deletions pkg/resourcemanager/sqlclient/sqlclient_godsk.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/Azure/go-autorest/autorest/to"
)

const typeOfService = "Microsoft.Sql/servers"

// getGoServersClient retrieves a ServersClient
func getGoServersClient() sql.ServersClient {
serversClient := sql.NewServersClient(config.SubscriptionID())
Expand Down Expand Up @@ -239,3 +241,43 @@ func (sdk GoSDKClient) DeleteSQLServer() (result autorest.Response, err error) {

return future.Result(serversClient)
}

// IsAsyncNotCompleted returns true if the error is due to async not completed
func (sdk GoSDKClient) IsAsyncNotCompleted(err error) (result bool) {
result = false
if err != nil && strings.Contains(err.Error(), "asynchronous operation has not completed") {
result = true
} else if strings.Contains(err.Error(), "is busy with another operation") {
result = true
}
return result
}

// GetServer returns a server
func (sdk GoSDKClient) GetServer() (result sql.Server, err error) {
serversClient := getGoServersClient()

return serversClient.Get(
sdk.Ctx,
sdk.ResourceGroupName,
sdk.ServerName,
)
}

// CheckNameAvailability determines whether a SQL resource can be created with the specified name
func (sdk GoSDKClient) CheckNameAvailability() (result AvailabilityResponse, err error) {
serversClient := getGoServersClient()

response, err := serversClient.CheckNameAvailability(
sdk.Ctx,
sql.CheckNameAvailabilityRequest{
Name: to.StringPtr(sdk.ServerName),
Type: to.StringPtr(typeOfService),
},
)
if err != nil {
return result, err
}

return ToAvailabilityResponse(response), err
}
20 changes: 20 additions & 0 deletions pkg/resourcemanager/sqlclient/sqlproperties.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,23 @@ func translateDBEdition(in DBEdition) (result sql.DatabaseEdition) {

return result
}

// AvailabilityResponse is the response for checking name validation
type AvailabilityResponse struct {
Available bool
Message string
Name string
}

// ToAvailabilityResponse converts CheckNameAvailabilityResponse to AvailabilityResponse
func ToAvailabilityResponse(response sql.CheckNameAvailabilityResponse) (result AvailabilityResponse) {
result.Available = *response.Available
if response.Message != nil {
result.Message = *response.Message
}
if response.Name != nil {
result.Name = *response.Name
}

return result
}

0 comments on commit becb841

Please sign in to comment.