From fa135e13d120fbe0c93b0e1981c57d22ea1bb371 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 22 Aug 2019 15:00:33 +0200 Subject: [PATCH 01/10] add databases client --- azurerm/internal/services/kusto/client.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/kusto/client.go b/azurerm/internal/services/kusto/client.go index 699620e3e25e..773eef803dfc 100644 --- a/azurerm/internal/services/kusto/client.go +++ b/azurerm/internal/services/kusto/client.go @@ -6,7 +6,8 @@ import ( ) type Client struct { - ClustersClient *kusto.ClustersClient + ClustersClient *kusto.ClustersClient + DatabasesClient *kusto.DatabasesClient } func BuildClient(o *common.ClientOptions) *Client { @@ -14,7 +15,11 @@ func BuildClient(o *common.ClientOptions) *Client { ClustersClient := kusto.NewClustersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ClustersClient.Client, o.ResourceManagerAuthorizer) + DatabasesClient := kusto.NewDatabasesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&DatabasesClient.Client, o.ResourceManagerAuthorizer) + return &Client{ - ClustersClient: &ClustersClient, + ClustersClient: &ClustersClient, + DatabasesClient: &DatabasesClient, } } From 824fd5d10a60c2b13c94469b2c043a33c8c4dec5 Mon Sep 17 00:00:00 2001 From: rob Date: Thu, 22 Aug 2019 16:58:58 +0200 Subject: [PATCH 02/10] add kusto database resource (no tests yet) --- azurerm/provider.go | 1 + azurerm/resource_arm_kusto_database.go | 197 +++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 azurerm/resource_arm_kusto_database.go diff --git a/azurerm/provider.go b/azurerm/provider.go index a4eff7f67e4d..e635212959f9 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -257,6 +257,7 @@ func Provider() terraform.ResourceProvider { "azurerm_key_vault": resourceArmKeyVault(), "azurerm_kubernetes_cluster": resourceArmKubernetesCluster(), "azurerm_kusto_cluster": resourceArmKustoCluster(), + "azurerm_kusto_database": resourceArmKustoDatabase(), "azurerm_lb_backend_address_pool": resourceArmLoadBalancerBackendAddressPool(), "azurerm_lb_nat_pool": resourceArmLoadBalancerNatPool(), "azurerm_lb_nat_rule": resourceArmLoadBalancerNatRule(), diff --git a/azurerm/resource_arm_kusto_database.go b/azurerm/resource_arm_kusto_database.go new file mode 100644 index 000000000000..3c8bfa708521 --- /dev/null +++ b/azurerm/resource_arm_kusto_database.go @@ -0,0 +1,197 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2019-01-21/kusto" + "github.com/hashicorp/terraform/helper/schema" + "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/utils" +) + +func resourceArmKustoDatabase() *schema.Resource { + return &schema.Resource{ + Create: resourceArmKustoDatabaseCreateUpdate, + Read: resourceArmKustoDatabaseRead, + Update: resourceArmKustoDatabaseCreateUpdate, + Delete: resourceArmKustoDatabaseDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "cluster_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAzureRMKustoClusterName, + }, + + "soft_delete_period": { + Type: schema.TypeString, + Optional: true, + }, + + "hot_cache_period": { + Type: schema.TypeString, + Optional: true, + }, + + "size": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + } +} + +func resourceArmKustoDatabaseCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).kusto.DatabasesClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for Azure Kusto Database creation.") + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + clusterName := d.Get("cluster_name").(string) + + if requireResourcesToBeImported && d.IsNewResource() { + server, err := client.Get(ctx, resourceGroup, clusterName, name) + if err != nil { + if !utils.ResponseWasNotFound(server.Response) { + return fmt.Errorf("Error checking for presence of existing Kusto Database %q (Resource Group %q, Cluster %q): %s", name, resourceGroup, clusterName, err) + } + } + + if server.ID != nil && *server.ID != "" { + return tf.ImportAsExistsError("azurerm_kusto_database", *server.ID) + } + } + + location := azure.NormalizeLocation(d.Get("location").(string)) + + databaseProperties := expandKustoDatabaseProperties(d) + + kustoDatabase := kusto.Database{ + Name: &name, + Location: &location, + DatabaseProperties: databaseProperties, + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, clusterName, name, kustoDatabase) + if err != nil { + return fmt.Errorf("Error creating or updating Kusto Cluster %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for completion of Kusto Cluster %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + } + + resp, getDetailsErr := client.Get(ctx, resourceGroup, clusterName, name) + if getDetailsErr != nil { + return fmt.Errorf("Error retrieving Kusto Cluster %q (Resource Group %q, Cluster %q): %+v", name, resourceGroup, clusterName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read ID for Kusto Cluster %q (Resource Group %q, Cluster %q)", name, resourceGroup, clusterName) + } + + d.SetId(*resp.ID) + + return resourceArmKustoDatabaseRead(d, meta) +} + +func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).kusto.DatabasesClient + ctx := meta.(*ArmClient).StopContext + + 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)) + } + + databaseProperties := *databaseResponse.DatabaseProperties + + d.Set("hot_cache_period", databaseProperties.HotCachePeriod) + d.Set("soft_delete_period", databaseProperties.SoftDeletePeriod) + + if statistics := databaseProperties.Statistics; statistics != nil { + d.Set("size", statistics.Size) + } + + return nil +} + +func resourceArmKustoDatabaseDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).kusto.DatabasesClient + ctx := meta.(*ArmClient).StopContext + + 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 %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 %q (Resource Group %q, Cluster %q): %+v", name, resGroup, clusterName, err) + } + + return nil +} + +func expandKustoDatabaseProperties(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 +} From 4aa414ad9172daf7e91964412431c419e75bc278 Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Aug 2019 12:57:38 +0200 Subject: [PATCH 03/10] add function to validate kusto database name --- azurerm/resource_arm_kusto_database.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_kusto_database.go b/azurerm/resource_arm_kusto_database.go index 3c8bfa708521..38c8595a92d1 100644 --- a/azurerm/resource_arm_kusto_database.go +++ b/azurerm/resource_arm_kusto_database.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "log" + "regexp" "github.com/Azure/azure-sdk-for-go/services/kusto/mgmt/2019-01-21/kusto" "github.com/hashicorp/terraform/helper/schema" @@ -24,9 +25,10 @@ func resourceArmKustoDatabase() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validateAzureRMKustoDatabaseName, }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -182,6 +184,24 @@ func resourceArmKustoDatabaseDelete(d *schema.ResourceData, meta interface{}) er return nil } +func validateAzureRMKustoDatabaseName(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 expandKustoDatabaseProperties(d *schema.ResourceData) *kusto.DatabaseProperties { databaseProperties := &kusto.DatabaseProperties{} From fbd630d43b21f4beaf243a998f1e727b00c33a4a Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 23 Aug 2019 12:59:38 +0200 Subject: [PATCH 04/10] add basic test and tests for soft_delete_period and hot_cache_period --- azurerm/resource_arm_kusto_database_test.go | 302 ++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 azurerm/resource_arm_kusto_database_test.go diff --git a/azurerm/resource_arm_kusto_database_test.go b/azurerm/resource_arm_kusto_database_test.go new file mode 100644 index 000000000000..b5b045585cb7 --- /dev/null +++ b/azurerm/resource_arm_kusto_database_test.go @@ -0,0 +1,302 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMKustoDatabase_basic(t *testing.T) { + resourceName := "azurerm_kusto_database.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(6) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKustoDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMKustoDatabase_basic(ri, rs, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabaseExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMKustoDatabase_softDeletePeriod(t *testing.T) { + resourceName := "azurerm_kusto_database.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(6) + preConfig := testAccAzureRMKustoDatabase_softDeletePeriod(ri, rs, testLocation()) + postConfig := testAccAzureRMKustoDatabase_softDeletePeriodUpdate(ri, rs, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKustoDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "soft_delete_period", "P7D"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "soft_delete_period", "P31D"), + ), + }, + }, + }) +} + +func TestAccAzureRMKustoDatabase_hotCachePeriod(t *testing.T) { + resourceName := "azurerm_kusto_database.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(6) + preConfig := testAccAzureRMKustoDatabase_hotCachePeriod(ri, rs, testLocation()) + postConfig := testAccAzureRMKustoDatabase_hotCachePeriodUpdate(ri, rs, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMKustoDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "hot_cache_period", "P7D"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKustoDatabaseExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "hot_cache_period", "P2W"), + ), + }, + }, + }) +} + +func testAccAzureRMKustoDatabase_basic(rInt int, rs string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%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 +} +`, rInt, location, rs, rInt) +} + +func testAccAzureRMKustoDatabase_softDeletePeriod(rInt int, rs string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%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 + + soft_delete_period = "P7D" +} +`, rInt, location, rs, rInt) +} + +func testAccAzureRMKustoDatabase_softDeletePeriodUpdate(rInt int, rs string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%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 + + soft_delete_period = "P31D" +} +`, rInt, location, rs, rInt) +} + +func testAccAzureRMKustoDatabase_hotCachePeriod(rInt int, rs string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%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 + + hot_cache_period = "P7D" +} +`, rInt, location, rs, rInt) +} + +func testAccAzureRMKustoDatabase_hotCachePeriodUpdate(rInt int, rs string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%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 + + hot_cache_period = "P2W" +} +`, rInt, location, rs, rInt) +} + +func testCheckAzureRMKustoDatabaseDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).kusto.DatabasesClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_kusto_database" { + continue + } + + resourceGroup := rs.Primary.Attributes["resource_group_name"] + clusterName := rs.Primary.Attributes["cluster_name"] + name := rs.Primary.Attributes["name"] + + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.Get(ctx, resourceGroup, clusterName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + return err + } + + return nil + } + + return nil +} + +func testCheckAzureRMKustoDatabaseExists(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) + } + + kustoDatabase := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Kusto Database: %s", kustoDatabase) + } + + clusterName, hasClusterName := rs.Primary.Attributes["cluster_name"] + if !hasClusterName { + return fmt.Errorf("Bad: no resource group found in state for Kusto Database: %s", kustoDatabase) + } + + client := testAccProvider.Meta().(*ArmClient).kusto.DatabasesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.Get(ctx, resourceGroup, clusterName, kustoDatabase) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Kusto Database %q (resource group: %q, cluster: %q) does not exist", kustoDatabase, resourceGroup, clusterName) + } + + return fmt.Errorf("Bad: Get on DatabasesClient: %+v", err) + } + + return nil + } +} From 073af9cb2ac10b0f64ef8ac7426720bb05feb1bd Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 26 Aug 2019 08:19:14 +0200 Subject: [PATCH 05/10] fix hot cache period test --- azurerm/resource_arm_kusto_database_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_kusto_database_test.go b/azurerm/resource_arm_kusto_database_test.go index b5b045585cb7..cbe2bc04017e 100644 --- a/azurerm/resource_arm_kusto_database_test.go +++ b/azurerm/resource_arm_kusto_database_test.go @@ -89,7 +89,7 @@ func TestAccAzureRMKustoDatabase_hotCachePeriod(t *testing.T) { Config: postConfig, Check: resource.ComposeTestCheckFunc( testCheckAzureRMKustoDatabaseExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "hot_cache_period", "P2W"), + resource.TestCheckResourceAttr(resourceName, "hot_cache_period", "P14DT12H"), ), }, }, @@ -234,7 +234,7 @@ resource "azurerm_kusto_database" "test" { location = azurerm_resource_group.rg.location cluster_name = azurerm_kusto_cluster.cluster.name - hot_cache_period = "P2W" + hot_cache_period = "P14DT12H" } `, rInt, location, rs, rInt) } From 2486e4f186b130ec6b1b485e5190c3ff896b37c0 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 26 Aug 2019 09:15:21 +0200 Subject: [PATCH 06/10] add documentation --- website/docs/r/kusto_database.html.markdown | 78 +++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 website/docs/r/kusto_database.html.markdown diff --git a/website/docs/r/kusto_database.html.markdown b/website/docs/r/kusto_database.html.markdown new file mode 100644 index 000000000000..4c1ef15ae6e1 --- /dev/null +++ b/website/docs/r/kusto_database.html.markdown @@ -0,0 +1,78 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_kusto_database" +sidebar_current: "docs-azurerm-resource-kusto-database" +description: |- + Manages Kusto / Data Explorer Database +--- + +# azurerm_kusto_database + +Manages a Kusto (also known as Azure Data Explorer) Database + +## Example Usage + +This example provisions a Kusto Database. + +```hcl +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" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Kusto Database to create. Changing this forces a new resource to be created. + +* `location` - (Required) The location where the Kusto Database should be created. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) Specifies the Resource Group where the Kusto Database should exist. Changing this forces a new resource to be created. + +* `cluster_name` - (Required) Specifies the name of the Kusto Cluster this database will be added to. Changing this forces a new resource to be created. + +* `hot_cache_period` - (Optional) The time the data that should be kept in cache for fast queries as ISO 8601 timespan. Default is unlimited. For more information see: [ISO 8601 Timespan](https://en.wikipedia.org/wiki/ISO_8601#Durations) + +* `soft_delete_period` - (Optional) The time the data should be kept before it stops being accessible to queries as ISO 8601 timespan. Default is unlimited. For more information see: [ISO 8601 Timespan](https://en.wikipedia.org/wiki/ISO_8601#Durations) + + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Kusto Cluster ID. + +* `size` - The size of the database in bytes. + +--- + +## Import + +Kusto Clusters can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_kusto_database.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Kusto/Clusters/cluster1/Databases/database1 +``` From 3563b1f6a7014c3db0fd4b58b196ca02abc00fcb Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 27 Aug 2019 16:12:25 +0200 Subject: [PATCH 07/10] validate soft_delete_period and hot_cache_period --- azurerm/resource_arm_kusto_database.go | 11 +- .../security/adaptiveapplicationcontrols.go | 296 ++++++++++++++++++ 2 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 vendor/github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security/adaptiveapplicationcontrols.go diff --git a/azurerm/resource_arm_kusto_database.go b/azurerm/resource_arm_kusto_database.go index 38c8595a92d1..eda8643cdd3d 100644 --- a/azurerm/resource_arm_kusto_database.go +++ b/azurerm/resource_arm_kusto_database.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform/helper/schema" "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/utils" ) @@ -43,13 +44,15 @@ func resourceArmKustoDatabase() *schema.Resource { }, "soft_delete_period": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.ISO8601Duration, }, "hot_cache_period": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.ISO8601Duration, }, "size": { diff --git a/vendor/github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security/adaptiveapplicationcontrols.go b/vendor/github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security/adaptiveapplicationcontrols.go new file mode 100644 index 000000000000..0710d2febfe7 --- /dev/null +++ b/vendor/github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security/adaptiveapplicationcontrols.go @@ -0,0 +1,296 @@ +package security + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// 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. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/autorest/validation" + "github.com/Azure/go-autorest/tracing" + "net/http" +) + +// AdaptiveApplicationControlsClient is the API spec for Microsoft.Security (Azure Security Center) resource provider +type AdaptiveApplicationControlsClient struct { + BaseClient +} + +// NewAdaptiveApplicationControlsClient creates an instance of the AdaptiveApplicationControlsClient client. +func NewAdaptiveApplicationControlsClient(subscriptionID string, ascLocation string) AdaptiveApplicationControlsClient { + return NewAdaptiveApplicationControlsClientWithBaseURI(DefaultBaseURI, subscriptionID, ascLocation) +} + +// NewAdaptiveApplicationControlsClientWithBaseURI creates an instance of the AdaptiveApplicationControlsClient client. +func NewAdaptiveApplicationControlsClientWithBaseURI(baseURI string, subscriptionID string, ascLocation string) AdaptiveApplicationControlsClient { + return AdaptiveApplicationControlsClient{NewWithBaseURI(baseURI, subscriptionID, ascLocation)} +} + +// Get gets an application control VM/server group. +// Parameters: +// groupName - name of an application control VM/server group +func (client AdaptiveApplicationControlsClient) Get(ctx context.Context, groupName string) (result AppWhitelistingGroup, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/AdaptiveApplicationControlsClient.Get") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: client.SubscriptionID, + Constraints: []validation.Constraint{{Target: "client.SubscriptionID", Name: validation.Pattern, Rule: `^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("security.AdaptiveApplicationControlsClient", "Get", err.Error()) + } + + req, err := client.GetPreparer(ctx, groupName) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Get", nil, "Failure preparing request") + return + } + + resp, err := client.GetSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Get", resp, "Failure sending request") + return + } + + result, err = client.GetResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Get", resp, "Failure responding to request") + } + + return +} + +// GetPreparer prepares the Get request. +func (client AdaptiveApplicationControlsClient) GetPreparer(ctx context.Context, groupName string) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "ascLocation": autorest.Encode("path", client.AscLocation), + "groupName": autorest.Encode("path", groupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-06-01-preview" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Security/locations/{ascLocation}/applicationWhitelistings/{groupName}", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// GetSender sends the Get request. The method will close the +// http.Response Body if it receives an error. +func (client AdaptiveApplicationControlsClient) GetSender(req *http.Request) (*http.Response, error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) +} + +// GetResponder handles the response to the Get request. The method always +// closes the http.Response Body. +func (client AdaptiveApplicationControlsClient) GetResponder(resp *http.Response) (result AppWhitelistingGroup, err error) { + err = autorest.Respond( + resp, + client.ByInspecting(), + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// List gets a list of application control VM/server groups for the subscription. +// Parameters: +// includePathRecommendations - include the policy rules +// summary - return output in a summarized form +func (client AdaptiveApplicationControlsClient) List(ctx context.Context, includePathRecommendations *bool, summary *bool) (result AppWhitelistingGroups, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/AdaptiveApplicationControlsClient.List") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: client.SubscriptionID, + Constraints: []validation.Constraint{{Target: "client.SubscriptionID", Name: validation.Pattern, Rule: `^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("security.AdaptiveApplicationControlsClient", "List", err.Error()) + } + + req, err := client.ListPreparer(ctx, includePathRecommendations, summary) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "List", nil, "Failure preparing request") + return + } + + resp, err := client.ListSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "List", resp, "Failure sending request") + return + } + + result, err = client.ListResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "List", resp, "Failure responding to request") + } + + return +} + +// ListPreparer prepares the List request. +func (client AdaptiveApplicationControlsClient) ListPreparer(ctx context.Context, includePathRecommendations *bool, summary *bool) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-06-01-preview" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + if includePathRecommendations != nil { + queryParameters["includePathRecommendations"] = autorest.Encode("query", *includePathRecommendations) + } + if summary != nil { + queryParameters["summary"] = autorest.Encode("query", *summary) + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Security/applicationWhitelistings", pathParameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// ListSender sends the List request. The method will close the +// http.Response Body if it receives an error. +func (client AdaptiveApplicationControlsClient) ListSender(req *http.Request) (*http.Response, error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) +} + +// ListResponder handles the response to the List request. The method always +// closes the http.Response Body. +func (client AdaptiveApplicationControlsClient) ListResponder(resp *http.Response) (result AppWhitelistingGroups, err error) { + err = autorest.Respond( + resp, + client.ByInspecting(), + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +// Put update an application control VM/server group +// Parameters: +// groupName - name of an application control VM/server group +// body - the updated VM/server group data +func (client AdaptiveApplicationControlsClient) Put(ctx context.Context, groupName string, body AppWhitelistingPutGroupData) (result AppWhitelistingGroup, err error) { + if tracing.IsEnabled() { + ctx = tracing.StartSpan(ctx, fqdn+"/AdaptiveApplicationControlsClient.Put") + defer func() { + sc := -1 + if result.Response.Response != nil { + sc = result.Response.Response.StatusCode + } + tracing.EndSpan(ctx, sc, err) + }() + } + if err := validation.Validate([]validation.Validation{ + {TargetValue: client.SubscriptionID, + Constraints: []validation.Constraint{{Target: "client.SubscriptionID", Name: validation.Pattern, Rule: `^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$`, Chain: nil}}}}); err != nil { + return result, validation.NewError("security.AdaptiveApplicationControlsClient", "Put", err.Error()) + } + + req, err := client.PutPreparer(ctx, groupName, body) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Put", nil, "Failure preparing request") + return + } + + resp, err := client.PutSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Put", resp, "Failure sending request") + return + } + + result, err = client.PutResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "security.AdaptiveApplicationControlsClient", "Put", resp, "Failure responding to request") + } + + return +} + +// PutPreparer prepares the Put request. +func (client AdaptiveApplicationControlsClient) PutPreparer(ctx context.Context, groupName string, body AppWhitelistingPutGroupData) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "ascLocation": autorest.Encode("path", client.AscLocation), + "groupName": autorest.Encode("path", groupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2015-06-01-preview" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/Microsoft.Security/locations/{ascLocation}/applicationWhitelistings/{groupName}", pathParameters), + autorest.WithJSON(body), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// PutSender sends the Put request. The method will close the +// http.Response Body if it receives an error. +func (client AdaptiveApplicationControlsClient) PutSender(req *http.Request) (*http.Response, error) { + sd := autorest.GetSendDecorators(req.Context(), azure.DoRetryWithRegistration(client.Client)) + return autorest.SendWithSender(client, req, sd...) +} + +// PutResponder handles the response to the Put request. The method always +// closes the http.Response Body. +func (client AdaptiveApplicationControlsClient) PutResponder(resp *http.Response) (result AppWhitelistingGroup, err error) { + err = autorest.Respond( + resp, + client.ByInspecting(), + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingJSON(&result), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} From 2df022a60796c10a4f62a59441e23658c4e1ee88 Mon Sep 17 00:00:00 2001 From: rob Date: Tue, 27 Aug 2019 16:13:39 +0200 Subject: [PATCH 08/10] validate soft_delete_period and hot_cache_period --- go.mod | 1 - go.sum | 7 ------- 2 files changed, 8 deletions(-) diff --git a/go.mod b/go.mod index 2c66d01d5342..ae12966f7f31 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/hashicorp/go-version v1.1.0 github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/terraform v0.12.6 - github.com/relvacode/iso8601 v0.0.0-20181221151331-e9cae14c704e // indirect github.com/satori/go.uuid v1.2.0 github.com/satori/uuid v0.0.0-20160927100844-b061729afc07 github.com/terraform-providers/terraform-provider-azuread v0.4.1-0.20190610202312-5a179146b9f9 diff --git a/go.sum b/go.sum index 8361b54b5139..24f523c3b6e1 100644 --- a/go.sum +++ b/go.sum @@ -21,7 +21,6 @@ github.com/Azure/azure-sdk-for-go v30.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v31.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v31.1.0+incompatible h1:5SzgnfAvUBdBwNTN23WLfZoCt/rGhLvd7QdCAaFXgY4= github.com/Azure/azure-sdk-for-go v31.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v32.3.0+incompatible h1:cPbYVpshHJc/lWNk0Gzhf8SLN+7qpdb8RQnRh0gntcI= github.com/Azure/go-autorest v10.15.4+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.7.0+incompatible h1:gzma19dc9ejB75D90E5S+/wXouzpZyA+CV+/MJPSD/k= github.com/Azure/go-autorest v11.7.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -407,8 +406,6 @@ github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/relvacode/iso8601 v0.0.0-20181221151331-e9cae14c704e h1:NQHGYUZfr1cCsFZwC31Thmhuc9K6eUUmeNI9J9QMfB0= -github.com/relvacode/iso8601 v0.0.0-20181221151331-e9cae14c704e/go.mod h1:Kn09ZkOSv8PRg6gPzFTGF6xIk6p7UFCVqGmS/+uUZ3Y= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -465,10 +462,6 @@ github.com/terraform-providers/terraform-provider-azuread v0.4.1-0.2019061020231 github.com/terraform-providers/terraform-provider-openstack v1.15.0 h1:adpjqej+F8BAX9dHmuPF47sUIkgifeqBu6p7iCsyj0Y= github.com/terraform-providers/terraform-provider-openstack v1.15.0/go.mod h1:2aQ6n/BtChAl1y2S60vebhyJyZXBsuAI5G4+lHrT1Ew= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tombuildsstuff/giovanni v0.3.0 h1:uOaTgr6mp5iba02s+pz+ugBZuygIhA2tN+FZAsivOvg= -github.com/tombuildsstuff/giovanni v0.3.0/go.mod h1:3UHcoRZCvWTjXMWCJ0epD1VROlPMwZeeof3vfP6NiWM= -github.com/tombuildsstuff/giovanni v0.3.1 h1:weKffbA9vYVUACa6u1XXW0alYoTLuphMZ0BMgg63a/A= -github.com/tombuildsstuff/giovanni v0.3.1/go.mod h1:3UHcoRZCvWTjXMWCJ0epD1VROlPMwZeeof3vfP6NiWM= github.com/tombuildsstuff/giovanni v0.3.2 h1:uKt7irq74daF0lvaA0X9bEuFKSDhceVy4DyWVPDRYeU= github.com/tombuildsstuff/giovanni v0.3.2/go.mod h1:3UHcoRZCvWTjXMWCJ0epD1VROlPMwZeeof3vfP6NiWM= github.com/ugorji/go v0.0.0-20180813092308-00b869d2f4a5 h1:cMjKdf4PxEBN9K5HaD9UMW8gkTbM0kMzkTa9SJe0WNQ= From 6f13e932f47fb0be700fd892ba6f941a50e8ad9d Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 30 Aug 2019 06:59:25 +0200 Subject: [PATCH 09/10] remove obsolete documentation line --- website/docs/r/kusto_database.html.markdown | 2 -- 1 file changed, 2 deletions(-) diff --git a/website/docs/r/kusto_database.html.markdown b/website/docs/r/kusto_database.html.markdown index 4c1ef15ae6e1..a8131081f71d 100644 --- a/website/docs/r/kusto_database.html.markdown +++ b/website/docs/r/kusto_database.html.markdown @@ -12,8 +12,6 @@ Manages a Kusto (also known as Azure Data Explorer) Database ## Example Usage -This example provisions a Kusto Database. - ```hcl resource "azurerm_resource_group" "rg" { name = "my-kusto-rg" From 0df5a8f29a3bfafde73dee2a42afc0805980e942 Mon Sep 17 00:00:00 2001 From: rob Date: Mon, 2 Sep 2019 07:55:03 +0200 Subject: [PATCH 10/10] add nil check for database properties --- azurerm/resource_arm_kusto_database.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/resource_arm_kusto_database.go b/azurerm/resource_arm_kusto_database.go index eda8643cdd3d..b43d6cb19dd7 100644 --- a/azurerm/resource_arm_kusto_database.go +++ b/azurerm/resource_arm_kusto_database.go @@ -150,13 +150,13 @@ func resourceArmKustoDatabaseRead(d *schema.ResourceData, meta interface{}) erro d.Set("location", azure.NormalizeLocation(*location)) } - databaseProperties := *databaseResponse.DatabaseProperties + if props := databaseResponse.DatabaseProperties; props != nil { + d.Set("hot_cache_period", props.HotCachePeriod) + d.Set("soft_delete_period", props.SoftDeletePeriod) - d.Set("hot_cache_period", databaseProperties.HotCachePeriod) - d.Set("soft_delete_period", databaseProperties.SoftDeletePeriod) - - if statistics := databaseProperties.Statistics; statistics != nil { - d.Set("size", statistics.Size) + if statistics := props.Statistics; statistics != nil { + d.Set("size", statistics.Size) + } } return nil