From 86fb8e3394751d3c805d499151e7c044cd84a48f Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 16 Dec 2019 14:12:48 -0800 Subject: [PATCH 1/7] Start of kusto database principal --- .../resource_arm_kusto_database_principal.go | 258 ++++++++++++++++++ ...ource_arm_kusto_database_principal_test.go | 1 + 2 files changed, 259 insertions(+) create mode 100644 azurerm/resource_arm_kusto_database_principal.go create mode 100644 azurerm/resource_arm_kusto_database_principal_test.go diff --git a/azurerm/resource_arm_kusto_database_principal.go b/azurerm/resource_arm_kusto_database_principal.go new file mode 100644 index 000000000000..2280b5676897 --- /dev/null +++ b/azurerm/resource_arm_kusto_database_principal.go @@ -0,0 +1,258 @@ +package azurerm + +import ( + "fmt" + "log" + "regexp" + "time" + + "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2019-05-15/kusto" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmKustoDatabasePrincipal() *schema.Resource { + return &schema.Resource{ + Create: resourceArmKustoDatabasePrincipalCreate, + Read: resourceArmKustoDatabasePrincipalRead, + Delete: resourceArmKustoDatabasePrincipalDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(60 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), + Delete: schema.DefaultTimeout(60 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "cluster_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAzureRMKustoClusterName, + }, + + "database_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAzureRMKustoDatabaseName, + }, + + "role": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(kusto.Admin), + string(kusto.Ingestor), + string(kusto.Monitor), + string(kusto.User), + string(kusto.UnrestrictedViewers), + string(kusto.Viewer), + }, false), + }, + + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + string(kusto.DatabasePrincipalTypeApp), + string(kusto.DatabasePrincipalTypeGroup), + string(kusto.DatabasePrincipalTypeUser), + }, false), + }, + + "fully_qualified_domain_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "email": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "application_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + }, + } +} + +func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Kusto.DatabasesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for Azure Kusto Database Principal creation.") + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + clusterName := d.Get("cluster_name").(string) + databaseName := d.Get("database_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error checking for presence of existing Kusto Database Principals %q (Resource Group %q, Cluster %q): %s", name, resourceGroup, clusterName, err) + } + } + + if principals := resp.Value; principals != nil { + for _, principal := range(*principals) { + if principal.Name != nil && *principal.Name == name { + return tf.ImportAsExistsError("azurerm_kusto_database_principal", *principal.Name) + } + } + } + } + + kustoPrincipal := kusto.DatabasePrincipal{ + Type: kusto.DatabasePrincipalType(d.Get("type").(string)), + } + + principals := []kusto.DatabasePrincipal{kustoPrincipal} + request := kusto.DatabasePrincipalListRequest{ + Value: &principals, + } + + resp, err := client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request) + if err != nil { + return fmt.Errorf("Error creating Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + } + + d.SetId(*resp.) + + return resourceArmKustoDatabaseRead(d, meta) +} + +func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Kusto.DatabasesClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resourceGroup := id.ResourceGroup + clusterName := id.Path["Clusters"] + name := id.Path["Databases"] + + databaseResponse, err := client.Get(ctx, resourceGroup, clusterName, name) + + if err != nil { + if utils.ResponseWasNotFound(databaseResponse.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error retrieving Kusto Database %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + d.Set("cluster_name", clusterName) + + if location := databaseResponse.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if props := databaseResponse.DatabaseProperties; props != nil { + d.Set("hot_cache_period", props.HotCachePeriod) + d.Set("soft_delete_period", props.SoftDeletePeriod) + + if statistics := props.Statistics; statistics != nil { + d.Set("size", statistics.Size) + } + } + + return nil +} + +func resourceArmKustoDatabaseDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Kusto.DatabasesClient + ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resGroup := id.ResourceGroup + clusterName := id.Path["Clusters"] + name := id.Path["Databases"] + + future, err := client.Delete(ctx, resGroup, clusterName, name) + if err != nil { + return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resGroup, clusterName, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for deletion of Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resGroup, clusterName, err) + } + + return nil +} + +func validateAzureRMKustoDatabasePrincipalName(v interface{}, k string) (warnings []string, errors []error) { + name := v.(string) + + if regexp.MustCompile(`^[\s]+$`).MatchString(name) { + errors = append(errors, fmt.Errorf("%q must not consist of whitespaces only", k)) + } + + if !regexp.MustCompile(`^[a-zA-Z0-9\s.-]+$`).MatchString(name) { + errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters, whitespaces, dashes and dots: %q", k, name)) + } + + if len(name) > 260 { + errors = append(errors, fmt.Errorf("%q must be (inclusive) between 4 and 22 characters long but is %d", k, len(name))) + } + + return warnings, errors +} + +func expandKustoDatabasePrincipalProperties(d *schema.ResourceData) *kusto.DatabaseProperties { + databaseProperties := &kusto.DatabaseProperties{} + + if softDeletePeriod, ok := d.GetOk("soft_delete_period"); ok { + databaseProperties.SoftDeletePeriod = utils.String(softDeletePeriod.(string)) + } + + if hotCachePeriod, ok := d.GetOk("hot_cache_period"); ok { + databaseProperties.HotCachePeriod = utils.String(hotCachePeriod.(string)) + } + + return databaseProperties +} diff --git a/azurerm/resource_arm_kusto_database_principal_test.go b/azurerm/resource_arm_kusto_database_principal_test.go new file mode 100644 index 000000000000..96f5b5587ee2 --- /dev/null +++ b/azurerm/resource_arm_kusto_database_principal_test.go @@ -0,0 +1 @@ +package azurerm From 919ddc70687336d4ad63073b092654d5237b3922 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 17 Dec 2019 18:24:53 -0800 Subject: [PATCH 2/7] Start of testing the resource --- azurerm/provider.go | 1 + .../resource_arm_kusto_database_principal.go | 179 ++++++++++-------- 2 files changed, 103 insertions(+), 77 deletions(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index 604329d73c15..3da292437b69 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -324,6 +324,7 @@ func Provider() terraform.ResourceProvider { "azurerm_kubernetes_cluster_node_pool": resourceArmKubernetesClusterNodePool(), "azurerm_kusto_cluster": resourceArmKustoCluster(), "azurerm_kusto_database": resourceArmKustoDatabase(), + "azurerm_kusto_database_principal": resourceArmKustoDatabasePrincipal(), "azurerm_kusto_eventhub_data_connection": resourceArmKustoEventHubDataConnection(), "azurerm_lb_backend_address_pool": resourceArmLoadBalancerBackendAddressPool(), "azurerm_lb_nat_pool": resourceArmLoadBalancerNatPool(), diff --git a/azurerm/resource_arm_kusto_database_principal.go b/azurerm/resource_arm_kusto_database_principal.go index 2280b5676897..0623259b738a 100644 --- a/azurerm/resource_arm_kusto_database_principal.go +++ b/azurerm/resource_arm_kusto_database_principal.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2019-05-15/kusto" @@ -37,8 +36,7 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, - Required: true, - ForceNew: true, + Computed: true, ValidateFunc: validate.NoEmptyStrings, }, @@ -59,7 +57,7 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { }, "role": { - Type: schema.TypeString, + Type: schema.TypeString, Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ @@ -73,7 +71,7 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { }, "type": { - Type: schema.TypeString, + Type: schema.TypeString, Required: true, ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ @@ -83,25 +81,28 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { }, false), }, - "fully_qualified_domain_name": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + // TODO try all of these together to see if I need to do ExactlyOneOf + "fully_qualified_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, ValidateFunc: validate.NoEmptyStrings, }, "email": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, ValidateFunc: validate.NoEmptyStrings, + ConflictsWith: []string{"app_id"}, }, - "application_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, + "app_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validate.UUID, + ConflictsWith: []string{"email"}, }, }, } @@ -118,6 +119,17 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf resourceGroup := d.Get("resource_group_name").(string) clusterName := d.Get("cluster_name").(string) databaseName := d.Get("database_name").(string) + role := d.Get("role").(string) + + database, err := client.Get(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if utils.ResponseWasNotFound(database.Response) { + return fmt.Errorf("Kusto Database %q (Resource Group %q) was not found", databaseName, resourceGroup) + } + + return fmt.Errorf("Error loading Kusto Database %q (Resource Group %q): %+v", databaseName, resourceGroup, err) + } + resourceId := fmt.Sprintf("%s/Principals/%s/Role/%s/Type/%s", *database.ID, name, role) if features.ShouldResourcesBeImported() && d.IsNewResource() { resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) @@ -128,16 +140,22 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf } if principals := resp.Value; principals != nil { - for _, principal := range(*principals) { - if principal.Name != nil && *principal.Name == name { - return tf.ImportAsExistsError("azurerm_kusto_database_principal", *principal.Name) + for _, principal := range *principals { + // kusto database principals are unique when looked at with name and role + if principal.Name != nil && *principal.Name == name && string(principal.Role) == role { + return tf.ImportAsExistsError("azurerm_kusto_database_principal", resourceId) } } } } kustoPrincipal := kusto.DatabasePrincipal{ - Type: kusto.DatabasePrincipalType(d.Get("type").(string)), + Type: kusto.DatabasePrincipalType(d.Get("type").(string)), + Role: kusto.DatabasePrincipalRole(role), + Name: utils.String(""), + Fqn: utils.String(d.Get("fully_qualified_name").(string)), + Email: utils.String(d.Get("email").(string)), + AppID: utils.String(d.Get("app_id").(string)), } principals := []kusto.DatabasePrincipal{kustoPrincipal} @@ -145,17 +163,17 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf Value: &principals, } - resp, err := client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request) + _, err = client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request) if err != nil { return fmt.Errorf("Error creating Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) } - d.SetId(*resp.) + d.SetId(resourceId) - return resourceArmKustoDatabaseRead(d, meta) + return resourceArmKustoDatabasePrincipalRead(d, meta) } -func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) error { +func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Kusto.DatabasesClient ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) defer cancel() @@ -167,10 +185,11 @@ func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) erro resourceGroup := id.ResourceGroup clusterName := id.Path["Clusters"] - name := id.Path["Databases"] - - databaseResponse, err := client.Get(ctx, resourceGroup, clusterName, name) + databaseName := id.Path["Databases"] + name := id.Path["Principals"] + role := id.Path["Role"] + databaseResponse, err := client.Get(ctx, resourceGroup, clusterName, databaseName) if err != nil { if utils.ResponseWasNotFound(databaseResponse.Response) { d.SetId("") @@ -179,27 +198,53 @@ func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error retrieving Kusto Database %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) } - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - d.Set("cluster_name", clusterName) + resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error checking for presence of existing Kusto Database Principals %q (Resource Group %q, Cluster %q): %s", name, resourceGroup, clusterName, err) + } + } - if location := databaseResponse.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) + principal := kusto.DatabasePrincipal{} + found := false + if principals := resp.Value; principals != nil { + for _, currPrincipal := range *principals { + // kusto database principals are unique when looked at with name and role + if currPrincipal.Name != nil && *currPrincipal.Name == name && string(currPrincipal.Role) == role { + principal = currPrincipal + found = true + break + } + } } - if props := databaseResponse.DatabaseProperties; props != nil { - d.Set("hot_cache_period", props.HotCachePeriod) - d.Set("soft_delete_period", props.SoftDeletePeriod) + if !found { + log.Printf("[DEBUG] Kusto Database Principal %q was not found - removing from state", name) + d.SetId("") + return nil + } - if statistics := props.Statistics; statistics != nil { - d.Set("size", statistics.Size) - } + d.Set("name", principal.Name) + d.Set("resource_group_name", resourceGroup) + d.Set("cluster_name", clusterName) + d.Set("database_name", databaseName) + + d.Set("role", string(principal.Role)) + d.Set("type", string(principal.Type)) + if fqn := principal.Fqn; fqn != nil { + d.Set("fully_qualified_name", fqn) + } + if email := principal.Email; email != nil { + d.Set("email", email) + } + if appID := principal.AppID; appID != nil { + d.Set("app_id", appID) } return nil } -func resourceArmKustoDatabaseDelete(d *schema.ResourceData, meta interface{}) error { +func resourceArmKustoDatabasePrincipalDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Kusto.DatabasesClient ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) defer cancel() @@ -211,48 +256,28 @@ func resourceArmKustoDatabaseDelete(d *schema.ResourceData, meta interface{}) er resGroup := id.ResourceGroup clusterName := id.Path["Clusters"] - name := id.Path["Databases"] - - future, err := client.Delete(ctx, resGroup, clusterName, name) - if err != nil { - return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resGroup, clusterName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resGroup, clusterName, err) - } - - return nil -} - -func validateAzureRMKustoDatabasePrincipalName(v interface{}, k string) (warnings []string, errors []error) { - name := v.(string) + databaseName := id.Path["Databases"] + name := id.Path["Principals"] + role := id.Path["Role"] - if regexp.MustCompile(`^[\s]+$`).MatchString(name) { - errors = append(errors, fmt.Errorf("%q must not consist of whitespaces only", k)) - } - - if !regexp.MustCompile(`^[a-zA-Z0-9\s.-]+$`).MatchString(name) { - errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters, whitespaces, dashes and dots: %q", k, name)) - } - - if len(name) > 260 { - errors = append(errors, fmt.Errorf("%q must be (inclusive) between 4 and 22 characters long but is %d", k, len(name))) + kustoPrincipal := kusto.DatabasePrincipal{ + Role: kusto.DatabasePrincipalRole(role), + Name: utils.String(""), + Fqn: utils.String(d.Get("fully_qualified_name").(string)), + Email: utils.String(d.Get("email").(string)), + AppID: utils.String(d.Get("app_id").(string)), + Type: kusto.DatabasePrincipalType(d.Get("type").(string)), } - return warnings, errors -} - -func expandKustoDatabasePrincipalProperties(d *schema.ResourceData) *kusto.DatabaseProperties { - databaseProperties := &kusto.DatabaseProperties{} - - if softDeletePeriod, ok := d.GetOk("soft_delete_period"); ok { - databaseProperties.SoftDeletePeriod = utils.String(softDeletePeriod.(string)) + principals := []kusto.DatabasePrincipal{kustoPrincipal} + request := kusto.DatabasePrincipalListRequest{ + Value: &principals, } - if hotCachePeriod, ok := d.GetOk("hot_cache_period"); ok { - databaseProperties.HotCachePeriod = utils.String(hotCachePeriod.(string)) + _, err = client.RemovePrincipals(ctx, resGroup, clusterName, databaseName, request) + if err != nil { + return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q, Database %q): %+v", name, resGroup, clusterName, databaseName, err) } - return databaseProperties + return nil } From f3f727d847777155e7041bee18d8aab0b40331cc Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 17 Dec 2019 23:53:08 -0800 Subject: [PATCH 3/7] finalizing kusto database principal --- .../resource_arm_kusto_database_principal.go | 126 ++++++++----- ...ource_arm_kusto_database_principal_test.go | 173 ++++++++++++++++++ website/azurerm.erb | 3 + .../r/kusto_database_principal.html.markdown | 97 ++++++++++ 4 files changed, 357 insertions(+), 42 deletions(-) create mode 100644 website/docs/r/kusto_database_principal.html.markdown diff --git a/azurerm/resource_arm_kusto_database_principal.go b/azurerm/resource_arm_kusto_database_principal.go index 0623259b738a..91e7fbcb5a5c 100644 --- a/azurerm/resource_arm_kusto_database_principal.go +++ b/azurerm/resource_arm_kusto_database_principal.go @@ -2,7 +2,9 @@ package azurerm import ( "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "log" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2019-05-15/kusto" @@ -10,7 +12,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -34,12 +35,6 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "resource_group_name": azure.SchemaResourceGroupName(), "cluster_name": { @@ -81,28 +76,40 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { }, false), }, - // TODO try all of these together to see if I need to do ExactlyOneOf - "fully_qualified_name": { + "client_id": { Type: schema.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validate.NoEmptyStrings, }, - "email": { + "object_id": { Type: schema.TypeString, - Optional: true, + Required: true, ForceNew: true, ValidateFunc: validate.NoEmptyStrings, - ConflictsWith: []string{"app_id"}, + }, + + "fully_qualified_name": { + Type: schema.TypeString, + Computed: true, + }, + + // These must be computed as the values passed in are overwritten by what the `fqn` returns. + // For more info: https://github.com/Azure/azure-sdk-for-go/issues/6547 + "name": { + Type: schema.TypeString, + Computed: true, + }, + + "email": { + Type: schema.TypeString, + Computed: true, }, "app_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: validate.UUID, - ConflictsWith: []string{"email"}, + Type: schema.TypeString, + Computed: true, }, }, } @@ -115,11 +122,22 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf log.Printf("[INFO] preparing arguments for Azure Kusto Database Principal creation.") - name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) clusterName := d.Get("cluster_name").(string) databaseName := d.Get("database_name").(string) role := d.Get("role").(string) + principalType := d.Get("type").(string) + + clientID := d.Get("client_id").(string) + objectID := d.Get("object_id").(string) + fqn := "" + if principalType == "User" { + fqn = fmt.Sprintf("aaduser=%s;%s", objectID, clientID) + } else if principalType == "Group" { + fqn = fmt.Sprintf("aadgroup=%s;%s", objectID, clientID) + } else if principalType == "App" { + fqn = fmt.Sprintf("aadapp=%s;%s", objectID, clientID) + } database, err := client.Get(ctx, resourceGroup, clusterName, databaseName) if err != nil { @@ -129,20 +147,20 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf return fmt.Errorf("Error loading Kusto Database %q (Resource Group %q): %+v", databaseName, resourceGroup, err) } - resourceId := fmt.Sprintf("%s/Principals/%s/Role/%s/Type/%s", *database.ID, name, role) + resourceId := fmt.Sprintf("%s/Role/%s/FQN/%s", *database.ID, role, fqn) if features.ShouldResourcesBeImported() && d.IsNewResource() { resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) if err != nil { if !utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error checking for presence of existing Kusto Database Principals %q (Resource Group %q, Cluster %q): %s", name, resourceGroup, clusterName, err) + return fmt.Errorf("Error checking for presence of existing Kusto Database Principals (Resource Group %q, Cluster %q): %s", resourceGroup, clusterName, err) } } if principals := resp.Value; principals != nil { for _, principal := range *principals { // kusto database principals are unique when looked at with name and role - if principal.Name != nil && *principal.Name == name && string(principal.Role) == role { + if string(principal.Role) == role && principal.Fqn != nil && *principal.Fqn == fqn { return tf.ImportAsExistsError("azurerm_kusto_database_principal", resourceId) } } @@ -150,12 +168,14 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf } kustoPrincipal := kusto.DatabasePrincipal{ - Type: kusto.DatabasePrincipalType(d.Get("type").(string)), - Role: kusto.DatabasePrincipalRole(role), + Type: kusto.DatabasePrincipalType(principalType), + Role: kusto.DatabasePrincipalRole(role), + Fqn: utils.String(fqn), + // These three must be specified or the api returns `The request is invalid.` + // For more info: https://github.com/Azure/azure-sdk-for-go/issues/6547 + Email: utils.String(""), + AppID: utils.String(""), Name: utils.String(""), - Fqn: utils.String(d.Get("fully_qualified_name").(string)), - Email: utils.String(d.Get("email").(string)), - AppID: utils.String(d.Get("app_id").(string)), } principals := []kusto.DatabasePrincipal{kustoPrincipal} @@ -165,7 +185,14 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf _, err = client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request) if err != nil { - return fmt.Errorf("Error creating Kusto Database Principal %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + return fmt.Errorf("Error creating Kusto Database Principal (Resource Group %q, Cluster %q): %+v", resourceGroup, clusterName, err) + } + + resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error checking for presence of existing Kusto Database Principals (Resource Group %q, Cluster %q): %s", resourceGroup, clusterName, err) + } } d.SetId(resourceId) @@ -186,8 +213,8 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac resourceGroup := id.ResourceGroup clusterName := id.Path["Clusters"] databaseName := id.Path["Databases"] - name := id.Path["Principals"] role := id.Path["Role"] + fqn := id.Path["FQN"] databaseResponse, err := client.Get(ctx, resourceGroup, clusterName, databaseName) if err != nil { @@ -195,13 +222,13 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac d.SetId("") return nil } - return fmt.Errorf("Error retrieving Kusto Database %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + return fmt.Errorf("Error retrieving Kusto Database %q (Resource Group %q, Cluster %q): %+v", databaseName, resourceGroup, clusterName, err) } resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) if err != nil { if !utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error checking for presence of existing Kusto Database Principals %q (Resource Group %q, Cluster %q): %s", name, resourceGroup, clusterName, err) + return fmt.Errorf("Error checking for presence of existing Kusto Database Principals %q (Resource Group %q, Cluster %q): %s", id, resourceGroup, clusterName, err) } } @@ -209,8 +236,8 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac found := false if principals := resp.Value; principals != nil { for _, currPrincipal := range *principals { - // kusto database principals are unique when looked at with name and role - if currPrincipal.Name != nil && *currPrincipal.Name == name && string(currPrincipal.Role) == role { + // kusto database principals are unique when looked at with fqn and role + if string(currPrincipal.Role) == role && currPrincipal.Fqn != nil && *currPrincipal.Fqn == fqn { principal = currPrincipal found = true break @@ -219,12 +246,11 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac } if !found { - log.Printf("[DEBUG] Kusto Database Principal %q was not found - removing from state", name) + log.Printf("[DEBUG] Kusto Database Principal %q was not found - removing from state", id) d.SetId("") return nil } - d.Set("name", principal.Name) d.Set("resource_group_name", resourceGroup) d.Set("cluster_name", clusterName) d.Set("database_name", databaseName) @@ -240,6 +266,20 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac if appID := principal.AppID; appID != nil { d.Set("app_id", appID) } + if name := principal.Name; name != nil { + d.Set("name", principal.Name) + } + + splitFQN := strings.Split(fqn, "=") + if len(splitFQN) != 2 { + return fmt.Errorf("Expected `fqn` to be in the format aadtype=objectid:clientid but got: %q", fqn) + } + splitIDs := strings.Split(splitFQN[1], ";") + if len(splitIDs) != 2 { + return fmt.Errorf("Expected `fqn` to be in the format aadtype=objectid:clientid but got: %q", fqn) + } + d.Set("object_id", splitIDs[0]) + d.Set("client_id", splitIDs[1]) return nil } @@ -257,16 +297,18 @@ func resourceArmKustoDatabasePrincipalDelete(d *schema.ResourceData, meta interf resGroup := id.ResourceGroup clusterName := id.Path["Clusters"] databaseName := id.Path["Databases"] - name := id.Path["Principals"] role := id.Path["Role"] + fqn := id.Path["FQN"] kustoPrincipal := kusto.DatabasePrincipal{ - Role: kusto.DatabasePrincipalRole(role), + Role: kusto.DatabasePrincipalRole(role), + Fqn: utils.String(fqn), + Type: kusto.DatabasePrincipalType(d.Get("type").(string)), + // These three must be specified or the api returns `The request is invalid.` + // For more info: https://github.com/Azure/azure-sdk-for-go/issues/6547 Name: utils.String(""), - Fqn: utils.String(d.Get("fully_qualified_name").(string)), - Email: utils.String(d.Get("email").(string)), - AppID: utils.String(d.Get("app_id").(string)), - Type: kusto.DatabasePrincipalType(d.Get("type").(string)), + Email: utils.String(""), + AppID: utils.String(""), } principals := []kusto.DatabasePrincipal{kustoPrincipal} @@ -276,7 +318,7 @@ func resourceArmKustoDatabasePrincipalDelete(d *schema.ResourceData, meta interf _, err = client.RemovePrincipals(ctx, resGroup, clusterName, databaseName, request) if err != nil { - return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q, Database %q): %+v", name, resGroup, clusterName, databaseName, err) + return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q, Database %q): %+v", id, resGroup, clusterName, databaseName, err) } return nil diff --git a/azurerm/resource_arm_kusto_database_principal_test.go b/azurerm/resource_arm_kusto_database_principal_test.go index 96f5b5587ee2..d6b12729b182 100644 --- a/azurerm/resource_arm_kusto_database_principal_test.go +++ b/azurerm/resource_arm_kusto_database_principal_test.go @@ -1 +1,174 @@ package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMKustoDatabasePrincipal_basic(t *testing.T) { + resourceName := "azurerm_kusto_database_principal.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(6) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKustoDatabasePrincipalDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMKustoDatabasePrincipal_basic(ri, rs, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabasePrincipalExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMKustoDatabasePrincipalDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).Kusto.DatabasesClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_kusto_database_principal" { + continue + } + + resourceGroup := rs.Primary.Attributes["resource_group_name"] + clusterName := rs.Primary.Attributes["cluster_name"] + databaseName := rs.Primary.Attributes["database_name"] + role := rs.Primary.Attributes["role"] + fqn := rs.Primary.Attributes["fully_qualified_name"] + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return err + } + + found := false + if principals := resp.Value; principals != nil { + for _, currPrincipal := range *principals { + // kusto database principals are unique when looked at with fqn and role + if string(currPrincipal.Role) == role && currPrincipal.Fqn != nil && *currPrincipal.Fqn == fqn { + found = true + break + } + } + } + if found { + return fmt.Errorf("Kusto Database Principal %q still exists", fqn) + } + + return nil + } + + return nil +} + +func testCheckAzureRMKustoDatabasePrincipalExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + role := rs.Primary.Attributes["role"] + fqn := rs.Primary.Attributes["fully_qualified_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Kusto Database Principal: %s", fqn) + } + + clusterName, hasClusterName := rs.Primary.Attributes["cluster_name"] + if !hasClusterName { + return fmt.Errorf("Bad: no cluster name found in state for Kusto Database Principal: %s", fqn) + } + + databaseName, hasDatabaseName := rs.Primary.Attributes["database_name"] + if !hasDatabaseName { + return fmt.Errorf("Bad: no datbase name found in state for Kusto Database Principal: %s", fqn) + } + + client := testAccProvider.Meta().(*ArmClient).Kusto.DatabasesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Kusto Database %q (resource group: %q, cluster: %q) does not exist", fqn, resourceGroup, clusterName) + } + + return fmt.Errorf("Bad: Get on DatabasesClient: %+v", err) + } + + found := false + if principals := resp.Value; principals != nil { + for _, currPrincipal := range *principals { + // kusto database principals are unique when looked at with fqn and role + if string(currPrincipal.Role) == role && currPrincipal.Fqn != nil && *currPrincipal.Fqn == fqn { + found = true + break + } + } + } + if !found { + return fmt.Errorf("Unable to find Kusto Database Principal %q", fqn) + } + + return nil + } +} + +func testAccAzureRMKustoDatabasePrincipal_basic(rInt int, rs string, location string) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + + +resource "azurerm_resource_group" "rg" { + name = "acctestRG-kusto-%d" + location = "%s" +} + +resource "azurerm_kusto_cluster" "cluster" { + name = "acctestkc%s" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + + sku { + name = "Dev(No SLA)_Standard_D11_v2" + capacity = 1 + } +} + +resource "azurerm_kusto_database" "test" { + name = "acctestkd-%d" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + cluster_name = azurerm_kusto_cluster.cluster.name +} + +resource "azurerm_kusto_database_principal" "test" { + resource_group_name = azurerm_resource_group.rg.name + cluster_name = azurerm_kusto_cluster.cluster.name + database_name = azurerm_kusto_database.test.name + + role = "Viewer" + type = "App" + client_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.client_id +} +`, rInt, location, rs, rInt) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 78e9c40c704c..f384ce0a2196 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -1045,6 +1045,9 @@
  • azurerm_kusto_database
  • +
  • + azurerm_kusto_database_principal +
  • azurerm_kusto_eventhub_data_connection
  • diff --git a/website/docs/r/kusto_database_principal.html.markdown b/website/docs/r/kusto_database_principal.html.markdown new file mode 100644 index 000000000000..4d012b5a839c --- /dev/null +++ b/website/docs/r/kusto_database_principal.html.markdown @@ -0,0 +1,97 @@ +--- +subcategory: "Data Explorer" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_kusto_database_principal" +sidebar_current: "docs-azurerm-resource-kusto-database-principal" +description: |- + Manages Kusto / Data Explorer Database Principal +--- + +# azurerm_kusto_database_principal + +Manages a Kusto (also known as Azure Data Explorer) Database Principal + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "rg" { + name = "my-kusto-rg" + location = "East US" +} + +resource "azurerm_kusto_cluster" "cluster" { + name = "kustocluster" + location = "${azurerm_resource_group.rg.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + + sku { + name = "Standard_D13_v2" + capacity = 2 + } +} + +resource "azurerm_kusto_database" "database" { + name = "my-kusto-database" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + cluster_name = azurerm_kusto_cluster.cluster.name + + hot_cache_period = "P7D" + soft_delete_period = "P31D" +} + +resource "azurerm_kusto_database_principal" "principal" { + resource_group_name = azurerm_resource_group.rg.name + cluster_name = azurerm_kusto_cluster.cluster.name + database_name = azurerm_kusto_database.test.name + + role = "Viewer" + type = "User" + client_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.client_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `resource_group_name` - (Required) Specifies the Resource Group where the Kusto Database Principal should exist. Changing this forces a new resource to be created. + +* `cluster_name` - (Required) Specifies the name of the Kusto Cluster this database principal will be added to. Changing this forces a new resource to be created. + +* `database_name` - (Required) Specified the name of the Kusto Database this principal will be added to. Changing this forces a new resource to be created. + +* `role` - (Required) Specifies the permissions the Principal will have. Valid values include `Admin`, `Ingestor`, `Monitor`, `UnrestrictedViewers`, `User`, `Viewer`. Changing this forces a new resource to be created. + +* `type` - (Required) Specifies the type of object the principal is. Valid values include `App`, `Group`, `User`. Changing this forces a new resource to be created. + +* `object_id` - (Required) An Object ID of a User, Group, or App. Changing this forces a new resource to be created. + +* `client_id` - (Required) The Client ID that owns the specified `object_id`. Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Kusto Database Principal ID. + +* `app_id` - The app id, if not empty, of the principal. + +* `email` - The email, if not empty, of the principal. + +* `fully_qualified_name` - The fully qualified name of the principal. + +* `name` - The name of the Kusto Database Principal. + +--- + +## Import + +Kusto Database Principals can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_kusto_database_principal.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Kusto/Clusters/cluster1/Databases/database1/Role/role1/FQN/some-guid +``` From 1a50b0a2c4a8c43c0f0f2d210b5ffc16732d02d8 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 23 Dec 2019 11:57:31 -0800 Subject: [PATCH 4/7] Finalize merge with master --- .../internal/services/kusto/registration.go | 1 + .../resource_arm_kusto_database_principal.go | 10 +++---- ...ource_arm_kusto_database_principal_test.go | 30 +++++++++---------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/azurerm/internal/services/kusto/registration.go b/azurerm/internal/services/kusto/registration.go index 805981e53a7a..7c6688bda6e9 100644 --- a/azurerm/internal/services/kusto/registration.go +++ b/azurerm/internal/services/kusto/registration.go @@ -21,6 +21,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ "azurerm_kusto_cluster": resourceArmKustoCluster(), "azurerm_kusto_database": resourceArmKustoDatabase(), + "azurerm_kusto_database_principal": resourceArmKustoDatabasePrincipal(), "azurerm_kusto_eventhub_data_connection": resourceArmKustoEventHubDataConnection(), } } diff --git a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go index 46f068678d1e..25cb536b5fc0 100644 --- a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go +++ b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go @@ -118,7 +118,7 @@ func resourceArmKustoDatabasePrincipal() *schema.Resource { func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Kusto.DatabasesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() log.Printf("[INFO] preparing arguments for Azure Kusto Database Principal creation.") @@ -202,8 +202,8 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf } func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Kusto.DatabasesClient - ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + client := meta.(*clients.Client).Kusto.DatabasesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() id, err := azure.ParseAzureResourceID(d.Id()) @@ -286,8 +286,8 @@ func resourceArmKustoDatabasePrincipalRead(d *schema.ResourceData, meta interfac } func resourceArmKustoDatabasePrincipalDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).Kusto.DatabasesClient - ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + client := meta.(*clients.Client).Kusto.DatabasesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() id, err := azure.ParseAzureResourceID(d.Id()) diff --git a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go index 739a22a87f84..91f3385a9c4d 100644 --- a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go +++ b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go @@ -2,33 +2,31 @@ package tests import ( "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "testing" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func TestAccAzureRMKustoDatabasePrincipal_basic(t *testing.T) { - resourceName := "azurerm_kusto_database_principal.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(6) + data := acceptance.BuildTestData(t, "azurerm_kusto_database_principal", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMKustoDatabasePrincipalDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMKustoDatabasePrincipal_basic(ri, rs, testLocation()), + Config: testAccAzureRMKustoDatabasePrincipal_basic(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKustoDatabasePrincipalExists(resourceName), + testCheckAzureRMKustoDatabasePrincipalExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -37,7 +35,7 @@ func TestAccAzureRMKustoDatabasePrincipal_basic(t *testing.T) { } func testCheckAzureRMKustoDatabasePrincipalDestroy(s *terraform.State) error { - client := testAccProvider.Meta().(*ArmClient).Kusto.DatabasesClient + client := acceptance.AzureProvider.Meta().(*clients.Client).Kusto.DatabasesClient for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_kusto_database_principal" { @@ -49,7 +47,7 @@ func testCheckAzureRMKustoDatabasePrincipalDestroy(s *terraform.State) error { databaseName := rs.Primary.Attributes["database_name"] role := rs.Primary.Attributes["role"] fqn := rs.Primary.Attributes["fully_qualified_name"] - ctx := testAccProvider.Meta().(*ArmClient).StopContext + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) if err != nil { if utils.ResponseWasNotFound(resp.Response) { @@ -103,8 +101,8 @@ func testCheckAzureRMKustoDatabasePrincipalExists(resourceName string) resource. return fmt.Errorf("Bad: no datbase name found in state for Kusto Database Principal: %s", fqn) } - client := testAccProvider.Meta().(*ArmClient).Kusto.DatabasesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext + client := acceptance.AzureProvider.Meta().(*clients.Client).Kusto.DatabasesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext resp, err := client.ListPrincipals(ctx, resourceGroup, clusterName, databaseName) if err != nil { if utils.ResponseWasNotFound(resp.Response) { @@ -132,7 +130,7 @@ func testCheckAzureRMKustoDatabasePrincipalExists(resourceName string) resource. } } -func testAccAzureRMKustoDatabasePrincipal_basic(rInt int, rs string, location string) string { +func testAccAzureRMKustoDatabasePrincipal_basic(data acceptance.TestData) string { return fmt.Sprintf(` data "azurerm_client_config" "current" {} @@ -170,5 +168,5 @@ resource "azurerm_kusto_database_principal" "test" { client_id = data.azurerm_client_config.current.tenant_id object_id = data.azurerm_client_config.current.client_id } -`, rInt, location, rs, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger) } From 9465f9126dd7c20c02f5ad1d2cd715482fc21f7f Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 23 Dec 2019 13:57:10 -0800 Subject: [PATCH 5/7] Lint --- .../services/kusto/resource_arm_kusto_database_principal.go | 4 ++-- .../tests/resource_arm_kusto_database_principal_test.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go index 25cb536b5fc0..f73279cd38f3 100644 --- a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go +++ b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go @@ -2,8 +2,6 @@ package kusto import ( "fmt" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "log" "strings" "time" @@ -13,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" diff --git a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go index 91f3385a9c4d..47104f5493ad 100644 --- a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go +++ b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go @@ -2,12 +2,12 @@ package tests import ( "fmt" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -98,7 +98,7 @@ func testCheckAzureRMKustoDatabasePrincipalExists(resourceName string) resource. databaseName, hasDatabaseName := rs.Primary.Attributes["database_name"] if !hasDatabaseName { - return fmt.Errorf("Bad: no datbase name found in state for Kusto Database Principal: %s", fqn) + return fmt.Errorf("Bad: no database name found in state for Kusto Database Principal: %s", fqn) } client := acceptance.AzureProvider.Meta().(*clients.Client).Kusto.DatabasesClient From ccfefd746d70ae73f12ea66634d641fa967dd5db Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 25 Dec 2019 17:09:51 -0800 Subject: [PATCH 6/7] Update resource_arm_kusto_database_principal.go --- .../services/kusto/resource_arm_kusto_database_principal.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go index f73279cd38f3..157745a9dcfe 100644 --- a/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go +++ b/azurerm/internal/services/kusto/resource_arm_kusto_database_principal.go @@ -184,8 +184,7 @@ func resourceArmKustoDatabasePrincipalCreate(d *schema.ResourceData, meta interf Value: &principals, } - _, err = client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request) - if err != nil { + if _, err = client.AddPrincipals(ctx, resourceGroup, clusterName, databaseName, request); err != nil { return fmt.Errorf("Error creating Kusto Database Principal (Resource Group %q, Cluster %q): %+v", resourceGroup, clusterName, err) } @@ -317,8 +316,7 @@ func resourceArmKustoDatabasePrincipalDelete(d *schema.ResourceData, meta interf Value: &principals, } - _, err = client.RemovePrincipals(ctx, resGroup, clusterName, databaseName, request) - if err != nil { + if _, err = client.RemovePrincipals(ctx, resGroup, clusterName, databaseName, request); err != nil { return fmt.Errorf("Error deleting Kusto Database Principal %q (Resource Group %q, Cluster %q, Database %q): %+v", id, resGroup, clusterName, databaseName, err) } From de55bbf43d25f08e05eebb7c2ff2d28b57b8fadc Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 25 Dec 2019 17:10:26 -0800 Subject: [PATCH 7/7] Update resource_arm_kusto_database_principal_test.go --- .../tests/resource_arm_kusto_database_principal_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go index 47104f5493ad..99941605fd79 100644 --- a/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go +++ b/azurerm/internal/services/kusto/tests/resource_arm_kusto_database_principal_test.go @@ -25,11 +25,7 @@ func TestAccAzureRMKustoDatabasePrincipal_basic(t *testing.T) { testCheckAzureRMKustoDatabasePrincipalExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) }