Skip to content

Commit

Permalink
New Resource: azurerm_databricks_workspace (#1134)
Browse files Browse the repository at this point in the history
* added databricks support

* fixed formatting and removed redundant lines

* now using configureClient in registerDatabricksClients

* changed redundant d.Get(workspace_name) to name

* changed location to use locationSchema()

* updated vendor with azure databricks sdk

* Address PR feedback

* Register Databricks provider

* Fix formatting

* Fix acceptance tests

* Fixing comments made in the PR

* Upgrading to v21.1.0 of the Azure SDK

* Validation for the Databricks Workspace name

```
$ acctests azurerm TestAzureRMDatabrickWorkspaceName
=== RUN   TestAzureRMDatabrickWorkspaceName
--- PASS: TestAzureRMDatabrickWorkspaceName (0.00s)
PASS
ok  	github.com/terraform-providers/terraform-provider-azurerm/azurerm	1.270s
```

* Fixing a merge conflict
  • Loading branch information
yaron2 authored and tombuildsstuff committed Oct 1, 2018
1 parent a833318 commit 3bb2097
Show file tree
Hide file tree
Showing 18 changed files with 3,886 additions and 4 deletions.
11 changes: 11 additions & 0 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/2017-10-01/containerregistry"
"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2018-03-31/containerservice"
"github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/2015-04-08/documentdb"
"github.com/Azure/azure-sdk-for-go/services/databricks/mgmt/2018-04-01/databricks"
analyticsAccount "github.com/Azure/azure-sdk-for-go/services/datalake/analytics/mgmt/2016-11-01/account"
"github.com/Azure/azure-sdk-for-go/services/datalake/store/2016-11-01/filesystem"
storeAccount "github.com/Azure/azure-sdk-for-go/services/datalake/store/mgmt/2016-11-01/account"
Expand Down Expand Up @@ -181,6 +182,9 @@ type ArmClient struct {
dataLakeAnalyticsAccountClient analyticsAccount.AccountsClient
dataLakeAnalyticsFirewallRulesClient analyticsAccount.FirewallRulesClient

// Databricks
databricksWorkspacesClient databricks.WorkspacesClient

// KeyVault
keyVaultClient keyvault.VaultsClient
keyVaultManagementClient keyVault.BaseClient
Expand Down Expand Up @@ -467,6 +471,7 @@ func getArmClient(c *authentication.Config) (*ArmClient, error) {
client.registerContainerRegistryClients(endpoint, c.SubscriptionID, auth, sender)
client.registerContainerServicesClients(endpoint, c.SubscriptionID, auth)
client.registerCosmosDBClients(endpoint, c.SubscriptionID, auth, sender)
client.registerDatabricksClients(endpoint, c.SubscriptionID, auth, sender)
client.registerDatabases(endpoint, c.SubscriptionID, auth, sender)
client.registerDataLakeStoreClients(endpoint, c.SubscriptionID, auth, sender)
client.registerDeviceClients(endpoint, c.SubscriptionID, auth, sender)
Expand Down Expand Up @@ -653,6 +658,12 @@ func (c *ArmClient) registerContainerServicesClients(endpoint, subscriptionId st
c.kubernetesClustersClient = kubernetesClustersClient
}

func (c *ArmClient) registerDatabricksClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) {
databricksWorkspacesClient := databricks.NewWorkspacesClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&databricksWorkspacesClient.Client, auth)
c.databricksWorkspacesClient = databricksWorkspacesClient
}

func (c *ArmClient) registerDatabases(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) {
// MySQL
mysqlConfigClient := mysql.NewConfigurationsClientWithBaseURI(endpoint, subscriptionId)
Expand Down
2 changes: 2 additions & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_container_service": resourceArmContainerService(),
"azurerm_container_group": resourceArmContainerGroup(),
"azurerm_cosmosdb_account": resourceArmCosmosDBAccount(),
"azurerm_databricks_workspace": resourceArmDatabricksWorkspace(),
"azurerm_data_lake_analytics_account": resourceArmDataLakeAnalyticsAccount(),
"azurerm_data_lake_analytics_firewall_rule": resourceArmDataLakeAnalyticsFirewallRule(),
"azurerm_data_lake_store": resourceArmDataLakeStore(),
Expand Down Expand Up @@ -391,6 +392,7 @@ func determineAzureResourceProvidersToRegister(providerList []resources.Provider
"Microsoft.ContainerInstance": {},
"Microsoft.ContainerRegistry": {},
"Microsoft.ContainerService": {},
"Microsoft.Databricks": {},
"Microsoft.DataLakeStore": {},
"Microsoft.DBforMySQL": {},
"Microsoft.DBforPostgreSQL": {},
Expand Down
203 changes: 203 additions & 0 deletions azurerm/resource_arm_databricks_workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package azurerm

import (
"fmt"
"log"
"regexp"

"github.com/Azure/azure-sdk-for-go/services/databricks/mgmt/2018-04-01/databricks"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmDatabricksWorkspace() *schema.Resource {
return &schema.Resource{
Create: resourceArmDatabricksWorkspaceCreateUpdate,
Read: resourceArmDatabricksWorkspaceRead,
Update: resourceArmDatabricksWorkspaceCreateUpdate,
Delete: resourceArmDatabricksWorkspaceDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateDatabricksWorkspaceName,
},

"location": locationSchema(),

"resource_group_name": resourceGroupNameSchema(),

"sku": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
"Standard",
"Premium",
}, false),
},

"tags": tagsSchema(),

"managed_resource_group_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceArmDatabricksWorkspaceCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).databricksWorkspacesClient
ctx := meta.(*ArmClient).StopContext
subscriptionID := meta.(*ArmClient).subscriptionId

log.Printf("[INFO] preparing arguments for Azure ARM Databricks Workspace creation.")

name := d.Get("name").(string)
location := azureRMNormalizeLocation(d.Get("location").(string))
resourceGroup := d.Get("resource_group_name").(string)
skuName := d.Get("sku").(string)

tags := d.Get("tags").(map[string]interface{})
expandedTags := expandTags(tags)

managedResourceGroupID := fmt.Sprintf("/subscriptions/%s/resourceGroups/databricks-rg-%s", subscriptionID, resourceGroup)

workspace := databricks.Workspace{
Sku: &databricks.Sku{
Name: utils.String(skuName),
},
Location: utils.String(location),
WorkspaceProperties: &databricks.WorkspaceProperties{
ManagedResourceGroupID: &managedResourceGroupID,
},
Tags: expandedTags,
}

future, err := client.CreateOrUpdate(ctx, workspace, resourceGroup, name)
if err != nil {
return fmt.Errorf("Error creating/updating Databricks Workspace %q (Resource Group %q): %+v", name, resourceGroup, err)
}

err = future.WaitForCompletionRef(ctx, client.Client)
if err != nil {
return fmt.Errorf("Error waiting for the completion of the creating/updating of Databricks Workspace %q (Resource Group %q): %+v", name, resourceGroup, err)
}

read, err := client.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("Error retrieving Databricks Workspace %q (Resource Group %q): %+v", name, resourceGroup, err)
}
if read.ID == nil {
return fmt.Errorf("Cannot read Databricks Workspace %q (Resource Group %q) ID", name, resourceGroup)
}

d.SetId(*read.ID)

return resourceArmDatabricksWorkspaceRead(d, meta)
}

func resourceArmDatabricksWorkspaceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).databricksWorkspacesClient
ctx := meta.(*ArmClient).StopContext

id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}
resourceGroup := id.ResourceGroup
name := id.Path["workspaces"]

resp, err := client.Get(ctx, resourceGroup, name)

if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[DEBUG] Databricks Workspace %q was not found in Resource Group %q - removing from state", name, resourceGroup)
d.SetId("")
return nil
}

return fmt.Errorf("Error making Read request on Azure Databricks Workspace %s: %s", name, err)
}

d.Set("name", name)
d.Set("resource_group_name", resourceGroup)

if location := resp.Location; location != nil {
d.Set("location", azureRMNormalizeLocation(*location))
}

if sku := resp.Sku; sku != nil {
d.Set("sku", sku.Name)
}

if props := resp.WorkspaceProperties; props != nil {
d.Set("managed_resource_group_id", props.ManagedResourceGroupID)
}

flattenAndSetTags(d, resp.Tags)

return nil
}

func resourceArmDatabricksWorkspaceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).databricksWorkspacesClient
ctx := meta.(*ArmClient).StopContext

id, err := parseAzureResourceID(d.Id())
if err != nil {
return err
}

resGroup := id.ResourceGroup
name := id.Path["workspaces"]

future, err := client.Delete(ctx, resGroup, name)
if err != nil {
return fmt.Errorf("Error deleting Databricks Workspace %q (Resource Group %q): %+v", name, resGroup, err)
}

err = future.WaitForCompletionRef(ctx, client.Client)
if err != nil {
if !response.WasNotFound(future.Response()) {
return fmt.Errorf("Error waiting for deletion of Databricks Workspace %q (Resource Group %q): %+v", name, resGroup, err)
}
}

return nil
}

func validateDatabricksWorkspaceName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

// Only alphanumeric characters, underscores, and hyphens are allowed, and the name must be 1-30 characters long.

// Cannot be empty
if len(value) == 0 {
errors = append(errors, fmt.Errorf(
"%q cannot be an empty string: %q", k, value))
}

// Cannot be more than 128 characters
if len(value) > 30 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 128 characters: %q", k, value))
}

// Must only contain alphanumeric characters or hyphens
if !regexp.MustCompile(`^[A-Za-z0-9-]*$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q can only contain alphanumeric characters and hyphens: %q",
k, value))
}

return
}
Loading

0 comments on commit 3bb2097

Please sign in to comment.