From 81f2521293e0481641d72e20310653b731f23735 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Sep 2019 22:40:29 -0500 Subject: [PATCH 001/498] New Resource: `azurerm_monitor_scheduled_query_rules` --- ...ta_source_monitor_scheduled_query_rules.go | 265 +++++++ ...urce_monitor_scheduled_query_rules_test.go | 243 +++++++ azurerm/internal/services/monitor/client.go | 5 + azurerm/provider.go | 2 + ...ource_arm_monitor_scheduled_query_rules.go | 685 ++++++++++++++++++ ..._arm_monitor_scheduled_query_rules_test.go | 320 ++++++++ ...onitor_scheduled_query_rules.html.markdown | 88 +++ ...onitor_scheduled_query_rules.html.markdown | 193 +++++ 8 files changed, 1801 insertions(+) create mode 100644 azurerm/data_source_monitor_scheduled_query_rules.go create mode 100644 azurerm/data_source_monitor_scheduled_query_rules_test.go create mode 100644 azurerm/resource_arm_monitor_scheduled_query_rules.go create mode 100644 azurerm/resource_arm_monitor_scheduled_query_rules_test.go create mode 100644 website/docs/d/monitor_scheduled_query_rules.html.markdown create mode 100644 website/docs/r/monitor_scheduled_query_rules.html.markdown diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go new file mode 100644 index 0000000000000..7d551ed10437b --- /dev/null +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -0,0 +1,265 @@ +package azurerm + +import ( + "fmt" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "action_type": { + Type: schema.TypeString, + Computed: true, + }, + "authorized_resources": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Elem: schema.TypeString, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "values": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", *resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + switch action := resp.Action.(type) { + case insights.AlertingAction: + d.Set("action_type", "Alerting") + d.Set("azns_action", *action.AznsAction) + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", *action.ThrottlingInMin) + d.Set("trigger", *action.Trigger) + case insights.LogToMetricAction: + d.Set("action_type", "LogToMetric") + d.Set("criteria", *action.Criteria) + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", *schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", *schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", *source.AuthorizedResources) + } + if source.DataSourceID != nil { + d.Set("data_source_id", *source.DataSourceID) + } + if source.Query != nil { + d.Set("query", *source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + // read-only props + d.Set("last_updated_time", *resp.LastUpdatedTime) + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go new file mode 100644 index 0000000000000..5aed5d9797329 --- /dev/null +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -0,0 +1,243 @@ +package azurerm + +import ( + "fmt" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttr(dataSourceName, "enabled", "true"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_percent Idle Time" + dimension { + name = "dimension" + operator = "Include" + values = ["latency"] + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(rInt int, rString string, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt, ts, ts) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(rInt int, rString string, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_log_analytics_workspace" "test2" { + name = "acctestWorkspace2-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +} diff --git a/azurerm/internal/services/monitor/client.go b/azurerm/internal/services/monitor/client.go index accb35d792cd9..137284ec756ca 100644 --- a/azurerm/internal/services/monitor/client.go +++ b/azurerm/internal/services/monitor/client.go @@ -17,6 +17,7 @@ type Client struct { DiagnosticSettingsCategoryClient *insights.DiagnosticSettingsCategoryClient LogProfilesClient *insights.LogProfilesClient MetricAlertsClient *insights.MetricAlertsClient + ScheduledQueryRulesClient *insights.ScheduledQueryRulesClient } func BuildClient(o *common.ClientOptions) *Client { @@ -44,6 +45,9 @@ func BuildClient(o *common.ClientOptions) *Client { MetricAlertsClient := insights.NewMetricAlertsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&MetricAlertsClient.Client, o.ResourceManagerAuthorizer) + ScheduledQueryRulesClient := insights.NewScheduledQueryRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ScheduledQueryRulesClient.Client, o.ResourceManagerAuthorizer) + return &Client{ AutoscaleSettingsClient: &AutoscaleSettingsClient, ActionGroupsClient: &ActionGroupsClient, @@ -53,5 +57,6 @@ func BuildClient(o *common.ClientOptions) *Client { DiagnosticSettingsCategoryClient: &DiagnosticSettingsCategoryClient, LogProfilesClient: &LogProfilesClient, MetricAlertsClient: &MetricAlertsClient, + ScheduledQueryRulesClient: &ScheduledQueryRulesClient, } } diff --git a/azurerm/provider.go b/azurerm/provider.go index 535d670e026ca..e28a2929189d2 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -106,6 +106,7 @@ func Provider() terraform.ResourceProvider { "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules(), "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), "azurerm_netapp_account": dataSourceArmNetAppAccount(), "azurerm_netapp_pool": dataSourceArmNetAppPool(), @@ -361,6 +362,7 @@ func Provider() terraform.ResourceProvider { "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules(), "azurerm_mssql_elasticpool": resourceArmMsSqlElasticPool(), "azurerm_mysql_configuration": resourceArmMySQLConfiguration(), "azurerm_mysql_database": resourceArmMySqlDatabase(), diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go new file mode 100644 index 0000000000000..ab85d9837572a --- /dev/null +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -0,0 +1,685 @@ +package azurerm + +import ( + "fmt" + "log" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "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/response" + "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/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRules() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesRead, + Update: resourceArmMonitorScheduledQueryRulesCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "action_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Alerting", + "LogToMetric", + }, false), + }, + "authorized_resources": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Include", + }, false), + }, + "values": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules", *existing.ID) + } + } + + actionType := d.Get("action_type").(string) + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if enabledRaw == false { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + var action insights.BasicAction + switch actionType { + case "Alerting": + action = expandMonitorScheduledQueryRulesAlertingAction(d) + case "LogToMetric": + action = expandMonitorScheduledQueryRulesLogToMetricAction(d) + default: + return fmt.Errorf("Invalid action_type %q. Value must be either 'Alerting' or 'LogToMetric'", actionType) + } + + source := expandMonitorScheduledQueryRulesSource(d) + schedule := expandMonitorScheduledQueryRulesSchedule(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", *resp.Description) + + switch action := resp.Action.(type) { + case insights.AlertingAction: + d.Set("action_type", "Alerting") + d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)) + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", *action.ThrottlingInMin) + d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + case insights.LogToMetricAction: + d.Set("action_type", "LogToMetric") + d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", *schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", *schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", *source.AuthorizedResources) + } + if source.DataSourceID != nil { + d.Set("data_source_id", *source.DataSourceID) + } + if source.Query != nil { + d.Set("query", *source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + // read-only props + d.Set("last_updated_time", *resp.LastUpdatedTime) + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { + aznsActionRaw := d.Get("azns_action").(*schema.Set).List() + aznsAction := expandMonitorScheduledQueryRulesAznsAction(aznsActionRaw) + severityRaw := d.Get("severity").(int) + severity := strconv.Itoa(severityRaw) + throttling := d.Get("throttling").(int) + + triggerRaw := d.Get("trigger").(*schema.Set).List() + trigger := expandMonitorScheduledQueryRulesTrigger(triggerRaw) + + action := insights.AlertingAction{ + AznsAction: aznsAction, + Severity: insights.AlertSeverity(severity), + ThrottlingInMin: utils.Int32(int32(throttling)), + Trigger: trigger, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.AzNsActionGroup { + result := insights.AzNsActionGroup{} + + for _, item := range input { + v := item.(map[string]interface{}) + actionGroups := v["action_group"].(*schema.Set).List() + + result.ActionGroup = utils.ExpandStringSlice(actionGroups) + result.EmailSubject = utils.String(v["email_subject"].(string)) + result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesCriteria(input []interface{}) *[]insights.Criteria { + criteria := make([]insights.Criteria, 0) + for _, item := range input { + v := item.(map[string]interface{}) + + dimensions := make([]insights.Dimension, 0) + for _, dimension := range v["dimension"].(*schema.Set).List() { + dVal := dimension.(map[string]interface{}) + dimensions = append(dimensions, insights.Dimension{ + Name: utils.String(dVal["name"].(string)), + Operator: utils.String(dVal["operator"].(string)), + Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), + }) + } + + criteria = append(criteria, insights.Criteria{ + MetricName: utils.String(v["metric_name"].(string)), + Dimensions: &dimensions, + }) + } + return &criteria +} + +func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { + criteriaRaw := d.Get("criteria").(*schema.Set).List() + criteria := expandMonitorScheduledQueryRulesCriteria(criteriaRaw) + + action := insights.LogToMetricAction{ + Criteria: criteria, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + + schedule := insights.Schedule{ + FrequencyInMinutes: utils.Int32(int32(frequency)), + TimeWindowInMinutes: utils.Int32(int32(timeWindow)), + } + + return &schedule +} + +func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { + result := insights.LogMetricTrigger{} + + for _, item := range input { + v := item.(map[string]interface{}) + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) + result.MetricColumn = utils.String(v["metric_column"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { + authorizedResources := d.Get("authorized_resources").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query := d.Get("query").(string) + + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResources), + DataSourceID: utils.String(dataSourceID), + Query: utils.String(query), + QueryType: insights.ResultCount, + } + + return &source +} + +func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.TriggerCondition { + result := insights.TriggerCondition{} + + for _, item := range input { + v := item.(map[string]interface{}) + metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() + + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTrigger = expandMonitorScheduledQueryRulesMetricTrigger(metricTriggerRaw) + } + + return &result +} + +func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + /*if err = d.Set("azure_function_receiver", flattenMonitorActionGroupAzureFunctionReceiver(group.AzureFunctionReceivers)); err != nil { + return fmt.Errorf("Error setting `azure_function_receiver`: %+v", err) + }*/ + v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesSchedule(input *insights.Schedule) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + if input.FrequencyInMinutes != nil { + result["frequency_in_minutes"] = int(*input.FrequencyInMinutes) + } + + if input.TimeWindowInMinutes != nil { + result["time_window_in_minutes"] = int(*input.TimeWindowInMinutes) + } + + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesSource(input *insights.Source) []interface{} { + result := make(map[string]interface{}) + + if input.AuthorizedResources != nil { + result["authorized_resources"] = *input.AuthorizedResources + } + if input.DataSourceID != nil { + result["data_source_id"] = *input.DataSourceID + } + if input.Query != nil { + result["query"] = *input.Query + } + result["query_type"] = string(input.QueryType) + + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go new file mode 100644 index 0000000000000..fa371118723fb --- /dev/null +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -0,0 +1,320 @@ +package azurerm + +import ( + "fmt" + "net/http" + "strings" + "testing" + "time" + + "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" +) + +func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_alertingAction(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "Alerting" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + custom_webhook_payload = "{}" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 5 + metric_trigger_type = "Consecutive" + metric_column = "Computer" + } + } +} +`, rInt, location, rInt, rInt, rInt, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "Alerting" + + authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 5 + metric_trigger_type = "Consecutive" + metric_column = "Computer" + } + } +} +`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_percent Idle Time" + dimension { + name = "dimension" + operator = "Include" + values = ["latency"] + } + } +} +`, rInt, location, rInt, rInt, rInt) +} + +func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_monitor_scheduled_query_rules" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(ctx, resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + } + } + + return nil +} + +func testCheckAzureRMMonitorScheduledQueryRulesExists(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) + } + + name := 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 Activity Log Alert Instance: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules.html.markdown new file mode 100644 index 0000000000000..804ec3e2606c8 --- /dev/null +++ b/website/docs/d/monitor_scheduled_query_rules.html.markdown @@ -0,0 +1,88 @@ +--- +subcategory: "" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" +description: |- + Get information about the specified Scheduled Query Rule. +--- + +# Data Source: azurerm_monitor_scheduled_query_rules + +Use this data source to access the properties of a Scheduled Query Rule. + +## Example Usage + +```hcl +data "azurerm_monitor_scheduled_query_rules" "example" { + resource_group_name = "terraform-example-rg" + name = "tfex-queryrule" +} + +output "query_rule_id" { + value = "${data.azurerm_monitor_scheduled_query_rules.example.id}" +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Scheduled Query Rule. +* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. + +## Attributes Reference + +* `id` - The ID of the Scheduled Query Rule. +* `azns_action` - An `azns_action` block as defined below. +* `action_type` - Must equal ether `AlertingAction` or `LogToMetricAction`. +* `authorized_resources` - List of Resource IDs referred into query. +* `criteria` - A `criteria` block as defined below. +* `data_source_id` - The resource uri over which log search query is to be run. +* `description` - The description of the Scheduled Query Rule. +* `enabled` - Whether this scheduled query rule is enabled. +* `frequency` - Frequency (in minutes) at which rule condition should be evaluated. +* `query` - Log search query. Required for action type - `alerting_action`. +* `query_type` - Must equal "ResultCount". +* `time_window` - Time window for which data needs to be fetched for query (should be greater than or equal to frequency_in_minutes). +* `severity` - Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. +* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. +* `trigger` - A `trigger` block as defined below. The condition that results in the alert rule being run. + +--- + +* `azns_action` supports the following: + +* `action_group` - (Optional) List of action group reference resource IDs. +* `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. +* `email_subject` - Custom subject override for all email ids in Azure action group. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +--- + +`metricTrigger` supports the following: + +* `metricColumn` - (Required) Evaluation of metric on a particular column. +* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) The threshold of the metric trigger. + +--- + +`trigger` supports the following: + +* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown new file mode 100644 index 0000000000000..439981bc06a5b --- /dev/null +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -0,0 +1,193 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules" +description: |- + Manages a Scheduled Query Rule within Azure Monitor +--- + +# azurerm_monitor_action_group + +Manages a Scheduled Query Rule within Azure Monitor. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "monitoring-resources" + location = "West US" +} + +resource "azurerm_application_insights" "example" { + name = "appinsights" + location = var.location + resource_group_name = azurerm_resource_group.example.name + application_type = "web" +} + +resource "azurerm_log_analytics_workspace" "example" { + name = "loganalytics" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku = "PerGB2018" + retention_in_days = 30 +} + +# Example: AlertingAction +resource "azurerm_scheduled_query_rule" "example" { + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "AlertingAction" + azns_action = { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = {} + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule AlertingAction example" + enabled = true + frequency = 5 + query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query_type = "ResultCount" + severity = "1" + time_window = 30 + trigger = { + threshold_operator = "GreaterThan" + threshold = 3 + } +} + +# Example: AlertingAction Cross-Resource +resource "azurerm_scheduled_query_rule" "example2" { + name = format("%s-queryrule2", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "AlertingAction" + authorized_resources = [azurerm_application_insights.example.id, + azurerm_log_analytics_workspace.example.id] + azns_action = { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = {} + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule AlertingAction cross-resource example" + enabled = true + frequency = 5 + query = "union requests, workspace(\"loganalytics\").Heartbeat" + query_type = "ResultCount" + severity = "1" + time_window = 30 + trigger = { + threshold_operator = "GreaterThan" + threshold = 3 + } +} + +# Example: LogToMetricAction +resource "azurerm_scheduled_query_rule" "example3" { + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "LogToMetricAction" + criteria = [{ + metric_name = "Average_% Idle Time" + dimensions = [{ + name = "dimension" + operator = "GreaterThan" + values = ["latency"] + }] + }] + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `action_type` - (Required) Must equal ether `AlertingAction` or `LogToMetricAction`. +* `authorized_resources` - (Optional) List of Resource IDs referred into query. +* `data_source_id` - (Required) The resource uri over which log search query is to be run. +* `description` - (Optional) The description of the Scheduled Query Rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. + +The following arguments are only supported when `action_type` is `AlertingAction`: + +* `azns_action` - (Optional) An `azns_action` block as defined below. +* `frequency` - (Optional) Frequency (in minutes) at which rule condition should be evaluated. Required when `action_type` is `AlertingAction`. +* `query` - (Optional) Log search query. Required when `action_type` is `AlertingAction`. +* `query_type` - (Optional) Must equal "ResultCount" for now. Required when `action_type` is `AlertingAction`. +* `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. +* `time_window` - (Optional) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). Required when `action_type` is `AlertingAction`. +* `trigger` - (Optional) The condition that results in the alert rule being run. Required when `action_type` is `AlertingAction`. + +The following arguments are only supported when `action_type` is `LogToMetricAction`: + +* `criteria` - (Optional) A `criteria` block as defined below. Required when `action_type` is `LogToMetricAction`. + +--- + +* `azns_action` supports the following: + +* `action_group` - (Optional) List of action group reference resource IDs. +* `custom_webhook_payload` - (Optional) Custom payload to be sent for all webhook payloads in alerting action. +* `email_subject` - (Optional) Custom subject override for all email ids in Azure action group. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +--- + +`metricTrigger` supports the following: + +* `metricColumn` - (Required) Evaluation of metric on a particular column. +* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) The threshold of the metric trigger. + +--- + +`trigger` supports the following: + +* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Scheduled Query Rule. +* `last_updated_time` - Last time the rule was updated in IS08601 format. +* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' + +## Import + +Scheduled Query Rules can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_monitor_scheduled_query_rules.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +``` From 5303ecd0bc242d24e1d3d46dd52238105950ef0c Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:25:12 -0600 Subject: [PATCH 002/498] Acceptance tests passing --- ...ta_source_monitor_scheduled_query_rules.go | 19 ++++++++----- ...urce_monitor_scheduled_query_rules_test.go | 27 ++++++++++++++----- ...ource_arm_monitor_scheduled_query_rules.go | 10 +++---- ..._arm_monitor_scheduled_query_rules_test.go | 24 ++++++++--------- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 7d551ed10437b..5d9c5bbbadb6a 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -85,8 +85,11 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { Computed: true, }, "values": { - Type: schema.TypeString, + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, }, }, @@ -220,17 +223,20 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - d.Set("azns_action", *action.AznsAction) + + aznsAction := flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction) + d.Set("azns_action", aznsAction) + severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", *action.Trigger) + d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", *action.Criteria) + d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } @@ -257,8 +263,9 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("query_type", string(source.QueryType)) } - // read-only props - d.Set("last_updated_time", *resp.LastUpdatedTime) + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", *lastUpdated) + } d.Set("provisioning_state", resp.ProvisioningState) return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go index 5aed5d9797329..2642ac2652a9c 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -15,16 +15,16 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), - resource.TestCheckResourceAttr(dataSourceName, "enabled", "true"), ), }, }, @@ -36,13 +36,14 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), ), @@ -56,13 +57,14 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), ), @@ -142,21 +144,20 @@ resource "azurerm_monitor_action_group" "test" { } resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestSqr-%d" + name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true action_type = "Alerting" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" query_type = "ResultCount" frequency = 60 time_window = 60 - severity = 3 azns_action { action_group = ["${azurerm_monitor_action_group.test.id}"] @@ -166,6 +167,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { trigger { operator = "GreaterThan" threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } } } @@ -232,6 +239,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { trigger { operator = "GreaterThan" threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } } } diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index ab85d9837572a..650cd33b995bf 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -346,6 +346,10 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", *lastUpdated) + } + d.Set("provisioning_state", resp.ProvisioningState) if resp.Enabled == insights.True { d.Set("enabled", true) @@ -395,17 +399,13 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("query_type", string(source.QueryType)) } - // read-only props - d.Set("last_updated_time", *resp.LastUpdatedTime) - d.Set("provisioning_state", resp.ProvisioningState) - return tags.FlattenAndSet(d, resp.Tags) } func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) - defer cancel() + defer cancel() id, err := azure.ParseAzureResourceID(d.Id()) if err != nil { diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index fa371118723fb..7d7c2d2fdce13 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -123,12 +123,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" + description = "test alerting action" enabled = true action_type = "Alerting" data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" query_type = "ResultCount" frequency = 60 @@ -142,13 +142,13 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } trigger { - operator = "GreaterThan" - threshold = 5000 + operator = "GreaterThan" + threshold = 5000 metric_trigger { operator = "GreaterThan" - threshold = 5 - metric_trigger_type = "Consecutive" - metric_column = "Computer" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" } } } @@ -189,13 +189,13 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" + description = "test alerting action cross-resource" enabled = true action_type = "Alerting" authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" query_type = "ResultCount" frequency = 60 @@ -212,9 +212,9 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { threshold = 5000 metric_trigger { operator = "GreaterThan" - threshold = 5 - metric_trigger_type = "Consecutive" - metric_column = "Computer" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" } } } From 607a00d86b40fbb0f92c9e384851ff86caaa6d54 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 3 Dec 2019 09:19:32 -0600 Subject: [PATCH 003/498] Fix linting errors; minor cleanup --- ...ta_source_monitor_scheduled_query_rules.go | 31 ++++---- ...ource_arm_monitor_scheduled_query_rules.go | 75 ++++--------------- ..._arm_monitor_scheduled_query_rules_test.go | 3 - 3 files changed, 32 insertions(+), 77 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 5d9c5bbbadb6a..6e12d24266485 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -213,7 +213,7 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("location", azure.NormalizeLocation(*location)) } - d.Set("description", *resp.Description) + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { @@ -223,48 +223,51 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - - aznsAction := flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction) - d.Set("azns_action", aznsAction) - + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) - d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } if schedule := resp.Schedule; schedule != nil { if schedule.FrequencyInMinutes != nil { - d.Set("frequency", *schedule.FrequencyInMinutes) + d.Set("frequency", schedule.FrequencyInMinutes) } if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", *schedule.TimeWindowInMinutes) + d.Set("time_window", schedule.TimeWindowInMinutes) } } if source := resp.Source; source != nil { if source.AuthorizedResources != nil { - d.Set("authorized_resources", *source.AuthorizedResources) + d.Set("authorized_resources", source.AuthorizedResources) } if source.DataSourceID != nil { - d.Set("data_source_id", *source.DataSourceID) + d.Set("data_source_id", source.DataSourceID) } if source.Query != nil { - d.Set("query", *source.Query) + d.Set("query", source.Query) } d.Set("query_type", string(source.QueryType)) } if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", *lastUpdated) + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) } d.Set("provisioning_state", resp.ProvisioningState) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index 650cd33b995bf..0f9d720f31a9f 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -269,7 +269,7 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m enabledRaw := d.Get("enabled").(bool) enabled := insights.True - if enabledRaw == false { + if !enabledRaw { enabled = insights.False } @@ -347,7 +347,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("location", azure.NormalizeLocation(*location)) } if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", *lastUpdated) + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) } d.Set("provisioning_state", resp.ProvisioningState) @@ -357,46 +357,39 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("enabled", false) } - d.Set("description", *resp.Description) + d.Set("description", resp.Description) switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)) + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) - d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } if schedule := resp.Schedule; schedule != nil { if schedule.FrequencyInMinutes != nil { - d.Set("frequency", *schedule.FrequencyInMinutes) + d.Set("frequency", schedule.FrequencyInMinutes) } if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", *schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", *source.AuthorizedResources) - } - if source.DataSourceID != nil { - d.Set("data_source_id", *source.DataSourceID) - } - if source.Query != nil { - d.Set("query", *source.Query) + d.Set("time_window", schedule.TimeWindowInMinutes) } - d.Set("query_type", string(source.QueryType)) } return tags.FlattenAndSet(d, resp.Tags) @@ -573,9 +566,6 @@ func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []int for _, criteria := range *input { v := make(map[string]interface{}) - /*if err = d.Set("azure_function_receiver", flattenMonitorActionGroupAzureFunctionReceiver(group.AzureFunctionReceivers)); err != nil { - return fmt.Errorf("Error setting `azure_function_receiver`: %+v", err) - }*/ v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) v["metric_name"] = *criteria.MetricName @@ -633,41 +623,6 @@ func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTri return []interface{}{result} } -func flattenAzureRmScheduledQueryRulesSchedule(input *insights.Schedule) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - if input.FrequencyInMinutes != nil { - result["frequency_in_minutes"] = int(*input.FrequencyInMinutes) - } - - if input.TimeWindowInMinutes != nil { - result["time_window_in_minutes"] = int(*input.TimeWindowInMinutes) - } - - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesSource(input *insights.Source) []interface{} { - result := make(map[string]interface{}) - - if input.AuthorizedResources != nil { - result["authorized_resources"] = *input.AuthorizedResources - } - if input.DataSourceID != nil { - result["data_source_id"] = *input.DataSourceID - } - if input.Query != nil { - result["query"] = *input.Query - } - result["query_type"] = string(input.QueryType) - - return []interface{}{result} -} - func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { result := make(map[string]interface{}) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index 7d7c2d2fdce13..b426231b251cb 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -38,7 +38,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { }, }, }) - return } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { @@ -66,7 +65,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }, }, }) - return } func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { @@ -94,7 +92,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }, }, }) - return } func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { From ebf84e9fa0ea474bb2d330c73977fa5d43315f4a Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:19:21 -0600 Subject: [PATCH 004/498] Minor updates and bug fixes - Fix some sprintf formatting - Improve documentation for cross-resource query - Don't create an empty metric_trigger {} if user doesn't specify block --- ...ta_source_monitor_scheduled_query_rules.go | 2 +- ...urce_monitor_scheduled_query_rules_test.go | 6 +- ...ource_arm_monitor_scheduled_query_rules.go | 23 +++++++- ..._arm_monitor_scheduled_query_rules_test.go | 24 +++----- ...onitor_scheduled_query_rules.html.markdown | 57 +++++++++++-------- 5 files changed, 66 insertions(+), 46 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 6e12d24266485..6f74ed992cf9b 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -255,7 +255,7 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in if source := resp.Source; source != nil { if source.AuthorizedResources != nil { - d.Set("authorized_resources", source.AuthorizedResources) + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) } if source.DataSourceID != nil { d.Set("data_source_id", source.DataSourceID) diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go index 2642ac2652a9c..b8090d408463d 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -104,11 +104,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { data_source_id = "${azurerm_application_insights.test.id}" criteria { - metric_name = "Average_percent Idle Time" + metric_name = "Average_%% Idle Time" dimension { - name = "dimension" + name = "InstanceName" operator = "Include" - values = ["latency"] + values = [""] } } } diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index 0f9d720f31a9f..a3e2e48dd468f 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -215,8 +215,9 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { }, false), }, "threshold": { - Type: schema.TypeFloat, - Required: true, + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, }, }, }, @@ -392,6 +393,19 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte } } + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + return tags.FlattenAndSet(d, resp.Tags) } @@ -500,8 +514,11 @@ func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights. } func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { - result := insights.LogMetricTrigger{} + if len(input) == 0 { + return nil + } + result := insights.LogMetricTrigger{} for _, item := range input { v := item.(map[string]interface{}) result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index b426231b251cb..e5de80da1288f 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -153,8 +153,6 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { - ts := time.Now().Format(time.RFC3339) - return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -192,11 +190,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" frequency = 60 - time_window = 60 + time_window = 60 severity = 3 azns_action { @@ -205,17 +203,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } + operator = "GreaterThan" + threshold = 5000 } } -`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +`, rInt, location, rInt, rInt, rInt, rInt) } func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { @@ -249,11 +241,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { data_source_id = "${azurerm_application_insights.test.id}" criteria { - metric_name = "Average_percent Idle Time" + metric_name = "Average_%% Idle Time" dimension { - name = "dimension" + name = "InstanceName" operator = "Include" - values = ["latency"] + values = [""] } } } diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown index 439981bc06a5b..dfcb7279a4f76 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -34,75 +34,86 @@ resource "azurerm_log_analytics_workspace" "example" { retention_in_days = 30 } -# Example: AlertingAction +# Example: Alerting Action resource "azurerm_scheduled_query_rule" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "AlertingAction" - azns_action = { + action_type = "Alerting" + azns_action { action_group = [] email_subject = "Email Header" - custom_webhook_payload = {} + custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule AlertingAction example" + description = "Scheduled query rule Alerting Action example" enabled = true frequency = 5 query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" query_type = "ResultCount" - severity = "1" + severity = 1 time_window = 30 - trigger = { + trigger { threshold_operator = "GreaterThan" threshold = 3 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "timestamp" + } } } -# Example: AlertingAction Cross-Resource +# Example: Alerting Action Cross-Resource resource "azurerm_scheduled_query_rule" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "AlertingAction" + action_type = "Alerting" authorized_resources = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] - azns_action = { + azns_action { action_group = [] email_subject = "Email Header" - custom_webhook_payload = {} + custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule AlertingAction cross-resource example" + description = "Scheduled query rule Alerting Action cross-resource example" enabled = true frequency = 5 - query = "union requests, workspace(\"loganalytics\").Heartbeat" + query = format(< ago(1h) | where ObjectName == "Processor" and CounterName == "%% Processor Time" | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); +let b=requests | where resultCode == "200" and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); +a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5 +QUERY + , azurerm_log_analytics_workspace.example.id) query_type = "ResultCount" severity = "1" time_window = 30 - trigger = { + trigger { threshold_operator = "GreaterThan" threshold = 3 } } -# Example: LogToMetricAction +# Example: LogToMetric Action resource "azurerm_scheduled_query_rule" "example3" { name = format("%s-queryrule3", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "LogToMetricAction" - criteria = [{ + action_type = "LogToMetric" + criteria { metric_name = "Average_% Idle Time" - dimensions = [{ - name = "dimension" - operator = "GreaterThan" - values = ["latency"] - }] - }] + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } + } data_source_id = azurerm_application_insights.example.id description = "Scheduled query rule LogToMetric example" enabled = true From ce59b1af4f98d5a74d502539dd5dfef135d04b91 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:26:08 -0600 Subject: [PATCH 005/498] Remove heredoc in docs example --- website/docs/r/monitor_scheduled_query_rules.html.markdown | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown index dfcb7279a4f76..8d18bebe2327c 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -84,12 +84,7 @@ resource "azurerm_scheduled_query_rule" "example2" { description = "Scheduled query rule Alerting Action cross-resource example" enabled = true frequency = 5 - query = format(< ago(1h) | where ObjectName == "Processor" and CounterName == "%% Processor Time" | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); -let b=requests | where resultCode == "200" and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); -a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5 -QUERY - , azurerm_log_analytics_workspace.example.id) + query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" severity = "1" time_window = 30 From a1bf9bacb68a0699b66722cc605236f07ca81f0a Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 11 Dec 2019 01:35:23 -0600 Subject: [PATCH 006/498] fix response import --- azurerm/resource_arm_monitor_scheduled_query_rules.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index a3e2e48dd468f..0a6e2ff31caca 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -7,10 +7,10 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "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/response" "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" From 8acb500d31c30f5af44d694a9c250a440e9c7534 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Dec 2019 17:51:08 -0600 Subject: [PATCH 007/498] Update tests and docs to pass checks --- ...urce_monitor_scheduled_query_rules_test.go | 60 ++++++-------- ..._arm_monitor_scheduled_query_rules_test.go | 79 ++++++++----------- ...onitor_scheduled_query_rules.html.markdown | 2 +- 3 files changed, 57 insertions(+), 84 deletions(-) rename azurerm/internal/services/monitor/{ => tests}/data_source_monitor_scheduled_query_rules_test.go (78%) rename azurerm/internal/services/monitor/{ => tests}/resource_arm_monitor_scheduled_query_rules_test.go (77%) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go similarity index 78% rename from azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go index 089835482e1e3..875fdaa762026 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go @@ -1,31 +1,25 @@ -package monitor +package tests import ( "fmt" "testing" "time" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, @@ -33,20 +27,16 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, @@ -54,27 +44,23 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -118,10 +104,10 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -181,10 +167,10 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -253,5 +239,5 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go similarity index 77% rename from azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go index 559bcacf3b43d..357a8ba2b0f94 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go @@ -1,38 +1,33 @@ -package monitor +package tests import ( "fmt" "net/http" - "strings" "testing" "time" - "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/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_alertingAction(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -41,25 +36,21 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -68,25 +59,21 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes } func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -94,7 +81,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }) } -func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -149,10 +136,10 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } } -`, rInt, location, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -207,10 +194,10 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { threshold = 5000 } } -`, rInt, location, rInt, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -249,12 +236,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } } -`, rInt, location, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_monitor_scheduled_query_rules" { @@ -264,7 +251,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error name := rs.Primary.Attributes["name"] resourceGroup := rs.Primary.Attributes["resource_group_name"] - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, resourceGroup, name) if err != nil { return nil @@ -292,10 +279,10 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) } - conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, resourceGroup, name) if err != nil { return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) } diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules.html.markdown index 804ec3e2606c8..d6651611d15b6 100644 --- a/website/docs/d/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "" +subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" From 7b25b377e643117ac99d36e4d128ae7596316614 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Dec 2019 19:23:26 -0600 Subject: [PATCH 008/498] Add moved tests to registration --- .../internal/services/monitor/registration.go | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index dfc09bd0b42dd..366450fc514f1 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -16,19 +16,21 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile()} + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules()} } From 39fb80f2e4e1d12a714e61dadc8b1523337f5962 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 8 Jan 2020 12:33:01 -0800 Subject: [PATCH 009/498] Key Vault: support for soft delete --- azurerm/helpers/validate/bool.go | 23 ++++ azurerm/helpers/validate/bool_test.go | 37 ++++++ .../keyvault/data_source_key_vault.go | 12 ++ .../keyvault/resource_arm_key_vault.go | 49 ++++++++ .../tests/data_source_key_vault_test.go | 32 ++++++ .../tests/resource_arm_key_vault_test.go | 106 ++++++++++++++++++ website/docs/d/key_vault.html.markdown | 4 + website/docs/r/key_vault.html.markdown | 6 + 8 files changed, 269 insertions(+) create mode 100644 azurerm/helpers/validate/bool.go create mode 100644 azurerm/helpers/validate/bool_test.go diff --git a/azurerm/helpers/validate/bool.go b/azurerm/helpers/validate/bool.go new file mode 100644 index 0000000000000..3c7901b3636c7 --- /dev/null +++ b/azurerm/helpers/validate/bool.go @@ -0,0 +1,23 @@ +package validate + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func BoolIsTrue() schema.SchemaValidateFunc { + return func(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(bool) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be bool", k)) + return + } + + if !v { + errors = append(errors, fmt.Errorf("%q can only be set to true, if not required remove key", k)) + return + } + return + } +} diff --git a/azurerm/helpers/validate/bool_test.go b/azurerm/helpers/validate/bool_test.go new file mode 100644 index 0000000000000..d9ba6b9627a93 --- /dev/null +++ b/azurerm/helpers/validate/bool_test.go @@ -0,0 +1,37 @@ +package validate + +import "testing" + +func TestBoolIsTrue(t *testing.T) { + + testCases := []struct { + Value bool + ShouldHaveError bool + }{ + { + Value: true, + ShouldHaveError: false, + }, { + Value: false, + ShouldHaveError: true, + }, + } + + t.Run("TestBoolIsTrue", func(t *testing.T) { + for _, value := range testCases { + _, errors := BoolIsTrue()(value.Value, "dummy") + hasErrors := len(errors) > 0 + + if value.ShouldHaveError && !hasErrors { + t.Fatalf("Expected an error but didn't get one for %t", value.Value) + return + } + + if !value.ShouldHaveError && hasErrors { + t.Fatalf("Expected %t to return no errors, but got some %+v", value.Value, errors) + return + } + + } + }) +} \ No newline at end of file diff --git a/azurerm/internal/services/keyvault/data_source_key_vault.go b/azurerm/internal/services/keyvault/data_source_key_vault.go index ef5bf1b85f549..6117855e4e12e 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault.go @@ -156,6 +156,16 @@ func dataSourceArmKeyVault() *schema.Resource { }, }, + "enabled_for_soft_delete": { + Type: schema.TypeBool, + Computed: true, + }, + + "enabled_for_purge_protection": { + Type: schema.TypeBool, + Computed: true, + }, + "tags": tags.SchemaDataSource(), }, } @@ -190,6 +200,8 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) + d.Set("enabled_for_soft_delete", props.EnableSoftDelete) + d.Set("enabled_for_purge_protection", props.EnablePurgeProtection) d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index a8dee0b0b0fa9..2b6cbf0ffbc01 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -157,6 +157,25 @@ func resourceArmKeyVault() *schema.Resource { Optional: true, }, + "enabled_for_soft_delete": { + Type: schema.TypeBool, + Optional: true, + ValidateFunc: validate.BoolIsTrue(), + }, + + "enabled_for_purge_protection": { + Type: schema.TypeBool, + Optional: true, + ValidateFunc: validate.BoolIsTrue(), + }, + + "purge_on_delete": { + Type: schema.TypeBool, + Optional: true, + Default: false, + ConflictsWith: []string{"enabled_for_purge_protection"}, + }, + "network_acls": { Type: schema.TypeList, Optional: true, @@ -252,6 +271,8 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e enabledForDeployment := d.Get("enabled_for_deployment").(bool) enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) enabledForTemplateDeployment := d.Get("enabled_for_template_deployment").(bool) + enabledForSoftDelete := d.Get("enabled_for_soft_delete").(bool) + enabledForPurgeProtection := d.Get("enabled_for_purge_protection").(bool) t := d.Get("tags").(map[string]interface{}) networkAclsRaw := d.Get("network_acls").([]interface{}) @@ -277,6 +298,16 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e Tags: tags.Expand(t), } + // This setting can only be set if it is true, if set when value is false API returns errors + if enabledForSoftDelete { + parameters.Properties.EnableSoftDelete = &enabledForSoftDelete + } + + // This setting can only be set if it is true, if set when value is false API returns errors + if enabledForPurgeProtection { + parameters.Properties.EnablePurgeProtection = &enabledForPurgeProtection + } + // Locking this resource so we don't make modifications to it at the same time if there is a // key vault access policy trying to update it as well locks.ByName(name, keyVaultResourceName) @@ -375,6 +406,8 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) + d.Set("enabled_for_soft_delete", props.EnableSoftDelete) + d.Set("enabled_for_purge_protection", props.EnablePurgeProtection) d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { @@ -461,6 +494,22 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } } + if d.Get("purge_on_delete").(bool) && d.Get("enabled_for_soft_delete").(bool) && err == nil { + log.Printf("[DEBUG] KeyVault %s marked for purge, executing purge", name) + location := d.Get("location").(string) + + future, err := client.PurgeDeleted(ctx, name, location) + if err != nil { + return err + } + + log.Printf("[DEBUG] Waiting for purge of KeyVault %s", name) + err = future.WaitForCompletionRef(ctx, client.Client) + if err != nil { + return fmt.Errorf("Error purging Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + return nil } diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 8953c5d82eff8..9b33dc5a66bea 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -111,6 +111,26 @@ func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { }) } +func TestAccDataSourceAzureRMKeyVault_enable_soft_delete(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_key_vault", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMKeyVaultDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMKeyVault_enable_soft_delete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_soft_delete", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_purge_protection", "false"), + ), + }, + }, + }) +} + func testAccDataSourceAzureRMKeyVault_basic(data acceptance.TestData) string { r := testAccAzureRMKeyVault_basic(data) return fmt.Sprintf(` @@ -146,3 +166,15 @@ data "azurerm_key_vault" "test" { } `, r) } + +func testAccDataSourceAzureRMKeyVault_enable_soft_delete(data acceptance.TestData) string { + r := testAccAzureRMKeyVault_enable_soft_delete(data) + return fmt.Sprintf(` +%s + +data "azurerm_key_vault" "test" { + name = "${azurerm_key_vault.test.name}" + resource_group_name = "${azurerm_key_vault.test.resource_group_name}" +} +`, r) +} diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index e492e07ba1e3f..2bc04b0b1b12d 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -331,6 +331,55 @@ func TestAccAzureRMKeyVault_justCert(t *testing.T) { }) } +func TestAccAzureRMKeyVault_soft_delete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") + expectedError := fmt.Sprintf("^Check failed: Check 1/1 error: Not found: %s", data.ResourceName) + errorRegEx, _ := regexp.Compile(expectedError) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMKeyVaultDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMKeyVault_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), + ), + }, + { + Config: testAccAzureRMKeyVault_enable_soft_delete(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "get"), + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "get"), + resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_soft_delete", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_purge_protection", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), + ), + }, + { + Config: testAccAzureRMKeyVault_purge_vault(data), + ExpectError: errorRegEx, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(data.ResourceName), + ), + }, + { + Config: testAccAzureRMKeyVault_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMKeyVaultExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), + resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), + resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), + ), + }, + }, + }) +} + func testCheckAzureRMKeyVaultDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -446,6 +495,10 @@ resource "azurerm_key_vault" "test" { "set", ] } + + tags = { + environment = "Production" + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } @@ -787,6 +840,59 @@ resource "azurerm_key_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } +func testAccAzureRMKeyVault_enable_soft_delete(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_key_vault" "test" { + name = "vault%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + + sku { + name = "premium" + } + + access_policy { + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + object_id = "${data.azurerm_client_config.current.client_id}" + + key_permissions = [ + "get", + ] + + secret_permissions = [ + "get", + ] + } + + enabled_for_soft_delete = true + purge_on_delete = true + + tags = { + environment = "Production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + +func testAccAzureRMKeyVault_purge_vault(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} +`, data.RandomInteger, data.Locations.Primary) +} + func testAccAzureRMKeyVault_complete(data acceptance.TestData) string { return fmt.Sprintf(` data "azurerm_client_config" "current" {} diff --git a/website/docs/d/key_vault.html.markdown b/website/docs/d/key_vault.html.markdown index 26314d2081299..cdb96e02f290d 100644 --- a/website/docs/d/key_vault.html.markdown +++ b/website/docs/d/key_vault.html.markdown @@ -54,6 +54,10 @@ The following attributes are exported: * `enabled_for_template_deployment` - Can Azure Resource Manager retrieve secrets from the Key Vault? +* `enabled_for_soft_delete` - Is soft delete enabled on this Key Vault? + +* `enabled_for_purge_protection` - Is purge protection enabled on this Key Vault? + * `tags` - A mapping of tags assigned to the Key Vault. A `sku` block exports the following: diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index 6d257aa5ad834..ed02b1c1903b4 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -84,6 +84,12 @@ The following arguments are supported: * `enabled_for_template_deployment` - (Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to `false`. +* `enabled_for_soft_delete` - (Optional) Boolean flag to specify whether the key vault is enabled for soft delete. Once enabled you can not disable this setting. + +* `purge_on_delete` - (Optional) Boolean flag to specify if the KeyVault should be purged on delete. This purges KeyVaults enabled for soft delete on resource deletition. + +* `enabled_for_purge_protection` - (Optional) Boolean flag to specify whether the key vault is enabled for purge protection, this conflicts with `purge_on_delete`. Once enabled you can not disable this setting. + * `network_acls` - (Optional) A `network_acls` block as defined below. * `tags` - (Optional) A mapping of tags to assign to the resource. From beafb4c57f0159bcb929024384f7ed21c7fe652d Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 8 Jan 2020 14:06:07 -0800 Subject: [PATCH 010/498] fix lint errors --- azurerm/helpers/validate/bool_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/azurerm/helpers/validate/bool_test.go b/azurerm/helpers/validate/bool_test.go index d9ba6b9627a93..d378dafc41b0d 100644 --- a/azurerm/helpers/validate/bool_test.go +++ b/azurerm/helpers/validate/bool_test.go @@ -3,7 +3,6 @@ package validate import "testing" func TestBoolIsTrue(t *testing.T) { - testCases := []struct { Value bool ShouldHaveError bool @@ -31,7 +30,6 @@ func TestBoolIsTrue(t *testing.T) { t.Fatalf("Expected %t to return no errors, but got some %+v", value.Value, errors) return } - } }) -} \ No newline at end of file +} From f874617e737b931d9d99096a65dbbfb21f77d9a8 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 20 Jan 2020 16:47:41 +1100 Subject: [PATCH 011/498] Add Directline --- azurerm/internal/services/bot/registration.go | 1 + .../resource_arm_bot_channel_directline.go | 322 ++++++++++++++++++ ...esource_arm_bot_channel_directline_test.go | 142 ++++++++ ...urce_arm_bot_channels_registration_test.go | 10 +- .../docs/r/bot_channel_directline.markdown | 67 ++++ 5 files changed, 538 insertions(+), 4 deletions(-) create mode 100644 azurerm/internal/services/bot/resource_arm_bot_channel_directline.go create mode 100644 azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go create mode 100644 website/docs/r/bot_channel_directline.markdown diff --git a/azurerm/internal/services/bot/registration.go b/azurerm/internal/services/bot/registration.go index a0eadf437cad2..67ee57b061c48 100644 --- a/azurerm/internal/services/bot/registration.go +++ b/azurerm/internal/services/bot/registration.go @@ -22,6 +22,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_bot_channel_email": resourceArmBotChannelEmail(), "azurerm_bot_channel_slack": resourceArmBotChannelSlack(), "azurerm_bot_channel_ms_teams": resourceArmBotChannelMsTeams(), + "azurerm_bot_channel_directline": resourceArmBotChannelDirectline(), "azurerm_bot_channels_registration": resourceArmBotChannelsRegistration(), "azurerm_bot_connection": resourceArmBotConnection(), "azurerm_bot_web_app": resourceArmBotWebApp(), diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go new file mode 100644 index 0000000000000..eda31f60573c2 --- /dev/null +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -0,0 +1,322 @@ +package bot + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/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/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" +) + +func resourceArmBotChannelDirectline() *schema.Resource { + return &schema.Resource{ + Create: resourceArmBotChannelDirectlineCreate, + Read: resourceArmBotChannelDirectlineRead, + Delete: resourceArmBotChannelDirectlineDelete, + Update: resourceArmBotChannelDirectlineUpdate, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "bot_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "site": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "site_name": { + Type: schema.TypeString, + Required: true, + }, + + "site_id": { + Type: schema.TypeString, + Computed: true, + }, + + "key": { + Type: schema.TypeString, + Computed: true, + }, + + "key2": { + Type: schema.TypeString, + Computed: true, + }, + + "is_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_v1_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_v3_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_secure_site_enabled": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + + "trusted_origins": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + } +} + +func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { + + sites := make([]botservice.DirectLineSite, len(input)) + + for i, element := range input { + + site := element.(map[string]interface{}) + if v, ok := site["site_name"]; ok { + siteName := v.(string) + sites[i].SiteName = &siteName + } + if v, ok := site["is_enabled"]; ok { + isEnabled := v.(bool) + sites[i].IsEnabled = &isEnabled + } + if v, ok := site["is_v1_enabled"]; ok { + isV1Enabled := v.(bool) + sites[i].IsV1Enabled = &isV1Enabled + } + if v, ok := site["is_v3_enabled"]; ok { + isV3Enabled := v.(bool) + sites[i].IsV3Enabled = &isV3Enabled + } + if v, ok := site["is_secure_site_enabled"]; ok { + isSecureSiteEnabled := v.(bool) + sites[i].IsSecureSiteEnabled = &isSecureSiteEnabled + } + if v, ok := site["trusted_origins"]; ok { + trustedOrigins := v.([]interface{}) + items := make([]string, len(trustedOrigins)) + for i, raw := range trustedOrigins { + items[i] = raw.(string) + } + sites[i].TrustedOrigins = &items + } + + } + + return &sites, nil +} + +func unExpandSites(input []botservice.DirectLineSite) []interface{} { + + sites := make([]interface{}, len(input)) + + for i, element := range input { + site := make(map[string]interface{}) + site["site_name"] = element.SiteName + site["key"] = element.Key + site["key2"] = element.Key2 + site["is_enabled"] = element.IsEnabled + site["is_v1_enabled"] = element.IsV1Enabled + site["is_v3_enabled"] = element.IsV3Enabled + site["is_secure_site_enabled"] = element.IsSecureSiteEnabled + site["trusted_origins"] = element.TrustedOrigins + + sites[i] = site + } + + return sites +} + +func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + resourceGroup := d.Get("resource_group_name").(string) + botName := d.Get("bot_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, string(botservice.ChannelNameDirectLineChannel1), botName) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of creating Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + } + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_bot_channel_directline", *existing.ID) + } + } + + sites, err := expandSites(d.Get("site").(*schema.Set).List()) + + channel := botservice.BotChannel{ + Properties: botservice.DirectLineChannel{ + Properties: &botservice.DirectLineChannelProperties{ + Sites: sites, + }, + ChannelName: botservice.ChannelNameDirectLineChannel1, + }, + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + Kind: botservice.KindBot, + } + + if _, err := client.Create(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + d.SetId(*resp.ID) + + return resourceArmBotChannelDirectlineRead(d, meta) +} + +func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + botName := id.Path["botServices"] + resp, err := client.Get(ctx, id.ResourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] Channel Directline for Bot %q (Resource Group %q) was not found - removing from state!", id.ResourceGroup, botName) + d.SetId("") + return nil + } + + return fmt.Errorf("Error reading Channel Directline for Bot %q (Resource Group %q): %+v", id.ResourceGroup, botName, err) + } + + d.Set("resource_group_name", id.ResourceGroup) + d.Set("location", resp.Location) + d.Set("bot_name", botName) + + channelsResp, err := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) + if props := channelsResp.Properties; props != nil { + if channel, ok := props.AsDirectLineChannel(); ok { + if channelProps := channel.Properties; channelProps != nil { + d.Set("site", unExpandSites(*channelProps.Sites)) + } + } + } + + return nil +} + +func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + botName := d.Get("bot_name").(string) + resourceGroup := d.Get("resource_group_name").(string) + sites, err := expandSites(d.Get("site").(*schema.Set).List()) + + channel := botservice.BotChannel{ + Properties: botservice.DirectLineChannel{ + Properties: &botservice.DirectLineChannelProperties{ + Sites: sites, + }, + ChannelName: botservice.ChannelNameDirectLineChannel1, + }, + Location: utils.String(azure.NormalizeLocation(d.Get("location").(string))), + Kind: botservice.KindBot, + } + + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + if resp.ID == nil { + return fmt.Errorf("Cannot read Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + + d.SetId(*resp.ID) + + return resourceArmBotChannelDirectlineRead(d, meta) +} + +func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Bot.ChannelClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + botName := id.Path["botServices"] + + resp, err := client.Delete(ctx, id.ResourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting Channel Directline for Bot %q (Resource Group %q): %+v", id.ResourceGroup, botName, err) + } + } + + return nil +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go new file mode 100644 index 0000000000000..42a83fabf8974 --- /dev/null +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -0,0 +1,142 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/preview/botservice/mgmt/2018-07-12/botservice" + "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" +) + +func testAccAzureRMBotChannelDirectline_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_basicConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testAccAzureRMBotChannelDirectline_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_basicConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMBotChannelDirectline_basicUpdate(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMBotChannelDirectlineExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Bot.ChannelClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + botName := rs.Primary.Attributes["bot_name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Bot Channel Directline") + } + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + if err != nil { + return fmt.Errorf("Bad: Get on botChannelClient: %+v", err) + } + + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Bot Channel Directline %q (resource group: %q / bot: %q) does not exist", name, resourceGroup, botName) + } + + return nil + } +} + +func testCheckAzureRMBotChannelDirectlineDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Bot.ChannelClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_bot_channel_directline" { + continue + } + + botName := rs.Primary.Attributes["bot_name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Bot Channel Directline still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, template) +} + +func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + is_enabled = false +} +`, template) +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go index 3ac73f98663a0..de8ef94f9e298 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go @@ -26,10 +26,12 @@ func TestAccAzureRMBotChannelsRegistration(t *testing.T) { "complete": testAccAzureRMBotConnection_complete, }, "channel": { - "slackBasic": testAccAzureRMBotChannelSlack_basic, - "slackUpdate": testAccAzureRMBotChannelSlack_update, - "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, - "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "slackBasic": testAccAzureRMBotChannelSlack_basic, + "slackUpdate": testAccAzureRMBotChannelSlack_update, + "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, + "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "directlineBasic": testAccAzureRMBotChannelDirectline_basic, + "directlineUpdate": testAccAzureRMBotChannelDirectline_update, }, "web_app": { "basic": testAccAzureRMBotWebApp_basic, diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown new file mode 100644 index 0000000000000..9218cc30e98ac --- /dev/null +++ b/website/docs/r/bot_channel_directline.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "Bot" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_bot_channel_directline" +description: |- + Manages an Directline integration for a Bot Channel +--- + +# azurerm_bot_connection + +Manages a Directline integration for a Bot Channel + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "northeurope" +} + +resource "azurerm_bot_channels_registration" "example" { + name = "example" + location = "global" + resource_group_name = "${azurerm_resource_group.example.name}" + sku = "F0" + microsoft_app_id = "${data.azurerm_client_config.current.service_principal_application_id}" +} + +resource "azurerm_bot_channel_directline" "example" { + bot_name = "${azurerm_bot_channels_registration.example.name}" + location = "${azurerm_bot_channels_registration.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + + site { + site_name = "default" + is_enabled = true + } +} +``` + +## Argument Reference + +The following arguments are supported: + +- `resource_group_name` - (Required) The name of the resource group in which to create the Bot Channel. Changing this forces a new resource to be created. + +- `location` - (Required) The supported Azure location where the resource exists. Changing this forces a new resource to be created. + +- `bot_name` - (Required) The name of the Bot Resource this channel will be associated with. Changing this forces a new resource to be created. + +- `site` - (Optional) The sites that belong to this channel. + +## Attributes Reference + +The following attributes are exported: + +- `id` - The Bot Channel ID. + +## Import + +The Microsoft Teams Channel for a Bot can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_bot_channel_ms_teams.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/MsTeamsChannel +``` From 9c08648867e7f022a31296d50b7e3692ea0baf2d Mon Sep 17 00:00:00 2001 From: john Date: Mon, 20 Jan 2020 17:40:10 +1100 Subject: [PATCH 012/498] fix tflint errors --- ...resource_arm_bot_channel_directline_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 42a83fabf8974..fddc3bf6f246a 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -116,27 +116,27 @@ func testCheckAzureRMBotChannelDirectlineDestroy(s *terraform.State) error { func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) - return fmt.Sprintf(` + return fmt.Sprintf(` %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, template) } func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) - return fmt.Sprintf(` + return fmt.Sprintf(` %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - is_enabled = false + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + is_enabled = false } `, template) } From eaa2039f8f647c3f2a215a68f4701aa9d55be826 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 20 Jan 2020 20:01:43 +1100 Subject: [PATCH 013/498] Fix linting errors --- .../bot/resource_arm_bot_channel_directline.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index eda31f60573c2..bada6a69cfadd 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -111,11 +111,9 @@ func resourceArmBotChannelDirectline() *schema.Resource { } func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { - sites := make([]botservice.DirectLineSite, len(input)) for i, element := range input { - site := element.(map[string]interface{}) if v, ok := site["site_name"]; ok { siteName := v.(string) @@ -145,14 +143,12 @@ func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { } sites[i].TrustedOrigins = &items } - } return &sites, nil } func unExpandSites(input []botservice.DirectLineSite) []interface{} { - sites := make([]interface{}, len(input)) for i, element := range input { @@ -192,7 +188,7 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac } } - sites, err := expandSites(d.Get("site").(*schema.Set).List()) + sites, _ := expandSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ @@ -249,7 +245,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ d.Set("location", resp.Location) d.Set("bot_name", botName) - channelsResp, err := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) + channelsResp, _ := client.ListWithKeys(ctx, id.ResourceGroup, botName, botservice.ChannelNameDirectLineChannel) if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { @@ -268,7 +264,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites, err := expandSites(d.Get("site").(*schema.Set).List()) + sites, _ := expandSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ From cbba6c0037c05090e3719da9343534f1086c4fae Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 20 Jan 2020 20:59:41 +1100 Subject: [PATCH 014/498] Add sensitive flags to keys --- .../bot/resource_arm_bot_channel_directline.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index bada6a69cfadd..a08cd5dd76daa 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -63,13 +63,15 @@ func resourceArmBotChannelDirectline() *schema.Resource { }, "key": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Sensitive: true, }, "key2": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeString, + Computed: true, + Sensitive: true, }, "is_enabled": { From 70a6a1815e7168be3c8a3e4be59f2e43e1fef880 Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Thu, 23 Jan 2020 14:16:44 -0800 Subject: [PATCH 015/498] Update website/docs/r/key_vault.html.markdown Co-Authored-By: Tom Harvey --- website/docs/r/key_vault.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index ed02b1c1903b4..c4089524fc731 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -88,7 +88,9 @@ The following arguments are supported: * `purge_on_delete` - (Optional) Boolean flag to specify if the KeyVault should be purged on delete. This purges KeyVaults enabled for soft delete on resource deletition. -* `enabled_for_purge_protection` - (Optional) Boolean flag to specify whether the key vault is enabled for purge protection, this conflicts with `purge_on_delete`. Once enabled you can not disable this setting. +* `enabled_for_purge_protection` - (Optional) Is Purge Protection enabled for this Key Vault? + +-> **NOTE:** Once Purge Protection has been Enabled there's currently no way to Disable it - [support for this is being tracked in this Azure API issue](https://github.com/Azure/azure-rest-api-specs/issues/8075) * `network_acls` - (Optional) A `network_acls` block as defined below. From 22701db8ce57618d3f8a0f7834e779afc2f19764 Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Thu, 23 Jan 2020 14:17:10 -0800 Subject: [PATCH 016/498] Update website/docs/r/key_vault.html.markdown Co-Authored-By: Tom Harvey --- website/docs/r/key_vault.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index c4089524fc731..b9b1364f5d90a 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -84,7 +84,9 @@ The following arguments are supported: * `enabled_for_template_deployment` - (Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to `false`. -* `enabled_for_soft_delete` - (Optional) Boolean flag to specify whether the key vault is enabled for soft delete. Once enabled you can not disable this setting. +* `enabled_for_soft_delete` - (Optional) Should Soft Delete be enabled for items in this Key Vault? + +-> **NOTE:** Once enabled you can not disable this setting. * `purge_on_delete` - (Optional) Boolean flag to specify if the KeyVault should be purged on delete. This purges KeyVaults enabled for soft delete on resource deletition. From 50563f8546f9cbff7908d31e885c924256420c7e Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Thu, 23 Jan 2020 14:22:24 -0800 Subject: [PATCH 017/498] Update azurerm/internal/services/keyvault/resource_arm_key_vault.go Co-Authored-By: Tom Harvey --- azurerm/internal/services/keyvault/resource_arm_key_vault.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 2b6cbf0ffbc01..ff00aa44c20ce 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -160,7 +160,6 @@ func resourceArmKeyVault() *schema.Resource { "enabled_for_soft_delete": { Type: schema.TypeBool, Optional: true, - ValidateFunc: validate.BoolIsTrue(), }, "enabled_for_purge_protection": { From 20e187610ca777e7824c9fde0096491ce6dabc8a Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sat, 25 Jan 2020 13:52:58 -0500 Subject: [PATCH 018/498] Add ExpressRoute Gateway resource and tests --- .../services/network/client/client.go | 5 + .../internal/services/network/registration.go | 1 + .../resource_arm_express_route_gateway.go | 206 +++++++++++++++ ...resource_arm_express_route_gateway_test.go | 234 ++++++++++++++++++ 4 files changed, 446 insertions(+) create mode 100644 azurerm/internal/services/network/resource_arm_express_route_gateway.go create mode 100644 azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go diff --git a/azurerm/internal/services/network/client/client.go b/azurerm/internal/services/network/client/client.go index 2788d928b6a77..9794b251ef663 100644 --- a/azurerm/internal/services/network/client/client.go +++ b/azurerm/internal/services/network/client/client.go @@ -14,6 +14,7 @@ type Client struct { DDOSProtectionPlansClient *network.DdosProtectionPlansClient ExpressRouteAuthsClient *network.ExpressRouteCircuitAuthorizationsClient ExpressRouteCircuitsClient *network.ExpressRouteCircuitsClient + ExpressRouteGatewaysClient *network.ExpressRouteGatewaysClient ExpressRoutePeeringsClient *network.ExpressRouteCircuitPeeringsClient InterfacesClient *network.InterfacesClient LoadBalancersClient *network.LoadBalancersClient @@ -68,6 +69,9 @@ func NewClient(o *common.ClientOptions) *Client { ExpressRouteCircuitsClient := network.NewExpressRouteCircuitsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ExpressRouteCircuitsClient.Client, o.ResourceManagerAuthorizer) + ExpressRouteGatewaysClient := network.NewExpressRouteGatewaysClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ExpressRouteGatewaysClient.Client, o.ResourceManagerAuthorizer) + ExpressRoutePeeringsClient := network.NewExpressRouteCircuitPeeringsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ExpressRoutePeeringsClient.Client, o.ResourceManagerAuthorizer) @@ -158,6 +162,7 @@ func NewClient(o *common.ClientOptions) *Client { DDOSProtectionPlansClient: &DDOSProtectionPlansClient, ExpressRouteAuthsClient: &ExpressRouteAuthsClient, ExpressRouteCircuitsClient: &ExpressRouteCircuitsClient, + ExpressRouteGatewaysClient: &ExpressRouteGatewaysClient, ExpressRoutePeeringsClient: &ExpressRoutePeeringsClient, InterfacesClient: &InterfacesClient, LoadBalancersClient: &LoadBalancersClient, diff --git a/azurerm/internal/services/network/registration.go b/azurerm/internal/services/network/registration.go index fc30e925d99b7..2603c9b651e18 100644 --- a/azurerm/internal/services/network/registration.go +++ b/azurerm/internal/services/network/registration.go @@ -51,6 +51,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_express_route_circuit_authorization": resourceArmExpressRouteCircuitAuthorization(), "azurerm_express_route_circuit_peering": resourceArmExpressRouteCircuitPeering(), "azurerm_express_route_circuit": resourceArmExpressRouteCircuit(), + "azurerm_express_route_gateway": resourceArmExpressRouteGateway(), "azurerm_firewall_application_rule_collection": resourceArmFirewallApplicationRuleCollection(), "azurerm_firewall_nat_rule_collection": resourceArmFirewallNatRuleCollection(), "azurerm_firewall_network_rule_collection": resourceArmFirewallNetworkRuleCollection(), diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go new file mode 100644 index 0000000000000..b179e79b3e6be --- /dev/null +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -0,0 +1,206 @@ +package network + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/hashicorp/go-azure-helpers/response" + "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/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +var expressRouteGatewayResourceName = "azurerm_express_route_gateway" + +func resourceArmExpressRouteGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceArmExpressRouteGatewayCreateUpdate, + Read: resourceArmExpressRouteGatewayRead, + Update: resourceArmExpressRouteGatewayCreateUpdate, + Delete: resourceArmExpressRouteGatewayDelete, + 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, + }, + + "location": azure.SchemaLocation(), + + "resource_group_name": azure.SchemaResourceGroupName(), + + "virtual_hub_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "scale_units": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 6), + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmExpressRouteGatewayCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.ExpressRouteGatewaysClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Println("[INFO] preparing arguments for ExpressRoute Gateway creation.") + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error checking for present of existing ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + if resp.ID != nil && *resp.ID != "" { + return tf.ImportAsExistsError("azurerm_express_route_gateway", *resp.ID) + } + } + + location := azure.NormalizeLocation(d.Get("location").(string)) + virtualHubId := d.Get("virtual_hub_id").(string) + t := d.Get("tags").(map[string]interface{}) + + parameters := network.ExpressRouteGateway{ + Location: utils.String(location), + ExpressRouteGatewayProperties: &network.ExpressRouteGatewayProperties{ + AutoScaleConfiguration: &network.ExpressRouteGatewayPropertiesAutoScaleConfiguration{ + Bounds: expandExpressRouteGatewayAutoScaleConfigurationBounds(d), + }, + VirtualHub: &network.VirtualHubID{ + ID: &virtualHubId, + }, + }, + Tags: tags.Expand(t), + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters) + if err != nil { + return fmt.Errorf("Error creating ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for creation of ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("Error retrieving ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("Cannot read ExpressRoute Gateway %q (Resource Group %q) ID", name, resourceGroup) + } + d.SetId(*resp.ID) + + return resourceArmExpressRouteGatewayRead(d, meta) +} + +func resourceArmExpressRouteGatewayRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.ExpressRouteGatewaysClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["expressRouteGateways"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[INFO] ExpressRoute Gateway %q does not exist - removing from state", d.Id()) + d.SetId("") + return nil + } + return fmt.Errorf("Error reading ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if props := resp.ExpressRouteGatewayProperties; props != nil { + d.Set("virtual_hub_id", props.VirtualHub.ID) + + if setErr := d.Set("scale_units", props.AutoScaleConfiguration.Bounds.Min); setErr != nil { + return fmt.Errorf("Error setting `scale_units`: %+v", setErr) + } + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmExpressRouteGatewayDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.ExpressRouteGatewaysClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["expressRouteGateways"] + + future, err := client.Delete(ctx, resourceGroup, name) + if err != nil { + if response.WasNotFound(future.Response()) { + return nil + } + return fmt.Errorf("Error deleting ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("Error waiting for deleting ExpressRoute Gateway %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceData) *network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds { + + minScaleUnits := int32(d.Get("scale_units").(int)) + configuration := network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ + Min: &minScaleUnits, + } + + return &configuration +} \ No newline at end of file diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go new file mode 100644 index 0000000000000..7c04aaaf32c95 --- /dev/null +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -0,0 +1,234 @@ +package tests + +import ( + "fmt" + //"net/http" + "testing" + + //"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "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/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMExpressRouteGateway_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_express_route_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMExpressRouteGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMExpressRouteGateway_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMExpressRouteGateway_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_express_route_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMExpressRouteGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMExpressRouteGateway_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), + ), + }, + { + Config: testAccAzureRMExpressRouteGateway_requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_express_route_gateway"), + }, + }, + }) +} + +func TestAccAzureRMExpressRouteGateway_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_express_route_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMExpressRouteGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMExpressRouteGateway_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMExpressRouteGateway_updateScaleUnits(data, 2), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "scale_units", "2"), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMExpressRouteGateway_tags(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_express_route_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMExpressRouteGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMExpressRouteGateway_tags(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMExpressRouteGatewayExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.ExpressRouteGatewaysClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("ExpressRoute Gateway not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + if resp, err := client.Get(ctx, resourceGroup, name); err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: ExpressRoute Gateway %q (Resource Group %q) does not exist", name, resourceGroup) + } + return fmt.Errorf("Bad: Get on network.ExpressRouteGatewaysClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMExpressRouteGatewayDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.ExpressRouteGatewaysClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_express_route_gateway" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + if resp, err := client.Get(ctx, resourceGroup, name); err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Get on network.ExpressRouteGatewaysClient: %+v", err) + } + } + + return nil + } + + return nil +} + +func testAccAzureRMExpressRouteGateway_basic(data acceptance.TestData) string { + template := testAccAzureRMExpressRouteGateway_template(data) + return fmt.Sprintf(` +%s +resource "azurerm_express_route_gateway" "test" { + name = "acctestER-gateway-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = 1 +} +`, template, data.RandomInteger) +} + +func testAccAzureRMExpressRouteGateway_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMExpressRouteGateway_basic(data) + return fmt.Sprintf(` +%s +resource "azurerm_express_route_gateway" "test" { + name = azurerm_express_route_gateway.test.name + resource_group_name = azurerm_express_route_gateway.test.name + location = azurerm_express_route_gateway.test.location + scale_units = 1 +} +`, template) +} + +func testAccAzureRMExpressRouteGateway_updateScaleUnits(data acceptance.TestData, scaleUnits int) string { + template := testAccAzureRMExpressRouteGateway_template(data) + return fmt.Sprintf(` +%s +resource "azurerm_express_route_gateway" "test" { + name = "acctestER-gateway-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = %d +} +`, template, data.RandomInteger, scaleUnits) +} + +func testAccAzureRMExpressRouteGateway_tags(data acceptance.TestData) string { + template := testAccAzureRMExpressRouteGateway_template(data) + return fmt.Sprintf(` +%s +resource "azurerm_express_route_gateway" "test" { + name = "acctestER-gateway-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = 1 + tags = { + Hello = "World" + } +} +`, template, data.RandomInteger) +} + +func testAccAzureRMExpressRouteGateway_template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} +resource "azurerm_virtual_wan" "test" { + name = "acctestvwan-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location +} +resource "azurerm_virtual_hub" "test" { + name = "acctestvhub-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + virtual_wan_id = azurerm_virtual_wan.test.id + address_prefix = "10.0.1.0/24" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} \ No newline at end of file From a791cc17a7bf6fd17cd0c56fbf4b63d50d6690ef Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sat, 25 Jan 2020 13:55:07 -0500 Subject: [PATCH 019/498] gofmt changes --- .../services/network/resource_arm_express_route_gateway.go | 2 +- .../network/tests/resource_arm_express_route_gateway_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index b179e79b3e6be..84d60e5b832ba 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -203,4 +203,4 @@ func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceDat } return &configuration -} \ No newline at end of file +} diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 7c04aaaf32c95..1dfcfe4ec8bda 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -231,4 +231,4 @@ resource "azurerm_virtual_hub" "test" { address_prefix = "10.0.1.0/24" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} \ No newline at end of file +} From f0f39781efeacf9df159965583bd2937da5c07b9 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sat, 25 Jan 2020 14:09:54 -0500 Subject: [PATCH 020/498] Add documentation --- .../r/express_route_gateway.html.markdown | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 website/docs/r/express_route_gateway.html.markdown diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown new file mode 100644 index 0000000000000..ad3c41fe427bc --- /dev/null +++ b/website/docs/r/express_route_gateway.html.markdown @@ -0,0 +1,76 @@ +--- +subcategory: "Network" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_express_route_gateway" +description: |- + Manages an ExpressRoute gateway. +--- + +# azurerm_express_route_gateway + +Manages an ExpressRoute gateway. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "exprtTest" + location = "West US" +} + +resource "azurerm_virtual_wan" "example" { + name = "example-virtualwan" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location +} + +resource "azurerm_virtual_hub" "example" { + name = "example-virtualhub" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + virtual_wan_id = azurerm_virtual_wan.example.id + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_express_route_gateway" "example" { + name = "expressRoute1" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + virtual_hub_id = azurerm_virtual_hub.example.id + scale_unts = 1 + + tags = { + environment = "Production" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the ExpressRoute circuit. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which to create the ExpressRoute circuit. Changing this forces a new resource to be created. + +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. + +* `virtual_hub_id` - (Required) The ID of a Virtual WAN within which the Virtual Hub should be created. + +* `scale_units` - (Required) The name of the peering location and **not** the Azure resource location. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Resource ID of the ExpressRoute gateway. + +## Import + +ExpressRoute gateways can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_express_route_gateway.myExpressRouteGateway /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/expressRouteGateways/myExpressRouteGateway +``` From 790752dde503059d7d501758a47bc70fc349f1ef Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sat, 25 Jan 2020 15:25:45 -0500 Subject: [PATCH 021/498] Resolve linting errors --- .../network/resource_arm_express_route_gateway.go | 3 --- .../tests/resource_arm_express_route_gateway_test.go | 2 +- website/docs/r/express_route_gateway.html.markdown | 10 +++++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index 84d60e5b832ba..789babfb476b7 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -19,8 +19,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -var expressRouteGatewayResourceName = "azurerm_express_route_gateway" - func resourceArmExpressRouteGateway() *schema.Resource { return &schema.Resource{ Create: resourceArmExpressRouteGatewayCreateUpdate, @@ -196,7 +194,6 @@ func resourceArmExpressRouteGatewayDelete(d *schema.ResourceData, meta interface } func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceData) *network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds { - minScaleUnits := int32(d.Get("scale_units").(int)) configuration := network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ Min: &minScaleUnits, diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 1dfcfe4ec8bda..26e34f8e44dec 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -227,7 +227,7 @@ resource "azurerm_virtual_hub" "test" { name = "acctestvhub-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location - virtual_wan_id = azurerm_virtual_wan.test.id + virtual_wan_id = azurerm_virtual_wan.test.id address_prefix = "10.0.1.0/24" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown index ad3c41fe427bc..fba48c292c7e0 100644 --- a/website/docs/r/express_route_gateway.html.markdown +++ b/website/docs/r/express_route_gateway.html.markdown @@ -33,11 +33,11 @@ resource "azurerm_virtual_hub" "example" { } resource "azurerm_express_route_gateway" "example" { - name = "expressRoute1" - resource_group_name = azurerm_resource_group.example.name - location = azurerm_resource_group.example.location - virtual_hub_id = azurerm_virtual_hub.example.id - scale_unts = 1 + name = "expressRoute1" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + virtual_hub_id = azurerm_virtual_hub.example.id + scale_unts = 1 tags = { environment = "Production" From 0069b65095ed48d24a95cec09612e31b574b5549 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sat, 25 Jan 2020 16:36:28 -0500 Subject: [PATCH 022/498] tflint fixes --- ...resource_arm_express_route_gateway_test.go | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 26e34f8e44dec..15a4f1e57052a 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -2,10 +2,8 @@ package tests import ( "fmt" - //"net/http" "testing" - //"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" "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" @@ -158,12 +156,13 @@ func testAccAzureRMExpressRouteGateway_basic(data acceptance.TestData) string { template := testAccAzureRMExpressRouteGateway_template(data) return fmt.Sprintf(` %s + resource "azurerm_express_route_gateway" "test" { name = "acctestER-gateway-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location - virtual_hub_id = azurerm_virtual_hub.test.id - scale_units = 1 + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = 1 } `, template, data.RandomInteger) } @@ -172,11 +171,12 @@ func testAccAzureRMExpressRouteGateway_requiresImport(data acceptance.TestData) template := testAccAzureRMExpressRouteGateway_basic(data) return fmt.Sprintf(` %s + resource "azurerm_express_route_gateway" "test" { name = azurerm_express_route_gateway.test.name resource_group_name = azurerm_express_route_gateway.test.name location = azurerm_express_route_gateway.test.location - scale_units = 1 + scale_units = 1 } `, template) } @@ -185,12 +185,13 @@ func testAccAzureRMExpressRouteGateway_updateScaleUnits(data acceptance.TestData template := testAccAzureRMExpressRouteGateway_template(data) return fmt.Sprintf(` %s + resource "azurerm_express_route_gateway" "test" { name = "acctestER-gateway-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location - virtual_hub_id = azurerm_virtual_hub.test.id - scale_units = %d + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = %d } `, template, data.RandomInteger, scaleUnits) } @@ -199,12 +200,13 @@ func testAccAzureRMExpressRouteGateway_tags(data acceptance.TestData) string { template := testAccAzureRMExpressRouteGateway_template(data) return fmt.Sprintf(` %s + resource "azurerm_express_route_gateway" "test" { name = "acctestER-gateway-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location - virtual_hub_id = azurerm_virtual_hub.test.id - scale_units = 1 + virtual_hub_id = azurerm_virtual_hub.test.id + scale_units = 1 tags = { Hello = "World" } @@ -218,11 +220,13 @@ resource "azurerm_resource_group" "test" { name = "acctestRG-%d" location = "%s" } + resource "azurerm_virtual_wan" "test" { name = "acctestvwan-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location } + resource "azurerm_virtual_hub" "test" { name = "acctestvhub-%d" resource_group_name = azurerm_resource_group.test.name From fef651def293da9bcb08ae1f9775d1c70261676b Mon Sep 17 00:00:00 2001 From: John Kendall Date: Sun, 26 Jan 2020 22:48:36 +1100 Subject: [PATCH 023/498] review feedback response --- .../resource_arm_bot_channel_directline.go | 177 ++++++++++-------- ...esource_arm_bot_channel_directline_test.go | 47 +++++ ...urce_arm_bot_channels_registration_test.go | 13 +- .../docs/r/bot_channel_directline.markdown | 16 +- 4 files changed, 168 insertions(+), 85 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index a08cd5dd76daa..219ab81122913 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -53,25 +53,9 @@ func resourceArmBotChannelDirectline() *schema.Resource { Schema: map[string]*schema.Schema{ "site_name": { - Type: schema.TypeString, - Required: true, - }, - - "site_id": { - Type: schema.TypeString, - Computed: true, - }, - - "key": { - Type: schema.TypeString, - Computed: true, - Sensitive: true, - }, - - "key2": { - Type: schema.TypeString, - Computed: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, "is_enabled": { @@ -102,9 +86,27 @@ func resourceArmBotChannelDirectline() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, + + "key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "key2": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "site_id": { + Type: schema.TypeString, + Computed: true, + }, }, }, }, @@ -112,64 +114,6 @@ func resourceArmBotChannelDirectline() *schema.Resource { } } -func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { - sites := make([]botservice.DirectLineSite, len(input)) - - for i, element := range input { - site := element.(map[string]interface{}) - if v, ok := site["site_name"]; ok { - siteName := v.(string) - sites[i].SiteName = &siteName - } - if v, ok := site["is_enabled"]; ok { - isEnabled := v.(bool) - sites[i].IsEnabled = &isEnabled - } - if v, ok := site["is_v1_enabled"]; ok { - isV1Enabled := v.(bool) - sites[i].IsV1Enabled = &isV1Enabled - } - if v, ok := site["is_v3_enabled"]; ok { - isV3Enabled := v.(bool) - sites[i].IsV3Enabled = &isV3Enabled - } - if v, ok := site["is_secure_site_enabled"]; ok { - isSecureSiteEnabled := v.(bool) - sites[i].IsSecureSiteEnabled = &isSecureSiteEnabled - } - if v, ok := site["trusted_origins"]; ok { - trustedOrigins := v.([]interface{}) - items := make([]string, len(trustedOrigins)) - for i, raw := range trustedOrigins { - items[i] = raw.(string) - } - sites[i].TrustedOrigins = &items - } - } - - return &sites, nil -} - -func unExpandSites(input []botservice.DirectLineSite) []interface{} { - sites := make([]interface{}, len(input)) - - for i, element := range input { - site := make(map[string]interface{}) - site["site_name"] = element.SiteName - site["key"] = element.Key - site["key2"] = element.Key2 - site["is_enabled"] = element.IsEnabled - site["is_v1_enabled"] = element.IsV1Enabled - site["is_v3_enabled"] = element.IsV3Enabled - site["is_secure_site_enabled"] = element.IsSecureSiteEnabled - site["trusted_origins"] = element.TrustedOrigins - - sites[i] = site - } - - return sites -} - func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Bot.ChannelClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) @@ -318,3 +262,80 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac return nil } + +func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { + sites := make([]botservice.DirectLineSite, len(input)) + + for i, element := range input { + site := element.(map[string]interface{}) + + if v, ok := site["site_name"].(string); ok { + sites[i].SiteName = &v + } + if v, ok := site["is_enabled"].(bool); ok { + sites[i].IsEnabled = &v + } + if v, ok := site["is_v1_enabled"].(bool); ok { + sites[i].IsV1Enabled = &v + } + if v, ok := site["is_v3_enabled"].(bool); ok { + sites[i].IsV3Enabled = &v + } + if v, ok := site["is_secure_site_enabled"].(bool); ok { + sites[i].IsSecureSiteEnabled = &v + } + if v, ok := site["trusted_origins"].([]interface{}); ok { + items := make([]string, len(v)) + for i, raw := range v { + items[i] = raw.(string) + } + sites[i].TrustedOrigins = &items + } + } + + return &sites, nil +} + +func unExpandSites(input []botservice.DirectLineSite) []interface{} { + sites := make([]interface{}, len(input)) + + for i, element := range input { + site := make(map[string]interface{}) + + if element.SiteName != nil { + site["site_name"] = *element.SiteName + } + + if element.Key != nil { + site["key"] = *element.Key + } + + if element.Key2 != nil { + site["key2"] = *element.Key2 + } + + if element.IsEnabled != nil { + site["is_enabled"] = *element.IsEnabled + } + + if element.IsV1Enabled != nil { + site["is_v1_enabled"] = *element.IsV1Enabled + } + + if element.IsV3Enabled != nil { + site["is_v3_enabled"] = *element.IsV3Enabled + } + + if element.IsSecureSiteEnabled != nil { + site["is_secure_site_enabled"] = *element.IsSecureSiteEnabled + } + + if element.TrustedOrigins != nil { + site["trusted_origins"] = *element.TrustedOrigins + } + + sites[i] = site + } + + return sites +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index fddc3bf6f246a..0bce701508ff2 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -32,6 +32,25 @@ func testAccAzureRMBotChannelDirectline_basic(t *testing.T) { }) } +func testAccAzureRMBotChannelDirectline_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMBotChannelDirectlineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMBotChannelDirectline_completeConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testAccAzureRMBotChannelDirectline_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_bot_channel_directline", "test") @@ -47,6 +66,13 @@ func testAccAzureRMBotChannelDirectline_update(t *testing.T) { ), }, data.ImportStep(), + { + Config: testAccAzureRMBotChannelDirectline_completeConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBotChannelDirectlineExists(data.ResourceName), + ), + }, + data.ImportStep(), { Config: testAccAzureRMBotChannelDirectline_basicUpdate(data), Check: resource.ComposeTestCheckFunc( @@ -127,6 +153,27 @@ resource "azurerm_bot_channel_directline" "test" { `, template) } +func testAccAzureRMBotChannelDirectline_completeConfig(data acceptance.TestData) string { + template := testAccAzureRMBotChannelsRegistration_basicConfig(data) + return fmt.Sprintf(` +%s + +resource "azurerm_bot_channel_directline" "test" { + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + site_name = "test" + is_enabled = true + is_v1_enabled = true + is_v3_enabled = true + is_secure_site_enabled = true + trusted_origins = ["https://example.com"] + } +} +`, template) +} + func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) string { template := testAccAzureRMBotChannelsRegistration_basicConfig(data) return fmt.Sprintf(` diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go index de8ef94f9e298..ff03fc069d7eb 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channels_registration_test.go @@ -26,12 +26,13 @@ func TestAccAzureRMBotChannelsRegistration(t *testing.T) { "complete": testAccAzureRMBotConnection_complete, }, "channel": { - "slackBasic": testAccAzureRMBotChannelSlack_basic, - "slackUpdate": testAccAzureRMBotChannelSlack_update, - "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, - "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, - "directlineBasic": testAccAzureRMBotChannelDirectline_basic, - "directlineUpdate": testAccAzureRMBotChannelDirectline_update, + "slackBasic": testAccAzureRMBotChannelSlack_basic, + "slackUpdate": testAccAzureRMBotChannelSlack_update, + "msteamsBasic": testAccAzureRMBotChannelMsTeams_basic, + "msteamsUpdate": testAccAzureRMBotChannelMsTeams_update, + "directlineBasic": testAccAzureRMBotChannelDirectline_basic, + "directlineComplete": testAccAzureRMBotChannelDirectline_complete, + "directlineUpdate": testAccAzureRMBotChannelDirectline_update, }, "web_app": { "basic": testAccAzureRMBotWebApp_basic, diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 9218cc30e98ac..450ea6df254f8 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -50,7 +50,21 @@ The following arguments are supported: - `bot_name` - (Required) The name of the Bot Resource this channel will be associated with. Changing this forces a new resource to be created. -- `site` - (Optional) The sites that belong to this channel. +- `site` - (Optional) A site represents a client application that you want to connect to your bot. Multiple `site` blocks may be defined as below + +A `site` block as the following properties: + +- `site_name` - (Required) The name of the site + +- `is_enabled` - (Optional) Enables/Disables this site. Enabled by default + +- `is_v1_enabled` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default + +- `is_v3_enabled` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default + +- `is_secure_site_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. + +- `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. ## Attributes Reference From 0cf5e60c6bfdddc1e6ec44686c71cfae16990b38 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sun, 26 Jan 2020 22:53:31 +0000 Subject: [PATCH 024/498] Resolve PR feedback --- .../resource_arm_express_route_gateway.go | 2 +- ...resource_arm_express_route_gateway_test.go | 62 ++++++------------- .../r/express_route_gateway.html.markdown | 12 ++-- 3 files changed, 25 insertions(+), 51 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index 789babfb476b7..e883985637eaa 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -58,7 +58,7 @@ func resourceArmExpressRouteGateway() *schema.Resource { "scale_units": { Type: schema.TypeInt, Required: true, - ValidateFunc: validation.IntBetween(1, 6), + ValidateFunc: validation.IntBetween(1, 10), }, "tags": tags.Schema(), diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 15a4f1e57052a..3455c5a922ad2 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -74,27 +74,15 @@ func TestAccAzureRMExpressRouteGateway_update(t *testing.T) { }, data.ImportStep(), { - Config: testAccAzureRMExpressRouteGateway_updateScaleUnits(data, 2), + Config: testAccAzureRMExpressRouteGateway_complete(data, 10), Check: resource.ComposeTestCheckFunc( testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "scale_units", "2"), + resource.TestCheckResourceAttr(data.ResourceName, "scale_units", "10"), ), }, data.ImportStep(), - }, - }) -} - -func TestAccAzureRMExpressRouteGateway_tags(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_express_route_gateway", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMExpressRouteGatewayDestroy, - Steps: []resource.TestStep{ { - Config: testAccAzureRMExpressRouteGateway_tags(data), + Config: testAccAzureRMExpressRouteGateway_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), ), @@ -167,21 +155,7 @@ resource "azurerm_express_route_gateway" "test" { `, template, data.RandomInteger) } -func testAccAzureRMExpressRouteGateway_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMExpressRouteGateway_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_express_route_gateway" "test" { - name = azurerm_express_route_gateway.test.name - resource_group_name = azurerm_express_route_gateway.test.name - location = azurerm_express_route_gateway.test.location - scale_units = 1 -} -`, template) -} - -func testAccAzureRMExpressRouteGateway_updateScaleUnits(data acceptance.TestData, scaleUnits int) string { +func testAccAzureRMExpressRouteGateway_complete(data acceptance.TestData, scaleUnits int) string { template := testAccAzureRMExpressRouteGateway_template(data) return fmt.Sprintf(` %s @@ -192,43 +166,43 @@ resource "azurerm_express_route_gateway" "test" { location = azurerm_resource_group.test.location virtual_hub_id = azurerm_virtual_hub.test.id scale_units = %d + + tags = { + Hello = "World" + } } `, template, data.RandomInteger, scaleUnits) } -func testAccAzureRMExpressRouteGateway_tags(data acceptance.TestData) string { - template := testAccAzureRMExpressRouteGateway_template(data) +func testAccAzureRMExpressRouteGateway_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMExpressRouteGateway_basic(data) return fmt.Sprintf(` %s resource "azurerm_express_route_gateway" "test" { - name = "acctestER-gateway-%d" - resource_group_name = azurerm_resource_group.test.name - location = azurerm_resource_group.test.location - virtual_hub_id = azurerm_virtual_hub.test.id - scale_units = 1 - tags = { - Hello = "World" - } + name = azurerm_express_route_gateway.test.name + resource_group_name = azurerm_express_route_gateway.test.name + location = azurerm_express_route_gateway.test.location + scale_units = azurerm_express_route_gateway.test.scale_units } -`, template, data.RandomInteger) +`, template) } func testAccAzureRMExpressRouteGateway_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-express-%d" location = "%s" } resource "azurerm_virtual_wan" "test" { - name = "acctestvwan-%d" + name = "acctest-VWAN-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location } resource "azurerm_virtual_hub" "test" { - name = "acctestvhub-%d" + name = "acctest-VHUB-%d" resource_group_name = azurerm_resource_group.test.name location = azurerm_resource_group.test.location virtual_wan_id = azurerm_virtual_wan.test.id diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown index fba48c292c7e0..a40ae80de023f 100644 --- a/website/docs/r/express_route_gateway.html.markdown +++ b/website/docs/r/express_route_gateway.html.markdown @@ -14,7 +14,7 @@ Manages an ExpressRoute gateway. ```hcl resource "azurerm_resource_group" "example" { - name = "exprtTest" + name = "example-resources" location = "West US" } @@ -49,15 +49,15 @@ resource "azurerm_express_route_gateway" "example" { The following arguments are supported: -* `name` - (Required) The name of the ExpressRoute circuit. Changing this forces a new resource to be created. +* `name` - (Required) The name of the ExpressRoute gateway. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to create the ExpressRoute circuit. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the ExpressRoute gateway. Changing this forces a new resource to be created. * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `virtual_hub_id` - (Required) The ID of a Virtual WAN within which the Virtual Hub should be created. +* `virtual_hub_id` - (Required) The ID of a Virtual HUB within which the ExpressRoute gateway should be created. -* `scale_units` - (Required) The name of the peering location and **not** the Azure resource location. +* `scale_units` - (Required) The number of scale units with which to provision the ExpressRoute gateway. Each scale unit is equal to 2Gbps, with support for up to 10 scale units (20Gbps). * `tags` - (Optional) A mapping of tags to assign to the resource. @@ -72,5 +72,5 @@ The following attributes are exported: ExpressRoute gateways can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_express_route_gateway.myExpressRouteGateway /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/expressRouteGateways/myExpressRouteGateway +terraform import azurerm_express_route_gateway.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/expressRouteGateways/myExpressRouteGateway ``` From 26c7fa123e82d305720cad768bb21481473cf932 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Sun, 26 Jan 2020 22:56:56 +0000 Subject: [PATCH 025/498] Resize test to reasonable size --- .../network/tests/resource_arm_express_route_gateway_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 3455c5a922ad2..155337c6743fa 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -74,10 +74,10 @@ func TestAccAzureRMExpressRouteGateway_update(t *testing.T) { }, data.ImportStep(), { - Config: testAccAzureRMExpressRouteGateway_complete(data, 10), + Config: testAccAzureRMExpressRouteGateway_complete(data, 2), Check: resource.ComposeTestCheckFunc( testCheckAzureRMExpressRouteGatewayExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "scale_units", "10"), + resource.TestCheckResourceAttr(data.ResourceName, "scale_units", "2"), ), }, data.ImportStep(), From 88a2788596c79f43f0cd77c4919c483b1a266e0b Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 28 Jan 2020 08:54:06 -0600 Subject: [PATCH 026/498] First pass update docs post-review --- ...cheduled_query_rules_action.html.markdown} | 29 ++---- ...or_scheduled_query_rules_log.html.markdown | 54 +++++++++++ ...cheduled_query_rules_action.html.markdown} | 75 ++++------------ ...or_scheduled_query_rules_log.html.markdown | 89 +++++++++++++++++++ 4 files changed, 164 insertions(+), 83 deletions(-) rename website/docs/d/{monitor_scheduled_query_rules.html.markdown => monitor_scheduled_query_rules_action.html.markdown} (77%) create mode 100644 website/docs/d/monitor_scheduled_query_rules_log.html.markdown rename website/docs/r/{monitor_scheduled_query_rules.html.markdown => monitor_scheduled_query_rules_action.html.markdown} (69%) create mode 100644 website/docs/r/monitor_scheduled_query_rules_log.html.markdown diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules_action.html.markdown similarity index 77% rename from website/docs/d/monitor_scheduled_query_rules.html.markdown rename to website/docs/d/monitor_scheduled_query_rules_action.html.markdown index d6651611d15b6..e66a2c7ff0c6b 100644 --- a/website/docs/d/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_action.html.markdown @@ -1,26 +1,26 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-action" description: |- - Get information about the specified Scheduled Query Rule. + Get information about the specified AlertingAction Scheduled Query Rule. --- # Data Source: azurerm_monitor_scheduled_query_rules -Use this data source to access the properties of a Scheduled Query Rule. +Use this data source to access the properties of an AlertingAction Scheduled Query Rule. ## Example Usage ```hcl -data "azurerm_monitor_scheduled_query_rules" "example" { +data "azurerm_monitor_scheduled_query_rules_action" "example" { resource_group_name = "terraform-example-rg" name = "tfex-queryrule" } output "query_rule_id" { - value = "${data.azurerm_monitor_scheduled_query_rules.example.id}" + value = "${data.azurerm_monitor_scheduled_query_rules_action.example.id}" } ``` @@ -33,9 +33,7 @@ output "query_rule_id" { * `id` - The ID of the Scheduled Query Rule. * `azns_action` - An `azns_action` block as defined below. -* `action_type` - Must equal ether `AlertingAction` or `LogToMetricAction`. * `authorized_resources` - List of Resource IDs referred into query. -* `criteria` - A `criteria` block as defined below. * `data_source_id` - The resource uri over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. @@ -57,21 +55,6 @@ output "query_rule_id" { --- -`criteria` supports the following: - -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. - ---- - -`dimension` supports the following: - -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. - ---- - `metricTrigger` supports the following: * `metricColumn` - (Required) Evaluation of metric on a particular column. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown new file mode 100644 index 0000000000000..a29912472b688 --- /dev/null +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-log" +description: |- + Get information about the specified LogToMetricAction Scheduled Query Rule. +--- + +# Data Source: azurerm_monitor_scheduled_query_rules_log + +Use this data source to access the properties of a LogToMetricAction Scheduled Query Rule. + +## Example Usage + +```hcl +data "azurerm_monitor_scheduled_query_rules_log" "example" { + resource_group_name = "terraform-example-rg" + name = "tfex-queryrule" +} + +output "query_rule_id" { + value = "${data.azurerm_monitor_scheduled_query_rules_log.example.id}" +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Scheduled Query Rule. +* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. + +## Attributes Reference + +* `id` - The ID of the Scheduled Query Rule. +* `criteria` - A `criteria` block as defined below. +* `data_source_id` - The resource uri over which log search query is to be run. +* `description` - The description of the Scheduled Query Rule. +* `enabled` - Whether this scheduled query rule is enabled. +* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules_action.html.markdown similarity index 69% rename from website/docs/r/monitor_scheduled_query_rules.html.markdown rename to website/docs/r/monitor_scheduled_query_rules_action.html.markdown index 8d18bebe2327c..5bd69d7d22e53 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_action.html.markdown @@ -1,15 +1,15 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-action" description: |- - Manages a Scheduled Query Rule within Azure Monitor + Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- -# azurerm_monitor_action_group +# azurerm_monitor_scheduled_query_rules_action -Manages a Scheduled Query Rule within Azure Monitor. +Manages an AlertingAction Scheduled Query Rule within Azure Monitor. ## Example Usage @@ -35,12 +35,11 @@ resource "azurerm_log_analytics_workspace" "example" { } # Example: Alerting Action -resource "azurerm_scheduled_query_rule" "example" { +resource "azurerm_scheduled_query_rule_action" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "Alerting" azns_action { action_group = [] email_subject = "Email Header" @@ -67,12 +66,11 @@ resource "azurerm_scheduled_query_rule" "example" { } # Example: Alerting Action Cross-Resource -resource "azurerm_scheduled_query_rule" "example2" { +resource "azurerm_scheduled_query_rule_action" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "Alerting" authorized_resources = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] azns_action { @@ -93,26 +91,6 @@ resource "azurerm_scheduled_query_rule" "example2" { threshold = 3 } } - -# Example: LogToMetric Action -resource "azurerm_scheduled_query_rule" "example3" { - name = format("%s-queryrule3", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - - action_type = "LogToMetric" - criteria { - metric_name = "Average_% Idle Time" - dimensions { - name = "InstanceName" - operator = "Include" - values = [""] - } - } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule LogToMetric example" - enabled = true -} ``` ## Argument Reference @@ -121,26 +99,18 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. -* `action_type` - (Required) Must equal ether `AlertingAction` or `LogToMetricAction`. * `authorized_resources` - (Optional) List of Resource IDs referred into query. +* `azns_action` - (Optional) An `azns_action` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. - -The following arguments are only supported when `action_type` is `AlertingAction`: - -* `azns_action` - (Optional) An `azns_action` block as defined below. -* `frequency` - (Optional) Frequency (in minutes) at which rule condition should be evaluated. Required when `action_type` is `AlertingAction`. -* `query` - (Optional) Log search query. Required when `action_type` is `AlertingAction`. -* `query_type` - (Optional) Must equal "ResultCount" for now. Required when `action_type` is `AlertingAction`. +* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. +* `query` - (Required) Log search query. +* `query_type` - (Required) Must equal "ResultCount" for now. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `time_window` - (Optional) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). Required when `action_type` is `AlertingAction`. -* `trigger` - (Optional) The condition that results in the alert rule being run. Required when `action_type` is `AlertingAction`. - -The following arguments are only supported when `action_type` is `LogToMetricAction`: - -* `criteria` - (Optional) A `criteria` block as defined below. Required when `action_type` is `LogToMetricAction`. +* `time_window` - (Required) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. +* `trigger` - (Required) The condition that results in the alert rule being run. --- @@ -152,21 +122,6 @@ The following arguments are only supported when `action_type` is `LogToMetricAct --- -`criteria` supports the following: - -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. - ---- - -`dimension` supports the following: - -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. - ---- - `metricTrigger` supports the following: * `metricColumn` - (Required) Evaluation of metric on a particular column. @@ -195,5 +150,5 @@ The following attributes are exported: Scheduled Query Rules can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_monitor_scheduled_query_rules.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +terraform import azurerm_monitor_scheduled_query_rules_action.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown new file mode 100644 index 0000000000000..a5d6895fb301c --- /dev/null +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -0,0 +1,89 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-log" +description: |- + Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor +--- + +# azurerm_monitor_scheduled_query_rules_log + +Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "monitoring-resources" + location = "West US" +} + +resource "azurerm_application_insights" "example" { + name = "appinsights" + location = var.location + resource_group_name = azurerm_resource_group.example.name + application_type = "web" +} + +resource "azurerm_scheduled_query_rule_log" "example3" { + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + criteria { + metric_name = "Average_% Idle Time" + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `criteria` - (Required) A `criteria` block as defined below. +* `data_source_id` - (Required) The resource uri over which log search query is to be run. +* `description` - (Optional) The description of the Scheduled Query Rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Scheduled Query Rule. +* `last_updated_time` - Last time the rule was updated in IS08601 format. +* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' + +## Import + +Scheduled Query Rules can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_monitor_scheduled_query_rules_log.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +``` From 3dcea9c3a267bc4492042266973d10e99b7b1907 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 28 Jan 2020 09:25:34 -0600 Subject: [PATCH 027/498] First pass at separating into two resources --- ...e_monitor_scheduled_query_rules_action.go} | 44 +- ...ource_monitor_scheduled_query_rules_log.go | 252 +++++++++ .../internal/services/monitor/registration.go | 30 +- ...m_monitor_scheduled_query_rules_action.go} | 185 +------ ...e_arm_monitor_scheduled_query_rules_log.go | 477 ++++++++++++++++++ ...itor_scheduled_query_rules_action_test.go} | 0 ..._monitor_scheduled_query_rules_log_test.go | 243 +++++++++ ...itor_scheduled_query_rules_action_test.go} | 75 +-- ..._monitor_scheduled_query_rules_log_test.go | 133 +++++ 9 files changed, 1164 insertions(+), 275 deletions(-) rename azurerm/internal/services/monitor/{data_source_monitor_scheduled_query_rules.go => data_source_monitor_scheduled_query_rules_action.go} (80%) create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go rename azurerm/internal/services/monitor/{resource_arm_monitor_scheduled_query_rules.go => resource_arm_monitor_scheduled_query_rules_action.go} (71%) create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go rename azurerm/internal/services/monitor/tests/{data_source_monitor_scheduled_query_rules_test.go => data_source_monitor_scheduled_query_rules_action_test.go} (100%) create mode 100644 azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go rename azurerm/internal/services/monitor/tests/{resource_arm_monitor_scheduled_query_rules_test.go => resource_arm_monitor_scheduled_query_rules_action_test.go} (77%) create mode 100644 azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go similarity index 80% rename from azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go rename to azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go index 49e77b42c4398..675173520cc9f 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go @@ -14,9 +14,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { +func dataSourceArmMonitorScheduledQueryRulesAction() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesActionRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -32,10 +32,6 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - "action_type": { - Type: schema.TypeString, - Computed: true, - }, "authorized_resources": { Type: schema.TypeSet, Computed: true, @@ -192,7 +188,7 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { } } -func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -221,28 +217,18 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("enabled", false) } - switch action := resp.Action.(type) { - case insights.AlertingAction: - d.Set("action_type", "Alerting") - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - d.Set("action_type", "LogToMetric") - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + var action insights.AlertingAction + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) } if schedule := resp.Schedule; schedule != nil { diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go new file mode 100644 index 0000000000000..ff14ae0516ea7 --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -0,0 +1,252 @@ +package monitor + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesLogRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "authorized_resources": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Elem: schema.TypeString, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "values": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + var action insights.LogToMetricAction + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index 366450fc514f1..d4aeb8e971231 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -14,23 +14,25 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules()} + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules_action": dataSourceArmMonitorScheduledQueryRulesAction(), + "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), - "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules_action": resourceArmMonitorScheduledQueryRulesAction(), + "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go similarity index 71% rename from azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go rename to azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go index 7a924f78ac16c..ff774f53231fd 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go @@ -20,12 +20,12 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func resourceArmMonitorScheduledQueryRules() *schema.Resource { +func resourceArmMonitorScheduledQueryRulesAction() *schema.Resource { return &schema.Resource{ - Create: resourceArmMonitorScheduledQueryRulesCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, - Update: resourceArmMonitorScheduledQueryRulesCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Create: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesActionRead, + Update: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesActionDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -49,14 +49,6 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { "location": azure.SchemaLocation(), - "action_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Alerting", - "LogToMetric", - }, false), - }, "authorized_resources": { Type: schema.TypeSet, Optional: true, @@ -89,44 +81,6 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { }, }, }, - "criteria": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dimension": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Include", - }, false), - }, - "values": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "metric_name": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, "data_source_id": { Type: schema.TypeString, Required: true, @@ -245,7 +199,7 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { } } -func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -262,11 +216,10 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m } if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules", *existing.ID) + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_action", *existing.ID) } } - actionType := d.Get("action_type").(string) description := d.Get("description").(string) enabledRaw := d.Get("enabled").(bool) @@ -278,15 +231,7 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m location := azure.NormalizeLocation(d.Get("location")) var action insights.BasicAction - switch actionType { - case "Alerting": - action = expandMonitorScheduledQueryRulesAlertingAction(d) - case "LogToMetric": - action = expandMonitorScheduledQueryRulesLogToMetricAction(d) - default: - return fmt.Errorf("Invalid action_type %q. Value must be either 'Alerting' or 'LogToMetric'", actionType) - } - + action = expandMonitorScheduledQueryRulesAlertingAction(d) source := expandMonitorScheduledQueryRulesSource(d) schedule := expandMonitorScheduledQueryRulesSchedule(d) @@ -318,10 +263,10 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m } d.SetId(*read.ID) - return resourceArmMonitorScheduledQueryRulesRead(d, meta) + return resourceArmMonitorScheduledQueryRulesActionRead(d, meta) } -func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -363,8 +308,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte switch action := resp.Action.(type) { case insights.AlertingAction: - d.Set("action_type", "Alerting") - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `azns_action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -373,14 +317,9 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } - case insights.LogToMetricAction: - d.Set("action_type", "LogToMetric") - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } @@ -410,7 +349,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte return tags.FlattenAndSet(d, resp.Tags) } -func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() @@ -433,13 +372,13 @@ func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta in func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { aznsActionRaw := d.Get("azns_action").(*schema.Set).List() - aznsAction := expandMonitorScheduledQueryRulesAznsAction(aznsActionRaw) + aznsAction := expandMonitorScheduledQueryRulesActionAznsAction(aznsActionRaw) severityRaw := d.Get("severity").(int) severity := strconv.Itoa(severityRaw) throttling := d.Get("throttling").(int) triggerRaw := d.Get("trigger").(*schema.Set).List() - trigger := expandMonitorScheduledQueryRulesTrigger(triggerRaw) + trigger := expandMonitorScheduledQueryRulesActionTrigger(triggerRaw) action := insights.AlertingAction{ AznsAction: aznsAction, @@ -452,7 +391,7 @@ func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *ins return &action } -func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.AzNsActionGroup { +func expandMonitorScheduledQueryRulesActionAznsAction(input []interface{}) *insights.AzNsActionGroup { result := insights.AzNsActionGroup{} for _, item := range input { @@ -467,41 +406,6 @@ func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.A return &result } -func expandMonitorScheduledQueryRulesCriteria(input []interface{}) *[]insights.Criteria { - criteria := make([]insights.Criteria, 0) - for _, item := range input { - v := item.(map[string]interface{}) - - dimensions := make([]insights.Dimension, 0) - for _, dimension := range v["dimension"].(*schema.Set).List() { - dVal := dimension.(map[string]interface{}) - dimensions = append(dimensions, insights.Dimension{ - Name: utils.String(dVal["name"].(string)), - Operator: utils.String(dVal["operator"].(string)), - Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), - }) - } - - criteria = append(criteria, insights.Criteria{ - MetricName: utils.String(v["metric_name"].(string)), - Dimensions: &dimensions, - }) - } - return &criteria -} - -func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { - criteriaRaw := d.Get("criteria").(*schema.Set).List() - criteria := expandMonitorScheduledQueryRulesCriteria(criteriaRaw) - - action := insights.LogToMetricAction{ - Criteria: criteria, - OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, - } - - return &action -} - func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { frequency := d.Get("frequency").(int) timeWindow := d.Get("time_window").(int) @@ -514,7 +418,7 @@ func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights. return &schedule } -func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { +func expandMonitorScheduledQueryRulesActionMetricTrigger(input []interface{}) *insights.LogMetricTrigger { if len(input) == 0 { return nil } @@ -546,7 +450,7 @@ func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.So return &source } -func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.TriggerCondition { +func expandMonitorScheduledQueryRulesActionTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} for _, item := range input { @@ -555,13 +459,13 @@ func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.Trig result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTrigger = expandMonitorScheduledQueryRulesMetricTrigger(metricTriggerRaw) + result.MetricTrigger = expandMonitorScheduledQueryRulesActionMetricTrigger(metricTriggerRaw) } return &result } -func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup) []interface{} { +func flattenAzureRmScheduledQueryRulesActionAznsAction(input *insights.AzNsActionGroup) []interface{} { result := make([]interface{}, 0) v := make(map[string]interface{}) @@ -577,50 +481,7 @@ func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup return result } -func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, criteria := range *input { - v := make(map[string]interface{}) - - v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) - v["metric_name"] = *criteria.MetricName - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesDimension(input *[]insights.Dimension) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, dimension := range *input { - v := make(map[string]interface{}) - - if dimension.Name != nil { - v["name"] = *dimension.Name - } - - if dimension.Operator != nil { - v["operator"] = *dimension.Operator - } - - if dimension.Values != nil { - v["values"] = *dimension.Values - } - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTrigger) []interface{} { +func flattenAzureRmScheduledQueryRulesActionMetricTrigger(input *insights.LogMetricTrigger) []interface{} { result := make(map[string]interface{}) if input == nil { @@ -641,7 +502,7 @@ func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTri return []interface{}{result} } -func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { +func flattenAzureRmScheduledQueryRulesActionTrigger(input *insights.TriggerCondition) []interface{} { result := make(map[string]interface{}) result["operator"] = string(input.ThresholdOperator) @@ -651,7 +512,7 @@ func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) } if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesMetricTrigger(input.MetricTrigger) + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesActionMetricTrigger(input.MetricTrigger) } return []interface{}{result} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go new file mode 100644 index 0000000000000..1167d81da80e2 --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -0,0 +1,477 @@ +package monitor + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" + "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/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesLogRead, + Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesLogDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "authorized_resources": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Include", + }, false), + }, + "values": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_log", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + var action insights.BasicAction + action = expandMonitorScheduledQueryRulesLogToMetricAction(d) + source := expandMonitorScheduledQueryRulesSource(d) + schedule := expandMonitorScheduledQueryRulesSchedule(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + switch action := resp.Action.(type) { + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { + criteria := make([]insights.Criteria, 0) + for _, item := range input { + v := item.(map[string]interface{}) + + dimensions := make([]insights.Dimension, 0) + for _, dimension := range v["dimension"].(*schema.Set).List() { + dVal := dimension.(map[string]interface{}) + dimensions = append(dimensions, insights.Dimension{ + Name: utils.String(dVal["name"].(string)), + Operator: utils.String(dVal["operator"].(string)), + Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), + }) + } + + criteria = append(criteria, insights.Criteria{ + MetricName: utils.String(v["metric_name"].(string)), + Dimensions: &dimensions, + }) + } + return &criteria +} + +func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { + criteriaRaw := d.Get("criteria").(*schema.Set).List() + criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) + + action := insights.LogToMetricAction{ + Criteria: criteria, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, + } + + return &action +} + +func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + v["dimension"] = flattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go similarity index 100% rename from azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go new file mode 100644 index 0000000000000..875fdaa762026 --- /dev/null +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -0,0 +1,243 @@ +package tests + +import ( + "fmt" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = [""] + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_log_analytics_workspace" "test2" { + name = "acctestWorkspace2-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go similarity index 77% rename from azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go index 357a8ba2b0f94..1bb822ff80a20 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go @@ -13,7 +13,7 @@ import ( ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -36,7 +36,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -58,29 +58,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }) } -func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), - ), - }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) @@ -103,7 +80,7 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_action" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" @@ -167,7 +144,7 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_action" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" @@ -197,54 +174,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - action_type = "LogToMetric" - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = [""] - } - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_monitor_scheduled_query_rules" { + if rs.Type != "azurerm_monitor_scheduled_query_rules_action" { continue } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go new file mode 100644 index 0000000000000..069f41ae89e72 --- /dev/null +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -0,0 +1,133 @@ +package tests + +import ( + "fmt" + "net/http" + "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" +) + +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + ), + }, + { + ResourceName: data.ResourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = [""] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_monitor_scheduled_query_rules_log" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.Get(ctx, resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + } + } + + return nil +} + +func testCheckAzureRMMonitorScheduledQueryRulesExists(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) + } + + name := 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 Activity Log Alert Instance: %s", name) + } + + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} From 27f7f4fa0ccd45f6d6a6a19bd133f02c2b2c86d3 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 29 Jan 2020 08:45:43 -0600 Subject: [PATCH 028/498] Rename action to alert in docs --- ...onitor_scheduled_query_rules_alert.html.markdown} | 10 +++++----- ...onitor_scheduled_query_rules_alert.html.markdown} | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) rename website/docs/d/{monitor_scheduled_query_rules_action.html.markdown => monitor_scheduled_query_rules_alert.html.markdown} (92%) rename website/docs/r/{monitor_scheduled_query_rules_action.html.markdown => monitor_scheduled_query_rules_alert.html.markdown} (93%) diff --git a/website/docs/d/monitor_scheduled_query_rules_action.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown similarity index 92% rename from website/docs/d/monitor_scheduled_query_rules_action.html.markdown rename to website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index e66a2c7ff0c6b..4d92728a89842 100644 --- a/website/docs/d/monitor_scheduled_query_rules_action.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -1,26 +1,26 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-action" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-alert" description: |- Get information about the specified AlertingAction Scheduled Query Rule. --- -# Data Source: azurerm_monitor_scheduled_query_rules +# Data Source: azurerm_monitor_scheduled_query_rules_alert Use this data source to access the properties of an AlertingAction Scheduled Query Rule. ## Example Usage ```hcl -data "azurerm_monitor_scheduled_query_rules_action" "example" { +data "azurerm_monitor_scheduled_query_rules_alert" "example" { resource_group_name = "terraform-example-rg" name = "tfex-queryrule" } output "query_rule_id" { - value = "${data.azurerm_monitor_scheduled_query_rules_action.example.id}" + value = "${data.azurerm_monitor_scheduled_query_rules_alert.example.id}" } ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_action.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown similarity index 93% rename from website/docs/r/monitor_scheduled_query_rules_action.html.markdown rename to website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 5bd69d7d22e53..d78cbf5c4eec9 100644 --- a/website/docs/r/monitor_scheduled_query_rules_action.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -1,13 +1,13 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-action" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-alert" description: |- Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- -# azurerm_monitor_scheduled_query_rules_action +# azurerm_monitor_scheduled_query_rules_alert Manages an AlertingAction Scheduled Query Rule within Azure Monitor. @@ -35,7 +35,7 @@ resource "azurerm_log_analytics_workspace" "example" { } # Example: Alerting Action -resource "azurerm_scheduled_query_rule_action" "example" { +resource "azurerm_scheduled_query_rule_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -66,7 +66,7 @@ resource "azurerm_scheduled_query_rule_action" "example" { } # Example: Alerting Action Cross-Resource -resource "azurerm_scheduled_query_rule_action" "example2" { +resource "azurerm_scheduled_query_rule_alert" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -150,5 +150,5 @@ The following attributes are exported: Scheduled Query Rules can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_monitor_scheduled_query_rules_action.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +terraform import azurerm_monitor_scheduled_query_rules_alert.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename ``` From 68f55a9f71ce98fd658a3a201df293c07bd8d79b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 31 Jan 2020 19:01:28 -0800 Subject: [PATCH 029/498] WIP Get value from provider --- azurerm/internal/features/user_flags.go | 19 +++ azurerm/internal/provider/features.go | 116 ++++++++++++++++++ azurerm/internal/provider/provider.go | 3 + .../keyvault/resource_arm_key_vault.go | 98 +++------------ 4 files changed, 156 insertions(+), 80 deletions(-) create mode 100644 azurerm/internal/features/user_flags.go create mode 100644 azurerm/internal/provider/features.go diff --git a/azurerm/internal/features/user_flags.go b/azurerm/internal/features/user_flags.go new file mode 100644 index 0000000000000..834b6bc903c37 --- /dev/null +++ b/azurerm/internal/features/user_flags.go @@ -0,0 +1,19 @@ +package features + +type UserFeatures struct { + VirtualMachine VirtualMachineFeatures + VirtualMachineScaleSet VirtualMachineScaleSetFeatures + KeyVault KeyVaultFeatures +} + +type VirtualMachineFeatures struct { + DeleteOSDiskOnDeletion bool +} + +type VirtualMachineScaleSetFeatures struct { + RollInstancesWhenRequired bool +} + +type KeyVaultFeatures struct { + PurgeSoftDeleteOnDestroy bool +} diff --git a/azurerm/internal/provider/features.go b/azurerm/internal/provider/features.go new file mode 100644 index 0000000000000..b2fc42cb05366 --- /dev/null +++ b/azurerm/internal/provider/features.go @@ -0,0 +1,116 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" +) + +func schemaFeatures() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + // TODO: make this Required in 2.0 + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "virtual_machine": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "delete_os_disk_on_deletion": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + + "virtual_machine_scale_set": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "roll_instances_when_required": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + + "key_vault": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "purge_soft_delete_on_destroy": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + } +} + +func expandFeatures(input []interface{}) features.UserFeatures { + // TODO: in 2.0 when Required this can become: + //val := input[0].(map[string]interface{}) + + var val map[string]interface{} + if len(input) > 0 { + val = input[0].(map[string]interface{}) + } + + // these are the defaults if omitted from the config + features := features.UserFeatures{ + // NOTE: ensure all nested objects are fully populated + VirtualMachine: features.VirtualMachineFeatures{ + DeleteOSDiskOnDeletion: true, + }, + VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{ + RollInstancesWhenRequired: true, + }, + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: false, + }, + } + + if raw, ok := val["virtual_machine"]; ok { + items := raw.([]interface{}) + if len(items) > 0 { + virtualMachinesRaw := items[0].(map[string]interface{}) + if v, ok := virtualMachinesRaw["delete_os_disk_on_deletion"]; ok { + features.VirtualMachine.DeleteOSDiskOnDeletion = v.(bool) + } + } + } + + if raw, ok := val["virtual_machine_scale_set"]; ok { + items := raw.([]interface{}) + if len(items) > 0 { + scaleSetRaw := items[0].(map[string]interface{}) + if v, ok := scaleSetRaw["roll_instances_when_required"]; ok { + features.VirtualMachineScaleSet.RollInstancesWhenRequired = v.(bool) + } + } + } + + if raw, ok := val["key_vault"]; ok { + items := raw.([]interface{}) + if len(items) > 0 { + keyVaultRaw := items[0].(map[string]interface{}) + if v, ok := keyVaultRaw["purge_soft_delete_on_destroy"]; ok { + features.KeyVault.PurgeSoftDeleteOnDestroy = v.(bool) + } + } + } + + return features +} diff --git a/azurerm/internal/provider/provider.go b/azurerm/internal/provider/provider.go index 6b3f8e263a1f1..44d4c8056f3d5 100644 --- a/azurerm/internal/provider/provider.go +++ b/azurerm/internal/provider/provider.go @@ -159,6 +159,8 @@ func AzureProvider() terraform.ResourceProvider { Description: "This will disable the Terraform Partner ID which is used if a custom `partner_id` isn't specified.", }, + "features": schemaFeatures(), + // Advanced feature flags "skip_credentials_validation": { Type: schema.TypeBool, @@ -282,6 +284,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { } } + const resourceProviderRegistrationErrorFmt = `Error ensuring Resource Providers are registered. Terraform automatically attempts to register the Resource Providers it supports to diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index ff00aa44c20ce..d0376f4717f1c 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -67,28 +67,6 @@ func resourceArmKeyVault() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - ConflictsWith: []string{"sku_name"}, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - string(keyvault.Standard), - string(keyvault.Premium), - }, false), - }, - }, - }, - }, - "sku_name": { Type: schema.TypeString, Optional: true, @@ -96,8 +74,7 @@ func resourceArmKeyVault() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{ string(keyvault.Standard), string(keyvault.Premium), - // TODO: revert this in 2.0 - }, true), + }, false), }, "vault_uri": { @@ -157,22 +134,9 @@ func resourceArmKeyVault() *schema.Resource { Optional: true, }, - "enabled_for_soft_delete": { - Type: schema.TypeBool, - Optional: true, - }, - - "enabled_for_purge_protection": { - Type: schema.TypeBool, - Optional: true, - ValidateFunc: validate.BoolIsTrue(), - }, - - "purge_on_delete": { - Type: schema.TypeBool, - Optional: true, - Default: false, - ConflictsWith: []string{"enabled_for_purge_protection"}, + "soft_delete_enabled": { + Type: schema.TypeBool, + Optional: true, }, "network_acls": { @@ -224,29 +188,6 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - // Remove in 2.0 - var sku keyvault.Sku - - if inputs := d.Get("sku").([]interface{}); len(inputs) != 0 { - input := inputs[0].(map[string]interface{}) - v := input["name"].(string) - - sku = keyvault.Sku{ - Family: &armKeyVaultSkuFamily, - Name: keyvault.SkuName(v), - } - } else { - // Keep in 2.0 - sku = keyvault.Sku{ - Family: &armKeyVaultSkuFamily, - Name: keyvault.SkuName(d.Get("sku_name").(string)), - } - } - - if sku.Name == "" { - return fmt.Errorf("either 'sku_name' or 'sku' must be defined in the configuration file") - } - log.Printf("[INFO] preparing arguments for Azure ARM KeyVault creation.") name := d.Get("name").(string) @@ -265,12 +206,18 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e } } + purgeSoftDeleteOnDestroy := meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy + + if purgeSoftDeleteOnDestroy { + log.Printf("[INFO] purgeSoftDeleteOnDestroy is true") + } + location := azure.NormalizeLocation(d.Get("location").(string)) tenantUUID := uuid.FromStringOrNil(d.Get("tenant_id").(string)) enabledForDeployment := d.Get("enabled_for_deployment").(bool) enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) enabledForTemplateDeployment := d.Get("enabled_for_template_deployment").(bool) - enabledForSoftDelete := d.Get("enabled_for_soft_delete").(bool) + enabledForSoftDelete := d.Get("soft_delete_enabled").(bool) enabledForPurgeProtection := d.Get("enabled_for_purge_protection").(bool) t := d.Get("tags").(map[string]interface{}) @@ -283,6 +230,11 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error expanding `access_policy`: %+v", policies) } + sku := keyvault.Sku{ + Family: &armKeyVaultSkuFamily, + Name: keyvault.SkuName(d.Get("sku_name").(string)), + } + parameters := keyvault.VaultCreateOrUpdateParameters{ Location: &location, Properties: &keyvault.VaultProperties{ @@ -405,16 +357,11 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) - d.Set("enabled_for_soft_delete", props.EnableSoftDelete) + d.Set("soft_delete_enabled", props.EnableSoftDelete) d.Set("enabled_for_purge_protection", props.EnablePurgeProtection) d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenKeyVaultSku(sku)); err != nil { - return fmt.Errorf("Error setting 'sku' for KeyVault %q: %+v", *resp.Name, err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting 'sku_name' for KeyVault %q: %+v", *resp.Name, err) } @@ -493,7 +440,7 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } } - if d.Get("purge_on_delete").(bool) && d.Get("enabled_for_soft_delete").(bool) && err == nil { + if d.Get("purge_on_delete").(bool) && d.Get("soft_delete_enabled").(bool) && err == nil { log.Printf("[DEBUG] KeyVault %s marked for purge, executing purge", name) location := d.Get("location").(string) @@ -512,15 +459,6 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { return nil } -// Remove in 2.0 -func flattenKeyVaultSku(sku *keyvault.Sku) []interface{} { - result := map[string]interface{}{ - "name": string(sku.Name), - } - - return []interface{}{result} -} - func flattenKeyVaultNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{ From 7dfdeb34ae35c43c571db2a16c8f7f39d7fb75eb Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 11:31:08 -0600 Subject: [PATCH 030/498] Fix code review items --- ...ta_source_monitor_scheduled_query_rules.go | 96 ++++ ...ce_monitor_scheduled_query_rules_action.go | 262 --------- ...rce_monitor_scheduled_query_rules_alert.go | 147 +++++ ...ource_monitor_scheduled_query_rules_log.go | 152 +---- .../internal/services/monitor/registration.go | 32 +- ...ource_arm_monitor_scheduled_query_rules.go | 207 +++++++ ...rm_monitor_scheduled_query_rules_action.go | 519 ------------------ ...arm_monitor_scheduled_query_rules_alert.go | 336 ++++++++++++ ...e_arm_monitor_scheduled_query_rules_log.go | 323 ++--------- ...nitor_scheduled_query_rules_alert_test.go} | 92 +--- ..._monitor_scheduled_query_rules_log_test.go | 185 +------ ...nitor_scheduled_query_rules_alert_test.go} | 28 +- ..._monitor_scheduled_query_rules_log_test.go | 7 +- ..._scheduled_query_rules_alert.html.markdown | 22 +- ...or_scheduled_query_rules_log.html.markdown | 10 +- ..._scheduled_query_rules_alert.html.markdown | 14 +- 16 files changed, 895 insertions(+), 1537 deletions(-) create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go rename azurerm/internal/services/monitor/tests/{data_source_monitor_scheduled_query_rules_action_test.go => data_source_monitor_scheduled_query_rules_alert_test.go} (65%) rename azurerm/internal/services/monitor/tests/{resource_arm_monitor_scheduled_query_rules_action_test.go => resource_arm_monitor_scheduled_query_rules_alert_test.go} (84%) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go new file mode 100644 index 0000000000000..72380eedcbd34 --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go @@ -0,0 +1,96 @@ +package monitor + +import ( + "fmt" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + switch action := resp.Action.(type) { + case insights.AlertingAction: + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go deleted file mode 100644 index 675173520cc9f..0000000000000 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go +++ /dev/null @@ -1,262 +0,0 @@ -package monitor - -import ( - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func dataSourceArmMonitorScheduledQueryRulesAction() *schema.Resource { - return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesActionRead, - - Timeouts: &schema.ResourceTimeout{ - Read: schema.DefaultTimeout(5 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - - "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), - - "location": azure.SchemaLocationForDataSource(), - - "authorized_resources": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Computed: true, - }, - "email_subject": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "criteria": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dimension": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - Elem: schema.TypeString, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "values": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "metric_name": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "data_source_id": { - Type: schema.TypeString, - Computed: true, - }, - "description": { - Type: schema.TypeString, - Computed: true, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "frequency": { - Type: schema.TypeInt, - Computed: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Computed: true, - }, - "query_type": { - Type: schema.TypeString, - Computed: true, - }, - "severity": { - Type: schema.TypeInt, - Computed: true, - }, - "throttling": { - Type: schema.TypeInt, - Computed: true, - }, - "time_window": { - Type: schema.TypeInt, - Computed: true, - }, - "trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Computed: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Computed: true, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - - "tags": tags.SchemaDataSource(), - }, - } -} - -func dataSourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - var action insights.AlertingAction - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go new file mode 100644 index 0000000000000..c7dc42763af8b --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -0,0 +1,147 @@ +package monitor + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" +) + +func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "authorized_resource_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index ff14ae0516ea7..cd0853c6dc728 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -1,21 +1,16 @@ package monitor import ( - "fmt" "time" - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesLogRead, + Read: dataSourceArmMonitorScheduledQueryRulesRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -31,36 +26,13 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - "authorized_resources": { + "authorized_resource_ids": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, }, - "azns_action": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Computed: true, - }, - "email_subject": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, "criteria": { Type: schema.TypeSet, Computed: true, @@ -109,10 +81,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "frequency": { - Type: schema.TypeInt, - Computed: true, - }, "last_updated_time": { Type: schema.TypeString, Computed: true, @@ -129,124 +97,8 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "severity": { - Type: schema.TypeInt, - Computed: true, - }, - "throttling": { - Type: schema.TypeInt, - Computed: true, - }, - "time_window": { - Type: schema.TypeInt, - Computed: true, - }, - "trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Computed: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Computed: true, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, "tags": tags.SchemaDataSource(), }, } } - -func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - var action insights.LogToMetricAction - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index d4aeb8e971231..495c3fbb4d4a8 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -14,25 +14,25 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_monitor_scheduled_query_rules_action": dataSourceArmMonitorScheduledQueryRulesAction(), - "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules_alert": dataSourceArmMonitorScheduledQueryRulesAlert(), + "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), - "azurerm_monitor_scheduled_query_rules_action": resourceArmMonitorScheduledQueryRulesAction(), - "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules_alert": resourceArmMonitorScheduledQueryRulesAlert(), + "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go new file mode 100644 index 0000000000000..b7661870314a0 --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go @@ -0,0 +1,207 @@ +package monitor + +import ( + "fmt" + "log" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/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/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}, action insights.BasicAction, schedule *insights.Schedule) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + switch action := resp.Action.(type) { + case insights.AlertingAction: + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query, ok := d.Get("query").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + if ok { + source.Query = utils.String(query) + } + + return &source +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go deleted file mode 100644 index ff774f53231fd..0000000000000 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go +++ /dev/null @@ -1,519 +0,0 @@ -package monitor - -import ( - "fmt" - "log" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" - "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/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmMonitorScheduledQueryRulesAction() *schema.Resource { - return &schema.Resource{ - Create: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesActionRead, - Update: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesActionDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, - }, - - "resource_group_name": azure.SchemaResourceGroupName(), - - "location": azure.SchemaLocation(), - - "authorized_resources": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Optional: true, - Default: "{}", - ValidateFunc: validation.ValidateJsonString, - }, - "email_subject": { - Type: schema.TypeString, - Optional: true, - }, - }, - }, - }, - "data_source_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - "description": { - Type: schema.TypeString, - Optional: true, - }, - "enabled": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "frequency": { - Type: schema.TypeInt, - Optional: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Optional: true, - }, - "query_type": { - Type: schema.TypeString, - Optional: true, - Default: "ResultCount", - ValidateFunc: validation.StringInSlice([]string{ - "ResultCount", - }, false), - }, - "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), - }, - "throttling": { - Type: schema.TypeInt, - Optional: true, - }, - "time_window": { - Type: schema.TypeInt, - Optional: true, - }, - "trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Required: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Consecutive", - "Total", - }, false), - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - ValidateFunc: validation.NoZeroValues, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, - - "tags": tags.Schema(), - }, - } -} - -func resourceArmMonitorScheduledQueryRulesActionCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_action", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesAlertingAction(d) - source := expandMonitorScheduledQueryRulesSource(d) - schedule := expandMonitorScheduledQueryRulesSchedule(d) - - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesActionRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesActionDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil -} - -func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { - aznsActionRaw := d.Get("azns_action").(*schema.Set).List() - aznsAction := expandMonitorScheduledQueryRulesActionAznsAction(aznsActionRaw) - severityRaw := d.Get("severity").(int) - severity := strconv.Itoa(severityRaw) - throttling := d.Get("throttling").(int) - - triggerRaw := d.Get("trigger").(*schema.Set).List() - trigger := expandMonitorScheduledQueryRulesActionTrigger(triggerRaw) - - action := insights.AlertingAction{ - AznsAction: aznsAction, - Severity: insights.AlertSeverity(severity), - ThrottlingInMin: utils.Int32(int32(throttling)), - Trigger: trigger, - OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, - } - - return &action -} - -func expandMonitorScheduledQueryRulesActionAznsAction(input []interface{}) *insights.AzNsActionGroup { - result := insights.AzNsActionGroup{} - - for _, item := range input { - v := item.(map[string]interface{}) - actionGroups := v["action_group"].(*schema.Set).List() - - result.ActionGroup = utils.ExpandStringSlice(actionGroups) - result.EmailSubject = utils.String(v["email_subject"].(string)) - result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) - } - - return &result -} - -func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { - frequency := d.Get("frequency").(int) - timeWindow := d.Get("time_window").(int) - - schedule := insights.Schedule{ - FrequencyInMinutes: utils.Int32(int32(frequency)), - TimeWindowInMinutes: utils.Int32(int32(timeWindow)), - } - - return &schedule -} - -func expandMonitorScheduledQueryRulesActionMetricTrigger(input []interface{}) *insights.LogMetricTrigger { - if len(input) == 0 { - return nil - } - - result := insights.LogMetricTrigger{} - for _, item := range input { - v := item.(map[string]interface{}) - result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) - result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) - result.MetricColumn = utils.String(v["metric_column"].(string)) - } - - return &result -} - -func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { - authorizedResources := d.Get("authorized_resources").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query := d.Get("query").(string) - - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResources), - DataSourceID: utils.String(dataSourceID), - Query: utils.String(query), - QueryType: insights.ResultCount, - } - - return &source -} - -func expandMonitorScheduledQueryRulesActionTrigger(input []interface{}) *insights.TriggerCondition { - result := insights.TriggerCondition{} - - for _, item := range input { - v := item.(map[string]interface{}) - metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() - - result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) - result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTrigger = expandMonitorScheduledQueryRulesActionMetricTrigger(metricTriggerRaw) - } - - return &result -} - -func flattenAzureRmScheduledQueryRulesActionAznsAction(input *insights.AzNsActionGroup) []interface{} { - result := make([]interface{}, 0) - v := make(map[string]interface{}) - - if input != nil { - if input.ActionGroup != nil { - v["action_group"] = *input.ActionGroup - } - v["email_subject"] = input.EmailSubject - v["custom_webhook_payload"] = input.CustomWebhookPayload - } - result = append(result, v) - - return result -} - -func flattenAzureRmScheduledQueryRulesActionMetricTrigger(input *insights.LogMetricTrigger) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - result["metric_trigger_type"] = string(input.MetricTriggerType) - - if input.MetricColumn != nil { - result["metric_column"] = *input.MetricColumn - } - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesActionTrigger(input *insights.TriggerCondition) []interface{} { - result := make(map[string]interface{}) - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesActionMetricTrigger(input.MetricTrigger) - } - - return []interface{}{result} -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go new file mode 100644 index 0000000000000..1a66e95f8ef03 --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -0,0 +1,336 @@ +package monitor + +import ( + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "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/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesRead, + Update: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "authorized_resource_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + }, + "action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { + var action insights.BasicAction + action = expandMonitorScheduledQueryRulesAlertingAction(d) + schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) + + return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) +} + +func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { + alertActionRaw := d.Get("action").(*schema.Set).List() + alertAction := expandMonitorScheduledQueryRulesAlertAction(alertActionRaw) + severityRaw := d.Get("severity").(int) + severity := strconv.Itoa(severityRaw) + throttling := d.Get("throttling").(int) + + triggerRaw := d.Get("trigger").(*schema.Set).List() + trigger := expandMonitorScheduledQueryRulesAlertTrigger(triggerRaw) + + action := insights.AlertingAction{ + AznsAction: alertAction, + Severity: insights.AlertSeverity(severity), + ThrottlingInMin: utils.Int32(int32(throttling)), + Trigger: trigger, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesAlertAction(input []interface{}) *insights.AzNsActionGroup { + result := insights.AzNsActionGroup{} + + for _, item := range input { + v := item.(map[string]interface{}) + actionGroups := v["action_group"].(*schema.Set).List() + + result.ActionGroup = utils.ExpandStringSlice(actionGroups) + result.EmailSubject = utils.String(v["email_subject"].(string)) + result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesAlertMetricTrigger(input []interface{}) *insights.LogMetricTrigger { + if len(input) == 0 { + return nil + } + + result := insights.LogMetricTrigger{} + for _, item := range input { + v := item.(map[string]interface{}) + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) + result.MetricColumn = utils.String(v["metric_column"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insights.Schedule { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + + schedule := insights.Schedule{ + FrequencyInMinutes: utils.Int32(int32(frequency)), + TimeWindowInMinutes: utils.Int32(int32(timeWindow)), + } + + return &schedule +} + +func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { + result := insights.TriggerCondition{} + + for _, item := range input { + v := item.(map[string]interface{}) + metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() + + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTrigger = expandMonitorScheduledQueryRulesAlertMetricTrigger(metricTriggerRaw) + } + + return &result +} + +func flattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 1167d81da80e2..a25ee0535b20d 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -1,30 +1,23 @@ package monitor import ( - "fmt" - "log" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" "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/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesLogRead, + Read: resourceArmMonitorScheduledQueryRulesRead, Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesLogDelete, + Delete: resourceArmMonitorScheduledQueryRulesDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -48,41 +41,18 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "location": azure.SchemaLocation(), - "authorized_resources": { + "authorized_resource_ids": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Optional: true, - Default: "{}", - ValidateFunc: validation.ValidateJsonString, - }, - "email_subject": { - Type: schema.TypeString, - Optional: true, - }, - }, + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, }, }, + "criteria": { Type: schema.TypeSet, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dimension": { @@ -91,12 +61,14 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, "operator": { Type: schema.TypeString, - Required: true, + Optional: true, + Default: "Include", ValidateFunc: validation.StringInSlice([]string{ "Include", }, false), @@ -105,15 +77,17 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeList, Required: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, }, }, }, "metric_name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, }, }, @@ -132,10 +106,6 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Optional: true, Default: true, }, - "frequency": { - Type: schema.TypeInt, - Optional: true, - }, "last_updated_time": { Type: schema.TypeString, Computed: true, @@ -144,92 +114,6 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "query": { - Type: schema.TypeString, - Optional: true, - }, - "query_type": { - Type: schema.TypeString, - Optional: true, - Default: "ResultCount", - ValidateFunc: validation.StringInSlice([]string{ - "ResultCount", - }, false), - }, - "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), - }, - "throttling": { - Type: schema.TypeInt, - Optional: true, - }, - "time_window": { - Type: schema.TypeInt, - Optional: true, - }, - "trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Required: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Consecutive", - "Total", - }, false), - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - ValidateFunc: validation.NoZeroValues, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, "tags": tags.Schema(), }, @@ -237,165 +121,9 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { } func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_log", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesLogToMetricAction(d) - source := expandMonitorScheduledQueryRulesSource(d) - schedule := expandMonitorScheduledQueryRulesSchedule(d) + action := expandMonitorScheduledQueryRulesLogToMetricAction(d) - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil + return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, nil) } func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { @@ -421,6 +149,19 @@ func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insight return &criteria } +func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + + return &source +} + func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { criteriaRaw := d.Get("criteria").(*schema.Set).List() criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go similarity index 65% rename from azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 875fdaa762026..8e9109393791a 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -9,25 +9,8 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -44,7 +27,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -60,59 +43,12 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - action_type = "LogToMetric" - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = [""] - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -130,13 +66,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" @@ -146,7 +81,7 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -163,8 +98,8 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) @@ -175,7 +110,7 @@ func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -201,24 +136,23 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestSqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" query_type = "ResultCount" - authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] frequency = 60 time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -235,8 +169,8 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index 875fdaa762026..bb4b7e3c04c07 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -3,14 +3,13 @@ package tests import ( "fmt" "testing" - "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -26,44 +25,10 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes }) } -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -80,13 +45,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_log" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + location = "${azurerm_resource_group.test.location}" description = "test log to metric action" enabled = true - action_type = "LogToMetric" data_source_id = "${azurerm_application_insights.test.id}" @@ -95,149 +59,14 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { dimension { name = "InstanceName" operator = "Include" - values = [""] + values = ["50"] } } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } - -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - action_type = "Alerting" - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - - frequency = 60 - time_window = 60 - - severity = 3 - azns_action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) -} - -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_log_analytics_workspace" "test2" { - name = "acctestWorkspace2-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestSqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - action_type = "Alerting" - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - - frequency = 60 - time_window = 60 - - severity = 3 - azns_action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) -} diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go similarity index 84% rename from azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 1bb822ff80a20..2947388733a5f 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -13,7 +13,7 @@ import ( ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -36,7 +36,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -63,7 +63,7 @@ func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.Tes return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -80,13 +80,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules_action" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" @@ -96,7 +95,7 @@ resource "azurerm_monitor_scheduled_query_rules_action" "test" { time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" custom_webhook_payload = "{}" @@ -119,7 +118,7 @@ resource "azurerm_monitor_scheduled_query_rules_action" "test" { func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -144,24 +143,23 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules_action" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action cross-resource" enabled = true - action_type = "Alerting" - authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] - data_source_id = "${azurerm_application_insights.test.id}" - query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" frequency = 60 time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -179,7 +177,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_monitor_scheduled_query_rules_action" { + if rs.Type != "azurerm_monitor_scheduled_query_rules_alert" { continue } @@ -200,7 +198,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error return nil } -func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(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] diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 069f41ae89e72..91e751dcf4b0c 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -37,7 +37,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -60,7 +60,6 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { location = "${azurerm_resource_group.test.location}" description = "test log to metric action" enabled = true - action_type = "LogToMetric" data_source_id = "${azurerm_application_insights.test.id}" @@ -69,14 +68,14 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { dimension { name = "InstanceName" operator = "Include" - values = [""] + values = ["50"] } } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 4d92728a89842..f44dbf8b87507 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -32,8 +32,8 @@ output "query_rule_id" { ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. -* `azns_action` - An `azns_action` block as defined below. -* `authorized_resources` - List of Resource IDs referred into query. +* `action` - An `action` block as defined below. +* `authorized_resource_ids` - List of Resource IDs referred into query. * `data_source_id` - The resource uri over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. @@ -47,9 +47,9 @@ output "query_rule_id" { --- -* `azns_action` supports the following: +* `action` supports the following: -* `action_group` - (Optional) List of action group reference resource IDs. +* `action_group` - List of action group reference resource IDs. * `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. * `email_subject` - Custom subject override for all email ids in Azure action group. @@ -57,15 +57,15 @@ output "query_rule_id" { `metricTrigger` supports the following: -* `metricColumn` - (Required) Evaluation of metric on a particular column. -* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. -* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) The threshold of the metric trigger. +* `metricColumn` - Evaluation of metric on a particular column. +* `metricTriggerType` - Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - The threshold of the metric trigger. --- `trigger` supports the following: -* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. -* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) Result or count threshold based on which rule should be triggered. +* `metricTrigger` - A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - Result or count threshold based on which rule should be triggered. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index a29912472b688..a16f97be51e5a 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -42,13 +42,13 @@ output "query_rule_id" { `criteria` supports the following: -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. +* `dimension` - A `dimension` block as defined below. +* `metric_name` - Name of the metric. --- `dimension` supports the following: -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. +* `name` - Name of the dimension. +* `operator` - Operator for dimension values, - 'Include'. +* `values` - List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index d78cbf5c4eec9..ff4487816ae6c 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -40,7 +40,7 @@ resource "azurerm_scheduled_query_rule_alert" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - azns_action { + action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" @@ -71,9 +71,9 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - authorized_resources = [azurerm_application_insights.example.id, + authorized_resource_ids = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] - azns_action { + action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" @@ -99,8 +99,8 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. -* `authorized_resources` - (Optional) List of Resource IDs referred into query. -* `azns_action` - (Optional) An `azns_action` block as defined below. +* `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. +* `action` - (Optional) An `action` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. @@ -114,9 +114,9 @@ The following arguments are supported: --- -* `azns_action` supports the following: +* `action` supports the following: -* `action_group` - (Optional) List of action group reference resource IDs. +* `action_group` - (Required) List of action group reference resource IDs. * `custom_webhook_payload` - (Optional) Custom payload to be sent for all webhook payloads in alerting action. * `email_subject` - (Optional) Custom subject override for all email ids in Azure action group. From 7220ba410f7ac07de3ff450d10e9803a79dbfa79 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 11:58:20 -0600 Subject: [PATCH 031/498] Fix lint issues and minor typos --- ...ce_arm_monitor_scheduled_query_rules_alert.go | 3 +-- ...urce_arm_monitor_scheduled_query_rules_log.go | 13 ------------- ...m_monitor_scheduled_query_rules_alert_test.go | 16 ++++++++-------- ...arm_monitor_scheduled_query_rules_log_test.go | 12 ++++++------ 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 1a66e95f8ef03..98bda4dbcd17e 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -195,8 +195,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { } func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesAlertingAction(d) + action := expandMonitorScheduledQueryRulesAlertingAction(d) schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index a25ee0535b20d..65c464e01f3ae 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -149,19 +149,6 @@ func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insight return &criteria } -func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - - return &source -} - func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { criteriaRaw := d.Get("criteria").(*schema.Set).List() criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 2947388733a5f..a16c0b8a5c533 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -18,12 +18,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, { @@ -41,12 +41,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, { @@ -172,7 +172,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -191,7 +191,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error } if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + return fmt.Errorf("Scheduled Query Rule still exists:\n%#v", resp) } } @@ -209,7 +209,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) name := 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 Activity Log Alert Instance: %s", name) + return fmt.Errorf("Bad: no resource group found in state for Scheduled Query Rule Instance: %s", name) } client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient @@ -221,7 +221,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: Scheduled Query Rule Instance %q (resource group: %q) does not exist", name, resourceGroup) } return nil diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 91e751dcf4b0c..8dd720c71463e 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -17,12 +17,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), }, { @@ -94,14 +94,14 @@ func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) er } if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + return fmt.Errorf("Scheduled Query Rule still exists:\n%#v", resp) } } return nil } -func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRulesLogExists(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] @@ -112,7 +112,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou name := 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 Activity Log Alert Instance: %s", name) + return fmt.Errorf("Bad: no resource group found in state for Scheduled Query Rule Instance: %s", name) } client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient @@ -124,7 +124,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: Scheduled Query Rule Instance %q (resource group: %q) does not exist", name, resourceGroup) } return nil From 3fa8441c0e0c0588574c3ad0eeff7e2383c09ca1 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 12:44:44 -0600 Subject: [PATCH 032/498] Fix lint issues #2 --- ...onitor_scheduled_query_rules_alert_test.go | 100 +++++++++--------- ..._monitor_scheduled_query_rules_log_test.go | 32 +++--- ...onitor_scheduled_query_rules_alert_test.go | 84 +++++++-------- ..._monitor_scheduled_query_rules_log_test.go | 28 ++--- ..._scheduled_query_rules_alert.html.markdown | 1 - ...or_scheduled_query_rules_log.html.markdown | 1 - ..._scheduled_query_rules_alert.html.markdown | 1 - ...or_scheduled_query_rules_log.html.markdown | 1 - 8 files changed, 122 insertions(+), 126 deletions(-) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 8e9109393791a..4f41939128074 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -68,39 +68,39 @@ resource "azurerm_monitor_action_group" "test" { resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } @@ -140,38 +140,38 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestSqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index bb4b7e3c04c07..d25c6a7de3558 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -46,27 +46,27 @@ resource "azurerm_monitor_action_group" "test" { } resource "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_application_insights.test.id}" - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } } data "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index a16c0b8a5c533..bedb59a884560 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -75,42 +75,42 @@ resource "azurerm_application_insights" "test" { } resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" + name = "acctestActionGroup-%d" resource_group_name = "${azurerm_resource_group.test.name}" short_name = "acctestag" } resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - query_type = "ResultCount" + query_type = "ResultCount" - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - custom_webhook_payload = "{}" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + custom_webhook_payload = "{}" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } @@ -145,29 +145,29 @@ resource "azurerm_monitor_action_group" "test" { resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action cross-resource" - enabled = true + description = "test alerting action cross-resource" + enabled = true - authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] - data_source_id = "${azurerm_application_insights.test.id}" - query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" + authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + query_type = "ResultCount" - frequency = 60 - time_window = 60 + frequency = 60 + time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } - trigger { - operator = "GreaterThan" - threshold = 5000 - } + trigger { + operator = "GreaterThan" + threshold = 5000 + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 8dd720c71463e..2fc2efdd82f98 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -49,7 +49,7 @@ resource "azurerm_application_insights" "test" { } resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" + name = "acctestActionGroup-%d" resource_group_name = "${azurerm_resource_group.test.name}" short_name = "acctestag" } @@ -58,19 +58,19 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } + description = "test log to metric action" + enabled = true + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index f44dbf8b87507..1998f0670646c 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-alert" description: |- Get information about the specified AlertingAction Scheduled Query Rule. --- diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index a16f97be51e5a..3633ba24d57f5 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-log" description: |- Get information about the specified LogToMetricAction Scheduled Query Rule. --- diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index ff4487816ae6c..54324cbadc21a 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-alert" description: |- Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index a5d6895fb301c..29f6e8291c19d 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-log" description: |- Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor --- From d2a15de9c2b14b1e3c08bc7b3caa600cf03b2254 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 13:12:41 -0600 Subject: [PATCH 033/498] Fix lint issues #3 --- ...ource_monitor_scheduled_query_rules_log.go | 1 - ...arm_monitor_scheduled_query_rules_alert.go | 2 +- ..._scheduled_query_rules_alert.html.markdown | 54 +++++++++---------- ...or_scheduled_query_rules_log.html.markdown | 24 ++++----- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index cd0853c6dc728..4a864f0f19f26 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -46,7 +46,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "name": { Type: schema.TypeString, Computed: true, - Elem: schema.TypeString, }, "operator": { Type: schema.TypeString, diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 98bda4dbcd17e..cee4212d9823b 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -67,7 +67,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "{}", - ValidateFunc: validation.ValidateJsonString, + ValidateFunc: validation.StringIsJSON, }, "email_subject": { Type: schema.TypeString, diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 54324cbadc21a..19cdc7ee01488 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -35,26 +35,26 @@ resource "azurerm_log_analytics_workspace" "example" { # Example: Alerting Action resource "azurerm_scheduled_query_rule_alert" "example" { - name = format("%s-queryrule", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action example" - enabled = true - frequency = 5 - query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" - query_type = "ResultCount" - severity = 1 - time_window = 30 + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule Alerting Action example" + enabled = true + frequency = 5 + query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query_type = "ResultCount" + severity = 1 + time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + threshold_operator = "GreaterThan" + threshold = 3 metric_trigger { operator = "GreaterThan" threshold = 1 @@ -66,28 +66,28 @@ resource "azurerm_scheduled_query_rule_alert" "example" { # Example: Alerting Action Cross-Resource resource "azurerm_scheduled_query_rule_alert" "example2" { - name = format("%s-queryrule2", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule2", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name authorized_resource_ids = [azurerm_application_insights.example.id, - azurerm_log_analytics_workspace.example.id] + azurerm_log_analytics_workspace.example.id] action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action cross-resource example" - enabled = true - frequency = 5 - query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" - severity = "1" - time_window = 30 + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule Alerting Action cross-resource example" + enabled = true + frequency = 5 + query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + query_type = "ResultCount" + severity = "1" + time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + threshold_operator = "GreaterThan" + threshold = 3 } } ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 29f6e8291c19d..7870b2c8d436e 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -26,21 +26,21 @@ resource "azurerm_application_insights" "example" { } resource "azurerm_scheduled_query_rule_log" "example3" { - name = format("%s-queryrule3", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name criteria { - metric_name = "Average_% Idle Time" - dimensions { - name = "InstanceName" - operator = "Include" - values = [""] - } + metric_name = "Average_% Idle Time" + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule LogToMetric example" - enabled = true + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true } ``` From 635e2c2cee5ddd8b008d89d1e0a3e4318350c3ec Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 3 Feb 2020 15:43:16 +1100 Subject: [PATCH 034/498] review fixes --- .../resource_arm_bot_channel_directline.go | 50 +++++++++---------- ...esource_arm_bot_channel_directline_test.go | 12 ++--- .../docs/r/bot_channel_directline.markdown | 27 ++++++---- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 219ab81122913..8678b9340873f 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -52,38 +52,38 @@ func resourceArmBotChannelDirectline() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "site_name": { + "name": { Type: schema.TypeString, Required: true, ValidateFunc: validate.NoEmptyStrings, }, - "is_enabled": { + "enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_v1_enabled": { + "v1_allowed": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_v3_enabled": { + "v3_allowed": { Type: schema.TypeBool, Optional: true, Default: true, }, - "is_secure_site_enabled": { + "enhanced_authentication_enabled": { Type: schema.TypeBool, Default: false, Optional: true, }, "trusted_origins": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, @@ -103,7 +103,7 @@ func resourceArmBotChannelDirectline() *schema.Resource { Sensitive: true, }, - "site_id": { + "id": { Type: schema.TypeString, Computed: true, }, @@ -134,12 +134,10 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac } } - sites, _ := expandSites(d.Get("site").(*schema.Set).List()) - channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ Properties: &botservice.DirectLineChannelProperties{ - Sites: sites, + Sites: expandDirectlineSites(d.Get("site").(*schema.Set).List()), }, ChannelName: botservice.ChannelNameDirectLineChannel1, }, @@ -195,7 +193,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { - d.Set("site", unExpandSites(*channelProps.Sites)) + d.Set("site", flattenDirectlineSites(*channelProps.Sites)) } } } @@ -210,7 +208,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites, _ := expandSites(d.Get("site").(*schema.Set).List()) + sites := expandDirectlineSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ @@ -263,25 +261,25 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac return nil } -func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { +func expandDirectlineSites(input []interface{}) *[]botservice.DirectLineSite { sites := make([]botservice.DirectLineSite, len(input)) for i, element := range input { site := element.(map[string]interface{}) - if v, ok := site["site_name"].(string); ok { + if v, ok := site["name"].(string); ok { sites[i].SiteName = &v } - if v, ok := site["is_enabled"].(bool); ok { + if v, ok := site["enabled"].(bool); ok { sites[i].IsEnabled = &v } - if v, ok := site["is_v1_enabled"].(bool); ok { + if v, ok := site["v1_allowed"].(bool); ok { sites[i].IsV1Enabled = &v } - if v, ok := site["is_v3_enabled"].(bool); ok { + if v, ok := site["v3_allowed"].(bool); ok { sites[i].IsV3Enabled = &v } - if v, ok := site["is_secure_site_enabled"].(bool); ok { + if v, ok := site["enhanced_authentication_enabled"].(bool); ok { sites[i].IsSecureSiteEnabled = &v } if v, ok := site["trusted_origins"].([]interface{}); ok { @@ -293,17 +291,17 @@ func expandSites(input []interface{}) (*[]botservice.DirectLineSite, error) { } } - return &sites, nil + return &sites } -func unExpandSites(input []botservice.DirectLineSite) []interface{} { +func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { sites := make([]interface{}, len(input)) for i, element := range input { site := make(map[string]interface{}) - if element.SiteName != nil { - site["site_name"] = *element.SiteName + if v := element.SiteName; v != nil { + site["name"] = *v } if element.Key != nil { @@ -315,19 +313,19 @@ func unExpandSites(input []botservice.DirectLineSite) []interface{} { } if element.IsEnabled != nil { - site["is_enabled"] = *element.IsEnabled + site["enabled"] = *element.IsEnabled } if element.IsV1Enabled != nil { - site["is_v1_enabled"] = *element.IsV1Enabled + site["v1_allowed"] = *element.IsV1Enabled } if element.IsV3Enabled != nil { - site["is_v3_enabled"] = *element.IsV3Enabled + site["v3_allowed"] = *element.IsV3Enabled } if element.IsSecureSiteEnabled != nil { - site["is_secure_site_enabled"] = *element.IsSecureSiteEnabled + site["enhanced_authentication_enabled"] = *element.IsSecureSiteEnabled } if element.TrustedOrigins != nil { diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 0bce701508ff2..b6f6bbc68df19 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -163,11 +163,11 @@ resource "azurerm_bot_channel_directline" "test" { location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" site { - site_name = "test" - is_enabled = true - is_v1_enabled = true - is_v3_enabled = true - is_secure_site_enabled = true + name = "test" + enabled = true + v1_allowed = true + v3_allowed = true + enhanced_authentication_enabled = true trusted_origins = ["https://example.com"] } } @@ -183,7 +183,7 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - is_enabled = false + enabled = false } `, template) } diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 450ea6df254f8..241054e3d7027 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -34,8 +34,8 @@ resource "azurerm_bot_channel_directline" "example" { resource_group_name = "${azurerm_resource_group.example.name}" site { - site_name = "default" - is_enabled = true + name = "default" + enabled = true } } ``` @@ -52,20 +52,27 @@ The following arguments are supported: - `site` - (Optional) A site represents a client application that you want to connect to your bot. Multiple `site` blocks may be defined as below -A `site` block as the following properties: +A `site` block has the following properties: -- `site_name` - (Required) The name of the site +- `name` - (Required) The name of the site -- `is_enabled` - (Optional) Enables/Disables this site. Enabled by default +- `enabled` - (Optional) Enables/Disables this site. Enabled by default -- `is_v1_enabled` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default +- `v1_allowed` - (Optional) Enables v1 of the Directline protocol for this site. Enabled by default -- `is_v3_enabled` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default +- `v3_allowed` - (Optional) Enables v3 of the Directline protocol for this site. Enabled by default -- `is_secure_site_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. +- `enhanced_authentication_enabled` - (Optional) Enables additional security measures for this site, see [Enhanced Directline Authentication Features](https://blog.botframework.com/2018/09/25/enhanced-direct-line-authentication-features). Disabled by default. - `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. +- `key` - (Computed) Primary key for accessing this site + +- `key2` - (Computed) Secondary key for accessing this site + +- `id` - (Computed) Id for the site + + ## Attributes Reference The following attributes are exported: @@ -74,8 +81,8 @@ The following attributes are exported: ## Import -The Microsoft Teams Channel for a Bot can be imported using the `resource id`, e.g. +The Directline Channel for a Bot can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_bot_channel_ms_teams.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/MsTeamsChannel +terraform import azurerm_bot_channel_directline.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.BotService/botServices/example/channels/DirectlineChannel ``` From d23b08421b52689e565db07bbe578539c2735183 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Mon, 3 Feb 2020 22:01:23 +1100 Subject: [PATCH 035/498] minor fix to directline tests --- .../bot/tests/resource_arm_bot_channel_directline_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index b6f6bbc68df19..1b1db1aba6ce7 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -164,7 +164,7 @@ resource "azurerm_bot_channel_directline" "test" { resource_group_name = "${azurerm_resource_group.test.name}" site { name = "test" - enabled = true + enabled = true v1_allowed = true v3_allowed = true enhanced_authentication_enabled = true @@ -183,7 +183,10 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - enabled = false + site { + name = "test" + enabled = false + } } `, template) } From 4ea7ed13973492873d9e7606771dea0ec207b459 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Tue, 4 Feb 2020 12:30:53 +1100 Subject: [PATCH 036/498] fix acc test --- .../bot/tests/resource_arm_bot_channel_directline_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index 1b1db1aba6ce7..ccbe57ea5b31a 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -149,6 +149,10 @@ resource "azurerm_bot_channel_directline" "test" { bot_name = "${azurerm_bot_channels_registration.test.name}" location = "${azurerm_bot_channels_registration.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + } } `, template) } From 924c38a465038e6762fd97f4ce3cf8d5c3fdba07 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 3 Feb 2020 18:21:32 -0800 Subject: [PATCH 037/498] Done except for purge on destroy --- azurerm/helpers/azure/key_vault.go | 17 ++++++++++ .../keyvault/resource_arm_key_vault.go | 33 +++++++++---------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/azurerm/helpers/azure/key_vault.go b/azurerm/helpers/azure/key_vault.go index 7957380bb5946..3ab6c2340fe8b 100644 --- a/azurerm/helpers/azure/key_vault.go +++ b/azurerm/helpers/azure/key_vault.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -118,3 +119,19 @@ func KeyVaultExists(ctx context.Context, client *keyvault.VaultsClient, keyVault return true, nil } + +func KeyVaultCustomizeDiff(d *schema.ResourceDiff, _ interface{}) error { + if d.HasChange("soft_delete_enabled") { + if old, new := d.GetChange("soft_delete_enabled"); old.(bool) && !new.(bool) { + return fmt.Errorf("the property 'soft_delete_enabled' cannot be set to false, enabling the soft delete for a vault is an irreversible action") + } + } + + if d.HasChange("purge_protection_enabled") { + if old, new := d.GetChange("purge_protection_enabled"); old.(bool) && !new.(bool) { + return fmt.Errorf("the property 'purge_protection_enabled' cannot be set to false, enabling the purge protection for a vault is an irreversible action") + } + } + + return nil +} diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 8d6448d1b456e..736a66d8eb955 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -138,6 +138,11 @@ func resourceArmKeyVault() *schema.Resource { Optional: true, }, + "purge_protection_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "network_acls": { Type: schema.TypeList, Optional: true, @@ -179,6 +184,8 @@ func resourceArmKeyVault() *schema.Resource { "tags": tags.Schema(), }, + + CustomizeDiff: azure.KeyVaultCustomizeDiff, } } @@ -204,20 +211,14 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e return tf.ImportAsExistsError("azurerm_key_vault", *existing.ID) } } - - purgeSoftDeleteOnDestroy := meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy - - if purgeSoftDeleteOnDestroy { - log.Printf("[INFO] purgeSoftDeleteOnDestroy is true") - } - location := azure.NormalizeLocation(d.Get("location").(string)) tenantUUID := uuid.FromStringOrNil(d.Get("tenant_id").(string)) enabledForDeployment := d.Get("enabled_for_deployment").(bool) enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) enabledForTemplateDeployment := d.Get("enabled_for_template_deployment").(bool) - enabledForSoftDelete := d.Get("soft_delete_enabled").(bool) - enabledForPurgeProtection := d.Get("enabled_for_purge_protection").(bool) + softDeleteEnabled := d.Get("soft_delete_enabled").(bool) + purgeProtectionEnabled := d.Get("purge_protection_enabled").(bool) + t := d.Get("tags").(map[string]interface{}) networkAclsRaw := d.Get("network_acls").([]interface{}) @@ -248,14 +249,12 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e Tags: tags.Expand(t), } - // This setting can only be set if it is true, if set when value is false API returns errors - if enabledForSoftDelete { - parameters.Properties.EnableSoftDelete = &enabledForSoftDelete + // This settings can only be set if it is true, if set when value is false API returns errors + if softDeleteEnabled { + parameters.Properties.EnableSoftDelete = &softDeleteEnabled } - - // This setting can only be set if it is true, if set when value is false API returns errors - if enabledForPurgeProtection { - parameters.Properties.EnablePurgeProtection = &enabledForPurgeProtection + if purgeProtectionEnabled { + parameters.Properties.EnablePurgeProtection = &purgeProtectionEnabled } // Locking this resource so we don't make modifications to it at the same time if there is a @@ -357,7 +356,7 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) d.Set("soft_delete_enabled", props.EnableSoftDelete) - d.Set("enabled_for_purge_protection", props.EnablePurgeProtection) + d.Set("purge_protection_enabled", props.EnablePurgeProtection) d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { From 04d4a12ae4639e2411b4c87bf53120266a2d58ad Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 5 Feb 2020 06:58:37 -0600 Subject: [PATCH 038/498] Fix documentation error --- .../r/monitor_scheduled_query_rules_alert.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 19cdc7ee01488..138e4fc9b472f 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -53,8 +53,8 @@ resource "azurerm_scheduled_query_rule_alert" "example" { severity = 1 time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + operator = "GreaterThan" + threshold = 3 metric_trigger { operator = "GreaterThan" threshold = 1 @@ -86,8 +86,8 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { severity = "1" time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + operator = "GreaterThan" + threshold = 3 } } ``` From 0f89dbde8fa1aa78bd8560fcdfaf6fb26d64e9ee Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 5 Feb 2020 16:24:10 -0800 Subject: [PATCH 039/498] Working soft delete and purge --- .../keyvault/data_source_key_vault.go | 8 ++--- .../keyvault/resource_arm_key_vault.go | 35 +++++++++++++------ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault.go b/azurerm/internal/services/keyvault/data_source_key_vault.go index 6117855e4e12e..82ecb8e5f06ee 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault.go @@ -156,12 +156,12 @@ func dataSourceArmKeyVault() *schema.Resource { }, }, - "enabled_for_soft_delete": { + "purge_protection_enabled": { Type: schema.TypeBool, Computed: true, }, - "enabled_for_purge_protection": { + "soft_delete_enabled": { Type: schema.TypeBool, Computed: true, }, @@ -200,8 +200,8 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("enabled_for_deployment", props.EnabledForDeployment) d.Set("enabled_for_disk_encryption", props.EnabledForDiskEncryption) d.Set("enabled_for_template_deployment", props.EnabledForTemplateDeployment) - d.Set("enabled_for_soft_delete", props.EnableSoftDelete) - d.Set("enabled_for_purge_protection", props.EnablePurgeProtection) + d.Set("soft_delete_enabled", props.EnableSoftDelete) + d.Set("purge_protection_enabled", props.EnablePurgeProtection) d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 736a66d8eb955..eb7207f76fbc0 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -133,16 +133,6 @@ func resourceArmKeyVault() *schema.Resource { Optional: true, }, - "soft_delete_enabled": { - Type: schema.TypeBool, - Optional: true, - }, - - "purge_protection_enabled": { - Type: schema.TypeBool, - Optional: true, - }, - "network_acls": { Type: schema.TypeList, Optional: true, @@ -182,6 +172,16 @@ func resourceArmKeyVault() *schema.Resource { }, }, + "purge_protection_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + + "soft_delete_enabled": { + Type: schema.TypeBool, + Optional: true, + }, + "tags": tags.Schema(), }, @@ -211,7 +211,20 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e return tf.ImportAsExistsError("azurerm_key_vault", *existing.ID) } } + + // before creating check to see if the key vault exists in the soft delete state location := azure.NormalizeLocation(d.Get("location").(string)) + softDel, err := client.GetDeleted(ctx, name, location) + if err != nil && !utils.ResponseWasNotFound(softDel.Response) { + return fmt.Errorf("Error retrieving soft deleted Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if props := softDel.Properties; props != nil { + delDate := (*props.DeletionDate).Format(time.RFC3339) + purgeDate := (*props.ScheduledPurgeDate).Format(time.RFC3339) + return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists in the soft delete state. The key vault was soft deleted on %s and is scheduled to be purged on %s", name, resourceGroup, delDate, purgeDate) + } + tenantUUID := uuid.FromStringOrNil(d.Get("tenant_id").(string)) enabledForDeployment := d.Get("enabled_for_deployment").(bool) enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) @@ -438,7 +451,7 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } } - if d.Get("purge_on_delete").(bool) && d.Get("soft_delete_enabled").(bool) && err == nil { + if meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy { log.Printf("[DEBUG] KeyVault %s marked for purge, executing purge", name) location := d.Get("location").(string) From eab1f69d01f174a5e289f8a1c6d818674d7ad966 Mon Sep 17 00:00:00 2001 From: v-cheye Date: Thu, 6 Feb 2020 09:42:09 +0800 Subject: [PATCH 040/498] Add name validation for azurerm_role_assignment --- .../authorization/resource_arm_role_assignment.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/authorization/resource_arm_role_assignment.go b/azurerm/internal/services/authorization/resource_arm_role_assignment.go index 7afbdb0edc2cb..f11016a66c8c7 100644 --- a/azurerm/internal/services/authorization/resource_arm_role_assignment.go +++ b/azurerm/internal/services/authorization/resource_arm_role_assignment.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "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" @@ -36,10 +37,11 @@ func resourceArmRoleAssignment() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validate.GUID, }, "scope": { From 023aa56a2bfaac84ff642f09216314c3b7b5c5f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 6 Feb 2020 16:53:48 -0800 Subject: [PATCH 041/498] Complete --- azurerm/helpers/azure/key_vault.go | 28 ++++ azurerm/internal/provider/features.go | 2 +- azurerm/internal/provider/provider.go | 1 - .../keyvault/resource_arm_key_vault.go | 37 +++-- .../tests/data_source_key_vault_test.go | 11 +- .../tests/resource_arm_key_vault_test.go | 142 ++++++++---------- website/docs/d/key_vault.html.markdown | 4 +- website/docs/index.html.markdown | 10 ++ website/docs/r/key_vault.html.markdown | 23 ++- 9 files changed, 157 insertions(+), 101 deletions(-) diff --git a/azurerm/helpers/azure/key_vault.go b/azurerm/helpers/azure/key_vault.go index 3ab6c2340fe8b..f75368e5d2374 100644 --- a/azurerm/helpers/azure/key_vault.go +++ b/azurerm/helpers/azure/key_vault.go @@ -3,6 +3,7 @@ package azure import ( "context" "fmt" + "time" "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -135,3 +136,30 @@ func KeyVaultCustomizeDiff(d *schema.ResourceDiff, _ interface{}) error { return nil } + +func KeyVaultGetSoftDeletedState(ctx context.Context, client *keyvault.VaultsClient, name string, location string) (deleteDate interface{}, purgeDate interface{}, err error) { + softDel, err := client.GetDeleted(ctx, name, location) + if err != nil { + return nil, nil, fmt.Errorf("unable to get soft delete state information: %+v", err) + } + + // the logic is this way because the GetDeleted call will return an existing key vault + // that is not soft deleted, but the Deleted Vault properties will be nil + if props := softDel.Properties; props != nil { + var delDate interface{} + var purgeDate interface{} + + if dd := props.DeletionDate; dd != nil { + delDate = (*dd).Format(time.RFC3339) + } + if pg := props.ScheduledPurgeDate; pg != nil { + purgeDate = (*pg).Format(time.RFC3339) + } + if delDate != nil && purgeDate != nil { + return delDate, purgeDate, nil + } + } + + // this means we found an existing key vault that is not soft deleted + return nil, nil, nil +} diff --git a/azurerm/internal/provider/features.go b/azurerm/internal/provider/features.go index 9c0321188939b..458d6d9b35153 100644 --- a/azurerm/internal/provider/features.go +++ b/azurerm/internal/provider/features.go @@ -78,7 +78,7 @@ func expandFeatures(input []interface{}) features.UserFeatures { RollInstancesWhenRequired: true, }, KeyVault: features.KeyVaultFeatures{ - PurgeSoftDeleteOnDestroy: false, + PurgeSoftDeleteOnDestroy: true, }, } diff --git a/azurerm/internal/provider/provider.go b/azurerm/internal/provider/provider.go index 77dc218e51405..b59f0af295a3c 100644 --- a/azurerm/internal/provider/provider.go +++ b/azurerm/internal/provider/provider.go @@ -285,7 +285,6 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { } } - const resourceProviderRegistrationErrorFmt = `Error ensuring Resource Providers are registered. Terraform automatically attempts to register the Resource Providers it supports to diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index eb7207f76fbc0..6d1772756f0bc 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -198,6 +198,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) + purgeProtectionEnabled := d.Get("purge_protection_enabled").(bool) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resourceGroup, name) @@ -214,15 +215,17 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e // before creating check to see if the key vault exists in the soft delete state location := azure.NormalizeLocation(d.Get("location").(string)) - softDel, err := client.GetDeleted(ctx, name, location) - if err != nil && !utils.ResponseWasNotFound(softDel.Response) { - return fmt.Errorf("Error retrieving soft deleted Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) + delDate, purgeDate, err := azure.KeyVaultGetSoftDeletedState(ctx, client, name, location) + if err == nil { + if delDate != nil || purgeDate != nil { + return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists in the soft delete state. The key vault was soft deleted on %s and is scheduled to be purged on %s, please use the Azure CLI tool to recover this Key Vault", name, resourceGroup, delDate.(string), purgeDate.(string)) + } + return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists", name, resourceGroup) } - if props := softDel.Properties; props != nil { - delDate := (*props.DeletionDate).Format(time.RFC3339) - purgeDate := (*props.ScheduledPurgeDate).Format(time.RFC3339) - return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists in the soft delete state. The key vault was soft deleted on %s and is scheduled to be purged on %s", name, resourceGroup, delDate, purgeDate) + // check to see if they enabled purge protection and purge on destroy + if purgeProtectionEnabled && meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy { + return fmt.Errorf("conflicting properties 'purge_protection_enabled' and 'purge_soft_delete_on_destroy' are both enabled for Key Vault %q (Resource Group %q). Please disable one of these paroperties and re-apply", name, resourceGroup) } tenantUUID := uuid.FromStringOrNil(d.Get("tenant_id").(string)) @@ -230,7 +233,6 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e enabledForDiskEncryption := d.Get("enabled_for_disk_encryption").(bool) enabledForTemplateDeployment := d.Get("enabled_for_template_deployment").(bool) softDeleteEnabled := d.Get("soft_delete_enabled").(bool) - purgeProtectionEnabled := d.Get("purge_protection_enabled").(bool) t := d.Get("tags").(map[string]interface{}) @@ -417,6 +419,12 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error retrieving Key Vault %q (Resource Group %q): %+v", name, resourceGroup, err) } + // Check to see if purge protection is enabled or not... + purgeProtectionEnabled := false + if ppe := read.Properties.EnablePurgeProtection; ppe != nil { + purgeProtectionEnabled = *ppe + } + // ensure we lock on the latest network names, to ensure we handle Azure's networking layer being limited to one change at a time virtualNetworkNames := make([]string, 0) if props := read.Properties; props != nil { @@ -452,9 +460,20 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } if meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy { - log.Printf("[DEBUG] KeyVault %s marked for purge, executing purge", name) location := d.Get("location").(string) + // check to see if purge protection is enabled or not + if purgeProtectionEnabled { + delDate, purgeDate, err := azure.KeyVaultGetSoftDeletedState(ctx, client, name, location) + if err == nil { + if delDate != nil && purgeDate != nil { + return fmt.Errorf("unable to purge Key Vault %q (Resource Group %q) because it has purge protection enabled. The key vault was soft deleted on %s and is scheduled to be purged on %s", name, resourceGroup, delDate.(string), purgeDate.(string)) + } + return fmt.Errorf("unable to purge Key Vault %q (Resource Group %q) because it has purge protection enabled", name, resourceGroup) + } + } + + log.Printf("[DEBUG] KeyVault %s marked for purge, executing purge", name) future, err := client.PurgeDeleted(ctx, name, location) if err != nil { return err diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 9b33dc5a66bea..18e6526a428de 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -111,7 +111,7 @@ func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { }) } -func TestAccDataSourceAzureRMKeyVault_enable_soft_delete(t *testing.T) { +func TestAccDataSourceAzureRMKeyVault_softDelete(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_key_vault", "test") resource.Test(t, resource.TestCase{ @@ -123,10 +123,13 @@ func TestAccDataSourceAzureRMKeyVault_enable_soft_delete(t *testing.T) { Config: testAccDataSourceAzureRMKeyVault_enable_soft_delete(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_soft_delete", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_purge_protection", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "soft_delete_enabled", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "purge_protection_enabled", "false"), ), }, + { + Config: testAccAzureRMKeyVault_softDeletePurge(data), + }, }, }) } @@ -168,7 +171,7 @@ data "azurerm_key_vault" "test" { } func testAccDataSourceAzureRMKeyVault_enable_soft_delete(data acceptance.TestData) string { - r := testAccAzureRMKeyVault_enable_soft_delete(data) + r := testAccAzureRMKeyVault_softDelete(data) return fmt.Sprintf(` %s diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 94912adf292a5..087882a0fe7fb 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -331,50 +331,35 @@ func TestAccAzureRMKeyVault_justCert(t *testing.T) { }) } -func TestAccAzureRMKeyVault_soft_delete(t *testing.T) { +func TestAccAzureRMKeyVault_softDelete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") - expectedError := fmt.Sprintf("^Check failed: Check 1/1 error: Not found: %s", data.ResourceName) - errorRegEx, _ := regexp.Compile(expectedError) - resource.Test(t, resource.TestCase{ + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMKeyVaultDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMKeyVault_basic(data), + Config: testAccAzureRMKeyVault_softDelete(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), + resource.TestCheckResourceAttr(data.ResourceName, "soft_delete_enabled", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "purge_protection_enabled", "false"), ), }, { - Config: testAccAzureRMKeyVault_enable_soft_delete(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "get"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "get"), - resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_soft_delete", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "enabled_for_purge_protection", "false"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), - ), + Config: testAccAzureRMKeyVault_softDeletePurge(data), }, { - Config: testAccAzureRMKeyVault_purge_vault(data), - ExpectError: errorRegEx, + Config: testAccAzureRMKeyVault_softDelete(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "soft_delete_enabled", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "purge_protection_enabled", "false"), ), }, { - Config: testAccAzureRMKeyVault_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), - ), + Config: testAccAzureRMKeyVault_softDeletePurge(data), }, }, }) @@ -840,59 +825,6 @@ resource "azurerm_key_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMKeyVault_enable_soft_delete(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "vault%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku { - name = "premium" - } - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.client_id}" - - key_permissions = [ - "get", - ] - - secret_permissions = [ - "get", - ] - } - - enabled_for_soft_delete = true - purge_on_delete = true - - tags = { - environment = "Production" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMKeyVault_purge_vault(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} -`, data.RandomInteger, data.Locations.Primary) -} - func testAccAzureRMKeyVault_complete(data acceptance.TestData) string { return fmt.Sprintf(` data "azurerm_client_config" "current" {} @@ -1036,3 +968,57 @@ access_policy { } `, oid) } + +func testAccAzureRMKeyVault_softDelete(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +provider "azurerm" { + alias = "keyVault" + + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_key_vault" "test" { + name = "vault%d" + provider = azurerm.keyVault + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + tenant_id = "${data.azurerm_client_config.current.tenant_id}" + soft_delete_enabled = true + purge_protection_enabled = false + + sku_name = "premium" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} + +func testAccAzureRMKeyVault_softDeletePurge(data acceptance.TestData) string { + return fmt.Sprintf(` +data "azurerm_client_config" "current" {} + +provider "azurerm" { + alias = "keyVault" + + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} +`, data.RandomInteger, data.Locations.Primary) +} diff --git a/website/docs/d/key_vault.html.markdown b/website/docs/d/key_vault.html.markdown index 73bb65e0f4236..40cf255b27446 100644 --- a/website/docs/d/key_vault.html.markdown +++ b/website/docs/d/key_vault.html.markdown @@ -53,9 +53,9 @@ The following attributes are exported: * `enabled_for_template_deployment` - Can Azure Resource Manager retrieve secrets from the Key Vault? -* `enabled_for_soft_delete` - Is soft delete enabled on this Key Vault? +* `soft_delete_enabled` - Is soft delete enabled on this Key Vault? -* `enabled_for_purge_protection` - Is purge protection enabled on this Key Vault? +* `purge_protection_enabled` - Is purge protection enabled on this Key Vault? * `tags` - A mapping of tags assigned to the Key Vault. diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 5732fa2caeac2..310b2c4def1b0 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -149,12 +149,22 @@ It's possible to customise the behaviour of certain Azure Provider resources usi The `features` block supports the following: +* `key_vault` - (Optional) A `key_vault` block as defined below. + * `virtual_machine` - (Optional) A `virtual_machine` block as defined below. * `virtual_machine_scale_set` - (Optional) A `virtual_machine_scale_set` block as defined below. --- +The `key_vault` block supports the following: + +* `purge_soft_delete_on_destroy` - (Optional) Should the `azurerm_key_vault` resource be permanently deleted (e.g. purged) when destroyed? Defaults to `true`. + +~> **Note:** When purge protection is enabled, a vault or an object in the deleted state cannot be purged until the retention period has passed. + +--- + The `virtual_machine` block supports the following: * `delete_os_disk_on_deletion` - (Optional) Should the `azurerm_linux_virtual_machine` and `azurerm_windows_virtual_machine` resources delete the OS Disk attached to the Virtual Machine when the Virtual Machine is destroyed? Defaults to `true`. diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index 9bf8807beb993..4a97eac0e3d73 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -15,6 +15,16 @@ Manages a Key Vault. ## Example Usage ```hcl +provider "azurerm" { + alias = "keyVault" + + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + resource "azurerm_resource_group" "example" { name = "resourceGroup1" location = "West US" @@ -22,10 +32,13 @@ resource "azurerm_resource_group" "example" { resource "azurerm_key_vault" "example" { name = "testvault" + provider = azurerm.keyVault location = "${azurerm_resource_group.example.location}" resource_group_name = "${azurerm_resource_group.example.name}" enabled_for_disk_encryption = true tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" + soft_delete_enabled = true + purge_protection_enabled = false sku_name = "standard" @@ -83,15 +96,13 @@ The following arguments are supported: * `enabled_for_template_deployment` - (Optional) Boolean flag to specify whether Azure Resource Manager is permitted to retrieve secrets from the key vault. Defaults to `false`. -* `enabled_for_soft_delete` - (Optional) Should Soft Delete be enabled for items in this Key Vault? - --> **NOTE:** Once enabled you can not disable this setting. +* `soft_delete_enabled` - (Optional) Should Soft Delete be enabled for this Key Vault? -* `purge_on_delete` - (Optional) Boolean flag to specify if the KeyVault should be purged on delete. This purges KeyVaults enabled for soft delete on resource deletition. +-> **NOTE:** Once `soft_delete_enabled` has been enabled it is an **irreversible** action. If you want to destroy this key vault before the 90 day purge policy expires you must set the `purge_soft_delete_on_destroy` to **true** in the `key_vault` section of the azure provider `features` block. -* `enabled_for_purge_protection` - (Optional) Is Purge Protection enabled for this Key Vault? +* `purge_protection_enabled` - (Optional) Is Purge Protection enabled for this Key Vault? --> **NOTE:** Once Purge Protection has been Enabled there's currently no way to Disable it - [support for this is being tracked in this Azure API issue](https://github.com/Azure/azure-rest-api-specs/issues/8075) +-> **NOTE:** Once `purge_protection_enabled` has been enabled it is an **irreversible** action. - [support for this is being tracked in this Azure API issue](https://github.com/Azure/azure-rest-api-specs/issues/8075) * `network_acls` - (Optional) A `network_acls` block as defined below. From 7b9909c21d2e675a21ea074d90b3f308ecff139b Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 6 Feb 2020 16:59:06 -0800 Subject: [PATCH 042/498] updated or to and --- azurerm/internal/services/keyvault/resource_arm_key_vault.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 6d1772756f0bc..2b6429646558d 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -217,7 +217,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e location := azure.NormalizeLocation(d.Get("location").(string)) delDate, purgeDate, err := azure.KeyVaultGetSoftDeletedState(ctx, client, name, location) if err == nil { - if delDate != nil || purgeDate != nil { + if delDate != nil && purgeDate != nil { return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists in the soft delete state. The key vault was soft deleted on %s and is scheduled to be purged on %s, please use the Azure CLI tool to recover this Key Vault", name, resourceGroup, delDate.(string), purgeDate.(string)) } return fmt.Errorf("unable to create Key Vault %q (Resource Group %q) becauese it already exists", name, resourceGroup) From 96a36df0b80f1ea75638635f60e5fde6c15ce3ee Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 6 Feb 2020 18:45:24 -0800 Subject: [PATCH 043/498] Fix features test cases --- azurerm/internal/provider/features_test.go | 111 ++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/provider/features_test.go b/azurerm/internal/provider/features_test.go index 09be0cd828f3f..41041e6d1e342 100644 --- a/azurerm/internal/provider/features_test.go +++ b/azurerm/internal/provider/features_test.go @@ -24,10 +24,13 @@ func TestExpandFeatures(t *testing.T) { VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{ RollInstancesWhenRequired: true, }, + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: true, + }, }, }, { - Name: "Complete", + Name: "Complete Enabled", Input: []interface{}{ map[string]interface{}{ "virtual_machine": []interface{}{ @@ -40,6 +43,11 @@ func TestExpandFeatures(t *testing.T) { "roll_instances_when_required": true, }, }, + "key_vault": []interface{}{ + map[string]interface{}{ + "purge_soft_delete_on_destroy": true, + }, + }, }, }, Expected: features.UserFeatures{ @@ -49,6 +57,42 @@ func TestExpandFeatures(t *testing.T) { VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{ RollInstancesWhenRequired: true, }, + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: true, + }, + }, + }, + { + Name: "Complete Disabled", + Input: []interface{}{ + map[string]interface{}{ + "virtual_machine": []interface{}{ + map[string]interface{}{ + "delete_os_disk_on_deletion": false, + }, + }, + "virtual_machine_scale_set": []interface{}{ + map[string]interface{}{ + "roll_instances_when_required": false, + }, + }, + "key_vault": []interface{}{ + map[string]interface{}{ + "purge_soft_delete_on_destroy": false, + }, + }, + }, + }, + Expected: features.UserFeatures{ + VirtualMachine: features.VirtualMachineFeatures{ + DeleteOSDiskOnDeletion: false, + }, + VirtualMachineScaleSet: features.VirtualMachineScaleSetFeatures{ + RollInstancesWhenRequired: false, + }, + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: false, + }, }, }, } @@ -62,6 +106,71 @@ func TestExpandFeatures(t *testing.T) { } } +func TestExpandFeaturesKeyVault(t *testing.T) { + testData := []struct { + Name string + Input []interface{} + EnvVars map[string]interface{} + Expected features.UserFeatures + }{ + { + Name: "Empty Block", + Input: []interface{}{ + map[string]interface{}{ + "key_vault": []interface{}{}, + }, + }, + Expected: features.UserFeatures{ + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: true, + }, + }, + }, + { + Name: "Purge Soft Delete On Destroy Enabled", + Input: []interface{}{ + map[string]interface{}{ + "key_vault": []interface{}{ + map[string]interface{}{ + "purge_soft_delete_on_destroy": true, + }, + }, + }, + }, + Expected: features.UserFeatures{ + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: true, + }, + }, + }, + { + Name: "Purge Soft Delete On Destroy Disabled", + Input: []interface{}{ + map[string]interface{}{ + "key_vault": []interface{}{ + map[string]interface{}{ + "purge_soft_delete_on_destroy": false, + }, + }, + }, + }, + Expected: features.UserFeatures{ + KeyVault: features.KeyVaultFeatures{ + PurgeSoftDeleteOnDestroy: false, + }, + }, + }, + } + + for _, testCase := range testData { + t.Logf("[DEBUG] Test Case: %q", testCase.Name) + result := expandFeatures(testCase.Input) + if !reflect.DeepEqual(result.KeyVault, testCase.Expected.KeyVault) { + t.Fatalf("Expected %+v but got %+v", result.KeyVault, testCase.Expected.KeyVault) + } + } +} + func TestExpandFeaturesVirtualMachine(t *testing.T) { testData := []struct { Name string From 3912093b6bc472adb627d6d92905366a1bceef42 Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Thu, 6 Feb 2020 22:05:13 -0800 Subject: [PATCH 044/498] Removed sku support from datasource --- .../keyvault/data_source_key_vault.go | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault.go b/azurerm/internal/services/keyvault/data_source_key_vault.go index 82ecb8e5f06ee..e940f74ebc078 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault.go @@ -34,20 +34,6 @@ func dataSourceArmKeyVault() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "sku_name": { Type: schema.TypeString, Computed: true, @@ -205,11 +191,6 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenKeyVaultDataSourceSku(sku)); err != nil { - return fmt.Errorf("Error setting `sku` for KeyVault %q: %+v", *resp.Name, err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting `sku_name` for KeyVault %q: %+v", *resp.Name, err) } @@ -230,15 +211,6 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { return tags.FlattenAndSet(d, resp.Tags) } -// Remove in 2.0 -func flattenKeyVaultDataSourceSku(sku *keyvault.Sku) []interface{} { - result := map[string]interface{}{ - "name": string(sku.Name), - } - - return []interface{}{result} -} - func flattenKeyVaultDataSourceNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{} From b02dd08ce513cf50b51d1bef4f01195c5511bdf9 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 7 Feb 2020 15:51:31 -0800 Subject: [PATCH 045/498] Add code to skip purge if not soft deleted --- .../internal/services/keyvault/resource_arm_key_vault.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 2b6429646558d..110bd66bebe6b 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -421,9 +421,13 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { // Check to see if purge protection is enabled or not... purgeProtectionEnabled := false + softDeleteEnabled := false if ppe := read.Properties.EnablePurgeProtection; ppe != nil { purgeProtectionEnabled = *ppe } + if sde := read.Properties.EnableSoftDelete; sde != nil { + softDeleteEnabled = *sde + } // ensure we lock on the latest network names, to ensure we handle Azure's networking layer being limited to one change at a time virtualNetworkNames := make([]string, 0) @@ -459,10 +463,10 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } } - if meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy { + if meta.(*clients.Client).Features.KeyVault.PurgeSoftDeleteOnDestroy && softDeleteEnabled { location := d.Get("location").(string) - // check to see if purge protection is enabled or not + // raise an error if the key vault is in the soft delete state and purge protection is enabled if purgeProtectionEnabled { delDate, purgeDate, err := azure.KeyVaultGetSoftDeletedState(ctx, client, name, location) if err == nil { From 96f858a4757a97f3b4607f61703e315ec4dadf93 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 7 Feb 2020 16:16:13 -0800 Subject: [PATCH 046/498] Remove depricated sku from tests --- .../tests/data_source_key_vault_test.go | 6 +- .../tests/resource_arm_key_vault_key_test.go | 10 +- .../tests/resource_arm_key_vault_test.go | 113 +----------------- 3 files changed, 8 insertions(+), 121 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 18e6526a428de..5105111f4a35e 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -46,7 +46,7 @@ func TestAccDataSourceAzureRMKeyVault_basicClassic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), @@ -71,7 +71,7 @@ func TestAccDataSourceAzureRMKeyVault_complete(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "get"), @@ -97,7 +97,7 @@ func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index b8bbcf8b3969f..345f95e0b5b9a 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -727,9 +727,7 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } + sku_name = "premium" access_policy { tenant_id = "${data.azurerm_client_config.current.tenant_id}" @@ -782,10 +780,8 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } - + sku_name = "premium" + access_policy { tenant_id = "${data.azurerm_client_config.current.tenant_id}" object_id = "${data.azurerm_client_config.current.service_principal_object_id}" diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 087882a0fe7fb..2a7c4ba816fbe 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -2,7 +2,6 @@ package tests import ( "fmt" - "regexp" "testing" "github.com/hashicorp/go-azure-helpers/response" @@ -92,44 +91,6 @@ func TestAccAzureRMKeyVault_basic(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMKeyVault_basicNotDefined(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVault_basicNotDefined(data), - ExpectError: regexp.MustCompile("either 'sku_name' or 'sku' must be defined in the configuration file"), - }, - }, - }) -} - -// Remove in 2.0 -func TestAccAzureRMKeyVault_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVault_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "premium"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMKeyVault_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -488,72 +449,6 @@ resource "azurerm_key_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMKeyVault_basicNotDefined(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "vault%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.client_id}" - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMKeyVault_basicClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "vault%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku { - name = "premium" - } - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.client_id}" - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMKeyVault_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVault_basic(data) return fmt.Sprintf(` @@ -778,9 +673,7 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } + sku_name = "premium" enabled_for_deployment = true enabled_for_disk_encryption = true @@ -808,9 +701,7 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } + sku_name = "premium" access_policy = [] From b8c1418dae86a76cd404a6c5cf1bafa0ae1ddd97 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 7 Feb 2020 16:46:57 -0800 Subject: [PATCH 047/498] Fix basic test --- .../tests/data_source_key_vault_test.go | 25 ------------------- .../tests/resource_arm_key_vault_test.go | 4 --- 2 files changed, 29 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 5105111f4a35e..cb53ca59a88bc 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -33,31 +33,6 @@ func TestAccDataSourceAzureRMKeyVault_basic(t *testing.T) { }) } -func TestAccDataSourceAzureRMKeyVault_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_key_vault", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMKeyVault_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), - resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), - ), - }, - }, - }) -} - func TestAccDataSourceAzureRMKeyVault_complete(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_key_vault", "test") diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 2a7c4ba816fbe..0e5eb626b83d8 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -441,10 +441,6 @@ resource "azurerm_key_vault" "test" { "set", ] } - - tags = { - environment = "Production" - } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } From abd8429b996d9ea471b8aa76e7ebb94482c32def Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 7 Feb 2020 16:56:13 -0800 Subject: [PATCH 048/498] Fix test case lint issue --- .../services/keyvault/tests/resource_arm_key_vault_key_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index 345f95e0b5b9a..154db1d273b46 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -781,7 +781,7 @@ resource "azurerm_key_vault" "test" { tenant_id = "${data.azurerm_client_config.current.tenant_id}" sku_name = "premium" - + access_policy { tenant_id = "${data.azurerm_client_config.current.tenant_id}" object_id = "${data.azurerm_client_config.current.service_principal_object_id}" From 8b74c722c3105305f40aa1556bf620bbb48fdbec Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Fri, 7 Feb 2020 23:31:02 -0800 Subject: [PATCH 049/498] add support for static website to azurerm_storage_account --- .../services/storage/client/client.go | 6 + .../storage/resource_arm_storage_account.go | 157 ++++++++++++++++++ .../resource_arm_storage_account_test.go | 80 +++++++++ .../2018-11-09/blob/accounts/README.md | 57 +++++++ .../2018-11-09/blob/accounts/client.go | 25 +++ .../blob/accounts/get_service_properties.go | 83 +++++++++ .../2018-11-09/blob/accounts/models.go | 55 ++++++ .../blob/accounts/set_service_properties.go | 76 +++++++++ .../2018-11-09/blob/accounts/version.go | 14 ++ vendor/modules.txt | 1 + website/docs/r/storage_account.html.markdown | 20 +++ 11 files changed, 574 insertions(+) create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/README.md create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/client.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/get_service_properties.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/models.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/set_service_properties.go create mode 100644 vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/version.go diff --git a/azurerm/internal/services/storage/client/client.go b/azurerm/internal/services/storage/client/client.go index 9e0af9c918bfb..204e6f9f39ce1 100644 --- a/azurerm/internal/services/storage/client/client.go +++ b/azurerm/internal/services/storage/client/client.go @@ -10,6 +10,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" az "github.com/Azure/go-autorest/autorest/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/common" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/file/directories" @@ -24,6 +25,7 @@ type Client struct { FileSystemsClient *filesystems.Client ManagementPoliciesClient storage.ManagementPoliciesClient BlobServicesClient storage.BlobServicesClient + BlobAccountsClient *accounts.Client environment az.Environment } @@ -40,6 +42,9 @@ func NewClient(options *common.ClientOptions) *Client { blobServicesClient := storage.NewBlobServicesClientWithBaseURI(options.ResourceManagerEndpoint, options.SubscriptionId) options.ConfigureClient(&blobServicesClient.Client, options.ResourceManagerAuthorizer) + blobAccountsClient := accounts.NewWithEnvironment(options.Environment) + blobAccountsClient.Authorizer = options.StorageAuthorizer + // TODO: switch Storage Containers to using the storage.BlobContainersClient // (which should fix #2977) when the storage clients have been moved in here return &Client{ @@ -47,6 +52,7 @@ func NewClient(options *common.ClientOptions) *Client { FileSystemsClient: &fileSystemsClient, ManagementPoliciesClient: managementPoliciesClient, BlobServicesClient: blobServicesClient, + BlobAccountsClient: &blobAccountsClient, environment: options.Environment, } } diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index dda85e0d247f6..3e3d5de99f642 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -27,6 +27,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues" ) @@ -452,6 +453,40 @@ func resourceArmStorageAccount() *schema.Resource { }, }, + "blob_account_properties": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "static_website": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + "index_document": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "error_document_404_path": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + }, + }, + }, + }, + }, + "primary_location": { Type: schema.TypeString, Computed: true, @@ -822,6 +857,24 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e } } + if val, ok := d.GetOk("blob_account_properties"); ok { + // static website only supported on Storage V2 + if accountKind == string(storage.StorageV2) { + blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient + + blobAccountProperties, err := expandBlobAccountProperties(val.([]interface{})) + if err != nil { + return fmt.Errorf("Error expanding `blob_account_properties` for Azure Storage Account %q: %+v", storageAccountName, err) + } + + if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, blobAccountProperties); err != nil { + return fmt.Errorf("Error updating Azure Storage Account `blob_account_properties` %q: %+v", storageAccountName, err) + } + } else { + return fmt.Errorf("`blob_account_properties` are only supported for Storage V2.") + } + } + return resourceArmStorageAccountRead(d, meta) } @@ -1046,6 +1099,26 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("queue_properties") } + if d.HasChange("blob_account_properties") { + // static website only supported on Storage V2 + if accountKind == string(storage.StorageV2) { + blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient + + blobAccounProperties, err := expandBlobAccountProperties(d.Get("blob_account_properties").([]interface{})) + if err != nil { + return fmt.Errorf("Error expanding `blob_account_properties` for Azure Storage Account %q: %+v", storageAccountName, err) + } + + if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, blobAccounProperties); err != nil { + return fmt.Errorf("Error updating Azure Storage Account `blob_account_properties` %q: %+v", storageAccountName, err) + } + } else { + return fmt.Errorf("`blob_account_properties` are only supported for Storage V2.") + } + + d.SetPartial("blob_account_properties") + } + d.Partial(false) return resourceArmStorageAccountRead(d, meta) } @@ -1260,6 +1333,22 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } } + // static website only supported on Storage V2 + if resp.Kind == storage.StorageV2 { + blobAccountClient := storageClient.BlobAccountsClient + + blobAccountProps, err := blobAccountClient.GetServiceProperties(ctx, name) + if err != nil { + if blobAccountProps.Response.Response != nil && !utils.ResponseWasNotFound(blobAccountProps.Response) { + return fmt.Errorf("Error reading blob account properties for AzureRM Storage Account %q: %+v", name, err) + } + } + + if err := d.Set("blob_account_properties", flattenBlobAccountProperties(blobAccountProps)); err != nil { + return fmt.Errorf("Error setting `blob_account_properties `for AzureRM Storage Account %q: %+v", name, err) + } + } + return tags.FlattenAndSet(d, resp.Tags) } @@ -1553,6 +1642,45 @@ func expandQueuePropertiesCors(input []interface{}) *queues.Cors { return cors } +func expandBlobAccountProperties(input []interface{}) (accounts.StorageServiceProperties, error) { + var err error + properties := accounts.StorageServiceProperties{} + if len(input) == 0 { + return properties, nil + } + + attrs := input[0].(map[string]interface{}) + + properties.StaticWebsite, err = expandBlobAccountPropertiesStaticWebsite(attrs["static_website"].([]interface{})) + if err != nil { + return properties, fmt.Errorf("Error expanding `static_website`: %+v", err) + } + + return properties, nil +} + +func expandBlobAccountPropertiesStaticWebsite(input []interface{}) (*accounts.StaticWebsite, error) { + if len(input) == 0 { + return &accounts.StaticWebsite{}, nil + } + + staticWebsiteAttr := input[0].(map[string]interface{}) + + staticWebsite := &accounts.StaticWebsite{ + Enabled: staticWebsiteAttr["enabled"].(bool), + } + + if v, ok := staticWebsiteAttr["index_document"]; ok { + staticWebsite.IndexDocument = v.(string) + } + + if v, ok := staticWebsiteAttr["error_document_404_path"]; ok { + staticWebsite.ErrorDocument404Path = v.(string) + } + + return staticWebsite, nil +} + func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{} @@ -1729,6 +1857,35 @@ func flattenCorsProperty(input string) []interface{} { return results } +func flattenBlobAccountProperties(input accounts.GetServicePropertiesResult) []interface{} { + if input.Response.Response == nil { + return []interface{}{} + } + + blobAccountProperties := make(map[string]interface{}) + + if storageServiceProps := input.StorageServiceProperties; storageServiceProps != nil { + if staticWebsite := storageServiceProps.StaticWebsite; staticWebsite != nil { + blobAccountProperties["static_website"] = flattenBlobAccountPropertiesStaticWebsite(*staticWebsite) + } + } + + if len(blobAccountProperties) == 0 { + return []interface{}{} + } + return []interface{}{blobAccountProperties} +} + +func flattenBlobAccountPropertiesStaticWebsite(input accounts.StaticWebsite) []interface{} { + staticWebsite := make(map[string]interface{}) + + staticWebsite["enabled"] = input.Enabled + staticWebsite["index_document"] = input.IndexDocument + staticWebsite["error_document_404_path"] = input.ErrorDocument404Path + + return []interface{}{staticWebsite} +} + func flattenStorageAccountBypass(input storage.Bypass) []interface{} { bypassValues := strings.Split(string(input), ", ") bypass := make([]interface{}, len(bypassValues)) diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index 24f8b1618d89e..a3a6bbf12130b 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -653,6 +653,32 @@ func TestAccAzureRMStorageAccount_queueProperties(t *testing.T) { }) } +func TestAccAzureRMStorageAccount_blobAccountProperties(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMStorageAccount_blobAccountProperties(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMStorageAccount_blobAccountPropertiesUpdated(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMStorageAccountExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure resource group exists in API @@ -1525,3 +1551,57 @@ resource "azurerm_storage_account" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomString) } + +func testAccAzureRMStorageAccount_blobAccountProperties(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-storage-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.test.name}" + + location = "${azurerm_resource_group.test.location}" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + + blob_account_properties { + static_website { + enabled = true + index_document = "index.html" + error_document_404_path = "404.html" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} + +func testAccAzureRMStorageAccount_blobAccountPropertiesUpdated(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-storage-%d" + location = "%s" +} + +resource "azurerm_storage_account" "test" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.test.name}" + + location = "${azurerm_resource_group.test.location}" + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + + blob_account_properties { + static_website { + enabled = true + index_document = "index-2.html" + error_document_404_path = "404-2.html" + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString) +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/README.md b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/README.md new file mode 100644 index 0000000000000..a2ec7bfa9567e --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/README.md @@ -0,0 +1,57 @@ +## Blob Storage Account SDK for API version 2018-11-09 + +This package allows you to interact with the Accounts Blob Storage API + +### Supported Authorizers + +* Azure Active Directory + +### Example Usage + +```go +package main + +import ( + "context" + "fmt" + "time" + + "github.com/Azure/go-autorest/autorest" + "github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts" +) + +func Example() error { + accountName := "storageaccount1" + + // e.g. https://github.com/tombuildsstuff/giovanni/blob/76f5f686c99ecdcc3fa533a0330d0e1aacb1c327/example/azuread-auth/main.go#L54 + client, err := buildClient() + if err != nil { + return fmt.Errorf("error building client: %s", err) + } + + ctx := context.TODO() + + input := StorageServiceProperties{ + StaticWebsite: &StaticWebsite{ + Enabled: true, + IndexDocument: index, + ErrorDocument404Path: errorDocument, + }, + } + + _, err = client.SetServiceProperties(ctx, accountName, input) + if err != nil { + return fmt.Errorf("error setting properties: %s", err) + } + + time.Sleep(2 * time.Second) + + _, err = accountsClient.GetServiceProperties(ctx, accountName) + if err != nil { + return fmt.Errorf("error getting properties: %s", err) + } + + return nil +} + +``` \ No newline at end of file diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/client.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/client.go new file mode 100644 index 0000000000000..0162ebbb0c331 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/client.go @@ -0,0 +1,25 @@ +package accounts + +import ( + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" +) + +// Client is the base client for Blob Storage Blobs. +type Client struct { + autorest.Client + BaseURI string +} + +// New creates an instance of the Client client. +func New() Client { + return NewWithEnvironment(azure.PublicCloud) +} + +// NewWithBaseURI creates an instance of the Client client. +func NewWithEnvironment(environment azure.Environment) Client { + return Client{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: environment.StorageEndpointSuffix, + } +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/get_service_properties.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/get_service_properties.go new file mode 100644 index 0000000000000..0ce98e04bceb1 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/get_service_properties.go @@ -0,0 +1,83 @@ +package accounts + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/autorest/validation" + "github.com/tombuildsstuff/giovanni/storage/internal/endpoints" + "net/http" +) + +type GetServicePropertiesResult struct { + autorest.Response + + ContentType string + StorageServiceProperties *StorageServiceProperties +} + +// GetServicePropertiesPreparer prepares the GetServiceProperties request. +func (client Client) GetServicePropertiesPreparer(ctx context.Context, accountName string) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "restype": "service", + "comp": "properties", + } + + headers := map[string]interface{}{ + "x-ms-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsGet(), + autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)), + autorest.WithHeaders(headers), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +func (client Client) GetServicePropertiesSender(req *http.Request) (*http.Response, error) { + return autorest.SendWithSender(client, req, + azure.DoRetryWithRegistration(client.Client)) +} + +func (client Client) GetServicePropertiesResponder(resp *http.Response) (result GetServicePropertiesResult, err error) { + if resp != nil && resp.Header != nil { + result.ContentType = resp.Header.Get("Content-Type") + } + + err = autorest.Respond( + resp, + client.ByInspecting(), + azure.WithErrorUnlessStatusCode(http.StatusOK), + autorest.ByUnmarshallingXML(&result.StorageServiceProperties), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +func (client Client) GetServiceProperties(ctx context.Context, accountName string) (result GetServicePropertiesResult, err error) { + if accountName == "" { + return result, validation.NewError("accounts.Client", "GetServiceProperties", "`accountName` cannot be an empty string.") + } + + req, err := client.GetServicePropertiesPreparer(ctx, accountName) + if err != nil { + err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", nil, "Failure preparing request") + return + } + + resp, err := client.GetServicePropertiesSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure sending request") + return + } + + result, err = client.GetServicePropertiesResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "accounts.Client", "GetServiceProperties", resp, "Failure responding to request") + return + } + + return +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/models.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/models.go new file mode 100644 index 0000000000000..f53b68c7e254e --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/models.go @@ -0,0 +1,55 @@ +package accounts + +import "github.com/Azure/go-autorest/autorest" + +type SetServicePropertiesResult struct { + autorest.Response +} + +type StorageServiceProperties struct { + // Cors - Specifies CORS rules for the Blob service. You can include up to five CorsRule elements in the request. If no CorsRule elements are included in the request body, all CORS rules will be deleted, and CORS will be disabled for the Blob service. + Cors *CorsRules `xml:"Cors,omitempty"` + // DefaultServiceVersion - DefaultServiceVersion indicates the default version to use for requests to the Blob service if an incoming request’s version is not specified. Possible values include version 2008-10-27 and all more recent versions. + DefaultServiceVersion *string `xml:"DefaultServiceVersion,omitempty"` + // DeleteRetentionPolicy - The blob service properties for soft delete. + DeleteRetentionPolicy *DeleteRetentionPolicy `xml:"DeleteRetentionPolicy,omitempty"` + // StaticWebsite - Optional + StaticWebsite *StaticWebsite `xml:"StaticWebsite,omitempty"` +} + +type StaticWebsite struct { + // Enabled - Required. Indicates whether static website support is enabled for the given account. + Enabled bool `xml:"Enabled,omitempty"` + // IndexDocument - Optional. The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive. + IndexDocument string `xml:"IndexDocument,omitempty"` + // ErrorDocument404Path - Optional. The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive. + ErrorDocument404Path string `xml:"ErrorDocument404Path,omitempty"` +} + +// CorsRules sets the CORS rules. You can include up to five CorsRule elements in the request. +type CorsRules struct { + // CorsRules - The List of CORS rules. You can include up to five CorsRule elements in the request. + CorsRules []CorsRule `xml:"CorsRules,omitempty"` +} + +// DeleteRetentionPolicy the blob service properties for soft delete. +type DeleteRetentionPolicy struct { + // Enabled - Indicates whether DeleteRetentionPolicy is enabled for the Blob service. + Enabled bool `xml:"Enabled,omitempty"` + // Days - Indicates the number of days that the deleted blob should be retained. The minimum specified value can be 1 and the maximum value can be 365. + Days int32 `xml:"Days,omitempty"` +} + +// CorsRule specifies a CORS rule for the Blob service. +type CorsRule struct { + // AllowedOrigins - Required if CorsRule element is present. A list of origin domains that will be allowed via CORS, or "" to allow all domains + AllowedOrigins []string `xml:"AllowedOrigins,omitempty"` + // AllowedMethods - Required if CorsRule element is present. A list of HTTP methods that are allowed to be executed by the origin. + AllowedMethods []string `xml:"AllowedMethods,omitempty"` + // MaxAgeInSeconds - Required if CorsRule element is present. The number of seconds that the client/browser should cache a preflight response. + MaxAgeInSeconds int32 `xml:"MaxAgeInSeconds,omitempty"` + // ExposedHeaders - Required if CorsRule element is present. A list of response headers to expose to CORS clients. + ExposedHeaders []string `xml:"ExposedHeaders,omitempty"` + // AllowedHeaders - Required if CorsRule element is present. A list of headers allowed to be part of the cross-origin request. + AllowedHeaders []string `xml:"AllowedHeaders,omitempty"` +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/set_service_properties.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/set_service_properties.go new file mode 100644 index 0000000000000..a11178c6b7ca9 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/set_service_properties.go @@ -0,0 +1,76 @@ +package accounts + +import ( + "context" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/azure" + "github.com/Azure/go-autorest/autorest/validation" + "github.com/tombuildsstuff/giovanni/storage/internal/endpoints" + "net/http" +) + +// SetServicePropertiesSender sends the SetServiceProperties request. The method will close the +// http.Response Body if it receives an error. +func (client Client) SetServicePropertiesSender(req *http.Request) (*http.Response, error) { + return autorest.SendWithSender(client, req, + azure.DoRetryWithRegistration(client.Client)) +} + +// SetServicePropertiesPreparer prepares the SetServiceProperties request. +func (client Client) SetServicePropertiesPreparer(ctx context.Context, accountName string, input StorageServiceProperties) (*http.Request, error) { + queryParameters := map[string]interface{}{ + "restype": "service", + "comp": "properties", + } + + headers := map[string]interface{}{ + "x-ms-version": APIVersion, + } + + preparer := autorest.CreatePreparer( + autorest.AsPut(), + autorest.WithBaseURL(endpoints.GetBlobEndpoint(client.BaseURI, accountName)), + autorest.WithHeaders(headers), + autorest.WithXML(input), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +// SetServicePropertiesResponder handles the response to the SetServiceProperties request. The method always +// closes the http.Response Body. +func (client Client) SetServicePropertiesResponder(resp *http.Response) (result SetServicePropertiesResult, err error) { + err = autorest.Respond( + resp, + client.ByInspecting(), + azure.WithErrorUnlessStatusCode(http.StatusAccepted), + autorest.ByClosing()) + result.Response = autorest.Response{Response: resp} + return +} + +func (client Client) SetServiceProperties(ctx context.Context, accountName string, input StorageServiceProperties) (result SetServicePropertiesResult, err error) { + if accountName == "" { + return result, validation.NewError("accounts.Client", "SetServiceProperties", "`accountName` cannot be an empty string.") + } + + req, err := client.SetServicePropertiesPreparer(ctx, accountName, input) + if err != nil { + err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", nil, "Failure preparing request") + return + } + + resp, err := client.SetServicePropertiesSender(req) + if err != nil { + result.Response = autorest.Response{Response: resp} + err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure sending request") + return + } + + result, err = client.SetServicePropertiesResponder(resp) + if err != nil { + err = autorest.NewErrorWithError(err, "accounts.Client", "SetServiceProperties", resp, "Failure responding to request") + return + } + + return +} diff --git a/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/version.go b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/version.go new file mode 100644 index 0000000000000..a097015cc6516 --- /dev/null +++ b/vendor/github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts/version.go @@ -0,0 +1,14 @@ +package accounts + +import ( + "fmt" + + "github.com/tombuildsstuff/giovanni/version" +) + +// APIVersion is the version of the API used for all Storage API Operations +const APIVersion = "2018-11-09" + +func UserAgent() string { + return fmt.Sprintf("tombuildsstuff/giovanni/%s storage/%s", version.Number, APIVersion) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f56e6c6c869f4..1b3cfc4f959fa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -328,6 +328,7 @@ github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/tf github.com/terraform-providers/terraform-provider-azuread/azuread/helpers/validate github.com/terraform-providers/terraform-provider-azuread/version # github.com/tombuildsstuff/giovanni v0.7.1 +github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/accounts github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers github.com/tombuildsstuff/giovanni/storage/2018-11-09/datalakestore/filesystems diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index b62d07a008e06..1230f62201362 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -117,6 +117,10 @@ The following arguments are supported: ~> **NOTE:** `queue_properties` cannot be set when the `access_tier` is set to `BlobStorage` +* `blob_account_properties` - (Optional) A `blob_account_properties` block as defined below. + +~> **NOTE:** `blob_account_properties` can only be set when the `account_kind` is set to `StorageV2` + * `network_rules` - (Optional) A `network_rules` block as documented below. * `tags` - (Optional) A mapping of tags to assign to the resource. @@ -229,6 +233,22 @@ A `queue_properties` block supports the following: * `hour_metrics` - (Optional) A `hour_metrics` block as defined below. +--- + +A `blob_account_properties` block supports the following: + +* `static_website` - (Optional) A `static_website` block as defined below. + +--- + +A `static_website` block supports the following: + +* `enabled` - (Required) Indicates whether static website support is enabled for the given account. + +* `index_document` - (Optional) The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive. + +* `error_document_404_path` - (Optional) The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive. + ## Attributes Reference The following attributes are exported in addition to the arguments listed above: From 1ec60bbb746e6c60490b7bc390f8312b6df7b453 Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Sat, 8 Feb 2020 12:18:22 -0800 Subject: [PATCH 050/498] update storage account static website docs --- website/docs/r/storage_account.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 1230f62201362..6dddfe6e71bc8 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -243,11 +243,11 @@ A `blob_account_properties` block supports the following: A `static_website` block supports the following: -* `enabled` - (Required) Indicates whether static website support is enabled for the given account. +* `enabled` - (Required) Indicates whether static website support is enabled for the given account. If a blob storage container named $web doesn't already exist in the account, one is created for you. Add the files of your site to this container. * `index_document` - (Optional) The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive. -* `error_document_404_path` - (Optional) The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive. +* `error_document_404_path` - (Optional) The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive. If the server returns a 404 error, and you have not specified an error document, then a default 404 page is returned to the user. ## Attributes Reference From 78ddff0e1414137012469a749202ec2032b9b6d8 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 8 Feb 2020 22:40:43 -0600 Subject: [PATCH 051/498] Add monitor helpers --- azurerm/helpers/azure/monitor.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 azurerm/helpers/azure/monitor.go diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go new file mode 100644 index 0000000000000..7303e4d52ded7 --- /dev/null +++ b/azurerm/helpers/azure/monitor.go @@ -0,0 +1,32 @@ +package azure + +import ( + "fmt" + "strings" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "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/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +// ValidateThreshold checks that a threshold value is between 0 and 10000 +// and is a whole number. The azure-sdk-for-go expects this value to be a float64 +// but the user validation rules want an integer. +func ValidateThreshold(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(float64) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be float64", k)) + } + + if v != float64(int64(v)) { + errors = append(errors, fmt.Errorf("%q must be a whole number", k)) + } + + if v < 0 || v > 10000 { + errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 inclusive", k)) + } + + return warnings, errors +} From e9ce2439140c8b164a832cecfad1e7de18e488c5 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sun, 9 Feb 2020 21:16:30 -0600 Subject: [PATCH 052/498] First pass address latest review --- azurerm/helpers/azure/monitor.go | 11 +- ...ta_source_monitor_scheduled_query_rules.go | 96 ------ ...rce_monitor_scheduled_query_rules_alert.go | 87 +++++- ...ource_monitor_scheduled_query_rules_log.go | 78 ++++- ...ource_arm_monitor_scheduled_query_rules.go | 207 ------------- ...arm_monitor_scheduled_query_rules_alert.go | 288 +++++++++++++++--- ...e_arm_monitor_scheduled_query_rules_log.go | 203 ++++++++++-- ...onitor_scheduled_query_rules_alert_test.go | 12 +- ..._monitor_scheduled_query_rules_log_test.go | 6 +- website/azurerm.erb | 16 + ..._scheduled_query_rules_alert.html.markdown | 26 +- ...or_scheduled_query_rules_log.html.markdown | 10 +- ..._scheduled_query_rules_alert.html.markdown | 20 +- ...or_scheduled_query_rules_log.html.markdown | 7 +- 14 files changed, 619 insertions(+), 448 deletions(-) delete mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go index 7303e4d52ded7..f5bf82a5bcf26 100644 --- a/azurerm/helpers/azure/monitor.go +++ b/azurerm/helpers/azure/monitor.go @@ -2,19 +2,12 @@ package azure import ( "fmt" - "strings" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "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/validate" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) // ValidateThreshold checks that a threshold value is between 0 and 10000 // and is a whole number. The azure-sdk-for-go expects this value to be a float64 // but the user validation rules want an integer. -func ValidateThreshold(i interface{}, k string) (warnings []string, errors []error) { +func ValidateMonitorScheduledQueryRulesAlertThreshold(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(float64) if !ok { errors = append(errors, fmt.Errorf("expected type of %q to be float64", k)) @@ -25,7 +18,7 @@ func ValidateThreshold(i interface{}, k string) (warnings []string, errors []err } if v < 0 || v > 10000 { - errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 inclusive", k)) + errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 (inclusive)", k)) } return warnings, errors diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go deleted file mode 100644 index 72380eedcbd34..0000000000000 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go +++ /dev/null @@ -1,96 +0,0 @@ -package monitor - -import ( - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go index c7dc42763af8b..cc535fed14527 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -1,16 +1,22 @@ package monitor import ( + "fmt" + "strconv" "time" + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesAlertRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -72,14 +78,6 @@ func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeInt, Computed: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, "query": { Type: schema.TypeString, Computed: true, @@ -145,3 +143,74 @@ func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, } } + +func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + action, ok := resp.Action.(insights.AlertingAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index 4a864f0f19f26..bad7e1f79797b 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -1,16 +1,21 @@ package monitor import ( + "fmt" "time" + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesLogRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -80,18 +85,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Computed: true, - }, "query_type": { Type: schema.TypeString, Computed: true, @@ -101,3 +94,62 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { }, } } + +func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + action, ok := resp.Action.(insights.LogToMetricAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go deleted file mode 100644 index b7661870314a0..0000000000000 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go +++ /dev/null @@ -1,207 +0,0 @@ -package monitor - -import ( - "fmt" - "log" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" - "github.com/hashicorp/terraform-plugin-sdk/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/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}, action insights.BasicAction, schedule *insights.Schedule) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - source := expandMonitorScheduledQueryRulesSource(d) - - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil -} - -func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query, ok := d.Get("query").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - if ok { - source.Query = utils.String(query) - } - - return &source -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index cee4212d9823b..3fb0fa6c8317d 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -1,24 +1,30 @@ package monitor import ( + "fmt" + "log" "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "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/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "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/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, + Read: resourceArmMonitorScheduledQueryRulesAlertRead, Update: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Delete: resourceArmMonitorScheduledQueryRulesAlertDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -35,7 +41,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringDoesNotContainAny("<>*%&:\\?+/"), }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -70,8 +76,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: validation.StringIsJSON, }, "email_subject": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -82,8 +89,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: azure.ValidateResourceID, }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 4096), }, "enabled": { Type: schema.TypeBool, @@ -91,20 +99,14 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Default: true, }, "frequency": { - Type: schema.TypeInt, - Optional: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(5, 1440), }, "query": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "query_type": { Type: schema.TypeString, @@ -115,27 +117,23 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, false), }, "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 4), }, "throttling": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 10000), }, "time_window": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(5, 2880), }, "trigger": { Type: schema.TypeSet, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_trigger": { @@ -144,8 +142,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_column": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "metric_trigger_type": { Type: schema.TypeString, @@ -167,7 +166,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { "threshold": { Type: schema.TypeFloat, Required: true, - ValidateFunc: validation.NoZeroValues, + ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -182,8 +181,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, false), }, "threshold": { - Type: schema.TypeFloat, - Required: true, + Type: schema.TypeFloat, + Required: true, + ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -197,8 +197,170 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { action := expandMonitorScheduledQueryRulesAlertingAction(d) schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if *schedule.TimeWindowInMinutes < *schedule.FrequencyInMinutes { + return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): time_window must be greater than or equal to frequency", name, resourceGroup) + } + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesAlertSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesAlertRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + action, ok := resp.Action.(insights.AlertingAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } - return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesAlertDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil } func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { @@ -225,10 +387,19 @@ func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *ins func expandMonitorScheduledQueryRulesAlertAction(input []interface{}) *insights.AzNsActionGroup { result := insights.AzNsActionGroup{} + if len(input) == 0 { + return &result + } for _, item := range input { - v := item.(map[string]interface{}) - actionGroups := v["action_group"].(*schema.Set).List() + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } + actionGroups := v["action_group"].(*schema.Set).List() result.ActionGroup = utils.ExpandStringSlice(actionGroups) result.EmailSubject = utils.String(v["email_subject"].(string)) result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) @@ -244,7 +415,13 @@ func expandMonitorScheduledQueryRulesAlertMetricTrigger(input []interface{}) *in result := insights.LogMetricTrigger{} for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) result.Threshold = utils.Float(v["threshold"].(float64)) result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) @@ -266,11 +443,34 @@ func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insi return &schedule } +func expandMonitorScheduledQueryRulesAlertSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query := d.Get("query").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + Query: utils.String(query), + QueryType: insights.ResultCount, + } + + return &source +} + func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} + if len(input) == 0 { + return &result + } for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 65c464e01f3ae..f9537f6a7306e 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -1,23 +1,29 @@ package monitor import ( + "fmt" + "log" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "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/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "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/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, + Read: resourceArmMonitorScheduledQueryRulesLogRead, Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Delete: resourceArmMonitorScheduledQueryRulesLogDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -34,7 +40,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringDoesNotContainAny("<>*%&:\\?+/"), }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -63,7 +69,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, "operator": { Type: schema.TypeString, @@ -78,7 +84,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -87,7 +93,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "metric_name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -98,22 +104,15 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { ValidateFunc: azure.ValidateResourceID, }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 4096), }, "enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, "tags": tags.Schema(), }, @@ -123,17 +122,169 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { action := expandMonitorScheduledQueryRulesLogToMetricAction(d) - return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, nil) + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesLogSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + action, ok := resp.Action.(insights.LogToMetricAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil } func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { criteria := make([]insights.Criteria, 0) + if len(input) == 0 { + return &criteria + } + for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } dimensions := make([]insights.Dimension, 0) for _, dimension := range v["dimension"].(*schema.Set).List() { - dVal := dimension.(map[string]interface{}) + if dimension == nil { + continue + } + dVal, ok := dimension.(map[string]interface{}) + if !ok { + continue + } dimensions = append(dimensions, insights.Dimension{ Name: utils.String(dVal["name"].(string)), Operator: utils.String(dVal["operator"].(string)), @@ -161,6 +312,18 @@ func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) * return &action } +func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + + return &source +} + func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { result := make([]interface{}, 0) diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index bedb59a884560..a558a53593667 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -26,11 +26,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } @@ -49,11 +45,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 2fc2efdd82f98..0706ca5810786 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -25,11 +25,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } diff --git a/website/azurerm.erb b/website/azurerm.erb index f9251797f18bc..7553baf65cf40 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -298,6 +298,14 @@ azurerm_monitor_log_profile +
  • + azurerm_monitor_scheduled_query_rules_alert +
  • + +
  • + azurerm_monitor_scheduled_query_rules_log +
  • +
  • azurerm_mssql_elasticpool
  • @@ -1703,6 +1711,14 @@
  • azurerm_metric_alertrule
  • + +
  • + azurerm_monitor_scheduled_query_rules_alert +
  • + +
  • + azurerm_monitor_scheduled_query_rules_log +
  • diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 1998f0670646c..7e513bf3c885a 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -26,23 +26,23 @@ output "query_rule_id" { ## Argument Reference * `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. +* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. * `action` - An `action` block as defined below. * `authorized_resource_ids` - List of Resource IDs referred into query. -* `data_source_id` - The resource uri over which log search query is to be run. +* `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. -* `frequency` - Frequency (in minutes) at which rule condition should be evaluated. -* `query` - Log search query. Required for action type - `alerting_action`. +* `frequency` - Frequency at which rule condition should be evaluated. +* `query` - Log search query. * `query_type` - Must equal "ResultCount". -* `time_window` - Time window for which data needs to be fetched for query (should be greater than or equal to frequency_in_minutes). -* `severity` - Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. -* `trigger` - A `trigger` block as defined below. The condition that results in the alert rule being run. +* `time_window` - Time window for which data needs to be fetched for query. +* `severity` - Severity of the alert. +* `throttling` - Time for which alerts should be throttled or suppressed. +* `trigger` - A `trigger` block as defined below. --- @@ -50,21 +50,21 @@ output "query_rule_id" { * `action_group` - List of action group reference resource IDs. * `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. -* `email_subject` - Custom subject override for all email ids in Azure action group. +* `email_subject` - Custom subject override for all email IDs in Azure action group. --- `metricTrigger` supports the following: * `metricColumn` - Evaluation of metric on a particular column. -* `metricTriggerType` - Metric Trigger Type - 'Consecutive' or 'Total'. -* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `metricTriggerType` - The metric trigger type. +* `operator` - Evaluation operation for rule. * `threshold` - The threshold of the metric trigger. --- `trigger` supports the following: -* `metricTrigger` - A `metricTrigger` block as defined above. Trigger condition for metric query rule. -* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `metricTrigger` - A `metricTrigger` block as defined above. +* `operator` - Evaluation operation for rule. * `threshold` - Result or count threshold based on which rule should be triggered. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index 3633ba24d57f5..af8890e478d20 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -26,16 +26,16 @@ output "query_rule_id" { ## Argument Reference * `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. +* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. * `criteria` - A `criteria` block as defined below. -* `data_source_id` - The resource uri over which log search query is to be run. +* `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this scheduled query rule is enabled. -* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. +* `enabled` - Whether this Scheduled Query Rule is enabled. +* `throttling` - Time for which alerts should be throttled or suppressed. --- @@ -49,5 +49,5 @@ output "query_rule_id" { `dimension` supports the following: * `name` - Name of the dimension. -* `operator` - Operator for dimension values, - 'Include'. +* `operator` - Operator for dimension values. * `values` - List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 138e4fc9b472f..647252ecd1e2a 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -49,7 +49,6 @@ resource "azurerm_scheduled_query_rule_alert" "example" { enabled = true frequency = 5 query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" - query_type = "ResultCount" severity = 1 time_window = 30 trigger { @@ -82,7 +81,6 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { enabled = true frequency = 5 query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" severity = "1" time_window = 30 trigger { @@ -98,18 +96,16 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `data_source_id` - (Required) The resource URI over which log search query is to be run. +* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. Values must be between 5 and 1440 (inclusive). +* `time_window` - (Required) Time window for which data needs to be fetched for query (must be greater than or equal to `frequency`). Values must be between 5 and 2880 (inclusive). +* `trigger` - (Required) The condition that results in the alert rule being run. * `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. * `action` - (Optional) An `action` block as defined below. -* `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. -* `query` - (Required) Log search query. -* `query_type` - (Required) Must equal "ResultCount" for now. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `time_window` - (Required) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. -* `trigger` - (Required) The condition that results in the alert rule being run. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 (inclusive). --- @@ -126,7 +122,7 @@ The following arguments are supported: * `metricColumn` - (Required) Evaluation of metric on a particular column. * `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. * `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) The threshold of the metric trigger. +* `threshold` - (Required) The threshold of the metric trigger. Values must be between 0 and 10000 inclusive. --- @@ -134,15 +130,13 @@ The following arguments are supported: * `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. * `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) Result or count threshold based on which rule should be triggered. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. Values must be between 0 and 10000 inclusive. ## Attributes Reference The following attributes are exported: * `id` - The ID of the Scheduled Query Rule. -* `last_updated_time` - Last time the rule was updated in IS08601 format. -* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' ## Import diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 7870b2c8d436e..48beb3b33359c 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -54,14 +54,15 @@ The following arguments are supported: * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 ( +inclusive). --- `criteria` supports the following: * `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. +* `metric_name` - (Required) Name of the metric. Supported metrics are listed in the Azure Monitor [Microsoft.OperationalInsights/workspaces](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported#microsoftoperationalinsightsworkspaces) metrics namespace. --- @@ -76,8 +77,6 @@ The following arguments are supported: The following attributes are exported: * `id` - The ID of the Scheduled Query Rule. -* `last_updated_time` - Last time the rule was updated in IS08601 format. -* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' ## Import From 6be137739e53937b60323d83141bc7255263195f Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Feb 2020 14:31:25 -0600 Subject: [PATCH 053/498] Updated to include TRIAL as a SKU Referencing PR 5652 https://github.com/terraform-providers/terraform-provider-azurerm/pull/5652 --- website/docs/r/databricks_workspace.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/databricks_workspace.html.markdown b/website/docs/r/databricks_workspace.html.markdown index c200849e8574b..51b169e76dea1 100644 --- a/website/docs/r/databricks_workspace.html.markdown +++ b/website/docs/r/databricks_workspace.html.markdown @@ -40,7 +40,7 @@ The following arguments are supported: * `location` - (Required) Specifies the supported Azure location where the resource has to be created. Changing this forces a new resource to be created. -* `sku` - (Required) The `sku` to use for the Databricks Workspace. Possible values are `standard` or `premium`. Changing this forces a new resource to be created. +* `sku` - (Required) The `sku` to use for the Databricks Workspace. Possible values are `standard`, `premium`, or `trial`. Changing this forces a new resource to be created. * `managed_resource_group_name` - (Optional) The name of the resource group where Azure should place the managed Databricks resources. Changing this forces a new resource to be created. From d1cf0b73d3e95f3c1c1191dca109f3f2d27dedac Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 10 Feb 2020 13:58:39 -0800 Subject: [PATCH 054/498] Initial port to new code base --- .../storage/data_source_storage_account.go | 27 -- .../storage/resource_arm_storage_account.go | 76 ---- ...arm_storage_account_encryption_settings.go | 327 +++++++++++++++++ ...torage_account_encryption_settings_test.go | 341 ++++++++++++++++++ .../resource_arm_storage_account_test.go | 155 -------- website/docs/r/storage_account.html.markdown | 6 - ..._account_encryption_settings.html.markdown | 133 +++++++ 7 files changed, 801 insertions(+), 264 deletions(-) create mode 100644 azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go create mode 100644 azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go create mode 100644 website/docs/r/storage_account_encryption_settings.html.markdown diff --git a/azurerm/internal/services/storage/data_source_storage_account.go b/azurerm/internal/services/storage/data_source_storage_account.go index ba8d8770769eb..6239a3385a1df 100644 --- a/azurerm/internal/services/storage/data_source_storage_account.go +++ b/azurerm/internal/services/storage/data_source_storage_account.go @@ -54,11 +54,6 @@ func dataSourceArmStorageAccount() *schema.Resource { Computed: true, }, - "account_encryption_source": { - Type: schema.TypeString, - Computed: true, - }, - "custom_domain": { Type: schema.TypeList, Computed: true, @@ -73,16 +68,6 @@ func dataSourceArmStorageAccount() *schema.Resource { }, }, - "enable_blob_encryption": { - Type: schema.TypeBool, - Computed: true, - }, - - "enable_file_encryption": { - Type: schema.TypeBool, - Computed: true, - }, - "enable_https_traffic_only": { Type: schema.TypeBool, Computed: true, @@ -330,18 +315,6 @@ func dataSourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) e } } - if encryption := props.Encryption; encryption != nil { - if services := encryption.Services; services != nil { - if blob := services.Blob; blob != nil { - d.Set("enable_blob_encryption", blob.Enabled) - } - if file := services.File; file != nil { - d.Set("enable_file_encryption", file.Enabled) - } - } - d.Set("account_encryption_source", string(encryption.KeySource)) - } - // Computed d.Set("primary_location", props.PrimaryLocation) d.Set("secondary_location", props.SecondaryLocation) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index dda85e0d247f6..c6a48bd2caacb 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -122,17 +122,6 @@ func resourceArmStorageAccount() *schema.Resource { }, true), }, - "account_encryption_source": { - Type: schema.TypeString, - Optional: true, - Default: string(storage.MicrosoftStorage), - ValidateFunc: validation.StringInSlice([]string{ - string(storage.MicrosoftKeyvault), - string(storage.MicrosoftStorage), - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - "custom_domain": { Type: schema.TypeList, Optional: true, @@ -153,18 +142,6 @@ func resourceArmStorageAccount() *schema.Resource { }, }, - "enable_blob_encryption": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - - "enable_file_encryption": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "enable_https_traffic_only": { Type: schema.TypeBool, Optional: true, @@ -672,15 +649,12 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e accountKind := d.Get("account_kind").(string) location := azure.NormalizeLocation(d.Get("location").(string)) t := d.Get("tags").(map[string]interface{}) - enableBlobEncryption := d.Get("enable_blob_encryption").(bool) - enableFileEncryption := d.Get("enable_file_encryption").(bool) enableHTTPSTrafficOnly := d.Get("enable_https_traffic_only").(bool) isHnsEnabled := d.Get("is_hns_enabled").(bool) accountTier := d.Get("account_tier").(string) replicationType := d.Get("account_replication_type").(string) storageType := fmt.Sprintf("%s_%s", accountTier, replicationType) - storageAccountEncryptionSource := d.Get("account_encryption_source").(string) parameters := storage.AccountCreateParameters{ Location: &location, @@ -691,15 +665,6 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e Kind: storage.Kind(accountKind), AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{ Encryption: &storage.Encryption{ - Services: &storage.EncryptionServices{ - Blob: &storage.EncryptionService{ - Enabled: utils.Bool(enableBlobEncryption), - }, - File: &storage.EncryptionService{ - Enabled: utils.Bool(enableFileEncryption), - }}, - KeySource: storage.KeySource(storageAccountEncryptionSource), - }, EnableHTTPSTrafficOnly: &enableHTTPSTrafficOnly, NetworkRuleSet: expandStorageAccountNetworkRules(d), IsHnsEnabled: &isHnsEnabled, @@ -903,35 +868,6 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("tags") } - if d.HasChange("enable_blob_encryption") || d.HasChange("enable_file_encryption") { - encryptionSource := d.Get("account_encryption_source").(string) - - opts := storage.AccountUpdateParameters{ - AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ - Encryption: &storage.Encryption{ - Services: &storage.EncryptionServices{}, - KeySource: storage.KeySource(encryptionSource), - }, - }, - } - - if d.HasChange("enable_blob_encryption") { - enableEncryption := d.Get("enable_blob_encryption").(bool) - opts.Encryption.Services.Blob = &storage.EncryptionService{ - Enabled: utils.Bool(enableEncryption), - } - - d.SetPartial("enable_blob_encryption") - } - - if d.HasChange("enable_file_encryption") { - enableEncryption := d.Get("enable_file_encryption").(bool) - opts.Encryption.Services.File = &storage.EncryptionService{ - Enabled: utils.Bool(enableEncryption), - } - d.SetPartial("enable_file_encryption") - } - if _, err := client.Update(ctx, resourceGroupName, storageAccountName, opts); err != nil { return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) } @@ -1122,18 +1058,6 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } } - if encryption := props.Encryption; encryption != nil { - if services := encryption.Services; services != nil { - if blob := services.Blob; blob != nil { - d.Set("enable_blob_encryption", blob.Enabled) - } - if file := services.File; file != nil { - d.Set("enable_file_encryption", file.Enabled) - } - } - d.Set("account_encryption_source", string(encryption.KeySource)) - } - // Computed d.Set("primary_location", props.PrimaryLocation) d.Set("secondary_location", props.SecondaryLocation) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go new file mode 100644 index 0000000000000..d536707a7398e --- /dev/null +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -0,0 +1,327 @@ +package azurerm + +import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" + "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/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmStorageAccountEncryptionSettings() *schema.Resource { + return &schema.Resource{ + Read: resourceArmStorageAccountEncryptionSettingsRead, + Create: resourceArmStorageAccountEncryptionSettingsCreateUpdate, + Update: resourceArmStorageAccountEncryptionSettingsCreateUpdate, + Delete: resourceArmStorageAccountEncryptionSettingsDelete, + + Importer: &schema.ResourceImporter{ + State: resourceArmStorageAccountEncryptionSettingsImportState, + }, + SchemaVersion: 2, + + Schema: map[string]*schema.Schema{ + "storage_account_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "enable_blob_encryption": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "enable_file_encryption": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "key_vault": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // This attribute is not used, it was only added + // to create a dependency between this resource + // and the key vault policy + "key_vault_policy_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "key_vault_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "key_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "key_version": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "key_vault_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceData, meta interface{}) error { + ctx := meta.(*ArmClient).StopContext + vaultClient := meta.(*ArmClient).keyVaultClient + client := meta.(*ArmClient).storageServiceClient + + storageAccountId := d.Get("storage_account_id").(string) + + id, err := azure.ParseAzureResourceID(storageAccountId) + if err != nil { + return err + } + + storageAccountName := id.Path["storageAccounts"] + resourceGroupName := id.ResourceGroup + + // set default values for the attributes + enableBlobEncryption := true + enableFileEncryption := true + + // create the update object with the default values + opts := storage.AccountUpdateParameters{ + AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ + Encryption: &storage.Encryption{ + Services: &storage.EncryptionServices{ + Blob: &storage.EncryptionService{ + Enabled: utils.Bool(enableBlobEncryption), + }, + File: &storage.EncryptionService{ + Enabled: utils.Bool(enableFileEncryption), + }}, + KeySource: storage.MicrosoftStorage, + KeyVaultProperties: &storage.KeyVaultProperties{}, + }, + }, + } + + if d.HasChange("enable_blob_encryption") || d.HasChange("enable_file_encryption") { + opts.Encryption.Services.Blob.Enabled = utils.Bool(d.Get("enable_blob_encryption").(bool)) + opts.Encryption.Services.File.Enabled = utils.Bool(d.Get("enable_file_encryption").(bool)) + } + + if keyVaultProperties := expandAzureRmStorageAccountKeyVaultProperties(d); keyVaultProperties.KeyName != utils.String("") { + if v, ok := d.GetOk("key_vault.0.key_vault_id"); ok { + // Get the key vault base URL from the key vault + keyVaultId := v.(string) + pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + + if err != nil { + return fmt.Errorf("Error looking up Key Vault URI from id %q: %+v", keyVaultId, err) + } + + keyVaultProperties.KeyVaultURI = utils.String(pKeyVaultBaseUrl) + opts.Encryption.KeyVaultProperties = keyVaultProperties + opts.Encryption.KeySource = storage.MicrosoftKeyvault + } + } + + _, err = client.Update(ctx, resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) + } + + resourceId := fmt.Sprintf("%s/encryptionSettings", storageAccountId) + d.SetId(resourceId) + + return resourceArmStorageAccountEncryptionSettingsRead(d, meta) +} + +func resourceArmStorageAccountEncryptionSettingsRead(d *schema.ResourceData, meta interface{}) error { + ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).storageServiceClient + + storageAccountId := d.Get("storage_account_id").(string) + + id, err := parseAzureResourceID(storageAccountId) + if err != nil { + return err + } + name := id.Path["storageAccounts"] + resGroup := id.ResourceGroup + + resp, err := client.GetProperties(ctx, resGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %+v", name, err) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if services := encryption.Services; services != nil { + if blob := services.Blob; blob != nil { + d.Set("enable_blob_encryption", blob.Enabled) + } + if file := services.File; file != nil { + d.Set("enable_file_encryption", file.Enabled) + } + } + + if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { + keyVaultId := d.Get("key_vault.0.key_vault_id").(string) + keyVaultPolicyId := d.Get("key_vault.0.key_vault_policy_id").(string) + + if err := d.Set("key_vault", flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties, keyVaultId, keyVaultPolicyId)); err != nil { + return fmt.Errorf("Error flattening `key_vault_properties`: %+v", err) + } + } + } + } + + return nil +} + +func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, meta interface{}) error { + ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).storageServiceClient + + storageAccountId := d.Get("storage_account_id").(string) + + id, err := azure.ParseAzureResourceID(storageAccountId) + if err != nil { + return err + } + + storageAccountName := id.Path["storageAccounts"] + resourceGroupName := id.ResourceGroup + + // Since this isn't a real object, just modifying an existing object + // "Delete" doesn't really make sense it should really be a "Revert to Default" + // So instead of the Delete func actually deleting the Storage Account I am + // making it reset the Storage Account to it's default state + opts := storage.AccountUpdateParameters{ + AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ + Encryption: &storage.Encryption{ + KeySource: storage.MicrosoftStorage, + }, + }, + } + + _, err = client.Update(ctx, resourceGroupName, storageAccountName, opts) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) + } + + return nil +} + +func resourceArmStorageAccountEncryptionSettingsImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).storageServiceClient + + id := d.Id() + + d.Set("storage_account_id", id) + + saId, err := parseAzureResourceID(id) + if err != nil { + return nil, err + } + name := saId.Path["storageAccounts"] + resGroup := saId.ResourceGroup + + resp, err := client.GetProperties(ctx, resGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil, nil + } + return nil, fmt.Errorf("Error importing the state of AzureRM Storage Account %q: %+v", name, err) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if services := encryption.Services; services != nil { + if blob := services.Blob; blob != nil { + d.Set("enable_blob_encryption", blob.Enabled) + } + if file := services.File; file != nil { + d.Set("enable_file_encryption", file.Enabled) + } + } + + if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { + if err := d.Set("key_vault", flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties, "", "")); err != nil { + return nil, fmt.Errorf("Error flattening `key_vault_properties` on import: %+v", err) + } + } + } + } + + resourceId := fmt.Sprintf("%s/encryptionSettings", id) + d.SetId(resourceId) + + results := make([]*schema.ResourceData, 1) + + results[0] = d + return results, nil +} + +func expandAzureRmStorageAccountKeyVaultProperties(d *schema.ResourceData) *storage.KeyVaultProperties { + vs := d.Get("key_vault").([]interface{}) + if len(vs) == 0 { + return &storage.KeyVaultProperties{} + } + + v := vs[0].(map[string]interface{}) + keyName := v["key_name"].(string) + keyVersion := v["key_version"].(string) + + return &storage.KeyVaultProperties{ + KeyName: utils.String(keyName), + KeyVersion: utils.String(keyVersion), + } +} + +func flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties *storage.KeyVaultProperties, keyVaultId string, keyVaultPolicyId string) []interface{} { + if keyVaultProperties == nil { + return make([]interface{}, 0) + } + + result := make(map[string]interface{}) + if keyVaultId != "" { + result["key_vault_id"] = keyVaultId + } + + if keyVaultPolicyId != "" { + result["key_vault_policy_id"] = keyVaultPolicyId + } + + if keyVaultProperties.KeyName != nil { + result["key_name"] = *keyVaultProperties.KeyName + } + if keyVaultProperties.KeyVersion != nil { + result["key_version"] = *keyVaultProperties.KeyVersion + } + if keyVaultProperties.KeyVaultURI != nil { + result["key_vault_uri"] = *keyVaultProperties.KeyVaultURI + } + + return []interface{}{result} +} diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go new file mode 100644 index 0000000000000..751b0b733fa63 --- /dev/null +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go @@ -0,0 +1,341 @@ +package azurerm + +import ( + "fmt" + "net/http" + "os" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" + "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" +) + +func TestAccAzureRMStorageAccountEncryptionSettings_basic(t *testing.T) { + parentResourceName := "azurerm_storage_account.testsa" + resourceName := "azurerm_storage_account_encryption_settings.custom" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + preConfig := testAccAzureRMStorageAccountEncryptionSettings_basic(ri, rs, location) + postConfig := testAccAzureRMStorageAccountEncryptionSettings_basicDelete(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "true"), + resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "true"), + ), + }, + { + // Delete the encryption settings resource and verify it is gone + // Whilst making sure the encryption settings on the storage account + // have been reverted to their default state + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), + testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisable(t *testing.T) { + _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") + if !exists { + t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") + } + + resourceName := "azurerm_storage_account_encryption_settings.custom" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + config := testAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisabled(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "false"), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisable(t *testing.T) { + _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") + if !exists { + t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") + } + + resourceName := "azurerm_storage_account_encryption_settings.custom" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + location := testLocation() + config := testAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisabled(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "false"), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageAccountEncryptionSettings_disappears(t *testing.T) { + parentResourceName := "azurerm_storage_account.testsa" + resourceName := "azurerm_storage_account_encryption_settings.custom" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + preConfig := testAccAzureRMStorageAccountEncryptionSettings_basic(ri, rs, testLocation()) + postConfig := testAccAzureRMStorageAccountEncryptionSettings_basicDelete(ri, rs, testLocation()) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "true"), + resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "true"), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), + testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName), + ), + }, + }, + }) +} + +func testCheckAzureRMStorageAccountExistsWithDefaultSettings(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) + } + + storageAccount := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + // Ensure resource group exists in API + ctx := testAccProvider.Meta().(*ArmClient).StopContext + conn := testAccProvider.Meta().(*ArmClient).storageServiceClient + + resp, err := conn.GetProperties(ctx, resourceGroup, storageAccount) + if err != nil { + return fmt.Errorf("Bad: Get on storageServiceClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: StorageAccount %q (resource group: %q) does not exist", storageAccount, resourceGroup) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if services := encryption.Services; services != nil { + if !*services.Blob.Enabled { + return fmt.Errorf("enable_blob_encryption not set to default: %s", resourceName) + } + if !*services.File.Enabled { + return fmt.Errorf("enable_file_encryption not set to default: %s", resourceName) + } + } + + if encryption.KeySource != storage.MicrosoftStorage { + return fmt.Errorf("%s keySource not set to default(storage.MicrosoftStorage): %s", resourceName, encryption.KeySource) + } + } else { + return fmt.Errorf("storage account encryption properties not found: %s", resourceName) + } + } + + return nil + } +} + +func testCheckAzureRMStorageAccountEncryptionSettingsExists(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) + } + + if storageAccountId := rs.Primary.Attributes["storage_account_id"]; storageAccountId == "" { + return fmt.Errorf("Unable to read storageAccountId: %s", resourceName) + } + + return nil + } +} + +func testCheckAzureRMStorageAccountDestroyed(s *terraform.State) error { + ctx := testAccProvider.Meta().(*ArmClient).StopContext + conn := testAccProvider.Meta().(*ArmClient).storageServiceClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_account" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.GetProperties(ctx, resourceGroup, name) + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Storage Account still exists:\n%#v", resp.AccountProperties) + } + } + + return nil +} + +func testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[resourceName] + if !ok { + return nil + } + + return fmt.Errorf("Found: %s", resourceName) + } +} + +func testAccAzureRMStorageAccountEncryptionSettings_basic(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "production" + } +} + +resource "azurerm_storage_account_encryption_settings" "custom" { + storage_account_id = "${azurerm_storage_account.testsa.id}" + enable_blob_encryption = true + enable_file_encryption = true +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageAccountEncryptionSettings_basicDelete(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "production" + } +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisabled(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "production" + } +} + +resource "azurerm_storage_account_encryption_settings" "custom" { + storage_account_id = "${azurerm_storage_account.testsa.id} + enable_file_encryption = false" +} +`, rInt, location, rString) +} + +func testAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisabled(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "production" + } +} + +resource "azurerm_storage_account_encryption_settings" "custom" { + storage_account_id = "${azurerm_storage_account.testsa.id} + enable_blob_encryption = false" +} +`, rInt, location, rString) +} diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index 24f8b1618d89e..99c1cda3a0e20 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -3,7 +3,6 @@ package tests import ( "fmt" "net/http" - "os" "regexp" "testing" @@ -212,68 +211,6 @@ func TestAccAzureRMStorageAccount_blobConnectionString(t *testing.T) { }) } -func TestAccAzureRMStorageAccount_blobEncryption(t *testing.T) { - _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") - if !exists { - t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") - } - data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMStorageAccount_blobEncryption(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_blob_encryption", "true"), - ), - }, - data.ImportStep(), - { - Config: testAccAzureRMStorageAccount_blobEncryptionDisabled(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_blob_encryption", "false"), - ), - }, - }, - }) -} - -func TestAccAzureRMStorageAccount_fileEncryption(t *testing.T) { - _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") - if !exists { - t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") - } - data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMStorageAccount_fileEncryption(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_file_encryption", "true"), - ), - }, - data.ImportStep(), - { - Config: testAccAzureRMStorageAccount_fileEncryptionDisabled(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_file_encryption", "false"), - ), - }, - }, - }) -} - func TestAccAzureRMStorageAccount_enableHttpsTrafficOnly(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") @@ -823,98 +760,6 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString) } -func testAccAzureRMStorageAccount_blobEncryption(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_blob_encryption = true - - tags = { - environment = "production" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - -func testAccAzureRMStorageAccount_blobEncryptionDisabled(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_blob_encryption = false - - tags = { - environment = "production" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - -func testAccAzureRMStorageAccount_fileEncryption(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_file_encryption = true - - tags = { - environment = "production" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - -func testAccAzureRMStorageAccount_fileEncryptionDisabled(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_file_encryption = false - - tags = { - environment = "production" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - func testAccAzureRMStorageAccount_enableHttpsTrafficOnly(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index b62d07a008e06..068392892101c 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -92,17 +92,11 @@ The following arguments are supported: * `access_tier` - (Optional) Defines the access tier for `BlobStorage`, `FileStorage` and `StorageV2` accounts. Valid options are `Hot` and `Cool`, defaults to `Hot`. -* `enable_blob_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for Blob storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. - -* `enable_file_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for File storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. - * `enable_https_traffic_only` - (Optional) Boolean flag which forces HTTPS if enabled, see [here](https://docs.microsoft.com/en-us/azure/storage/storage-require-secure-transfer/) for more information. * `is_hns_enabled` - (Optional) Is Hierarchical Namespace enabled? This can be used with Azure Data Lake Storage Gen 2 ([see here for more information](https://docs.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-quickstart-create-account/)). Changing this forces a new resource to be created. -* `account_encryption_source` - (Optional) The Encryption Source for this Storage Account. Possible values are `Microsoft.Keyvault` and `Microsoft.Storage`. Defaults to `Microsoft.Storage`. - * `custom_domain` - (Optional) A `custom_domain` block as documented below. * `enable_advanced_threat_protection` (Optional) Boolean flag which controls if advanced threat protection is enabled, see [here](https://docs.microsoft.com/en-us/azure/storage/common/storage-advanced-threat-protection) for more information. Defaults to `false`. diff --git a/website/docs/r/storage_account_encryption_settings.html.markdown b/website/docs/r/storage_account_encryption_settings.html.markdown new file mode 100644 index 0000000000000..88680d48328a1 --- /dev/null +++ b/website/docs/r/storage_account_encryption_settings.html.markdown @@ -0,0 +1,133 @@ +--- +subcategory: "Storage" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_storage_account_encryption_settings" +description: |- + Manages the encryption settings of an Azure Storage Account. +--- + +# azurerm_storage_account_encryption_settings + +Manages the encryption settings of an Azure Storage Account. + +## Example Usage + +```hcl +resource "azurerm_storage_account_encryption_settings" "tfex" { + storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.Storage/storageAccounts/tfexstorageaccount" + + key_vault { + key_vault_policy_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault/objectId/00000000-0000-0000-0000-000000000000" + key_vault_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault" + key_name = "tfex-key" + key_version = "955b9ad9579e4501a311df5493bacd02" + } +} +``` + +## Example Usage with User Managed Key Vault Key + +```hcl +resource "azurerm_resource_group" "tfex" { + name = "tfex-RG" + location = "westeurope" +} + +resource "azurerm_key_vault" "tfex" { + name = "tfex-key-vault" + location = "${azurerm_resource_group.tfex.location}" + resource_group_name = "${azurerm_resource_group.tfex.name}" + enabled_for_disk_encryption = true + tenant_id = "00000000-0000-0000-0000-000000000000" + + sku { + name = "standard" + } + + tags { + environment = "testing" + } +} + +resource "azurerm_key_vault_key" "tfex" { + name = "tfex-key" + key_vault_id = "${azurerm_key_vault.tfex.id}" + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] +} + +resource "azurerm_key_vault_access_policy" "tfex" { + key_vault_id = "${azurerm_key_vault.tfex.id}" + tenant_id = "00000000-0000-0000-0000-000000000000" + object_id = "${azurerm_storage_account.tfex.identity.0.principal_id}" + + key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] + secret_permissions = ["get"] +} + +resource "azurerm_storage_account" "tfex" { + name = "tfexstorageaccount" + resource_group_name = "${azurerm_resource_group.tfex.name}" + location = "${azurerm_resource_group.tfex.location}" + account_tier = "Standard" + account_replication_type = "GRS" + + identity { + type = "SystemAssigned" + } + + tags { + environment = "testing" + } +} + +resource "azurerm_storage_account_encryption_settings" "tfex" { + storage_account_id = "${azurerm_storage_account.tfex.id}" + + key_vault { + key_vault_policy_id = "${azurerm_key_vault_access_policy.tfex.id}" + key_vault_id = "${azurerm_key_vault.tfex.id}" + key_name = "${azurerm_key_vault_key.tfex.name}" + key_version = "${azurerm_key_vault_key.tfex.version}" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `storage_account_id` - (Required) The id of the storage account to manage the encryption settings for. + +* `enable_blob_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for Blob storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. + +* `enable_file_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for File storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. + +* `key_vault` - (Optional) A `key_vault` block as documented below. + +--- + +* `key_vault` supports the following: + +* `key_vault_id` - (Required) The ID of the Key Vault. +* `key_vault_policy_id` - (Required) The resource ID of the `azurerm_key_vault_access_policy` granting the storage account access to the key vault. +* `key_name` - (Required) The name of Key Vault key. +* `key_version` - (Required) The version of Key Vault key. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The storage account encryption settings Resource ID. +* `key_vault_uri` - The base URI of the Key Vault. + +--- + +## Import + +Storage Accounts Encryption Settings can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_storage_account_encryption_settings.tfex /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount +``` \ No newline at end of file From 8f9d064990fb90efd72b0cdce8f440cee244b2ae Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 10 Feb 2020 16:12:07 -0800 Subject: [PATCH 055/498] Got it to compile --- .../internal/services/storage/registration.go | 23 +++---- .../storage/resource_arm_storage_account.go | 6 -- ...arm_storage_account_encryption_settings.go | 63 +++++++++++-------- ...torage_account_encryption_settings_test.go | 2 +- ..._account_encryption_settings.html.markdown | 48 ++++++++------ 5 files changed, 81 insertions(+), 61 deletions(-) diff --git a/azurerm/internal/services/storage/registration.go b/azurerm/internal/services/storage/registration.go index bdf608f1635cf..bc6bb490477ab 100644 --- a/azurerm/internal/services/storage/registration.go +++ b/azurerm/internal/services/storage/registration.go @@ -25,16 +25,17 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_storage_account": resourceArmStorageAccount(), - "azurerm_storage_account_network_rules": resourceArmStorageAccountNetworkRules(), - "azurerm_storage_blob": resourceArmStorageBlob(), - "azurerm_storage_container": resourceArmStorageContainer(), - "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), - "azurerm_storage_management_policy": resourceArmStorageManagementPolicy(), - "azurerm_storage_queue": resourceArmStorageQueue(), - "azurerm_storage_share": resourceArmStorageShare(), - "azurerm_storage_share_directory": resourceArmStorageShareDirectory(), - "azurerm_storage_table": resourceArmStorageTable(), - "azurerm_storage_table_entity": resourceArmStorageTableEntity(), + "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_account_encryption_settings": resourceArmStorageAccountEncryptionSettings(), + "azurerm_storage_account_network_rules": resourceArmStorageAccountNetworkRules(), + "azurerm_storage_blob": resourceArmStorageBlob(), + "azurerm_storage_container": resourceArmStorageContainer(), + "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), + "azurerm_storage_management_policy": resourceArmStorageManagementPolicy(), + "azurerm_storage_queue": resourceArmStorageQueue(), + "azurerm_storage_share": resourceArmStorageShare(), + "azurerm_storage_share_directory": resourceArmStorageShareDirectory(), + "azurerm_storage_table": resourceArmStorageTable(), + "azurerm_storage_table_entity": resourceArmStorageTableEntity(), } } diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index c6a48bd2caacb..6ce053f5425d5 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -664,7 +664,6 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e Tags: tags.Expand(t), Kind: storage.Kind(accountKind), AccountPropertiesCreateParameters: &storage.AccountPropertiesCreateParameters{ - Encryption: &storage.Encryption{ EnableHTTPSTrafficOnly: &enableHTTPSTrafficOnly, NetworkRuleSet: expandStorageAccountNetworkRules(d), IsHnsEnabled: &isHnsEnabled, @@ -868,11 +867,6 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("tags") } - if _, err := client.Update(ctx, resourceGroupName, storageAccountName, opts); err != nil { - return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) - } - } - if d.HasChange("custom_domain") { opts := storage.AccountUpdateParameters{ AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go index d536707a7398e..0ba2bc5380a48 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -1,26 +1,35 @@ -package azurerm +package storage import ( "fmt" + "time" - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" - "github.com/hashicorp/terraform/helper/schema" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "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/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmStorageAccountEncryptionSettings() *schema.Resource { return &schema.Resource{ - Read: resourceArmStorageAccountEncryptionSettingsRead, - Create: resourceArmStorageAccountEncryptionSettingsCreateUpdate, - Update: resourceArmStorageAccountEncryptionSettingsCreateUpdate, - Delete: resourceArmStorageAccountEncryptionSettingsDelete, - + Read: resourceArmStorageAccountEncryptionSettingsRead, + Create: resourceArmStorageAccountEncryptionSettingsCreateUpdate, + Update: resourceArmStorageAccountEncryptionSettingsCreateUpdate, + Delete: resourceArmStorageAccountEncryptionSettingsDelete, + SchemaVersion: 2, Importer: &schema.ResourceImporter{ - State: resourceArmStorageAccountEncryptionSettingsImportState, + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), }, - SchemaVersion: 2, Schema: map[string]*schema.Schema{ "storage_account_id": { @@ -83,9 +92,10 @@ func resourceArmStorageAccountEncryptionSettings() *schema.Resource { } func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceData, meta interface{}) error { - ctx := meta.(*ArmClient).StopContext - vaultClient := meta.(*ArmClient).keyVaultClient - client := meta.(*ArmClient).storageServiceClient + vaultClient := meta.(*clients.Client).KeyVault.VaultsClient + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() storageAccountId := d.Get("storage_account_id").(string) @@ -139,7 +149,7 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD } } - _, err = client.Update(ctx, resourceGroupName, storageAccountName, opts) + _, err = storageClient.Update(ctx, resourceGroupName, storageAccountName, opts) if err != nil { return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) } @@ -151,19 +161,20 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD } func resourceArmStorageAccountEncryptionSettingsRead(d *schema.ResourceData, meta interface{}) error { - ctx := meta.(*ArmClient).StopContext - client := meta.(*ArmClient).storageServiceClient + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() storageAccountId := d.Get("storage_account_id").(string) - id, err := parseAzureResourceID(storageAccountId) + id, err := azure.ParseAzureResourceID(storageAccountId) if err != nil { return err } name := id.Path["storageAccounts"] resGroup := id.ResourceGroup - resp, err := client.GetProperties(ctx, resGroup, name) + resp, err := storageClient.GetProperties(ctx, resGroup, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") @@ -198,8 +209,9 @@ func resourceArmStorageAccountEncryptionSettingsRead(d *schema.ResourceData, met } func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, meta interface{}) error { - ctx := meta.(*ArmClient).StopContext - client := meta.(*ArmClient).storageServiceClient + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() storageAccountId := d.Get("storage_account_id").(string) @@ -223,7 +235,7 @@ func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, m }, } - _, err = client.Update(ctx, resourceGroupName, storageAccountName, opts) + _, err = storageClient.Update(ctx, resourceGroupName, storageAccountName, opts) if err != nil { return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) } @@ -232,21 +244,22 @@ func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, m } func resourceArmStorageAccountEncryptionSettingsImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - ctx := meta.(*ArmClient).StopContext - client := meta.(*ArmClient).storageServiceClient + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() id := d.Id() d.Set("storage_account_id", id) - saId, err := parseAzureResourceID(id) + saId, err := azure.ParseAzureResourceID(id) if err != nil { return nil, err } name := saId.Path["storageAccounts"] resGroup := saId.ResourceGroup - resp, err := client.GetProperties(ctx, resGroup, name) + resp, err := storageClient.GetProperties(ctx, resGroup, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go index 751b0b733fa63..cc994667f9407 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-10-01/storage" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" diff --git a/website/docs/r/storage_account_encryption_settings.html.markdown b/website/docs/r/storage_account_encryption_settings.html.markdown index 88680d48328a1..c234b895f6eec 100644 --- a/website/docs/r/storage_account_encryption_settings.html.markdown +++ b/website/docs/r/storage_account_encryption_settings.html.markdown @@ -28,6 +28,16 @@ resource "azurerm_storage_account_encryption_settings" "tfex" { ## Example Usage with User Managed Key Vault Key ```hcl +provider "azurerm" { + alias = "keyVault" + + features { + key_vault { + purge_soft_delete_on_destroy = true + } + } +} + resource "azurerm_resource_group" "tfex" { name = "tfex-RG" location = "westeurope" @@ -35,32 +45,34 @@ resource "azurerm_resource_group" "tfex" { resource "azurerm_key_vault" "tfex" { name = "tfex-key-vault" - location = "${azurerm_resource_group.tfex.location}" - resource_group_name = "${azurerm_resource_group.tfex.name}" - enabled_for_disk_encryption = true + provider = azurerm.keyVault + location = azurerm_resource_group.tfex.location + resource_group_name = azurerm_resource_group.tfex.name tenant_id = "00000000-0000-0000-0000-000000000000" + + enabled_for_disk_encryption = true + soft_delete_enabled = true + purge_protection_enabled = false - sku { - name = "standard" - } + sku_name = "standard" - tags { + tags = { environment = "testing" } } resource "azurerm_key_vault_key" "tfex" { name = "tfex-key" - key_vault_id = "${azurerm_key_vault.tfex.id}" + key_vault_id = azurerm_key_vault.tfex.id key_type = "RSA" key_size = 2048 key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] } resource "azurerm_key_vault_access_policy" "tfex" { - key_vault_id = "${azurerm_key_vault.tfex.id}" + key_vault_id = azurerm_key_vault.tfex.id tenant_id = "00000000-0000-0000-0000-000000000000" - object_id = "${azurerm_storage_account.tfex.identity.0.principal_id}" + object_id = azurerm_storage_account.tfex.identity.0.principal_id key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] secret_permissions = ["get"] @@ -68,8 +80,8 @@ resource "azurerm_key_vault_access_policy" "tfex" { resource "azurerm_storage_account" "tfex" { name = "tfexstorageaccount" - resource_group_name = "${azurerm_resource_group.tfex.name}" - location = "${azurerm_resource_group.tfex.location}" + resource_group_name = azurerm_resource_group.tfex.name + location = azurerm_resource_group.tfex.location account_tier = "Standard" account_replication_type = "GRS" @@ -77,19 +89,19 @@ resource "azurerm_storage_account" "tfex" { type = "SystemAssigned" } - tags { + tags = { environment = "testing" } } resource "azurerm_storage_account_encryption_settings" "tfex" { - storage_account_id = "${azurerm_storage_account.tfex.id}" + storage_account_id = azurerm_storage_account.tfex.id key_vault { - key_vault_policy_id = "${azurerm_key_vault_access_policy.tfex.id}" - key_vault_id = "${azurerm_key_vault.tfex.id}" - key_name = "${azurerm_key_vault_key.tfex.name}" - key_version = "${azurerm_key_vault_key.tfex.version}" + key_vault_policy_id = azurerm_key_vault_access_policy.tfex.id + key_vault_id = azurerm_key_vault.tfex.id + key_name = azurerm_key_vault_key.tfex.name + key_version = azurerm_key_vault_key.tfex.version } } ``` From 7c10eb5955c1ad6e500d728e3b01a3b10396912f Mon Sep 17 00:00:00 2001 From: aqche <39076898+aqche@users.noreply.github.com> Date: Mon, 10 Feb 2020 17:11:12 -0800 Subject: [PATCH 056/498] Apply suggestions from code review Co-Authored-By: Tom Harvey --- .../storage/resource_arm_storage_account.go | 23 +++++++++++++++++-- website/docs/r/storage_account.html.markdown | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 3e3d5de99f642..6759bbfbebb1e 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -1346,7 +1346,13 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err if err := d.Set("blob_account_properties", flattenBlobAccountProperties(blobAccountProps)); err != nil { return fmt.Errorf("Error setting `blob_account_properties `for AzureRM Storage Account %q: %+v", name, err) + var staticWebsite []interface{} + if resp.Kind == storage.StorageV2 { + staticWebsite = flattenStaticWebsite(...) } + if err := d.Set("static_website", staticWebsite); err != nil { + return fmt.Errorf("Error setting `blob_account_properties `for AzureRM Storage Account %q: %+v", name, err) + } } return tags.FlattenAndSet(d, resp.Tags) @@ -1644,7 +1650,11 @@ func expandQueuePropertiesCors(input []interface{}) *queues.Cors { func expandBlobAccountProperties(input []interface{}) (accounts.StorageServiceProperties, error) { var err error - properties := accounts.StorageServiceProperties{} + properties := accounts.StorageServiceProperties{ + StaticWebsite: accounts.StaticWebsite{ + Enabled: false, + } + } if len(input) == 0 { return properties, nil } @@ -1883,7 +1893,16 @@ func flattenBlobAccountPropertiesStaticWebsite(input accounts.StaticWebsite) []i staticWebsite["index_document"] = input.IndexDocument staticWebsite["error_document_404_path"] = input.ErrorDocument404Path - return []interface{}{staticWebsite} + if !input.Enabled { + return []interface{}{} + } + + return []interface{}{ + map[string]interface{}{ + "index_document": input.IndexDocument, + "error_document_404_path": index.ErrorDocument404Path, + }, + } } func flattenStorageAccountBypass(input storage.Bypass) []interface{} { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 6dddfe6e71bc8..f989988c35342 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -247,7 +247,7 @@ A `static_website` block supports the following: * `index_document` - (Optional) The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive. -* `error_document_404_path` - (Optional) The absolute path to a webpage that Azure Storage serves for requests that do not correspond to an existing file. For example, error/404.html. Only a single custom 404 page is supported in each static website. The value is case-sensitive. If the server returns a 404 error, and you have not specified an error document, then a default 404 page is returned to the user. +* `error_document_404_path` - (Optional) The absolute path to a custom webpage that should be used when a request is made which does not correspond to an existing file. ## Attributes Reference From f349fafbaadad07393471609d0af46f5d4910db6 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 10 Feb 2020 20:53:16 -0600 Subject: [PATCH 057/498] Corrected Prefix Length The maximum IP prefix length that can be reserved (according to docs.microsoft) is `/28` or 16 usable addresses. https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-address-prefix#constraints --- website/docs/r/public_ip_prefix.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/public_ip_prefix.html.markdown b/website/docs/r/public_ip_prefix.html.markdown index 50827aed4e228..e34444fc9cc70 100644 --- a/website/docs/r/public_ip_prefix.html.markdown +++ b/website/docs/r/public_ip_prefix.html.markdown @@ -45,7 +45,7 @@ The following arguments are supported: -> **Note** Public IP Prefix can only be created with Standard SKUs at this time. -* `prefix_length` - (Optional) Specifies the number of bits of the prefix. The value can be set between 24 (256 addresses) and 31 (2 addresses). Changing this forces a new resource to be created. +* `prefix_length` - (Optional) Specifies the number of bits of the prefix. The value can be set between 28 (16 addresses) and 31 (2 addresses). Changing this forces a new resource to be created. -> **Please Note:**: There may be Public IP address limits on the subscription . [More information available here](https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits?toc=%2fazure%2fvirtual-network%2ftoc.json#publicip-address) From 10e222d3c890a066d6663029c6be5123ab6a0020 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Mon, 10 Feb 2020 19:01:36 -0800 Subject: [PATCH 058/498] Mostly working --- ...arm_storage_account_encryption_settings.go | 33 ++----------------- ..._account_encryption_settings.html.markdown | 6 +--- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go index 0ba2bc5380a48..32c868cba41fe 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -37,17 +37,6 @@ func resourceArmStorageAccountEncryptionSettings() *schema.Resource { Required: true, ValidateFunc: azure.ValidateResourceID, }, - "enable_blob_encryption": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - - "enable_file_encryption": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, "key_vault": { Type: schema.TypeList, @@ -107,9 +96,7 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD storageAccountName := id.Path["storageAccounts"] resourceGroupName := id.ResourceGroup - // set default values for the attributes - enableBlobEncryption := true - enableFileEncryption := true + // TODO: Validate that the key vault has both soft delete and purge protection enabled // create the update object with the default values opts := storage.AccountUpdateParameters{ @@ -117,10 +104,10 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD Encryption: &storage.Encryption{ Services: &storage.EncryptionServices{ Blob: &storage.EncryptionService{ - Enabled: utils.Bool(enableBlobEncryption), + Enabled: true, }, File: &storage.EncryptionService{ - Enabled: utils.Bool(enableFileEncryption), + Enabled: true, }}, KeySource: storage.MicrosoftStorage, KeyVaultProperties: &storage.KeyVaultProperties{}, @@ -128,11 +115,6 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD }, } - if d.HasChange("enable_blob_encryption") || d.HasChange("enable_file_encryption") { - opts.Encryption.Services.Blob.Enabled = utils.Bool(d.Get("enable_blob_encryption").(bool)) - opts.Encryption.Services.File.Enabled = utils.Bool(d.Get("enable_file_encryption").(bool)) - } - if keyVaultProperties := expandAzureRmStorageAccountKeyVaultProperties(d); keyVaultProperties.KeyName != utils.String("") { if v, ok := d.GetOk("key_vault.0.key_vault_id"); ok { // Get the key vault base URL from the key vault @@ -270,15 +252,6 @@ func resourceArmStorageAccountEncryptionSettingsImportState(d *schema.ResourceDa if props := resp.AccountProperties; props != nil { if encryption := props.Encryption; encryption != nil { - if services := encryption.Services; services != nil { - if blob := services.Blob; blob != nil { - d.Set("enable_blob_encryption", blob.Enabled) - } - if file := services.File; file != nil { - d.Set("enable_file_encryption", file.Enabled) - } - } - if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { if err := d.Set("key_vault", flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties, "", "")); err != nil { return nil, fmt.Errorf("Error flattening `key_vault_properties` on import: %+v", err) diff --git a/website/docs/r/storage_account_encryption_settings.html.markdown b/website/docs/r/storage_account_encryption_settings.html.markdown index c234b895f6eec..118ffcf34b92a 100644 --- a/website/docs/r/storage_account_encryption_settings.html.markdown +++ b/website/docs/r/storage_account_encryption_settings.html.markdown @@ -52,7 +52,7 @@ resource "azurerm_key_vault" "tfex" { enabled_for_disk_encryption = true soft_delete_enabled = true - purge_protection_enabled = false + purge_protection_enabled = true sku_name = "standard" @@ -112,10 +112,6 @@ The following arguments are supported: * `storage_account_id` - (Required) The id of the storage account to manage the encryption settings for. -* `enable_blob_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for Blob storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. - -* `enable_file_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for File storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. - * `key_vault` - (Optional) A `key_vault` block as documented below. --- From fef89d3e391a7ecf21ef22eda99fa910ce220ee3 Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Mon, 10 Feb 2020 19:16:20 -0800 Subject: [PATCH 059/498] address code review suggestions --- .../services/storage/client/client.go | 2 +- .../storage/resource_arm_storage_account.go | 181 ++++++------------ .../resource_arm_storage_account_test.go | 32 ++-- website/docs/r/storage_account.html.markdown | 14 +- 4 files changed, 77 insertions(+), 152 deletions(-) diff --git a/azurerm/internal/services/storage/client/client.go b/azurerm/internal/services/storage/client/client.go index 50ffac155a0b7..adc2f7eb2c14d 100644 --- a/azurerm/internal/services/storage/client/client.go +++ b/azurerm/internal/services/storage/client/client.go @@ -45,7 +45,7 @@ func NewClient(options *common.ClientOptions) *Client { options.ConfigureClient(&blobServicesClient.Client, options.ResourceManagerAuthorizer) blobAccountsClient := accounts.NewWithEnvironment(options.Environment) - blobAccountsClient.Authorizer = options.StorageAuthorizer + options.ConfigureClient(&blobAccountsClient.Client, options.StorageAuthorizer) // TODO: switch Storage Containers to using the storage.BlobContainersClient // (which should fix #2977) when the storage clients have been moved in here diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 6759bbfbebb1e..7d2662b4253d8 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -453,35 +453,22 @@ func resourceArmStorageAccount() *schema.Resource { }, }, - "blob_account_properties": { + "static_website": { Type: schema.TypeList, Optional: true, Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "static_website": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "enabled": { - Type: schema.TypeBool, - Required: true, - }, - "index_document": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "error_document_404_path": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - }, - }, + "index_document": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "error_404_document": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -857,21 +844,17 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e } } - if val, ok := d.GetOk("blob_account_properties"); ok { + if val, ok := d.GetOk("static_website"); ok { // static website only supported on Storage V2 - if accountKind == string(storage.StorageV2) { - blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient + if accountKind != string(storage.StorageV2) { + return fmt.Errorf("`static_website` is only supported for Storage V2.") + } + blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient - blobAccountProperties, err := expandBlobAccountProperties(val.([]interface{})) - if err != nil { - return fmt.Errorf("Error expanding `blob_account_properties` for Azure Storage Account %q: %+v", storageAccountName, err) - } + staticWebsiteProps := expandStaticWebsiteProperties(val.([]interface{})) - if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, blobAccountProperties); err != nil { - return fmt.Errorf("Error updating Azure Storage Account `blob_account_properties` %q: %+v", storageAccountName, err) - } - } else { - return fmt.Errorf("`blob_account_properties` are only supported for Storage V2.") + if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, staticWebsiteProps); err != nil { + return fmt.Errorf("Error updating Azure Storage Account `static_website` %q: %+v", storageAccountName, err) } } @@ -1099,24 +1082,20 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("queue_properties") } - if d.HasChange("blob_account_properties") { + if d.HasChange("static_website") { // static website only supported on Storage V2 - if accountKind == string(storage.StorageV2) { - blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient + if accountKind != string(storage.StorageV2) { + return fmt.Errorf("`static_website` are only supported for Storage V2.") + } + blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient - blobAccounProperties, err := expandBlobAccountProperties(d.Get("blob_account_properties").([]interface{})) - if err != nil { - return fmt.Errorf("Error expanding `blob_account_properties` for Azure Storage Account %q: %+v", storageAccountName, err) - } + staticWebsiteProps := expandStaticWebsiteProperties(d.Get("static_website").([]interface{})) - if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, blobAccounProperties); err != nil { - return fmt.Errorf("Error updating Azure Storage Account `blob_account_properties` %q: %+v", storageAccountName, err) - } - } else { - return fmt.Errorf("`blob_account_properties` are only supported for Storage V2.") + if _, err = blobAccountClient.SetServiceProperties(ctx, storageAccountName, staticWebsiteProps); err != nil { + return fmt.Errorf("Error updating Azure Storage Account `static_website` %q: %+v", storageAccountName, err) } - d.SetPartial("blob_account_properties") + d.SetPartial("static_website") } d.Partial(false) @@ -1333,26 +1312,24 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err } } + var staticWebsite []interface{} + // static website only supported on Storage V2 if resp.Kind == storage.StorageV2 { blobAccountClient := storageClient.BlobAccountsClient - blobAccountProps, err := blobAccountClient.GetServiceProperties(ctx, name) + staticWebsiteProps, err := blobAccountClient.GetServiceProperties(ctx, name) if err != nil { - if blobAccountProps.Response.Response != nil && !utils.ResponseWasNotFound(blobAccountProps.Response) { - return fmt.Errorf("Error reading blob account properties for AzureRM Storage Account %q: %+v", name, err) + if staticWebsiteProps.Response.Response != nil && !utils.ResponseWasNotFound(staticWebsiteProps.Response) { + return fmt.Errorf("Error reading static website for AzureRM Storage Account %q: %+v", name, err) } } - if err := d.Set("blob_account_properties", flattenBlobAccountProperties(blobAccountProps)); err != nil { - return fmt.Errorf("Error setting `blob_account_properties `for AzureRM Storage Account %q: %+v", name, err) - var staticWebsite []interface{} - if resp.Kind == storage.StorageV2 { - staticWebsite = flattenStaticWebsite(...) - } - if err := d.Set("static_website", staticWebsite); err != nil { - return fmt.Errorf("Error setting `blob_account_properties `for AzureRM Storage Account %q: %+v", name, err) - } + staticWebsite = flattenStaticWebsiteProperties(staticWebsiteProps) + } + + if err := d.Set("static_website", staticWebsite); err != nil { + return fmt.Errorf("Error setting `static_website `for AzureRM Storage Account %q: %+v", name, err) } return tags.FlattenAndSet(d, resp.Tags) @@ -1648,47 +1625,29 @@ func expandQueuePropertiesCors(input []interface{}) *queues.Cors { return cors } -func expandBlobAccountProperties(input []interface{}) (accounts.StorageServiceProperties, error) { - var err error +func expandStaticWebsiteProperties(input []interface{}) accounts.StorageServiceProperties { properties := accounts.StorageServiceProperties{ - StaticWebsite: accounts.StaticWebsite{ + StaticWebsite: &accounts.StaticWebsite{ Enabled: false, - } - } - if len(input) == 0 { - return properties, nil - } - - attrs := input[0].(map[string]interface{}) - - properties.StaticWebsite, err = expandBlobAccountPropertiesStaticWebsite(attrs["static_website"].([]interface{})) - if err != nil { - return properties, fmt.Errorf("Error expanding `static_website`: %+v", err) + }, } - - return properties, nil -} - -func expandBlobAccountPropertiesStaticWebsite(input []interface{}) (*accounts.StaticWebsite, error) { if len(input) == 0 { - return &accounts.StaticWebsite{}, nil + return properties } - staticWebsiteAttr := input[0].(map[string]interface{}) + attr := input[0].(map[string]interface{}) - staticWebsite := &accounts.StaticWebsite{ - Enabled: staticWebsiteAttr["enabled"].(bool), - } + properties.StaticWebsite.Enabled = true - if v, ok := staticWebsiteAttr["index_document"]; ok { - staticWebsite.IndexDocument = v.(string) + if v, ok := attr["index_document"]; ok { + properties.StaticWebsite.IndexDocument = v.(string) } - if v, ok := staticWebsiteAttr["error_document_404_path"]; ok { - staticWebsite.ErrorDocument404Path = v.(string) + if v, ok := attr["error_404_document"]; ok { + properties.StaticWebsite.ErrorDocument404Path = v.(string) } - return staticWebsite, nil + return properties } func flattenStorageAccountNetworkRules(input *storage.NetworkRuleSet) []interface{} { @@ -1867,42 +1826,22 @@ func flattenCorsProperty(input string) []interface{} { return results } -func flattenBlobAccountProperties(input accounts.GetServicePropertiesResult) []interface{} { - if input.Response.Response == nil { - return []interface{}{} - } - - blobAccountProperties := make(map[string]interface{}) - +func flattenStaticWebsiteProperties(input accounts.GetServicePropertiesResult) []interface{} { if storageServiceProps := input.StorageServiceProperties; storageServiceProps != nil { if staticWebsite := storageServiceProps.StaticWebsite; staticWebsite != nil { - blobAccountProperties["static_website"] = flattenBlobAccountPropertiesStaticWebsite(*staticWebsite) - } - } - - if len(blobAccountProperties) == 0 { - return []interface{}{} - } - return []interface{}{blobAccountProperties} -} - -func flattenBlobAccountPropertiesStaticWebsite(input accounts.StaticWebsite) []interface{} { - staticWebsite := make(map[string]interface{}) - - staticWebsite["enabled"] = input.Enabled - staticWebsite["index_document"] = input.IndexDocument - staticWebsite["error_document_404_path"] = input.ErrorDocument404Path + if !staticWebsite.Enabled { + return []interface{}{} + } - if !input.Enabled { - return []interface{}{} - } - - return []interface{}{ - map[string]interface{}{ - "index_document": input.IndexDocument, - "error_document_404_path": index.ErrorDocument404Path, - }, + return []interface{}{ + map[string]interface{}{ + "index_document": staticWebsite.IndexDocument, + "error_404_document": staticWebsite.ErrorDocument404Path, + }, + } + } } + return []interface{}{} } func flattenStorageAccountBypass(input storage.Bypass) []interface{} { diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index a3a6bbf12130b..9133bf1ea44f6 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -653,7 +653,7 @@ func TestAccAzureRMStorageAccount_queueProperties(t *testing.T) { }) } -func TestAccAzureRMStorageAccount_blobAccountProperties(t *testing.T) { +func TestAccAzureRMStorageAccount_staticWebsiteProperties(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") resource.ParallelTest(t, resource.TestCase{ @@ -662,14 +662,14 @@ func TestAccAzureRMStorageAccount_blobAccountProperties(t *testing.T) { CheckDestroy: testCheckAzureRMStorageAccountDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMStorageAccount_blobAccountProperties(data), + Config: testAccAzureRMStorageAccount_staticWebsiteProperties(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMStorageAccountExists(data.ResourceName), ), }, data.ImportStep(), { - Config: testAccAzureRMStorageAccount_blobAccountPropertiesUpdated(data), + Config: testAccAzureRMStorageAccount_staticWebsitePropertiesUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMStorageAccountExists(data.ResourceName), ), @@ -1552,7 +1552,7 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString) } -func testAccAzureRMStorageAccount_blobAccountProperties(data acceptance.TestData) string { +func testAccAzureRMStorageAccount_staticWebsiteProperties(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-storage-%d" @@ -1567,19 +1567,16 @@ resource "azurerm_storage_account" "test" { account_kind = "StorageV2" account_tier = "Standard" account_replication_type = "LRS" - - blob_account_properties { - static_website { - enabled = true - index_document = "index.html" - error_document_404_path = "404.html" - } + + static_website { + index_document = "index.html" + error_404_document = "404.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) } -func testAccAzureRMStorageAccount_blobAccountPropertiesUpdated(data acceptance.TestData) string { +func testAccAzureRMStorageAccount_staticWebsitePropertiesUpdated(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-storage-%d" @@ -1594,13 +1591,10 @@ resource "azurerm_storage_account" "test" { account_kind = "StorageV2" account_tier = "Standard" account_replication_type = "LRS" - - blob_account_properties { - static_website { - enabled = true - index_document = "index-2.html" - error_document_404_path = "404-2.html" - } + + static_website { + index_document = "index-2.html" + error_404_document = "404-2.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index e56bb91b97fb4..661e3683793f9 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -117,9 +117,9 @@ The following arguments are supported: ~> **NOTE:** `queue_properties` cannot be set when the `access_tier` is set to `BlobStorage` -* `blob_account_properties` - (Optional) A `blob_account_properties` block as defined below. +* `static_website` - (Optional) A `static_website` block as defined below. -~> **NOTE:** `blob_account_properties` can only be set when the `account_kind` is set to `StorageV2` +~> **NOTE:** `static_website` can only be set when the `account_kind` is set to `StorageV2` * `network_rules` - (Optional) A `network_rules` block as documented below. @@ -235,19 +235,11 @@ A `queue_properties` block supports the following: --- -A `blob_account_properties` block supports the following: - -* `static_website` - (Optional) A `static_website` block as defined below. - ---- - A `static_website` block supports the following: -* `enabled` - (Required) Indicates whether static website support is enabled for the given account. If a blob storage container named $web doesn't already exist in the account, one is created for you. Add the files of your site to this container. - * `index_document` - (Optional) The webpage that Azure Storage serves for requests to the root of a website or any subfolder. For example, index.html. The value is case-sensitive. -* `error_document_404_path` - (Optional) The absolute path to a custom webpage that should be used when a request is made which does not correspond to an existing file. +* `error_404_document` - (Optional) The absolute path to a custom webpage that should be used when a request is made which does not correspond to an existing file. ## Attributes Reference From f697f8ad5056efeda917354512008abab2c9126c Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Mon, 10 Feb 2020 19:18:34 -0800 Subject: [PATCH 060/498] are -> is --- .../internal/services/storage/resource_arm_storage_account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 7d2662b4253d8..4c59eb4047750 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -1085,7 +1085,7 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e if d.HasChange("static_website") { // static website only supported on Storage V2 if accountKind != string(storage.StorageV2) { - return fmt.Errorf("`static_website` are only supported for Storage V2.") + return fmt.Errorf("`static_website` is only supported for Storage V2.") } blobAccountClient := meta.(*clients.Client).Storage.BlobAccountsClient From 16c7b24bf075d22244292d33f0d2525ce141dfcd Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Mon, 10 Feb 2020 19:34:27 -0800 Subject: [PATCH 061/498] tflint fixes --- .../storage/tests/resource_arm_storage_account_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index 9133bf1ea44f6..e10215508a7d4 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -1569,8 +1569,8 @@ resource "azurerm_storage_account" "test" { account_replication_type = "LRS" static_website { - index_document = "index.html" - error_404_document = "404.html" + index_document = "index.html" + error_404_document = "404.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) @@ -1593,8 +1593,8 @@ resource "azurerm_storage_account" "test" { account_replication_type = "LRS" static_website { - index_document = "index-2.html" - error_404_document = "404-2.html" + index_document = "index-2.html" + error_404_document = "404-2.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) From 4b190a438f13ac2a4778808397c82e4fdfc4604a Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Mon, 10 Feb 2020 19:59:13 -0800 Subject: [PATCH 062/498] tflint fix 2 --- .../tests/resource_arm_storage_account_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index e10215508a7d4..36c78e15794c3 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -1567,10 +1567,10 @@ resource "azurerm_storage_account" "test" { account_kind = "StorageV2" account_tier = "Standard" account_replication_type = "LRS" - + static_website { - index_document = "index.html" - error_404_document = "404.html" + index_document = "index.html" + error_404_document = "404.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) @@ -1591,10 +1591,10 @@ resource "azurerm_storage_account" "test" { account_kind = "StorageV2" account_tier = "Standard" account_replication_type = "LRS" - + static_website { - index_document = "index-2.html" - error_404_document = "404-2.html" + index_document = "index-2.html" + error_404_document = "404-2.html" } } `, data.RandomInteger, data.Locations.Primary, data.RandomString) From 14d0825cc0c0f81d9d2ed1367d08dda729bafb4f Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 11 Feb 2020 10:07:10 -0600 Subject: [PATCH 063/498] Validate metric_trigger query; add example to docs --- ...arm_monitor_scheduled_query_rules_alert.go | 13 ++++++- ..._scheduled_query_rules_alert.html.markdown | 37 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 3fb0fa6c8317d..6ea171c6cd89a 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" @@ -204,10 +205,20 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - if *schedule.TimeWindowInMinutes < *schedule.FrequencyInMinutes { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + if timeWindow < frequency { return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): time_window must be greater than or equal to frequency", name, resourceGroup) } + query := d.Get("query").(string) + _, ok := d.GetOk("metric_trigger") + if ok { + if !(strings.Contains(query, "summarize") && strings.Contains(query, "AggregatedValue") && strings.Contains(query, "bin")) { + return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): query must contain summarize, AggregatedValue, and bin when metric_trigger is specified", name, resourceGroup) + } + } + if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resourceGroup, name) if err != nil { diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 647252ecd1e2a..09cc587790910 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -33,7 +33,36 @@ resource "azurerm_log_analytics_workspace" "example" { retention_in_days = 30 } -# Example: Alerting Action + +# Example: Alerting Action with result count trigger +# Alert if more than three HTTP requests returned a >= 500 result code +# in the past 30 minutes +resource "azurerm_scheduled_query_rule_alert" "example" { + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = "{}" + } + data_source_id = azurerm_application_insights.example.id + description = "Result count trigger example - alert when total results cross threshold" + enabled = true + frequency = 5 + query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + severity = 1 + time_window = 30 + trigger { + operator = "GreaterThan" + threshold = 3 + } +} + +# Example: Alerting Action with metric trigger +# Alert if more than three HTTP requests returned a >= 500 result code +# in the past 30 minutes that have the same operation (ie: GET /) resource "azurerm_scheduled_query_rule_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location @@ -45,10 +74,10 @@ resource "azurerm_scheduled_query_rule_alert" "example" { custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action example" + description = "Metric trigger example - query results grouped by metric; alert when results per metric_column cross threshold" enabled = true frequency = 5 - query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by operation_Name, bin(timestamp, 5m)" severity = 1 time_window = 30 trigger { @@ -58,7 +87,7 @@ resource "azurerm_scheduled_query_rule_alert" "example" { operator = "GreaterThan" threshold = 1 metric_trigger_type = "Total" - metric_column = "timestamp" + metric_column = "operation_Name" } } } From 6f7c7720577ca2cfb427cb428ca532b145364281 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Wed, 12 Feb 2020 09:49:07 +1100 Subject: [PATCH 064/498] fix site attributes --- website/docs/r/bot_channel_directline.markdown | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 241054e3d7027..33ae413f20722 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -66,12 +66,6 @@ A `site` block has the following properties: - `trusted_origins` - (Optional) This field is required when `is_secure_site_enabled` is enabled. Determines which origins can establish a Directline conversation for this site. -- `key` - (Computed) Primary key for accessing this site - -- `key2` - (Computed) Secondary key for accessing this site - -- `id` - (Computed) Id for the site - ## Attributes Reference @@ -79,6 +73,16 @@ The following attributes are exported: - `id` - The Bot Channel ID. +--- + +A `site` block exports the following: + +- `key` - Primary key for accessing this site + +- `key2` - Secondary key for accessing this site + +- `id` - Id for the site + ## Import The Directline Channel for a Bot can be imported using the `resource id`, e.g. From 2f4c11727aa86ae6b1f4b4d5731f33076ef19d78 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Wed, 12 Feb 2020 09:54:33 +1100 Subject: [PATCH 065/498] format docs --- website/docs/r/bot_channel_directline.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/bot_channel_directline.markdown b/website/docs/r/bot_channel_directline.markdown index 33ae413f20722..5ac64028af915 100644 --- a/website/docs/r/bot_channel_directline.markdown +++ b/website/docs/r/bot_channel_directline.markdown @@ -34,7 +34,7 @@ resource "azurerm_bot_channel_directline" "example" { resource_group_name = "${azurerm_resource_group.example.name}" site { - name = "default" + name = "default" enabled = true } } From b15d1b390eb42e61cbc7704e8ed59dbc73b99068 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 11 Feb 2020 18:34:18 -0800 Subject: [PATCH 066/498] Progress --- azurerm/helpers/azure/key_vault.go | 29 +++++++++++ .../keyvault/resource_arm_key_vault_key.go | 51 +++++++------------ ...arm_storage_account_encryption_settings.go | 13 +++-- website/docs/r/key_vault.html.markdown | 11 ++-- website/docs/r/key_vault_key.html.markdown | 2 + ..._account_encryption_settings.html.markdown | 20 ++++---- 6 files changed, 72 insertions(+), 54 deletions(-) diff --git a/azurerm/helpers/azure/key_vault.go b/azurerm/helpers/azure/key_vault.go index f75368e5d2374..b070b87a71600 100644 --- a/azurerm/helpers/azure/key_vault.go +++ b/azurerm/helpers/azure/key_vault.go @@ -163,3 +163,32 @@ func KeyVaultGetSoftDeletedState(ctx context.Context, client *keyvault.VaultsCli // this means we found an existing key vault that is not soft deleted return nil, nil, nil } + +func KeyVaultIsSoftDeleteAndPurgeProtected(ctx context.Context, client *keyvault.VaultsClient, keyVaultId string) bool { + id, err := ParseAzureResourceID(keyVaultId) + if err != nil { + return false + } + resourceGroup := id.ResourceGroup + name := id.Path["vaults"] + + resp, err := client.Get(ctx, resourceGroup, name) + + if props := resp.Properties; props != nil { + softDeleteEnabled := false + purgeProtectionEnabled := false + + if esd := props.EnableSoftDelete; esd != nil { + softDeleteEnabled = *esd + } + if epp := props.EnableSoftDelete; epp != nil { + purgeProtectionEnabled = *epp + } + + if softDeleteEnabled && purgeProtectionEnabled { + return true + } + } + + return false +} diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go index 73dc13da185ef..454aaa8728d74 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go @@ -46,23 +46,17 @@ func resourceArmKeyVaultKey() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + "key_vault_access_policy_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, "key_type": { @@ -174,28 +168,15 @@ func resourceArmKeyVaultKeyCreate(d *schema.ResourceData, meta interface{}) erro log.Print("[INFO] preparing arguments for AzureRM KeyVault Key creation.") name := d.Get("name").(string) - keyVaultBaseUri := d.Get("vault_uri").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUri == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUri = pKeyVaultBaseUrl - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUri) - if err != nil { - return fmt.Errorf("Error unable to find key vault ID from URL %q for certificate %q: %+v", keyVaultBaseUri, name, err) - } - d.Set("key_vault_id", id) + pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) } + keyVaultBaseUri := pKeyVaultBaseUrl + if features.ShouldResourcesBeImported() { existing, err := client.GetKey(ctx, keyVaultBaseUri, name, "") if err != nil { @@ -330,6 +311,8 @@ func resourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) error ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() + keyVaultAccessPolicyId := d.Get("key_vault_access_policy_id").(string) + id, err := azure.ParseKeyVaultChildID(d.Id()) if err != nil { return err @@ -367,7 +350,7 @@ func resourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) error } d.Set("name", id.Name) - d.Set("vault_uri", id.KeyVaultBaseUrl) + d.Set("key_vault_access_policy_id", keyVaultAccessPolicyId) if key := resp.Key; key != nil { d.Set("key_type", string(key.Kty)) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go index 32c868cba41fe..c9e61d23393a9 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -96,18 +96,17 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD storageAccountName := id.Path["storageAccounts"] resourceGroupName := id.ResourceGroup - // TODO: Validate that the key vault has both soft delete and purge protection enabled - // create the update object with the default values + alwaysEnabled := true opts := storage.AccountUpdateParameters{ AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ Encryption: &storage.Encryption{ Services: &storage.EncryptionServices{ Blob: &storage.EncryptionService{ - Enabled: true, + Enabled: utils.Bool(alwaysEnabled), }, File: &storage.EncryptionService{ - Enabled: true, + Enabled: utils.Bool(alwaysEnabled), }}, KeySource: storage.MicrosoftStorage, KeyVaultProperties: &storage.KeyVaultProperties{}, @@ -125,6 +124,10 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD return fmt.Errorf("Error looking up Key Vault URI from id %q: %+v", keyVaultId, err) } + if azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { + return fmt.Errorf("Key Vault %q is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultId) + } + keyVaultProperties.KeyVaultURI = utils.String(pKeyVaultBaseUrl) opts.Encryption.KeyVaultProperties = keyVaultProperties opts.Encryption.KeySource = storage.MicrosoftKeyvault @@ -219,7 +222,7 @@ func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, m _, err = storageClient.Update(ctx, resourceGroupName, storageAccountName, opts) if err != nil { - return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) + return fmt.Errorf("Error deleting Azure Storage Account Encryption %q: %+v", storageAccountName, err) } return nil diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index 39cff382c4413..3726d985fa135 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -15,6 +15,8 @@ Manages a Key Vault. ## Example Usage ```hcl +data "azurerm_client_config" "current" {} + provider "azurerm" { alias = "keyVault" @@ -36,16 +38,15 @@ resource "azurerm_key_vault" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - enabled_for_disk_encryption = true - tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" + tenant_id = data.azurerm_client_config.current.tenant_id soft_delete_enabled = true purge_protection_enabled = false sku_name = "standard" access_policy { - tenant_id = "d6e396d0-5584-41dc-9fc0-268df99bc610" - object_id = "d746815a-0433-4a21-b95d-fc437d2d475b" + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.service_principal_object_id key_permissions = [ "get", @@ -66,7 +67,7 @@ resource "azurerm_key_vault" "example" { } tags = { - environment = "Production" + environment = "Testing" } } ``` diff --git a/website/docs/r/key_vault_key.html.markdown b/website/docs/r/key_vault_key.html.markdown index 415d4af543d2f..a854886a837cb 100644 --- a/website/docs/r/key_vault_key.html.markdown +++ b/website/docs/r/key_vault_key.html.markdown @@ -82,6 +82,8 @@ The following arguments are supported: * `key_vault_id` - (Required) The ID of the Key Vault where the Key should be created. Changing this forces a new resource to be created. +* `key_vault_access_policy_id` - (Optional) The ID of the Key Vault Access Policy which should exist before the Key should be created. Changing this forces a new resource to be created. + * `key_type` - (Required) Specifies the Key Type to use for this Key Vault Key. Possible values are `EC` (Elliptic Curve), `EC-HSM`, `Oct` (Octet), `RSA` and `RSA-HSM`. Changing this forces a new resource to be created. * `key_size` - (Optional) Specifies the Size of the RSA key to create in bytes. For example, 1024 or 2048. *Note*: This field is required if `key_type` is `RSA` or `RSA-HSM`. Changing this forces a new resource to be created. diff --git a/website/docs/r/storage_account_encryption_settings.html.markdown b/website/docs/r/storage_account_encryption_settings.html.markdown index 118ffcf34b92a..553bdcdfad954 100644 --- a/website/docs/r/storage_account_encryption_settings.html.markdown +++ b/website/docs/r/storage_account_encryption_settings.html.markdown @@ -50,9 +50,8 @@ resource "azurerm_key_vault" "tfex" { resource_group_name = azurerm_resource_group.tfex.name tenant_id = "00000000-0000-0000-0000-000000000000" - enabled_for_disk_encryption = true soft_delete_enabled = true - purge_protection_enabled = true + purge_protection_enabled = false sku_name = "standard" @@ -62,17 +61,18 @@ resource "azurerm_key_vault" "tfex" { } resource "azurerm_key_vault_key" "tfex" { - name = "tfex-key" - key_vault_id = azurerm_key_vault.tfex.id - key_type = "RSA" - key_size = 2048 - key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] + name = "tfex-key" + key_vault_id = azurerm_key_vault.tfex.id + key_vault_access_policy_id = azurerm_key_vault_access_policy.tfex.id + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] } resource "azurerm_key_vault_access_policy" "tfex" { - key_vault_id = azurerm_key_vault.tfex.id - tenant_id = "00000000-0000-0000-0000-000000000000" - object_id = azurerm_storage_account.tfex.identity.0.principal_id + key_vault_id = azurerm_key_vault.tfex.id + tenant_id = "00000000-0000-0000-0000-000000000000" + object_id = azurerm_storage_account.tfex.identity.0.principal_id key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] secret_permissions = ["get"] From 000f916504e52c6dba38990dc41792fa7c6db392 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 11 Feb 2020 20:39:32 -0600 Subject: [PATCH 067/498] Update IP Prefix validation IP Prefix can be deployed as a maximum /28 ip space. The code would allow a max of /24 which is not correct. Updated to support /28 as the max. --- .../internal/services/network/resource_arm_public_ip_prefix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/network/resource_arm_public_ip_prefix.go b/azurerm/internal/services/network/resource_arm_public_ip_prefix.go index 4249c2ed00b8d..304f093f68f05 100644 --- a/azurerm/internal/services/network/resource_arm_public_ip_prefix.go +++ b/azurerm/internal/services/network/resource_arm_public_ip_prefix.go @@ -59,7 +59,7 @@ func resourceArmPublicIpPrefix() *schema.Resource { Optional: true, Default: 28, ForceNew: true, - ValidateFunc: validation.IntBetween(24, 31), + ValidateFunc: validation.IntBetween(28, 31), }, "ip_prefix": { From 371aa19e1e159c7a43447a9c311858d39a158cfe Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Tue, 11 Feb 2020 23:49:42 -0500 Subject: [PATCH 068/498] Requested changes to error handling & structure Documentation fixes --- .../resource_arm_express_route_gateway.go | 31 ++++++++++++------- ...resource_arm_express_route_gateway_test.go | 2 +- .../r/express_route_gateway.html.markdown | 21 +++++++++++-- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index e883985637eaa..5008b5e87567c 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -92,11 +92,14 @@ func resourceArmExpressRouteGatewayCreateUpdate(d *schema.ResourceData, meta int virtualHubId := d.Get("virtual_hub_id").(string) t := d.Get("tags").(map[string]interface{}) + minScaleUnits := int32(d.Get("scale_units").(int)) parameters := network.ExpressRouteGateway{ Location: utils.String(location), ExpressRouteGatewayProperties: &network.ExpressRouteGatewayProperties{ AutoScaleConfiguration: &network.ExpressRouteGatewayPropertiesAutoScaleConfiguration{ - Bounds: expandExpressRouteGatewayAutoScaleConfigurationBounds(d), + Bounds: &network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ + Min: &minScaleUnits, + }, }, VirtualHub: &network.VirtualHubID{ ID: &virtualHubId, @@ -154,11 +157,17 @@ func resourceArmExpressRouteGatewayRead(d *schema.ResourceData, meta interface{} } if props := resp.ExpressRouteGatewayProperties; props != nil { - d.Set("virtual_hub_id", props.VirtualHub.ID) + virtualHubId := "" + if props.VirtualHub != nil && props.VirtualHub.ID != nil { + virtualHubId = *props.VirtualHub.ID + } + d.Set("virtual_hub_id", virtualHubId) - if setErr := d.Set("scale_units", props.AutoScaleConfiguration.Bounds.Min); setErr != nil { - return fmt.Errorf("Error setting `scale_units`: %+v", setErr) + scaleUnits := 0 + if props.AutoScaleConfiguration != nil && props.AutoScaleConfiguration.Bounds != nil && props.AutoScaleConfiguration.Bounds.Min != nil { + scaleUnits = int(*props.AutoScaleConfiguration.Bounds.Min) } + d.Set("scale_units", scaleUnits) } return tags.FlattenAndSet(d, resp.Tags) @@ -193,11 +202,11 @@ func resourceArmExpressRouteGatewayDelete(d *schema.ResourceData, meta interface return nil } -func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceData) *network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds { - minScaleUnits := int32(d.Get("scale_units").(int)) - configuration := network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ - Min: &minScaleUnits, - } +// func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceData) *network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds { +// minScaleUnits := int32(d.Get("scale_units").(int)) +// configuration := network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ +// Min: &minScaleUnits, +// } - return &configuration -} +// return &configuration +// } diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index 155337c6743fa..ff468064d7fab 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -179,7 +179,7 @@ func testAccAzureRMExpressRouteGateway_requiresImport(data acceptance.TestData) return fmt.Sprintf(` %s -resource "azurerm_express_route_gateway" "test" { +resource "azurerm_express_route_gateway" "import" { name = azurerm_express_route_gateway.test.name resource_group_name = azurerm_express_route_gateway.test.name location = azurerm_express_route_gateway.test.location diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown index a40ae80de023f..27900d800de6e 100644 --- a/website/docs/r/express_route_gateway.html.markdown +++ b/website/docs/r/express_route_gateway.html.markdown @@ -15,7 +15,7 @@ Manages an ExpressRoute gateway. ```hcl resource "azurerm_resource_group" "example" { name = "example-resources" - location = "West US" + location = "West Europe" } resource "azurerm_virtual_wan" "example" { @@ -65,11 +65,26 @@ The following arguments are supported: The following attributes are exported: -* `id` - The Resource ID of the ExpressRoute gateway. +* `id` - The ID of the ExpressRoute gateway. + +### Timeouts + +~> **Note:** Custom Timeouts are available [as an opt-in Beta in version 1.43 of the Azure Provider](/docs/providers/azurerm/guides/2.0-beta.html) and will be enabled by default in version 2.0 of the Azure Provider. + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 60 minutes) Used when creating the ExpressRoute Gateway. + +* `update` - (Defaults to 60 minutes) Used when updating the ExpressRoute Gateway. + +* `read` - (Defaults to 5 minutes) Used when retrieving the ExpressRoute Gateway. + +* `delete` - (Defaults to 60 minutes) Used when deleting the ExpressRoute Gateway. + ## Import -ExpressRoute gateways can be imported using the `resource id`, e.g. +ExpressRoute Gateways can be imported using the `resource id`, e.g. ```shell terraform import azurerm_express_route_gateway.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/expressRouteGateways/myExpressRouteGateway From d0864cbd2ceea2b152783e16f2fd8277629b0cea Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Tue, 11 Feb 2020 23:51:18 -0500 Subject: [PATCH 069/498] remove commented block --- .../network/resource_arm_express_route_gateway.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index 5008b5e87567c..731594d7fd24f 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -201,12 +201,3 @@ func resourceArmExpressRouteGatewayDelete(d *schema.ResourceData, meta interface return nil } - -// func expandExpressRouteGatewayAutoScaleConfigurationBounds(d *schema.ResourceData) *network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds { -// minScaleUnits := int32(d.Get("scale_units").(int)) -// configuration := network.ExpressRouteGatewayPropertiesAutoScaleConfigurationBounds{ -// Min: &minScaleUnits, -// } - -// return &configuration -// } From 6de712f0dfcb34176b5311f66ee4bc86f7226668 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Wed, 12 Feb 2020 00:33:40 -0500 Subject: [PATCH 070/498] Add express_route_gateway to website sidebar --- website/azurerm.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/azurerm.erb b/website/azurerm.erb index 45745f5158f32..eb3f9efbc3f61 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -202,6 +202,10 @@ azurerm_express_route_circuit +
  • + azurerm_express_route_gateway +
  • +
  • azurerm_firewall
  • From 3123d0212ab58b4ab445e14ba0e2506fe6b42391 Mon Sep 17 00:00:00 2001 From: Brent Harrison Date: Wed, 12 Feb 2020 00:40:48 -0500 Subject: [PATCH 071/498] Correct sidebar location --- website/azurerm.erb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/azurerm.erb b/website/azurerm.erb index eb3f9efbc3f61..a00c87244b48b 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -202,10 +202,6 @@ azurerm_express_route_circuit -
  • - azurerm_express_route_gateway -
  • -
  • azurerm_firewall
  • @@ -1721,6 +1717,10 @@ azurerm_express_route_circuit_peering +
  • + azurerm_express_route_gateway +
  • +
  • azurerm_firewall
  • From 9f174d4483ca7525a6a4d2e63fe8db531f868a13 Mon Sep 17 00:00:00 2001 From: Variour Date: Wed, 12 Feb 2020 13:45:42 +0100 Subject: [PATCH 072/498] add recommendation for scope parameter value Recommendation is to use the first entry of the assignable_scopes parameter. It is sourced from the microsoft docs. Section 4 in the following howto: https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles-rest#create-a-custom-role --- website/docs/r/role_definition.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/role_definition.html.markdown b/website/docs/r/role_definition.html.markdown index 5c733e4d12b8b..26ba0b82eaf4e 100644 --- a/website/docs/r/role_definition.html.markdown +++ b/website/docs/r/role_definition.html.markdown @@ -41,7 +41,7 @@ The following arguments are supported: * `name` - (Required) The name of the Role Definition. Changing this forces a new resource to be created. -* `scope` - (Required) The scope at which the Role Definition applies too, such as `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333`, `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup`, or `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup/providers/Microsoft.Compute/virtualMachines/myVM`. Changing this forces a new resource to be created. +* `scope` - (Required) The scope at which the Role Definition applies too, such as `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333`, `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup`, or `/subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup/providers/Microsoft.Compute/virtualMachines/myVM`. It is recommended to use the first entry of the `assignable_scopes`. Changing this forces a new resource to be created. * `description` - (Optional) A description of the Role Definition. From b44a0c2732d3eadac9df6c86221dc2cb137c5f0d Mon Sep 17 00:00:00 2001 From: John Schmidt Date: Wed, 12 Feb 2020 13:22:48 -0800 Subject: [PATCH 073/498] Documentation changed based on observed terraform and Azure API behavior. --- website/docs/r/virtual_machine_scale_set.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/virtual_machine_scale_set.html.markdown b/website/docs/r/virtual_machine_scale_set.html.markdown index 6452175c6d72b..7b402578d0b84 100644 --- a/website/docs/r/virtual_machine_scale_set.html.markdown +++ b/website/docs/r/virtual_machine_scale_set.html.markdown @@ -437,7 +437,7 @@ output "principal_id" { * `name` - (Required) Specifies name of the IP configuration. * `subnet_id` - (Required) Specifies the identifier of the subnet. -* `application_gateway_backend_address_pool_ids` - (Optional) Specifies an array of references to backend address pools of application gateways. A scale set can reference backend address pools of multiple application gateways. Multiple scale sets cannot use the same application gateway. +* `application_gateway_backend_address_pool_ids` - (Optional) Specifies an array of references to backend address pools of application gateways. A scale set can reference backend address pools of multiple application gateways. Multiple scale sets can use the same application gateway. * `load_balancer_backend_address_pool_ids` - (Optional) Specifies an array of references to backend address pools of load balancers. A scale set can reference backend address pools of one public and one internal load balancer. Multiple scale sets cannot use the same load balancer. -> **NOTE:** When using this field you'll also need to configure a Rule for the Load Balancer, and use a `depends_on` between this resource and the Load Balancer Rule. From 99b6fe5f22658bcfe23002e0cb92d4156d9fece9 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 12 Feb 2020 14:25:52 -0800 Subject: [PATCH 074/498] Make error msg more user friendly --- ...rce_arm_storage_account_encryption_settings.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go index c9e61d23393a9..c5d2a5e51fd33 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -118,17 +118,26 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD if v, ok := d.GetOk("key_vault.0.key_vault_id"); ok { // Get the key vault base URL from the key vault keyVaultId := v.(string) - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + + kvId, err := azure.ParseAzureResourceID(keyVaultId) + if err != nil { + return err + } + + keyVaultAccountName := kvId.Path["vaults"] + keyVaultResourceGroupName := kvId.ResourceGroup + + pKeyVaultBaseURL, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) if err != nil { return fmt.Errorf("Error looking up Key Vault URI from id %q: %+v", keyVaultId, err) } if azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { - return fmt.Errorf("Key Vault %q is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultId) + return fmt.Errorf("Key Vault %q (Resource Group %q) is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultAccountName, keyVaultResourceGroupName) } - keyVaultProperties.KeyVaultURI = utils.String(pKeyVaultBaseUrl) + keyVaultProperties.KeyVaultURI = utils.String(pKeyVaultBaseURL) opts.Encryption.KeyVaultProperties = keyVaultProperties opts.Encryption.KeySource = storage.MicrosoftKeyvault } From bb8ed6858fa58a5da11ba0f0d7c6d8e331ee01a6 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Wed, 12 Feb 2020 14:56:30 -0800 Subject: [PATCH 075/498] Update error conditional --- .../storage/resource_arm_storage_account_encryption_settings.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go index c5d2a5e51fd33..e03e8a77d9c3d 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go @@ -133,7 +133,7 @@ func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceD return fmt.Errorf("Error looking up Key Vault URI from id %q: %+v", keyVaultId, err) } - if azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { + if !azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { return fmt.Errorf("Key Vault %q (Resource Group %q) is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultAccountName, keyVaultResourceGroupName) } From ccde214c3eb589a38453cedbf298c7921cf318bc Mon Sep 17 00:00:00 2001 From: John Kendall Date: Thu, 13 Feb 2020 17:45:23 +1100 Subject: [PATCH 076/498] resolve review comments --- .../resource_arm_bot_channel_directline.go | 59 +++++++++++++++---- ...esource_arm_bot_channel_directline_test.go | 50 ++++++++-------- website/azurerm.erb | 4 ++ 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 8678b9340873f..30b28aa95ed15 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -149,6 +149,12 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } + // Create does not include sites properly, so we need to update as well + time.Sleep(10 * time.Second) + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) if err != nil { return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) @@ -193,7 +199,7 @@ func resourceArmBotChannelDirectlineRead(d *schema.ResourceData, meta interface{ if props := channelsResp.Properties; props != nil { if channel, ok := props.AsDirectLineChannel(); ok { if channelProps := channel.Properties; channelProps != nil { - d.Set("site", flattenDirectlineSites(*channelProps.Sites)) + d.Set("site", flattenDirectlineSites(filterSites(channelProps.Sites))) } } } @@ -208,12 +214,11 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac botName := d.Get("bot_name").(string) resourceGroup := d.Get("resource_group_name").(string) - sites := expandDirectlineSites(d.Get("site").(*schema.Set).List()) channel := botservice.BotChannel{ Properties: botservice.DirectLineChannel{ Properties: &botservice.DirectLineChannelProperties{ - Sites: sites, + Sites: expandDirectlineSites(d.Get("site").(*schema.Set).List()), }, ChannelName: botservice.ChannelNameDirectLineChannel1, }, @@ -225,6 +230,12 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } + // Create does not include sites properly, so we need to update as well + time.Sleep(10 * time.Second) + if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { + return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) + } + resp, err := client.Get(ctx, resourceGroup, botName, string(botservice.ChannelNameDirectLineChannel1)) if err != nil { return fmt.Errorf("Error making get request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) @@ -264,31 +275,39 @@ func resourceArmBotChannelDirectlineDelete(d *schema.ResourceData, meta interfac func expandDirectlineSites(input []interface{}) *[]botservice.DirectLineSite { sites := make([]botservice.DirectLineSite, len(input)) - for i, element := range input { + for _, element := range input { + if element == nil { + continue + } + site := element.(map[string]interface{}) + expanded := botservice.DirectLineSite{} if v, ok := site["name"].(string); ok { - sites[i].SiteName = &v + expanded.SiteName = &v } if v, ok := site["enabled"].(bool); ok { - sites[i].IsEnabled = &v + expanded.IsEnabled = &v } if v, ok := site["v1_allowed"].(bool); ok { - sites[i].IsV1Enabled = &v + expanded.IsV1Enabled = &v } if v, ok := site["v3_allowed"].(bool); ok { - sites[i].IsV3Enabled = &v + expanded.IsV3Enabled = &v } if v, ok := site["enhanced_authentication_enabled"].(bool); ok { - sites[i].IsSecureSiteEnabled = &v + expanded.IsSecureSiteEnabled = &v } - if v, ok := site["trusted_origins"].([]interface{}); ok { - items := make([]string, len(v)) - for i, raw := range v { + if v, ok := site["trusted_origins"].(*schema.Set); ok { + origins := v.List() + items := make([]string, len(origins)) + for i, raw := range origins { items[i] = raw.(string) } - sites[i].TrustedOrigins = &items + expanded.TrustedOrigins = &items } + + sites = append(sites, expanded) } return &sites @@ -337,3 +356,17 @@ func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { return sites } + +// When creating a new directline channel, a Default Site is created +// There is a race condition where this site is not removed before the create request is completed +func filterSites(sites *[]botservice.DirectLineSite) []botservice.DirectLineSite { + + filtered := make([]botservice.DirectLineSite, 0) + for _, site := range *sites { + if *site.SiteName == "Default Site" { + continue + } + filtered = append(filtered, site) + } + return filtered +} diff --git a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go index ccbe57ea5b31a..94c210e8eabf4 100644 --- a/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go +++ b/azurerm/internal/services/bot/tests/resource_arm_bot_channel_directline_test.go @@ -146,13 +146,13 @@ func testAccAzureRMBotChannelDirectline_basicConfig(data acceptance.TestData) st %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = true - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + } } `, template) } @@ -163,17 +163,17 @@ func testAccAzureRMBotChannelDirectline_completeConfig(data acceptance.TestData) %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = true - v1_allowed = true - v3_allowed = true - enhanced_authentication_enabled = true - trusted_origins = ["https://example.com"] - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = true + v1_allowed = true + v3_allowed = true + enhanced_authentication_enabled = true + trusted_origins = ["https://example.com"] + } } `, template) } @@ -184,13 +184,13 @@ func testAccAzureRMBotChannelDirectline_basicUpdate(data acceptance.TestData) st %s resource "azurerm_bot_channel_directline" "test" { - bot_name = "${azurerm_bot_channels_registration.test.name}" - location = "${azurerm_bot_channels_registration.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - site { - name = "test" - enabled = false - } + bot_name = "${azurerm_bot_channels_registration.test.name}" + location = "${azurerm_bot_channels_registration.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + site { + name = "test" + enabled = false + } } `, template) } diff --git a/website/azurerm.erb b/website/azurerm.erb index 648428026d863..4b3538480598f 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -846,6 +846,10 @@ azurerm_bot_channel_slack +
  • + azurerm_bot_channel_directline +
  • +
  • azurerm_bot_channels_registration
  • From 41402a1712f63ad2c8d50d89565eeb8579641fc7 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Thu, 13 Feb 2020 09:14:53 +0000 Subject: [PATCH 077/498] 2.0 todos and associated tests --- .../data_source_api_management.go | 28 +- .../resource_arm_api_management.go | 265 ++---------------- .../data_source_api_management_group_test.go | 6 +- ...data_source_api_management_product_test.go | 13 +- .../tests/data_source_api_management_test.go | 13 +- .../data_source_api_management_user_test.go | 13 +- ...e_arm_api_management_api_operation_test.go | 6 +- ...urce_arm_api_management_api_policy_test.go | 12 +- ...urce_arm_api_management_api_schema_test.go | 6 +- .../resource_arm_api_management_api_test.go | 6 +- ...arm_api_management_api_version_set_test.go | 6 +- ...pi_management_authorization_server_test.go | 6 +- ...esource_arm_api_management_backend_test.go | 6 +- ...rce_arm_api_management_certificate_test.go | 6 +- ...resource_arm_api_management_logger_test.go | 2 +- ...management_openid_connect_provider_test.go | 6 +- ..._arm_api_management_product_policy_test.go | 12 +- ...esource_arm_api_management_product_test.go | 6 +- .../tests/resource_arm_api_management_test.go | 79 ------ website/docs/r/api_management.html.markdown | 12 - 20 files changed, 54 insertions(+), 455 deletions(-) diff --git a/azurerm/internal/services/apimanagement/data_source_api_management.go b/azurerm/internal/services/apimanagement/data_source_api_management.go index f482b9cc0c902..329c8d0ff5b98 100644 --- a/azurerm/internal/services/apimanagement/data_source_api_management.go +++ b/azurerm/internal/services/apimanagement/data_source_api_management.go @@ -47,24 +47,6 @@ func dataSourceApiManagementService() *schema.Resource { Computed: true, }, - // TODO: Remove in 2.0 - "sku": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - }, - "capacity": { - Type: schema.TypeInt, - Computed: true, - }, - }, - }, - }, - "sku_name": { Type: schema.TypeString, Computed: true, @@ -211,15 +193,7 @@ func dataSourceApiManagementRead(d *schema.ResourceData, meta interface{}) error } } - if sku := resp.Sku; sku != nil { - // TODO: Remove in 2.0 - if err := d.Set("sku", flattenApiManagementServiceSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - if err := d.Set("sku_name", flattenApiManagementServiceSkuName(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku_name`: %+v", err) - } - } + d.Set("sku_name", flattenApiManagementServiceSkuName(resp.Sku)) return tags.FlattenAndSet(d, resp.Tags) } diff --git a/azurerm/internal/services/apimanagement/resource_arm_api_management.go b/azurerm/internal/services/apimanagement/resource_arm_api_management.go index 5146ebd6650df..02630cfe75391 100644 --- a/azurerm/internal/services/apimanagement/resource_arm_api_management.go +++ b/azurerm/internal/services/apimanagement/resource_arm_api_management.go @@ -75,41 +75,9 @@ func resourceArmApiManagementService() *schema.Resource { ValidateFunc: validate.ApiManagementServicePublisherEmail, }, - // TODO: Remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - ConflictsWith: []string{"sku_name"}, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(apimanagement.SkuTypeDeveloper), - string(apimanagement.SkuTypeBasic), - string(apimanagement.SkuTypeStandard), - string(apimanagement.SkuTypePremium), - }, false), - }, - - "capacity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntAtLeast(0), - }, - }, - }, - }, - "sku_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, // TODO: Remove computed in 2.0 - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: azure.MinCapacitySkuNameInSlice([]string{ string(apimanagement.SkuTypeDeveloper), string(apimanagement.SkuTypeBasic), @@ -205,7 +173,6 @@ func resourceArmApiManagementService() *schema.Resource { "protocols": { Type: schema.TypeList, Optional: true, - Computed: true, // TODO: remove in 2.0 MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -221,115 +188,40 @@ func resourceArmApiManagementService() *schema.Resource { "security": { Type: schema.TypeList, Optional: true, - Computed: true, // TODO: Remove in 2.0 ? MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "enable_backend_ssl30": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_backend_ssl30"}, + Type: schema.TypeBool, + Optional: true, }, "enable_backend_tls10": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_backend_tls10"}, + Type: schema.TypeBool, + Optional: true, }, "enable_backend_tls11": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_backend_tls11"}, + Type: schema.TypeBool, + Optional: true, }, "enable_frontend_ssl30": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_frontend_ssl30"}, + Type: schema.TypeBool, + Optional: true, }, "enable_frontend_tls10": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_frontend_tls10"}, + Type: schema.TypeBool, + Optional: true, }, "enable_frontend_tls11": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_frontend_tls11"}, + Type: schema.TypeBool, + Optional: true, }, "enable_triple_des_ciphers": { - Type: schema.TypeBool, - Optional: true, - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.disable_triple_des_chipers", "security.0.disable_triple_des_ciphers"}, - }, - - //the follow have all been replaced by the `enable` flags - "disable_backend_ssl30": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_backend_ssl30"}, - Deprecated: "This field has been deprecated in favour of the `enable_backend_ssl30` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_backend_tls10": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_backend_tls10"}, - Deprecated: "This field has been deprecated in favour of the `enable_backend_tls10` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_backend_tls11": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_backend_tls11"}, - Deprecated: "This field has been deprecated in favour of the `enable_backend_tls11` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_frontend_ssl30": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_frontend_ssl30"}, - Deprecated: "This field has been deprecated in favour of the `enable_frontend_ssl30` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_frontend_tls10": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_frontend_tls10"}, - Deprecated: "This field has been deprecated in favour of the `enable_frontend_tls10` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_frontend_tls11": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"security.0.enable_frontend_tls11"}, - Deprecated: "This field has been deprecated in favour of the `enable_frontend_tls11` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", - }, - "disable_triple_des_chipers": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Deprecated: "This field has been deprecated in favour of the `disable_triple_des_ciphers` property to correct the spelling. it will be removed in version 2.0 of the provider", - ConflictsWith: []string{"security.0.disable_triple_des_ciphers"}, - }, - "disable_triple_des_ciphers": { Type: schema.TypeBool, Optional: true, - // Default: false, // TODO: Remove in 2.0 - Computed: true, // TODO: Remove in 2.0 - ConflictsWith: []string{"security.0.enable_triple_des_ciphers"}, - Deprecated: "This field has been deprecated in favour of the `enable_triple_des_ciphers` which correctly reflects the boolean value. it will be removed in version 2.0 of the provider", }, }, }, @@ -486,13 +378,7 @@ func resourceArmApiManagementServiceCreateUpdate(d *schema.ResourceData, meta in ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - // TODO: Remove in 2.0 - sku := expandAzureRmApiManagementSku(d) - if sku == nil { - if sku = expandAzureRmApiManagementSkuName(d); sku == nil { - return fmt.Errorf("either 'sku_name' or 'sku' must be defined in the configuration file") - } - } + sku := expandAzureRmApiManagementSkuName(d) log.Printf("[INFO] preparing arguments for API Management Service creation.") @@ -693,14 +579,8 @@ func resourceArmApiManagementServiceRead(d *schema.ResourceData, meta interface{ } } - if sku := resp.Sku; sku != nil { - // TODO: Remove in 2.0 - if err := d.Set("sku", flattenApiManagementServiceSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - if err := d.Set("sku_name", flattenApiManagementServiceSkuName(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku_name`: %+v", err) - } + if err := d.Set("sku_name", flattenApiManagementServiceSkuName(resp.Sku)); err != nil { + return fmt.Errorf("Error setting `sku_name`: %+v", err) } if err := d.Set("sign_in", flattenApiManagementSignInSettings(signInSettings)); err != nil { @@ -985,29 +865,6 @@ func flattenAzureRmApiManagementMachineIdentity(identity *apimanagement.ServiceI return []interface{}{result} } -// TODO: Remove in 2.0 timeframe -func expandAzureRmApiManagementSku(d *schema.ResourceData) *apimanagement.ServiceSkuProperties { - var name string - var capacity int32 - - vs := d.Get("sku").([]interface{}) - - if len(vs) == 0 { - return nil - } - - // guaranteed by MinItems in the schema - v := vs[0].(map[string]interface{}) - - name = v["name"].(string) - capacity = int32(v["capacity"].(int)) - - return &apimanagement.ServiceSkuProperties{ - Name: apimanagement.SkuType(name), - Capacity: utils.Int32(capacity), - } -} - func expandAzureRmApiManagementSkuName(d *schema.ResourceData) *apimanagement.ServiceSkuProperties { vs := d.Get("sku_name").(string) @@ -1034,21 +891,6 @@ func flattenApiManagementServiceSkuName(input *apimanagement.ServiceSkuPropertie return fmt.Sprintf("%s_%d", string(input.Name), *input.Capacity) } -func flattenApiManagementServiceSku(input *apimanagement.ServiceSkuProperties) []interface{} { - if input == nil { - return []interface{}{} - } - - sku := make(map[string]interface{}) - - sku["name"] = string(input.Name) - if input.Capacity != nil { - sku["capacity"] = *input.Capacity - } - - return []interface{}{sku} -} - func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*string { backendProtocolSsl3 := false backendProtocolTls10 := false @@ -1058,61 +900,15 @@ func expandApiManagementCustomProperties(d *schema.ResourceData) map[string]*str frontendProtocolTls11 := false tripleDesCiphers := false - //if vs := d.Get("security").([]interface{}); len(vs) > 0 { - //v := vs[0].(map[string]interface{}) - // restore these in 2.0 - // backendProtocolSsl3 = v["enable_backend_ssl30"].(bool) - // backendProtocolTls10 = v["enable_backend_tls10"].(bool) - // backendProtocolTls11 = v["enable_backend_tls11"].(bool) - // frontendProtocolSsl3 = v["enable_frontend_ssl30"].(bool) - // frontendProtocolTls10 = v["enable_frontend_tls10"].(bool) - // frontendProtocolTls11 = v["enable_frontend_tls11"].(bool) - // tripleDesCiphers = v["enable_triple_des_ciphers"].(bool) - //} - - // remove all these for 2.0 - if c, ok := d.GetOkExists("security.0.enable_triple_des_ciphers"); ok { - tripleDesCiphers = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_triple_des_ciphers"); ok { - tripleDesCiphers = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_triple_des_chipers"); ok { - tripleDesCiphers = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_frontend_tls11"); ok { - frontendProtocolTls11 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_frontend_tls11"); ok { - frontendProtocolTls11 = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_frontend_tls10"); ok { - frontendProtocolTls10 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_frontend_tls10"); ok { - frontendProtocolTls10 = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_frontend_ssl30"); ok { - frontendProtocolSsl3 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_frontend_ssl30"); ok { - frontendProtocolSsl3 = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_backend_tls11"); ok { - backendProtocolTls11 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_backend_ssl30"); ok { - backendProtocolTls11 = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_backend_tls10"); ok { - backendProtocolTls10 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_backend_tls10"); ok { - backendProtocolTls10 = c.(bool) - } - - if c, ok := d.GetOkExists("security.0.enable_backend_ssl30"); ok { - backendProtocolSsl3 = c.(bool) - } else if c, ok := d.GetOkExists("security.0.disable_backend_ssl30"); ok { - backendProtocolSsl3 = c.(bool) + if vs := d.Get("security").([]interface{}); len(vs) > 0 { + v := vs[0].(map[string]interface{}) + backendProtocolSsl3 = v["enable_backend_ssl30"].(bool) + backendProtocolTls10 = v["enable_backend_tls10"].(bool) + backendProtocolTls11 = v["enable_backend_tls11"].(bool) + frontendProtocolSsl3 = v["enable_frontend_ssl30"].(bool) + frontendProtocolTls10 = v["enable_frontend_tls10"].(bool) + frontendProtocolTls11 = v["enable_frontend_tls11"].(bool) + tripleDesCiphers = v["enable_triple_des_ciphers"].(bool) } customProperties := map[string]*string{ @@ -1145,15 +941,6 @@ func flattenApiManagementSecurityCustomProperties(input map[string]*string) []in output["enable_frontend_tls11"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolTls11) output["enable_triple_des_ciphers"] = parseApiManagementNilableDictionary(input, apimTripleDesCiphers) - output["disable_backend_ssl30"] = parseApiManagementNilableDictionary(input, apimBackendProtocolSsl3) // TODO: Remove in 2.0 - output["disable_backend_tls10"] = parseApiManagementNilableDictionary(input, apimBackendProtocolTls10) // TODO: Remove in 2.0 - output["disable_backend_tls11"] = parseApiManagementNilableDictionary(input, apimBackendProtocolTls11) // TODO: Remove in 2.0 - output["disable_frontend_ssl30"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolSsl3) // TODO: Remove in 2.0 - output["disable_frontend_tls10"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolTls10) // TODO: Remove in 2.0 - output["disable_frontend_tls11"] = parseApiManagementNilableDictionary(input, apimFrontendProtocolTls11) // TODO: Remove in 2.0 - output["disable_triple_des_chipers"] = parseApiManagementNilableDictionary(input, apimTripleDesCiphers) // TODO: Remove in 2.0 - output["disable_triple_des_ciphers"] = parseApiManagementNilableDictionary(input, apimTripleDesCiphers) // TODO: Remove in 2.0 - return []interface{}{output} } diff --git a/azurerm/internal/services/apimanagement/tests/data_source_api_management_group_test.go b/azurerm/internal/services/apimanagement/tests/data_source_api_management_group_test.go index a5b18026b829f..91cc90ac5597c 100644 --- a/azurerm/internal/services/apimanagement/tests/data_source_api_management_group_test.go +++ b/azurerm/internal/services/apimanagement/tests/data_source_api_management_group_test.go @@ -41,11 +41,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_group" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/data_source_api_management_product_test.go b/azurerm/internal/services/apimanagement/tests/data_source_api_management_product_test.go index 4c6ae3ae60170..58d0a5d663c1f 100644 --- a/azurerm/internal/services/apimanagement/tests/data_source_api_management_product_test.go +++ b/azurerm/internal/services/apimanagement/tests/data_source_api_management_product_test.go @@ -39,15 +39,10 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - publisher_name = "pub1" - publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } - + name = "acctestAM-%d" + publisher_name = "pub1" + publisher_email = "pub1@email.com" + sku_name = "Developer_1" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" } diff --git a/azurerm/internal/services/apimanagement/tests/data_source_api_management_test.go b/azurerm/internal/services/apimanagement/tests/data_source_api_management_test.go index 0efd692c1e068..aeca7634a929f 100644 --- a/azurerm/internal/services/apimanagement/tests/data_source_api_management_test.go +++ b/azurerm/internal/services/apimanagement/tests/data_source_api_management_test.go @@ -39,15 +39,10 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - publisher_name = "pub1" - publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } - + name = "acctestAM-%d" + publisher_name = "pub1" + publisher_email = "pub1@email.com" + sku_name = "Developer_1" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" } diff --git a/azurerm/internal/services/apimanagement/tests/data_source_api_management_user_test.go b/azurerm/internal/services/apimanagement/tests/data_source_api_management_user_test.go index d418a69cc6f53..ed655416f8e53 100644 --- a/azurerm/internal/services/apimanagement/tests/data_source_api_management_user_test.go +++ b/azurerm/internal/services/apimanagement/tests/data_source_api_management_user_test.go @@ -38,15 +38,10 @@ resource "azurerm_resource_group" "test" { } resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - publisher_name = "pub1" - publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } - + name = "acctestAM-%d" + publisher_name = "pub1" + publisher_email = "pub1@email.com" + sku_name = "Developer_1" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go index dfbda05bd8862..2902e271967e3 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go @@ -496,11 +496,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_api" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_policy_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_policy_test.go index 01f78f6b64255..43d008e446358 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_policy_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_policy_test.go @@ -182,11 +182,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_api" "test" { @@ -235,11 +231,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_api" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go index 019fd65bb06b5..d71d224d70f96 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go @@ -157,11 +157,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_api" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_test.go index a0b0bb8dbb76c..858a33be0ca18 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_test.go @@ -534,11 +534,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_version_set_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_version_set_test.go index 660e2a0a763d5..5cd88d2aa9452 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_version_set_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_version_set_test.go @@ -268,11 +268,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_authorization_server_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_authorization_server_test.go index bce30b68d9904..4f6f621c00763 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_authorization_server_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_authorization_server_test.go @@ -222,11 +222,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_backend_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_backend_test.go index dabe3c2633f0b..33f50deae5a30 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_backend_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_backend_test.go @@ -450,11 +450,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } `, data.RandomInteger, testName, data.Locations.Primary, data.RandomInteger, testName) } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_certificate_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_certificate_test.go index 9e9f11a5df186..96fcbdf2be1e3 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_certificate_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_certificate_test.go @@ -131,11 +131,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_certificate" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_logger_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_logger_test.go index 03b6eb97fbce6..bf410a65df16e 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_logger_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_logger_test.go @@ -263,7 +263,7 @@ resource "azurerm_eventhub_namespace" "test" { name = "acctesteventhubnamespace-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Basic" + sku_name = "Basic_1" } resource "azurerm_eventhub" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_openid_connect_provider_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_openid_connect_provider_test.go index 7a165628b67de..fecf4454683b3 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_openid_connect_provider_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_openid_connect_provider_test.go @@ -194,11 +194,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_policy_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_policy_test.go index 0dbeffb131959..c9bfb50e67e78 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_policy_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_policy_test.go @@ -157,11 +157,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_product" "test" { @@ -209,11 +205,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_product" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_test.go index 308a9e97f331f..669148dcab8f7 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_product_test.go @@ -386,11 +386,7 @@ resource "azurerm_api_management" "test" { resource_group_name = "${azurerm_resource_group.test.name}" publisher_name = "pub1" publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } + sku_name = "Developer_1" } resource "azurerm_api_management_product" "test" { diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go index a31d047b5a5f4..4bcf07de2babe 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_test.go @@ -2,7 +2,6 @@ package tests import ( "fmt" - "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -32,43 +31,6 @@ func TestAccAzureRMApiManagement_basic(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMApiManagement_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_api_management", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMApiManagementDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMApiManagement_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMApiManagementExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -// Remove in 2.0 -func TestAccAzureRMApiManagement_basicNotDefined(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_api_management", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMApiManagementDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMApiManagement_basicNotDefined(data), - ExpectError: regexp.MustCompile("either 'sku_name' or 'sku' must be defined in the configuration file"), - }, - }, - }) -} - func TestAccAzureRMApiManagement_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -282,47 +244,6 @@ resource "azurerm_api_management" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -// Remove in 2.0 -func testAccAzureRMApiManagement_basicClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - publisher_name = "pub1" - publisher_email = "pub1@email.com" - - sku { - name = "Developer" - capacity = 1 - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -// Remove in 2.0 -func testAccAzureRMApiManagement_basicNotDefined(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_api_management" "test" { - name = "acctestAM-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - publisher_name = "pub1" - publisher_email = "pub1@email.com" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMApiManagement_policyXmlContent(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/api_management.html.markdown b/website/docs/r/api_management.html.markdown index 8dc484ad51a88..e4a863dec1482 100644 --- a/website/docs/r/api_management.html.markdown +++ b/website/docs/r/api_management.html.markdown @@ -55,8 +55,6 @@ The following arguments are supported: * `publisher_email` - (Required) The email of publisher/company. -* `sku` - (Deprecated) A `sku` block as documented below - * `sku_name` - (Required) `sku_name` is a string consisting of two parts separated by an underscore(\_). The fist part is the `name`, valid values include: `Developer`, `Basic`, `Standard` and `Premium`. The second part is the `capacity` (e.g. the number of deployed units of the `sku`), which must be a positive `integer` (e.g. `Developer_1`). --- @@ -232,16 +230,6 @@ A `security` block supports the following: --- -A `sku` block supports the following: (Deprecated) - -* `name` - (Required) Specifies the Pricing Tier for the API Management Service. Possible values include: Developer, Basic, Standard and Premium. - -* `capacity` - (Required) Specifies the Pricing Capacity for the API Management Service. - --> **Note:** This property has been deprecated in favour of the `sku_name` property and will be removed in version 2.0 of the provider. - ---- - A `sign_in` block supports the following: * `enabled` - (Required) Should anonymous users be redirected to the sign in page? From bd260e078676628ae30fdf87c60040b04f37beab Mon Sep 17 00:00:00 2001 From: jackofallops Date: Thu, 13 Feb 2020 10:36:25 +0000 Subject: [PATCH 078/498] added optional bool defaults for diff --- .../services/apimanagement/resource_arm_api_management.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/azurerm/internal/services/apimanagement/resource_arm_api_management.go b/azurerm/internal/services/apimanagement/resource_arm_api_management.go index 02630cfe75391..50c643795192a 100644 --- a/azurerm/internal/services/apimanagement/resource_arm_api_management.go +++ b/azurerm/internal/services/apimanagement/resource_arm_api_management.go @@ -194,34 +194,41 @@ func resourceArmApiManagementService() *schema.Resource { "enable_backend_ssl30": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_backend_tls10": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_backend_tls11": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_frontend_ssl30": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_frontend_tls10": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_frontend_tls11": { Type: schema.TypeBool, Optional: true, + Default: false, }, "enable_triple_des_ciphers": { Type: schema.TypeBool, Optional: true, + Default: false, }, }, }, From 88ac09e6e99c3bcdc6d43ddcefb0cbcd148e9e22 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Thu, 13 Feb 2020 14:32:19 +0000 Subject: [PATCH 079/498] Added Computed flag to TypeList resources with default values --- .../services/apimanagement/resource_arm_api_management.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azurerm/internal/services/apimanagement/resource_arm_api_management.go b/azurerm/internal/services/apimanagement/resource_arm_api_management.go index 50c643795192a..9a013976fa968 100644 --- a/azurerm/internal/services/apimanagement/resource_arm_api_management.go +++ b/azurerm/internal/services/apimanagement/resource_arm_api_management.go @@ -173,6 +173,7 @@ func resourceArmApiManagementService() *schema.Resource { "protocols": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -188,6 +189,7 @@ func resourceArmApiManagementService() *schema.Resource { "security": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ From d8e3d89c6a2993df5de22eb29d777d52ae87107a Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 21:46:35 -0800 Subject: [PATCH 080/498] postgres service to 2.0 --- .../resource_arm_postgresql_server.go | 161 +----------------- .../resource_arm_postgresql_server_test.go | 22 --- 2 files changed, 8 insertions(+), 175 deletions(-) diff --git a/azurerm/internal/services/postgres/resource_arm_postgresql_server.go b/azurerm/internal/services/postgres/resource_arm_postgresql_server.go index d1bcb127aef6e..8cc850d40b9c5 100644 --- a/azurerm/internal/services/postgres/resource_arm_postgresql_server.go +++ b/azurerm/internal/services/postgres/resource_arm_postgresql_server.go @@ -60,10 +60,8 @@ func resourceArmPostgreSQLServer() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), "sku_name": { - Type: schema.TypeString, - Optional: true, // required in 2.0 - Computed: true, // remove in 2.0 - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ "B_Gen4_1", "B_Gen4_2", @@ -88,82 +86,6 @@ func resourceArmPostgreSQLServer() *schema.Resource { }, false), }, - // remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku_name"}, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "B_Gen4_1", - "B_Gen4_2", - "B_Gen5_1", - "B_Gen5_2", - "GP_Gen4_2", - "GP_Gen4_4", - "GP_Gen4_8", - "GP_Gen4_16", - "GP_Gen4_32", - "GP_Gen5_2", - "GP_Gen5_4", - "GP_Gen5_8", - "GP_Gen5_16", - "GP_Gen5_32", - "GP_Gen5_64", - "MO_Gen5_2", - "MO_Gen5_4", - "MO_Gen5_8", - "MO_Gen5_16", - "MO_Gen5_32", - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - - "capacity": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntInSlice([]int{ - 1, - 2, - 4, - 8, - 16, - 32, - 64, - }), - }, - - "tier": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(postgresql.Basic), - string(postgresql.GeneralPurpose), - string(postgresql.MemoryOptimized), - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - - "family": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Gen4", - "Gen5", - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - }, - }, - }, - "administrator_login": { Type: schema.TypeString, Required: true, @@ -250,17 +172,6 @@ func resourceArmPostgreSQLServer() *schema.Resource { "tags": tags.Schema(), }, - - CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { - tier, _ := diff.GetOk("sku.0.tier") - storageMB, _ := diff.GetOk("storage_profile.0.storage_mb") - - if strings.ToLower(tier.(string)) == "basic" && storageMB.(int) > 1048576 { - return fmt.Errorf("basic pricing tier only supports upto 1,048,576 MB (1TB) of storage") - } - - return nil - }, } } @@ -288,17 +199,9 @@ func resourceArmPostgreSQLServerCreate(d *schema.ResourceData, meta interface{}) } } - var sku *postgresql.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandServerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for PostgreSQL Server %s (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandAzureRmPostgreSQLServerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for PostgreSQL Server %q (Resource Group %q)", name, resourceGroup) + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding `sku_name` for PostgreSQL Server %s (Resource Group %q): %v", name, resourceGroup, err) } properties := postgresql.ServerForCreate{ @@ -348,17 +251,9 @@ func resourceArmPostgreSQLServerUpdate(d *schema.ResourceData, meta interface{}) name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - var sku *postgresql.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandServerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for PostgreSQL Server %q (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandAzureRmPostgreSQLServerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for PostgreSQL Server %q (Resource Group %q)", name, resourceGroup) + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding `sku_name` for PostgreSQL Server %s (Resource Group %q): %v", name, resourceGroup, err) } properties := postgresql.ServerUpdateParameters{ @@ -428,9 +323,6 @@ func resourceArmPostgreSQLServerRead(d *schema.ResourceData, meta interface{}) e d.Set("version", string(resp.Version)) d.Set("ssl_enforcement", string(resp.SslEnforcement)) - if err := d.Set("sku", flattenPostgreSQLServerSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } if sku := resp.Sku; sku != nil { d.Set("sku_name", sku.Name) } @@ -508,23 +400,6 @@ func expandServerSkuName(skuName string) (*postgresql.Sku, error) { }, nil } -func expandAzureRmPostgreSQLServerSku(d *schema.ResourceData) *postgresql.Sku { - skus := d.Get("sku").([]interface{}) - sku := skus[0].(map[string]interface{}) - - name := sku["name"].(string) - capacity := sku["capacity"].(int) - tier := sku["tier"].(string) - family := sku["family"].(string) - - return &postgresql.Sku{ - Name: utils.String(name), - Tier: postgresql.SkuTier(tier), - Capacity: utils.Int32(int32(capacity)), - Family: utils.String(family), - } -} - func expandAzureRmPostgreSQLStorageProfile(d *schema.ResourceData) *postgresql.StorageProfile { storageprofiles := d.Get("storage_profile").([]interface{}) storageprofile := storageprofiles[0].(map[string]interface{}) @@ -542,26 +417,6 @@ func expandAzureRmPostgreSQLStorageProfile(d *schema.ResourceData) *postgresql.S } } -func flattenPostgreSQLServerSku(resp *postgresql.Sku) []interface{} { - values := map[string]interface{}{} - - if name := resp.Name; name != nil { - values["name"] = *name - } - - if capacity := resp.Capacity; capacity != nil { - values["capacity"] = *capacity - } - - values["tier"] = string(resp.Tier) - - if family := resp.Family; family != nil { - values["family"] = *family - } - - return []interface{}{values} -} - func flattenPostgreSQLStorageProfile(resp *postgresql.StorageProfile) []interface{} { values := map[string]interface{}{} diff --git a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go index a90489d476d83..7a137ac85862f 100644 --- a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go +++ b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go @@ -33,28 +33,6 @@ func TestAccAzureRMPostgreSQLServer_basicNinePointFive(t *testing.T) { }) } -// TODO: remove in 2.0 -func TestAccAzureRMPostgreSQLServer_basicNinePointFiveOldSku(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_postgresql_server", "test") - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMPostgreSQLServerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMPostgreSQLServer_basicNinePointFiveOldSku(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMPostgreSQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), - resource.TestCheckResourceAttr(data.ResourceName, "version", "9.5"), - resource.TestCheckResourceAttr(data.ResourceName, "ssl_enforcement", "Enabled"), - ), - }, - data.ImportStep("administrator_login_password"), - }, - }) -} - func TestAccAzureRMPostgreSQLServer_basicNinePointSix(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_postgresql_server", "test") resource.ParallelTest(t, resource.TestCase{ From 160f8cf963b4b4899583bf8df00a0b84df954a5f Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 09:57:12 -0800 Subject: [PATCH 081/498] Preparing the the storage package for 2.0 --- .../storage/resource_arm_storage_account.go | 65 +------------------ .../storage/resource_arm_storage_blob.go | 8 +-- .../storage/resource_arm_storage_table.go | 5 -- .../resource_arm_storage_account_test.go | 64 ------------------ .../tests/resource_arm_storage_table_test.go | 4 -- website/docs/r/storage_account.html.markdown | 4 -- website/docs/r/storage_table.html.markdown | 3 - 7 files changed, 6 insertions(+), 147 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index dda85e0d247f6..6380874a70c34 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -8,10 +8,6 @@ import ( "strings" "time" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/iothub" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" - - "github.com/Azure/azure-sdk-for-go/services/preview/security/mgmt/v1.0/security" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" azautorest "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/go-azure-helpers/response" @@ -24,8 +20,11 @@ import ( "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/locks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/iothub" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues" ) @@ -177,14 +176,6 @@ func resourceArmStorageAccount() *schema.Resource { ForceNew: true, }, - // TODO remove this in 2.0 for the dedicated resource - "enable_advanced_threat_protection": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the new 'azurerm_advanced_threat_protection' resource and will be removed in version 2.0 of the provider", - }, - "network_rules": { Type: schema.TypeList, Optional: true, @@ -646,7 +637,6 @@ func validateAzureRMStorageAccountTags(v interface{}, _ string) (warnings []stri func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Storage.AccountsClient - advancedThreatProtectionClient := meta.(*clients.Client).SecurityCenter.AdvancedThreatProtectionClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -766,22 +756,6 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e log.Printf("[INFO] storage account %q ID: %q", storageAccountName, *account.ID) d.SetId(*account.ID) - // TODO: deprecate & split this out into it's own resource in 2.0 - // as this is not available in all regions, and presumably off by default - // lets only try to set this value when true - // TODO in 2.0 switch to guarding this with d.GetOkExists() ? - if v := d.Get("enable_advanced_threat_protection").(bool); v { - advancedThreatProtectionSetting := security.AdvancedThreatProtectionSetting{ - AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ - IsEnabled: utils.Bool(v), - }, - } - - if _, err = advancedThreatProtectionClient.Create(ctx, d.Id(), advancedThreatProtectionSetting); err != nil { - return fmt.Errorf("Error updating Azure Storage Account enable_advanced_threat_protection %q: %+v", storageAccountName, err) - } - } - if val, ok := d.GetOk("blob_properties"); ok { // FileStorage does not support blob settings if accountKind != string(storage.FileStorage) { @@ -830,7 +804,6 @@ func resourceArmStorageAccountCreate(d *schema.ResourceData, meta interface{}) e // available requires a call to Update per parameter... func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Storage.AccountsClient - advancedThreatProtectionClient := meta.(*clients.Client).SecurityCenter.AdvancedThreatProtectionClient ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -989,20 +962,6 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e d.SetPartial("network_rules") } - if d.HasChange("enable_advanced_threat_protection") { - opts := security.AdvancedThreatProtectionSetting{ - AdvancedThreatProtectionProperties: &security.AdvancedThreatProtectionProperties{ - IsEnabled: utils.Bool(d.Get("enable_advanced_threat_protection").(bool)), - }, - } - - if _, err := advancedThreatProtectionClient.Create(ctx, d.Id(), opts); err != nil { - return fmt.Errorf("Error updating Azure Storage Account enable_advanced_threat_protection %q: %+v", storageAccountName, err) - } - - d.SetPartial("enable_advanced_threat_protection") - } - if d.HasChange("blob_properties") { // FileStorage does not support blob settings if accountKind != string(storage.FileStorage) { @@ -1052,7 +1011,6 @@ func resourceArmStorageAccountUpdate(d *schema.ResourceData, meta interface{}) e func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Storage.AccountsClient - advancedThreatProtectionClient := meta.(*clients.Client).SecurityCenter.AdvancedThreatProtectionClient endpointSuffix := meta.(*clients.Client).Account.Environment.StorageEndpointSuffix ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -1193,23 +1151,6 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err return err } - // TODO in 2.0 switch to guarding this with d.GetOkExists() - atp, err := advancedThreatProtectionClient.Get(ctx, d.Id()) - if err != nil { - msg := err.Error() - if !strings.Contains(msg, "The resource namespace 'Microsoft.Security' is invalid.") { - if !strings.Contains(msg, "No registered resource provider found for location '") { - if !strings.Contains(msg, "' and API version '2017-08-01-preview' for type ") { - return fmt.Errorf("Error reading the advanced threat protection settings of AzureRM Storage Account %q: %+v", name, err) - } - } - } - } else { - if atpp := atp.AdvancedThreatProtectionProperties; atpp != nil { - d.Set("enable_advanced_threat_protection", atpp.IsEnabled) - } - } - storageClient := meta.(*clients.Client).Storage account, err := storageClient.FindAccount(ctx, name) if err != nil { diff --git a/azurerm/internal/services/storage/resource_arm_storage_blob.go b/azurerm/internal/services/storage/resource_arm_storage_blob.go index bcf7801da9dbd..7e6835ac4c822 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_blob.go +++ b/azurerm/internal/services/storage/resource_arm_storage_blob.go @@ -9,7 +9,6 @@ import ( "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/suppress" "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" @@ -61,10 +60,9 @@ func resourceArmStorageBlob() *schema.Resource { }, "type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - DiffSuppressFunc: suppress.CaseDifference, // TODO: remove in 2.0 + Type: schema.TypeString, + Required: true, + ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ "Append", "Block", diff --git a/azurerm/internal/services/storage/resource_arm_storage_table.go b/azurerm/internal/services/storage/resource_arm_storage_table.go index 7d2960cafec03..21d52120c07da 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_table.go +++ b/azurerm/internal/services/storage/resource_arm_storage_table.go @@ -8,7 +8,6 @@ import ( "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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" @@ -63,9 +62,6 @@ func resourceArmStorageTable() *schema.Resource { ValidateFunc: ValidateArmStorageAccountName, }, - // TODO: deprecate this in the docs - "resource_group_name": azure.SchemaResourceGroupNameDeprecated(), - "acl": { Type: schema.TypeSet, Optional: true, @@ -199,7 +195,6 @@ func resourceArmStorageTableRead(d *schema.ResourceData, meta interface{}) error d.Set("name", id.TableName) d.Set("storage_account_name", id.AccountName) - d.Set("resource_group_name", account.ResourceGroup) if err := d.Set("acl", flattenStorageTableACLs(acls)); err != nil { return fmt.Errorf("Error flattening `acl`: %+v", err) diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index 24f8b1618d89e..aac39ac243f15 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -571,34 +571,6 @@ func TestAccAzureRMStorageAccount_networkRulesDeleted(t *testing.T) { }) } -func TestAccAzureRMStorageAccount_enableAdvancedThreatProtection(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMStorageAccount_enableAdvancedThreatProtection(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_advanced_threat_protection", "true"), - ), - }, - data.ImportStep(), - { - Config: testAccAzureRMStorageAccount_enableAdvancedThreatProtectionDisabled(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_advanced_threat_protection", "false"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMStorageAccount_blobProperties(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_storage_account", "test") @@ -1339,42 +1311,6 @@ resource "azurerm_storage_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomString) } -func testAccAzureRMStorageAccount_enableAdvancedThreatProtection(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_advanced_threat_protection = true -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - -func testAccAzureRMStorageAccount_enableAdvancedThreatProtectionDisabled(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-storage-%d" - location = "%s" -} - -resource "azurerm_storage_account" "test" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - account_tier = "Standard" - account_replication_type = "LRS" - enable_advanced_threat_protection = false -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString) -} - func testAccAzureRMStorageAccount_blobProperties(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_table_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_table_test.go index d07f2387d5b8b..391decdc72dd7 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_table_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_table_test.go @@ -277,7 +277,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_table" "test" { name = "acctestst%d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger) @@ -290,7 +289,6 @@ func testAccAzureRMStorageTable_requiresImport(data acceptance.TestData) string resource "azurerm_storage_table" "import" { name = "${azurerm_storage_table.test.name}" - resource_group_name = "${azurerm_storage_table.test.resource_group_name}" storage_account_name = "${azurerm_storage_table.test.storage_account_name}" } `, template) @@ -317,7 +315,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_table" "test" { name = "acctestst%d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" acl { id = "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI" @@ -353,7 +350,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_table" "test" { name = "acctestst%d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" acl { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index 95c4ccff93fd7..648f1440199db 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -105,10 +105,6 @@ The following arguments are supported: * `custom_domain` - (Optional) A `custom_domain` block as documented below. -* `enable_advanced_threat_protection` (Optional) Boolean flag which controls if advanced threat protection is enabled, see [here](https://docs.microsoft.com/en-us/azure/storage/common/storage-advanced-threat-protection) for more information. Defaults to `false`. - -~> **Note:** `enable_advanced_threat_protection` is not supported in all regions. - * `identity` - (Optional) A `identity` block as defined below. * `blob_properties` - (Optional) A `blob_properties` block as defined below. diff --git a/website/docs/r/storage_table.html.markdown b/website/docs/r/storage_table.html.markdown index 5107c08548abb..909864dfd0d8e 100644 --- a/website/docs/r/storage_table.html.markdown +++ b/website/docs/r/storage_table.html.markdown @@ -28,7 +28,6 @@ resource "azurerm_storage_account" "example" { resource "azurerm_storage_table" "example" { name = "mysampletable" - resource_group_name = azurerm_resource_group.example.name storage_account_name = azurerm_storage_account.example.name } ``` @@ -42,8 +41,6 @@ The following arguments are supported: * `storage_account_name` - (Required) Specifies the storage account in which to create the storage table. Changing this forces a new resource to be created. -* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to create the storage table. - * `acl` - (Optional) One or more `acl` blocks as defined below. --- From 4b239e07bff78cca9b92596dcad085273f9da49f Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 10:43:15 -0800 Subject: [PATCH 082/498] Removed additional deprecated fields --- .../storage/resource_arm_storage_account.go | 10 --- .../storage/resource_arm_storage_blob.go | 16 +---- .../storage/resource_arm_storage_container.go | 17 ----- .../storage/resource_arm_storage_queue.go | 4 -- .../storage/resource_arm_storage_share.go | 6 -- ...storage_account_blob_container_sas_test.go | 1 - .../resource_arm_storage_account_test.go | 18 ----- .../tests/resource_arm_storage_blob_test.go | 70 ++++++------------- .../resource_arm_storage_container_test.go | 9 --- .../tests/resource_arm_storage_share_test.go | 7 -- .../resource_arm_storage_table_entity_test.go | 1 - website/docs/r/storage_blob.html.markdown | 5 -- .../docs/r/storage_container.html.markdown | 5 -- website/docs/r/storage_queue.html.markdown | 3 - website/docs/r/storage_share.html.markdown | 3 - 15 files changed, 22 insertions(+), 153 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 6380874a70c34..f7a46c557dec3 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -78,15 +78,6 @@ func resourceArmStorageAccount() *schema.Resource { Default: string(storage.Storage), }, - "account_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This field has been split into `account_tier` and `account_replication_type`", - ValidateFunc: ValidateArmStorageAccountType, - DiffSuppressFunc: suppress.CaseDifference, - }, - "account_tier": { Type: schema.TypeString, Required: true, @@ -1064,7 +1055,6 @@ func resourceArmStorageAccountRead(d *schema.ResourceData, meta interface{}) err d.Set("account_kind", resp.Kind) if sku := resp.Sku; sku != nil { - d.Set("account_type", sku.Name) d.Set("account_tier", sku.Tier) d.Set("account_replication_type", strings.Split(fmt.Sprintf("%v", sku.Name), "_")[1]) } diff --git a/azurerm/internal/services/storage/resource_arm_storage_blob.go b/azurerm/internal/services/storage/resource_arm_storage_blob.go index 7e6835ac4c822..d9d469f5774b7 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_blob.go +++ b/azurerm/internal/services/storage/resource_arm_storage_blob.go @@ -8,7 +8,6 @@ import ( "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/clients" @@ -67,7 +66,7 @@ func resourceArmStorageBlob() *schema.Resource { "Append", "Block", "Page", - }, true), + }, false), }, "size": { @@ -131,18 +130,6 @@ func resourceArmStorageBlob() *schema.Resource { }, "metadata": MetaDataComputedSchema(), - - // Deprecated fields - "attempts": { - Type: schema.TypeInt, - Optional: true, - Default: 1, - ForceNew: true, - Deprecated: "Retries are now handled by the Azure SDK as such this field is no longer necessary and will be removed in v2.0 of the Azure Provider", - ValidateFunc: validation.IntAtLeast(1), - }, - - "resource_group_name": azure.SchemaResourceGroupNameDeprecated(), }, } } @@ -312,7 +299,6 @@ func resourceArmStorageBlobRead(d *schema.ResourceData, meta interface{}) error d.Set("name", id.BlobName) d.Set("storage_container_name", id.ContainerName) d.Set("storage_account_name", id.AccountName) - d.Set("resource_group_name", account.ResourceGroup) d.Set("access_tier", string(props.AccessTier)) d.Set("content_type", props.ContentType) diff --git a/azurerm/internal/services/storage/resource_arm_storage_container.go b/azurerm/internal/services/storage/resource_arm_storage_container.go index 0971adb3adaaf..f4aa2908d9a83 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_container.go +++ b/azurerm/internal/services/storage/resource_arm_storage_container.go @@ -7,7 +7,6 @@ import ( "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/clients" @@ -75,17 +74,6 @@ func resourceArmStorageContainer() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - - "resource_group_name": azure.SchemaResourceGroupNameDeprecated(), - - "properties": { - Type: schema.TypeMap, - Computed: true, - Deprecated: "This field will be removed in version 2.0 of the Azure Provider", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, }, } } @@ -229,7 +217,6 @@ func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) e d.Set("name", id.ContainerName) d.Set("storage_account_name", id.AccountName) - d.Set("resource_group_name", account.ResourceGroup) d.Set("container_access_type", flattenStorageContainerAccessLevel(props.AccessLevel)) @@ -237,10 +224,6 @@ func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error setting `metadata`: %+v", err) } - if err := d.Set("properties", flattenStorageContainerProperties(props)); err != nil { - return fmt.Errorf("Error setting `properties`: %+v", err) - } - d.Set("has_immutability_policy", props.HasImmutabilityPolicy) d.Set("has_legal_hold", props.HasLegalHold) diff --git a/azurerm/internal/services/storage/resource_arm_storage_queue.go b/azurerm/internal/services/storage/resource_arm_storage_queue.go index b512884cd6fbc..ba77e57565bad 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_queue.go +++ b/azurerm/internal/services/storage/resource_arm_storage_queue.go @@ -7,7 +7,6 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" @@ -50,8 +49,6 @@ func resourceArmStorageQueue() *schema.Resource { ValidateFunc: ValidateArmStorageAccountName, }, - "resource_group_name": azure.SchemaResourceGroupNameDeprecated(), - "metadata": MetaDataSchema(), }, } @@ -204,7 +201,6 @@ func resourceArmStorageQueueRead(d *schema.ResourceData, meta interface{}) error d.Set("name", id.QueueName) d.Set("storage_account_name", id.AccountName) - d.Set("resource_group_name", account.ResourceGroup) if err := d.Set("metadata", FlattenMetaData(metaData.MetaData)); err != nil { return fmt.Errorf("Error setting `metadata`: %s", err) diff --git a/azurerm/internal/services/storage/resource_arm_storage_share.go b/azurerm/internal/services/storage/resource_arm_storage_share.go index 04eb1ff535859..9c4edd8c7a436 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_share.go +++ b/azurerm/internal/services/storage/resource_arm_storage_share.go @@ -7,7 +7,6 @@ import ( "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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" @@ -55,8 +54,6 @@ func resourceArmStorageShare() *schema.Resource { ValidateFunc: ValidateArmStorageShareName, }, - "resource_group_name": azure.SchemaResourceGroupNameDeprecated(), - "storage_account_name": { Type: schema.TypeString, Required: true, @@ -230,9 +227,6 @@ func resourceArmStorageShareRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error flattening `acl`: %+v", err) } - // Deprecated: remove in 2.0 - d.Set("resource_group_name", account.ResourceGroup) - return nil } diff --git a/azurerm/internal/services/storage/tests/data_source_storage_account_blob_container_sas_test.go b/azurerm/internal/services/storage/tests/data_source_storage_account_blob_container_sas_test.go index 6b719546e072d..ac44c2e5bd8a3 100644 --- a/azurerm/internal/services/storage/tests/data_source_storage_account_blob_container_sas_test.go +++ b/azurerm/internal/services/storage/tests/data_source_storage_account_blob_container_sas_test.go @@ -65,7 +65,6 @@ resource "azurerm_storage_account" "storage" { resource "azurerm_storage_container" "container" { name = "sas-test" - resource_group_name = "${azurerm_resource_group.rg.name}" storage_account_name = "${azurerm_storage_account.storage.name}" container_access_type = "private" } diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go index aac39ac243f15..d436d6c51e09d 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_test.go @@ -18,24 +18,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/terraform" ) -func TestValidateArmStorageAccountType(t *testing.T) { - testCases := []struct { - input string - shouldError bool - }{ - {"standard_lrs", false}, - {"invalid", true}, - } - - for _, test := range testCases { - _, es := storage.ValidateArmStorageAccountType(test.input, "account_type") - - if test.shouldError && len(es) == 0 { - t.Fatalf("Expected validating account_type %q to fail", test.input) - } - } -} - func TestValidateArmStorageAccountName(t *testing.T) { testCases := []struct { input string diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go index ddc5438f401b7..33f70757fb2bc 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go @@ -54,7 +54,7 @@ func TestAccAzureRMStorageBlob_appendEmpty(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -78,7 +78,7 @@ func TestAccAzureRMStorageBlob_appendEmptyMetaData(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -102,7 +102,7 @@ func TestAccAzureRMStorageBlob_blockEmpty(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -126,7 +126,7 @@ func TestAccAzureRMStorageBlob_blockEmptyAzureADAuth(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -150,7 +150,7 @@ func TestAccAzureRMStorageBlob_blockEmptyMetaData(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -175,7 +175,7 @@ func TestAccAzureRMStorageBlob_blockEmptyAccessTier(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, { Config: testAccAzureRMStorageBlob_blockEmptyAccessTier(data, blobs.Hot), @@ -213,7 +213,7 @@ func TestAccAzureRMStorageBlob_blockFromInlineContent(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source_content", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source_content", "type"}, }, }, }) @@ -237,7 +237,7 @@ func TestAccAzureRMStorageBlob_blockFromPublicBlob(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source_uri", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source_uri", "type"}, }, }, }) @@ -261,7 +261,7 @@ func TestAccAzureRMStorageBlob_blockFromPublicFile(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source_uri", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source_uri", "type"}, }, }, }) @@ -285,7 +285,7 @@ func TestAccAzureRMStorageBlob_blockFromExistingBlob(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source_uri", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source_uri", "type"}, }, }, }) @@ -318,7 +318,7 @@ func TestAccAzureRMStorageBlob_blockFromLocalFile(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source", "type"}, }, }, }) @@ -342,7 +342,7 @@ func TestAccAzureRMStorageBlob_contentType(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, { Config: testAccAzureRMStorageBlob_contentTypeUpdated(data), @@ -354,7 +354,7 @@ func TestAccAzureRMStorageBlob_contentType(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -378,7 +378,7 @@ func TestAccAzureRMStorageBlob_contentTypePremium(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -402,7 +402,7 @@ func TestAccAzureRMStorageBlob_pageEmpty(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -426,7 +426,7 @@ func TestAccAzureRMStorageBlob_pageEmptyPremium(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -450,7 +450,7 @@ func TestAccAzureRMStorageBlob_pageEmptyMetaData(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -474,7 +474,7 @@ func TestAccAzureRMStorageBlob_pageFromExistingBlob(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source_uri", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source_uri", "type"}, }, }, }) @@ -507,7 +507,7 @@ func TestAccAzureRMStorageBlob_pageFromLocalFile(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "source", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "source", "type"}, }, }, }) @@ -554,7 +554,7 @@ func TestAccAzureRMStorageBlob_update(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, { Config: testAccAzureRMStorageBlob_updateUpdated(data), @@ -566,7 +566,7 @@ func TestAccAzureRMStorageBlob_update(t *testing.T) { ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"attempts", "parallelism", "size", "type"}, + ImportStateVerifyIgnore: []string{"parallelism", "size", "type"}, }, }, }) @@ -763,7 +763,6 @@ func testAccAzureRMStorageBlob_appendEmpty(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "append" @@ -778,7 +777,6 @@ func testAccAzureRMStorageBlob_appendEmptyMetaData(data acceptance.TestData) str resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "append" @@ -797,7 +795,6 @@ func testAccAzureRMStorageBlob_blockEmpty(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -823,7 +820,6 @@ func testAccAzureRMStorageBlob_blockEmptyMetaData(data acceptance.TestData) stri resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -842,7 +838,6 @@ func testAccAzureRMStorageBlob_blockEmptyAccessTier(data acceptance.TestData, ac resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -858,7 +853,6 @@ func testAccAzureRMStorageBlob_blockFromInlineContent(data acceptance.TestData) resource "azurerm_storage_blob" "test" { name = "rick.morty" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -874,7 +868,6 @@ func testAccAzureRMStorageBlob_blockFromPublicBlob(data acceptance.TestData) str resource "azurerm_storage_blob" "source" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -884,14 +877,12 @@ resource "azurerm_storage_blob" "source" { resource "azurerm_storage_container" "second" { name = "second" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } resource "azurerm_storage_blob" "test" { name = "copied.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.second.name}" type = "block" @@ -908,7 +899,6 @@ func testAccAzureRMStorageBlob_blockFromPublicFile(data acceptance.TestData) str resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -925,7 +915,6 @@ func testAccAzureRMStorageBlob_blockFromExistingBlob(data acceptance.TestData) s resource "azurerm_storage_blob" "source" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -935,7 +924,6 @@ resource "azurerm_storage_blob" "source" { resource "azurerm_storage_blob" "test" { name = "copied.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -952,7 +940,6 @@ func testAccAzureRMStorageBlob_blockFromLocalBlob(data acceptance.TestData, file resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -968,7 +955,6 @@ func testAccAzureRMStorageBlob_contentType(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.ext" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -985,7 +971,6 @@ func testAccAzureRMStorageBlob_contentTypePremium(data acceptance.TestData) stri resource "azurerm_storage_blob" "test" { name = "example.ext" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1002,7 +987,6 @@ func testAccAzureRMStorageBlob_contentTypeUpdated(data acceptance.TestData) stri resource "azurerm_storage_blob" "test" { name = "example.ext" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1019,7 +1003,6 @@ func testAccAzureRMStorageBlob_pageEmpty(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1035,7 +1018,6 @@ func testAccAzureRMStorageBlob_pageEmptyPremium(data acceptance.TestData) string resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1051,7 +1033,6 @@ func testAccAzureRMStorageBlob_pageEmptyMetaData(data acceptance.TestData) strin resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1071,7 +1052,6 @@ func testAccAzureRMStorageBlob_pageFromExistingBlob(data acceptance.TestData) st resource "azurerm_storage_blob" "source" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1081,7 +1061,6 @@ resource "azurerm_storage_blob" "source" { resource "azurerm_storage_blob" "test" { name = "copied.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1098,7 +1077,6 @@ func testAccAzureRMStorageBlob_pageFromLocalBlob(data acceptance.TestData, fileN resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "page" @@ -1146,7 +1124,6 @@ func testAccAzureRMStorageBlob_requiresImport(data acceptance.TestData) string { resource "azurerm_storage_blob" "import" { name = "${azurerm_storage_blob.test.name}" - resource_group_name = "${azurerm_storage_blob.test.resource_group_name}" storage_account_name = "${azurerm_storage_blob.test.storage_account_name}" storage_container_name = "${azurerm_storage_blob.test.storage_container_name}" type = "${azurerm_storage_blob.test.type}" @@ -1162,7 +1139,6 @@ func testAccAzureRMStorageBlob_update(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -1182,7 +1158,6 @@ func testAccAzureRMStorageBlob_updateUpdated(data acceptance.TestData) string { resource "azurerm_storage_blob" "test" { name = "example.vhd" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "block" @@ -1213,7 +1188,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "%s" } @@ -1238,7 +1212,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "%s" } @@ -1262,7 +1235,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "%s" } diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go index 45753cc73f351..a15e49e8ed850 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go @@ -311,7 +311,6 @@ func testAccAzureRMStorageContainer_basic(data acceptance.TestData) string { resource "azurerm_storage_container" "test" { name = "vhds" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -336,7 +335,6 @@ func testAccAzureRMStorageContainer_requiresImport(data acceptance.TestData) str resource "azurerm_storage_container" "import" { name = "${azurerm_storage_container.test.name}" - resource_group_name = "${azurerm_storage_container.test.resource_group_name}" storage_account_name = "${azurerm_storage_container.test.storage_account_name}" container_access_type = "${azurerm_storage_container.test.container_access_type}" } @@ -350,7 +348,6 @@ func testAccAzureRMStorageContainer_update(data acceptance.TestData, accessType resource "azurerm_storage_container" "test" { name = "vhds" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "%s" } @@ -364,7 +361,6 @@ func testAccAzureRMStorageContainer_metaData(data acceptance.TestData) string { resource "azurerm_storage_container" "test" { name = "vhds" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" @@ -382,7 +378,6 @@ func testAccAzureRMStorageContainer_metaDataUpdated(data acceptance.TestData) st resource "azurerm_storage_container" "test" { name = "vhds" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" @@ -401,7 +396,6 @@ func testAccAzureRMStorageContainer_metaDataEmpty(data acceptance.TestData) stri resource "azurerm_storage_container" "test" { name = "vhds" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" @@ -418,7 +412,6 @@ func testAccAzureRMStorageContainer_root(data acceptance.TestData) string { resource "azurerm_storage_container" "test" { name = "$root" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -432,7 +425,6 @@ func testAccAzureRMStorageContainer_web(data acceptance.TestData) string { resource "azurerm_storage_container" "test" { name = "$web" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -448,7 +440,6 @@ resource "azurerm_resource_group" "test" { resource "azurerm_storage_account" "test" { name = "acctestacc%s" - resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" account_tier = "Standard" account_replication_type = "LRS" diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_share_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_share_test.go index 211babe020461..be1d26afd4d9a 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_share_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_share_test.go @@ -266,7 +266,6 @@ func testAccAzureRMStorageShare_basic(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" } `, template, data.RandomString) @@ -279,7 +278,6 @@ func testAccAzureRMStorageShare_metaData(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" metadata = { @@ -296,7 +294,6 @@ func testAccAzureRMStorageShare_metaDataUpdated(data acceptance.TestData) string resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" metadata = { @@ -314,7 +311,6 @@ func testAccAzureRMStorageShare_acl(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" acl { @@ -337,7 +333,6 @@ func testAccAzureRMStorageShare_aclUpdated(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" acl { @@ -368,7 +363,6 @@ func testAccAzureRMStorageShare_requiresImport(data acceptance.TestData) string resource "azurerm_storage_share" "import" { name = "${azurerm_storage_share.test.name}" - resource_group_name = "${azurerm_storage_share.test.resource_group_name}" storage_account_name = "${azurerm_storage_share.test.storage_account_name}" } `, template) @@ -381,7 +375,6 @@ func testAccAzureRMStorageShare_updateQuota(data acceptance.TestData) string { resource "azurerm_storage_share" "test" { name = "testshare%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" quota = 5 } diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go index df29e6263cc51..d23872c16f7b7 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go @@ -249,7 +249,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_table" "test" { name = "acctestst%d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger) diff --git a/website/docs/r/storage_blob.html.markdown b/website/docs/r/storage_blob.html.markdown index 511f92eefe2bf..9ab5f98f37592 100644 --- a/website/docs/r/storage_blob.html.markdown +++ b/website/docs/r/storage_blob.html.markdown @@ -35,7 +35,6 @@ resource "azurerm_storage_container" "example" { resource "azurerm_storage_blob" "example" { name = "my-awesome-content.zip" - resource_group_name = azurerm_resource_group.example.name storage_account_name = azurerm_storage_account.example.name storage_container_name = azurerm_storage_container.example.name type = "Block" @@ -75,10 +74,6 @@ The following arguments are supported: * `metadata` - (Optional) A map of custom blob metadata. -* `attempts` - (Optional / **Deprecated**) The number of attempts to make per page or block when uploading. Defaults to `1`. - -* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to create the storage container. - ## Attributes Reference The following attributes are exported in addition to the arguments listed above: diff --git a/website/docs/r/storage_container.html.markdown b/website/docs/r/storage_container.html.markdown index eddbca6ffccc7..3600e019e1732 100644 --- a/website/docs/r/storage_container.html.markdown +++ b/website/docs/r/storage_container.html.markdown @@ -32,7 +32,6 @@ resource "azurerm_storage_account" "example" { resource "azurerm_storage_container" "example" { name = "vhds" - resource_group_name = azurerm_resource_group.example.name storage_account_name = azurerm_storage_account.example.name container_access_type = "private" } @@ -50,8 +49,6 @@ The following arguments are supported: * `metadata` - (Optional) A mapping of MetaData for this Container. -* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to create the storage container. This field is no longer used and will be removed in 2.0. - ## Attributes Reference The following attributes are exported in addition to the arguments listed above: @@ -62,8 +59,6 @@ The following attributes are exported in addition to the arguments listed above: * `has_legal_hold` - Is there a Legal Hold configured on this Storage Container? -* `properties` - (**Deprecated**) Key-value definition of additional properties associated to the Storage Container - ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: diff --git a/website/docs/r/storage_queue.html.markdown b/website/docs/r/storage_queue.html.markdown index e4223e600f2f1..06aee1e33cc70 100644 --- a/website/docs/r/storage_queue.html.markdown +++ b/website/docs/r/storage_queue.html.markdown @@ -28,7 +28,6 @@ resource "azurerm_storage_account" "example" { resource "azurerm_storage_queue" "example" { name = "mysamplequeue" - resource_group_name = azurerm_resource_group.example.name storage_account_name = azurerm_storage_account.example.name } ``` @@ -41,8 +40,6 @@ The following arguments are supported: * `storage_account_name` - (Required) Specifies the Storage Account in which the Storage Queue should exist. Changing this forces a new resource to be created. -* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to create the storage queue. - * `metadata` - (Optional) A mapping of MetaData which should be assigned to this Storage Queue. ## Attributes Reference diff --git a/website/docs/r/storage_share.html.markdown b/website/docs/r/storage_share.html.markdown index 49a593513ad30..fb8213835e31c 100644 --- a/website/docs/r/storage_share.html.markdown +++ b/website/docs/r/storage_share.html.markdown @@ -48,9 +48,6 @@ The following arguments are supported: * `metadata` - (Optional) A mapping of MetaData for this File Share. -* `resource_group_name` - (Optional / **Deprecated**) The name of the resource group in which to - create the share. Changing this forces a new resource to be created. - --- A `acl` block supports the following: From 36a5888307a4655e1e8a80d971bdc3339c36cddb Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 10:45:16 -0800 Subject: [PATCH 083/498] fix imports --- .../internal/services/storage/resource_arm_storage_account.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index f7a46c557dec3..9d1fa745a2e9f 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -24,7 +24,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/network" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" "github.com/tombuildsstuff/giovanni/storage/2018-11-09/queue/queues" ) From d8a66011f3e0387ece6a258f308dd7383b2ae05f Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 11:53:14 -0800 Subject: [PATCH 084/498] fix up tests --- .../data_source_storage_container_test.go | 1 - .../tests/resource_arm_storage_blob_test.go | 42 +++++++++---------- .../resource_arm_storage_container_test.go | 1 + 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/azurerm/internal/services/storage/tests/data_source_storage_container_test.go b/azurerm/internal/services/storage/tests/data_source_storage_container_test.go index 351a2ab4e5a34..2797f681fb284 100644 --- a/azurerm/internal/services/storage/tests/data_source_storage_container_test.go +++ b/azurerm/internal/services/storage/tests/data_source_storage_container_test.go @@ -47,7 +47,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "containerdstest-%s" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" metadata = { diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go index 33f70757fb2bc..c8be718c8028f 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go @@ -765,7 +765,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "append" + type = "Append" } `, template) } @@ -779,7 +779,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "append" + type = "Append" metadata = { hello = "world" @@ -797,7 +797,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" } `, template) } @@ -822,7 +822,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" metadata = { hello = "world" @@ -840,7 +840,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" access_tier = "%s" } `, template, string(accessTier)) @@ -855,7 +855,7 @@ resource "azurerm_storage_blob" "test" { name = "rick.morty" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source_content = "Wubba Lubba Dub Dub" } `, template) @@ -870,7 +870,7 @@ resource "azurerm_storage_blob" "source" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" content_type = "application/x-iso9660-image" } @@ -885,7 +885,7 @@ resource "azurerm_storage_blob" "test" { name = "copied.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.second.name}" - type = "block" + type = "Block" source_uri = "${azurerm_storage_blob.source.id}" content_type = "${azurerm_storage_blob.source.content_type}" } @@ -901,7 +901,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" content_type = "application/x-iso9660-image" } @@ -917,7 +917,7 @@ resource "azurerm_storage_blob" "source" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" content_type = "application/x-iso9660-image" } @@ -926,7 +926,7 @@ resource "azurerm_storage_blob" "test" { name = "copied.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source_uri = "${azurerm_storage_blob.source.id}" content_type = "${azurerm_storage_blob.source.content_type}" } @@ -942,7 +942,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" source = "%s" } `, template, fileName) @@ -957,7 +957,7 @@ resource "azurerm_storage_blob" "test" { name = "example.ext" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 content_type = "image/png" } @@ -973,7 +973,7 @@ resource "azurerm_storage_blob" "test" { name = "example.ext" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 content_type = "image/png" } @@ -989,7 +989,7 @@ resource "azurerm_storage_blob" "test" { name = "example.ext" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 content_type = "image/gif" } @@ -1005,7 +1005,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 } `, template) @@ -1020,7 +1020,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 } `, template) @@ -1035,7 +1035,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 metadata = { @@ -1063,7 +1063,7 @@ resource "azurerm_storage_blob" "test" { name = "copied.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" source_uri = "${azurerm_storage_blob.source.id}" content_type = "${azurerm_storage_blob.source.content_type}" } @@ -1079,7 +1079,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" source = "%s" } `, template, fileName) @@ -1160,7 +1160,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" size = 5120 content_type = "vnd/mountain-mover-3000" metadata = { diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go index a15e49e8ed850..f1e8a151ed680 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_container_test.go @@ -440,6 +440,7 @@ resource "azurerm_resource_group" "test" { resource "azurerm_storage_account" "test" { name = "acctestacc%s" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" account_tier = "Standard" account_replication_type = "LRS" From 35f7f202a4298c66f9bec3a6a06af6159fd83bf1 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 14:35:52 -0800 Subject: [PATCH 085/498] Continue fixing tests --- .../tests/data_source_storage_management_policy_test.go | 2 +- .../services/storage/tests/resource_arm_storage_blob_test.go | 4 ++-- .../resource_arm_storage_data_lake_gen2_filesystem_test.go | 2 +- .../storage/tests/resource_arm_storage_table_entity_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/storage/tests/data_source_storage_management_policy_test.go b/azurerm/internal/services/storage/tests/data_source_storage_management_policy_test.go index 2c1e9ad47d5ac..28b5e8394d2df 100644 --- a/azurerm/internal/services/storage/tests/data_source_storage_management_policy_test.go +++ b/azurerm/internal/services/storage/tests/data_source_storage_management_policy_test.go @@ -9,7 +9,7 @@ import ( ) func TestAccDataSourceAzureRMStorageManagementPolicy_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_storage_account", "test") + data := acceptance.BuildTestData(t, "data.azurerm_storage_management_policy", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go index c8be718c8028f..b0f6f4e4dc5cc 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go @@ -1054,7 +1054,7 @@ resource "azurerm_storage_blob" "source" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "page" + type = "Page" size = 5120 content_type = "application/x-iso9660-image" } @@ -1141,7 +1141,7 @@ resource "azurerm_storage_blob" "test" { name = "example.vhd" storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" - type = "block" + type = "Block" size = 5120 content_type = "vnd/panda+pops" metadata = { diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_data_lake_gen2_filesystem_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_data_lake_gen2_filesystem_test.go index 44d993cc0c86f..b43b5a26b6871 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_data_lake_gen2_filesystem_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_data_lake_gen2_filesystem_test.go @@ -155,7 +155,7 @@ func testAccAzureRMStorageDataLakeGen2FileSystem_requiresImport(data acceptance. resource "azurerm_storage_data_lake_gen2_filesystem" "import" { name = azurerm_storage_data_lake_gen2_filesystem.test.name - storage_account_id = azurerm_storage_data_lake_gen2_filesystem.storage_account_id + storage_account_id = azurerm_storage_data_lake_gen2_filesystem.test.storage_account_id } `, template) } diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go index d23872c16f7b7..2598bb8bcf363 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go @@ -37,7 +37,7 @@ func TestAccAzureRMTableEntity_requiresImport(t *testing.T) { t.Skip("Skipping since resources aren't required to be imported") return } - data := acceptance.BuildTestData(t, "azurerm_storage_table_entity", "test") + data := acceptance.BuildTestData(t, "azurerm_storage_table_entity", "import") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -200,7 +200,7 @@ func testAccAzureRMTableEntity_requiresImport(data acceptance.TestData) string { return fmt.Sprintf(` %s -resource "azurerm_storage_table_entity" "test" { +resource "azurerm_storage_table_entity" "import" { storage_account_name = "${azurerm_storage_account.test.name}" table_name = "${azurerm_storage_table.test.name}" From 81d8944f0a1b3007b2a2a24a22aa8a487d41aafb Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 14:37:45 -0800 Subject: [PATCH 086/498] Revert web changes --- .../web/resource_arm_app_service_plan.go | 62 ++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/azurerm/internal/services/web/resource_arm_app_service_plan.go b/azurerm/internal/services/web/resource_arm_app_service_plan.go index db32dd0b5efde..93d65b7652da9 100644 --- a/azurerm/internal/services/web/resource_arm_app_service_plan.go +++ b/azurerm/internal/services/web/resource_arm_app_service_plan.go @@ -94,21 +94,63 @@ func resourceArmAppServicePlan() *schema.Resource { }, }, + "properties": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Deprecated: "These properties have been moved to the top level", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "app_service_environment_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + Deprecated: "This property has been moved to the top level", + ConflictsWith: []string{"app_service_environment_id"}, + }, + + "reserved": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Deprecated: "This property has been moved to the top level", + ConflictsWith: []string{"reserved"}, + }, + + "per_site_scaling": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Deprecated: "This property has been moved to the top level", + ConflictsWith: []string{"per_site_scaling"}, + }, + }, + }, + }, + /// AppServicePlanProperties "app_service_environment_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ConflictsWith: []string{"properties.0.app_service_environment_id"}, }, "per_site_scaling": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"properties.0.per_site_scaling"}, }, "reserved": { - Type: schema.TypeBool, - Optional: true, + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"properties.0.reserved"}, }, "maximum_elastic_worker_count": { @@ -264,6 +306,10 @@ func resourceArmAppServicePlanRead(d *schema.ResourceData, meta interface{}) err d.Set("kind", resp.Kind) if props := resp.AppServicePlanProperties; props != nil { + if err := d.Set("properties", flattenAppServiceProperties(props)); err != nil { + return fmt.Errorf("Error setting `properties`: %+v", err) + } + if profile := props.HostingEnvironmentProfile; profile != nil { d.Set("app_service_environment_id", profile.ID) } @@ -366,4 +412,4 @@ func validateAppServicePlanName(v interface{}, k string) (warnings []string, err } return warnings, errors -} +} \ No newline at end of file From 9353b9efadce355e6aac807b5988e09f65781455 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 18:04:13 -0800 Subject: [PATCH 087/498] Update resource_arm_app_service_plan.go --- azurerm/internal/services/web/resource_arm_app_service_plan.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/web/resource_arm_app_service_plan.go b/azurerm/internal/services/web/resource_arm_app_service_plan.go index 93d65b7652da9..cb867d4ad749d 100644 --- a/azurerm/internal/services/web/resource_arm_app_service_plan.go +++ b/azurerm/internal/services/web/resource_arm_app_service_plan.go @@ -412,4 +412,4 @@ func validateAppServicePlanName(v interface{}, k string) (warnings []string, err } return warnings, errors -} \ No newline at end of file +} From f0c23ee719be4f9a5717bd6e54204f99dfc4d4c5 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Wed, 12 Feb 2020 18:05:29 -0800 Subject: [PATCH 088/498] Remove unused method --- .../storage/resource_arm_storage_container.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_container.go b/azurerm/internal/services/storage/resource_arm_storage_container.go index f4aa2908d9a83..2efbdf8154696 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_container.go +++ b/azurerm/internal/services/storage/resource_arm_storage_container.go @@ -260,21 +260,6 @@ func resourceArmStorageContainerDelete(d *schema.ResourceData, meta interface{}) return nil } -func flattenStorageContainerProperties(input containers.ContainerProperties) map[string]interface{} { - output := map[string]interface{}{ - "last_modified": input.Header.Get("Last-Modified"), - "lease_duration": "", - "lease_state": string(input.LeaseState), - "lease_status": string(input.LeaseStatus), - } - - if input.LeaseDuration != nil { - output["lease_duration"] = string(*input.LeaseDuration) - } - - return output -} - func expandStorageContainerAccessLevel(input string) containers.AccessLevel { // for historical reasons, "private" above is an empty string in the API // so the enum doesn't 1:1 match. You could argue the SDK should handle this From b6d0fb85bc9c86b402511ef22c581a80c3c128bb Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 13 Feb 2020 12:41:40 +0100 Subject: [PATCH 089/498] r/storage: fixing broken tests --- .../storage/tests/resource_arm_storage_blob_test.go | 6 +++--- .../storage/tests/resource_arm_storage_table_entity_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go index b0f6f4e4dc5cc..a1916bf6f0308 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_blob_test.go @@ -871,7 +871,7 @@ resource "azurerm_storage_blob" "source" { storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "Block" - source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" + source_uri = "http://old-releases.ubuntu.com/releases/bionic/ubuntu-18.04-desktop-amd64.iso" content_type = "application/x-iso9660-image" } @@ -902,7 +902,7 @@ resource "azurerm_storage_blob" "test" { storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "Block" - source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" + source_uri = "http://old-releases.ubuntu.com/releases/bionic/ubuntu-18.04-desktop-amd64.iso" content_type = "application/x-iso9660-image" } `, template) @@ -918,7 +918,7 @@ resource "azurerm_storage_blob" "source" { storage_account_name = "${azurerm_storage_account.test.name}" storage_container_name = "${azurerm_storage_container.test.name}" type = "Block" - source_uri = "http://releases.ubuntu.com/18.04.3/ubuntu-18.04.3-desktop-amd64.iso" + source_uri = "http://old-releases.ubuntu.com/releases/bionic/ubuntu-18.04-desktop-amd64.iso" content_type = "application/x-iso9660-image" } diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go index 2598bb8bcf363..8f31b96016a08 100644 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_table_entity_test.go @@ -37,7 +37,7 @@ func TestAccAzureRMTableEntity_requiresImport(t *testing.T) { t.Skip("Skipping since resources aren't required to be imported") return } - data := acceptance.BuildTestData(t, "azurerm_storage_table_entity", "import") + data := acceptance.BuildTestData(t, "azurerm_storage_table_entity", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, From 698f296d3da9b63f26021dcbf35714910292aacd Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 13 Feb 2020 13:07:34 +0100 Subject: [PATCH 090/498] r/storage_account_network_rules: switching to use the networkruleset from props --- .../storage/resource_arm_storage_account_network_rules.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go index a85b4e115b252..6e987f0f79b87 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go @@ -115,11 +115,15 @@ func resourceArmStorageAccountNetworkRulesCreateUpdate(d *schema.ResourceData, m return fmt.Errorf("Storage Account %q (Resource Group %q) was not found", storageAccountName, resourceGroup) } - return fmt.Errorf("Error loading Storage Account %q (Resource Group %q): %+v", storageAccountName, resourceGroup, err) + return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): %+v", storageAccountName, resourceGroup, err) } if features.ShouldResourcesBeImported() { - if checkForNonDefaultStorageAccountNetworkRule(storageAccount.NetworkRuleSet) { + if storageAccount.AccountProperties == nil { + return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): `properties` was nil", storageAccountName, resourceGroup) + } + + if checkForNonDefaultStorageAccountNetworkRule(storageAccount.AccountProperties.NetworkRuleSet) { return tf.ImportAsExistsError("azurerm_storage_account_network_rule", *storageAccount.ID) } } From cfe947b1cab3c9c960db48372561524aedfcd411 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 13 Feb 2020 13:46:34 +0100 Subject: [PATCH 091/498] r/app_service_plan: fixing a bad rebase --- .../internal/services/web/resource_arm_app_service_plan.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/azurerm/internal/services/web/resource_arm_app_service_plan.go b/azurerm/internal/services/web/resource_arm_app_service_plan.go index cb867d4ad749d..70ced7d9b7328 100644 --- a/azurerm/internal/services/web/resource_arm_app_service_plan.go +++ b/azurerm/internal/services/web/resource_arm_app_service_plan.go @@ -306,10 +306,6 @@ func resourceArmAppServicePlanRead(d *schema.ResourceData, meta interface{}) err d.Set("kind", resp.Kind) if props := resp.AppServicePlanProperties; props != nil { - if err := d.Set("properties", flattenAppServiceProperties(props)); err != nil { - return fmt.Errorf("Error setting `properties`: %+v", err) - } - if profile := props.HostingEnvironmentProfile; profile != nil { d.Set("app_service_environment_id", profile.ID) } From ab640a81c460681caf66b7531c1ce06058366587 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 13 Feb 2020 18:58:08 +0100 Subject: [PATCH 092/498] r/postgresql_server: fixing broken tests --- .../resource_arm_postgresql_server_test.go | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go index 7a137ac85862f..e5011a79dc950 100644 --- a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go +++ b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go @@ -213,7 +213,7 @@ func TestAccAzureRMPostgreSQLServer_updated(t *testing.T) { Config: testAccAzureRMPostgreSQLServer_basicNinePointSix(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPostgreSQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_2"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_2"), resource.TestCheckResourceAttr(data.ResourceName, "version", "9.6"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "51200"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.auto_grow", "Disabled"), @@ -246,10 +246,7 @@ func TestAccAzureRMPostgreSQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMPostgreSQLServer_generalPurpose(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPostgreSQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_32"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.capacity", "32"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.tier", "GeneralPurpose"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.family", "Gen5"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_32"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), @@ -258,10 +255,7 @@ func TestAccAzureRMPostgreSQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMPostgreSQLServer_memoryOptimized(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPostgreSQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "MO_Gen5_16"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.capacity", "16"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.tier", "MemoryOptimized"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.family", "Gen5"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "MO_Gen5_16"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "4194304"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), @@ -582,13 +576,7 @@ resource "azurerm_postgresql_server" "test" { name = "acctest-psql-server-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "MO_Gen5_16" - capacity = 16 - tier = "MemoryOptimized" - family = "Gen5" - } + sku_name = "MO_Gen5_16" storage_profile { storage_mb = 4194304 From a703f356acc1c04c6aa31549aa4525db7c4c24de Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Thu, 13 Feb 2020 19:13:25 +0100 Subject: [PATCH 093/498] r/postgresql_server: missed a failing test condition --- .../postgres/tests/resource_arm_postgresql_server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go index e5011a79dc950..b6a6ad04b8ea9 100644 --- a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go +++ b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go @@ -224,7 +224,7 @@ func TestAccAzureRMPostgreSQLServer_updated(t *testing.T) { Config: testAccAzureRMPostgreSQLServer_basicNinePointSixUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMPostgreSQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_4"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_4"), resource.TestCheckResourceAttr(data.ResourceName, "version", "9.6"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.auto_grow", "Enabled"), From 1d4684a36f4e26ec7919418e37b5fe6b0ef5b659 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 13 Feb 2020 14:56:28 -0800 Subject: [PATCH 094/498] Rename resource --- azurerm/helpers/azure/key_vault.go | 10 + azurerm/internal/acceptance/data.go | 13 +- .../internal/services/storage/registration.go | 24 +- ...rm_storage_account_customer_managed_key.go | 249 +++++++++++++ ...arm_storage_account_encryption_settings.go | 325 ----------------- ...orage_account_customer_managed_key_test.go | 221 ++++++++++++ ...torage_account_encryption_settings_test.go | 341 ------------------ ...ccount_customer_managed_key.html.markdown} | 53 +-- 8 files changed, 524 insertions(+), 712 deletions(-) create mode 100644 azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go delete mode 100644 azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go create mode 100644 azurerm/internal/services/storage/tests/resource_arm_storage_account_customer_managed_key_test.go delete mode 100644 azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go rename website/docs/r/{storage_account_encryption_settings.html.markdown => storage_account_customer_managed_key.html.markdown} (58%) diff --git a/azurerm/helpers/azure/key_vault.go b/azurerm/helpers/azure/key_vault.go index b070b87a71600..e5e68e8ec8ef8 100644 --- a/azurerm/helpers/azure/key_vault.go +++ b/azurerm/helpers/azure/key_vault.go @@ -7,6 +7,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -192,3 +193,12 @@ func KeyVaultIsSoftDeleteAndPurgeProtected(ctx context.Context, client *keyvault return false } + +func KeyVaultGetResourceNameResource(resourceId string, namePathKey string) (resourceName interface{}, resourceGroup interface{}, err error) { + id, err := azure.ParseAzureResourceID(resourceId) + if err != nil { + return nil, nil, err + } + + return id.Path[namePathKey], id.ResourceGroup, nil +} diff --git a/azurerm/internal/acceptance/data.go b/azurerm/internal/acceptance/data.go index 3e79ea88bee17..2a7ad06e102e7 100644 --- a/azurerm/internal/acceptance/data.go +++ b/azurerm/internal/acceptance/data.go @@ -24,7 +24,7 @@ type TestData struct { // Locations is a set of Azure Regions which should be used for this Test Locations Regions - // RandomString is a random integer which is unique to this test case + // RandomInteger is a random integer which is unique to this test case RandomInteger int // RandomString is a random 5 character string is unique to this test case @@ -90,6 +90,7 @@ func BuildTestData(t *testing.T, resourceType string, resourceLabel string) Test return testData } +// RandomIntOfLength is a random 8 to 18 digit integer which is unique to this test case func (td *TestData) RandomIntOfLength(len int) int { // len should not be // - greater then 18, longest a int can represent @@ -116,3 +117,13 @@ func (td *TestData) RandomIntOfLength(len int) int { return i } + +// RandomStringOfLength is a random 1 to 1024 character string which is unique to this test case +func (td *TestData) RandomStringOfLength(len int) string { + // len should not be less then 1 or greater than 1024 + if 1 > len || len > 1024 { + panic(fmt.Sprintf("Invalid Test: RandomStringOfLength: length argument must be between 1 and 1024 characters")) + } + + return acctest.RandString(len) +} diff --git a/azurerm/internal/services/storage/registration.go b/azurerm/internal/services/storage/registration.go index bc6bb490477ab..608eebed13136 100644 --- a/azurerm/internal/services/storage/registration.go +++ b/azurerm/internal/services/storage/registration.go @@ -25,17 +25,17 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_storage_account": resourceArmStorageAccount(), - "azurerm_storage_account_encryption_settings": resourceArmStorageAccountEncryptionSettings(), - "azurerm_storage_account_network_rules": resourceArmStorageAccountNetworkRules(), - "azurerm_storage_blob": resourceArmStorageBlob(), - "azurerm_storage_container": resourceArmStorageContainer(), - "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), - "azurerm_storage_management_policy": resourceArmStorageManagementPolicy(), - "azurerm_storage_queue": resourceArmStorageQueue(), - "azurerm_storage_share": resourceArmStorageShare(), - "azurerm_storage_share_directory": resourceArmStorageShareDirectory(), - "azurerm_storage_table": resourceArmStorageTable(), - "azurerm_storage_table_entity": resourceArmStorageTableEntity(), + "azurerm_storage_account": resourceArmStorageAccount(), + "azurerm_storage_account_customer_managed_key": resourceArmStorageAccountCustomerManagedKey(), + "azurerm_storage_account_network_rules": resourceArmStorageAccountNetworkRules(), + "azurerm_storage_blob": resourceArmStorageBlob(), + "azurerm_storage_container": resourceArmStorageContainer(), + "azurerm_storage_data_lake_gen2_filesystem": resourceArmStorageDataLakeGen2FileSystem(), + "azurerm_storage_management_policy": resourceArmStorageManagementPolicy(), + "azurerm_storage_queue": resourceArmStorageQueue(), + "azurerm_storage_share": resourceArmStorageShare(), + "azurerm_storage_share_directory": resourceArmStorageShareDirectory(), + "azurerm_storage_table": resourceArmStorageTable(), + "azurerm_storage_table_entity": resourceArmStorageTableEntity(), } } diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go new file mode 100644 index 0000000000000..280717be845a5 --- /dev/null +++ b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go @@ -0,0 +1,249 @@ +package storage + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "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/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmStorageAccountCustomerManagedKey() *schema.Resource { + return &schema.Resource{ + Read: resourceArmStorageAccountCustomerManagedKeyRead, + Create: resourceArmStorageAccountCustomerManagedKeyCreateUpdate, + Update: resourceArmStorageAccountCustomerManagedKeyCreateUpdate, + Delete: resourceArmStorageAccountCustomerManagedKeyDelete, + SchemaVersion: 2, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "storage_account_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "key_vault_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "key_vault_access_policy_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "key_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "key_version": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, + }, + "key_vault_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmStorageAccountCustomerManagedKeyCreateUpdate(d *schema.ResourceData, meta interface{}) error { + vaultClient := meta.(*clients.Client).KeyVault.VaultsClient + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + keyVaultId := d.Get("key_vault_id").(string) + keyName := d.Get("key_name").(string) + keyVersion := d.Get("key_version").(string) + storageAccountId := d.Get("storage_account_id").(string) + encryptionServices := true + + storageAccountName, storageAccountResourceGroupName, err := azure.KeyVaultGetResourceNameResource(storageAccountId, "storageAccounts") + if err != nil { + return err + } + + keyVaultAccountName, keyVaultResourceGroupName, err := azure.KeyVaultGetResourceNameResource(keyVaultId, "vaults") + if err != nil { + return err + } + + // First check to see if the key vault is configured correctly or not + if !azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { + return fmt.Errorf("Key Vault %q (Resource Group %q) is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultAccountName, keyVaultResourceGroupName) + } + + pKeyVaultBaseURL, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Key Vault URI from Key Vault %q (Resource Group %q): %+v", keyVaultAccountName, keyVaultResourceGroupName, err) + } + + props := storage.AccountUpdateParameters{ + AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ + Encryption: &storage.Encryption{ + Services: &storage.EncryptionServices{ + Blob: &storage.EncryptionService{ + Enabled: utils.Bool(encryptionServices), + }, + File: &storage.EncryptionService{ + Enabled: utils.Bool(encryptionServices), + }, + }, + KeySource: storage.MicrosoftKeyvault, + KeyVaultProperties: &storage.KeyVaultProperties{ + KeyName: utils.String(keyName), + KeyVersion: utils.String(keyVersion), + KeyVaultURI: utils.String(pKeyVaultBaseURL), + }, + }, + }, + } + + _, err = storageClient.Update(ctx, storageAccountResourceGroupName.(string), storageAccountName.(string), props) + if err != nil { + return fmt.Errorf("Error updating Azure Storage Account %q (Resource Group %q) Customer Managed Key : %+v", storageAccountName, storageAccountResourceGroupName, err) + } + + resourceId := fmt.Sprintf("%s/customerManagedKey", storageAccountId) + d.SetId(resourceId) + + return resourceArmStorageAccountCustomerManagedKeyRead(d, meta) +} + +func resourceArmStorageAccountCustomerManagedKeyRead(d *schema.ResourceData, meta interface{}) error { + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + storageAccountId := d.Get("storage_account_id").(string) + keyVaultId := d.Get("key_vault_id").(string) + keyVaultPolicy := d.Get("key_vault_access_policy_id").(string) + + d.Set("storage_account_id", storageAccountId) + d.Set("key_vault_id", keyVaultId) + d.Set("key_vault_access_policy_id", keyVaultPolicy) + + name, resGroup, err := azure.KeyVaultGetResourceNameResource(storageAccountId, "storageAccounts") + if err != nil { + return err + } + + resp, err := storageClient.GetProperties(ctx, resGroup.(string), name.(string), "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error reading the state of AzureRM Storage Account %q (Resource Group %q): %+v", name, resGroup, err) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { + d.Set("key_name", *keyVaultProperties.KeyName) + d.Set("key_version", *keyVaultProperties.KeyVersion) + d.Set("key_vault_uri", *keyVaultProperties.KeyVaultURI) + } + } + } + + return nil +} + +func resourceArmStorageAccountCustomerManagedKeyDelete(d *schema.ResourceData, meta interface{}) error { + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + storageAccountId := d.Get("storage_account_id").(string) + + storageAccountName, resourceGroupName, err := azure.KeyVaultGetResourceNameResource(storageAccountId, "storageAccounts") + if err != nil { + return err + } + + // Since this isn't a real object, just modifying an existing object + // "Delete" doesn't really make sense it should really be a "Revert to Default" + // So instead of the Delete func actually deleting the Storage Account I am + // making it reset the Storage Account to it's default state + opts := storage.AccountUpdateParameters{ + AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ + Encryption: &storage.Encryption{ + KeySource: storage.MicrosoftStorage, + }, + }, + } + + _, err = storageClient.Update(ctx, resourceGroupName.(string), storageAccountName.(string), opts) + if err != nil { + return fmt.Errorf("Error deleting AzureRM Storage Account %q (Resource Group %q) %q: %+v", storageAccountName.(string), resourceGroupName.(string), err) + } + + return nil +} + +func resourceArmStorageAccountCustomerManagedKeyImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + storageClient := meta.(*clients.Client).Storage.AccountsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := d.Id() + + d.Set("storage_account_id", id) + d.Set("key_vault_id", "") + d.Set("key_vault_access_policy_id", "") + + name, resGroup, err := azure.KeyVaultGetResourceNameResource(id, "storageAccounts") + if err != nil { + return nil, err + } + + resp, err := storageClient.GetProperties(ctx, resGroup.(string), name.(string), "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil, nil + } + return nil, fmt.Errorf("Error importing the state of AzureRM Storage Account %q (Resource Group %q): %+v", name.(string), resGroup.(string), err) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { + d.Set("key_name", keyVaultProperties.KeyName) + d.Set("key_version", keyVaultProperties.KeyVersion) + d.Set("key_vault_uri", keyVaultProperties.KeyVaultURI) + } + } + } + + resourceId := fmt.Sprintf("%s/customerManagedKey", id) + d.SetId(resourceId) + + results := make([]*schema.ResourceData, 1) + + results[0] = d + return results, nil +} diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go b/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go deleted file mode 100644 index e03e8a77d9c3d..0000000000000 --- a/azurerm/internal/services/storage/resource_arm_storage_account_encryption_settings.go +++ /dev/null @@ -1,325 +0,0 @@ -package storage - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "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/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmStorageAccountEncryptionSettings() *schema.Resource { - return &schema.Resource{ - Read: resourceArmStorageAccountEncryptionSettingsRead, - Create: resourceArmStorageAccountEncryptionSettingsCreateUpdate, - Update: resourceArmStorageAccountEncryptionSettingsCreateUpdate, - Delete: resourceArmStorageAccountEncryptionSettingsDelete, - SchemaVersion: 2, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "storage_account_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - - "key_vault": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - // This attribute is not used, it was only added - // to create a dependency between this resource - // and the key vault policy - "key_vault_policy_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - - "key_vault_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - - "key_name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "key_version": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validate.NoEmptyStrings, - }, - "key_vault_uri": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, - } -} - -func resourceArmStorageAccountEncryptionSettingsCreateUpdate(d *schema.ResourceData, meta interface{}) error { - vaultClient := meta.(*clients.Client).KeyVault.VaultsClient - storageClient := meta.(*clients.Client).Storage.AccountsClient - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - storageAccountId := d.Get("storage_account_id").(string) - - id, err := azure.ParseAzureResourceID(storageAccountId) - if err != nil { - return err - } - - storageAccountName := id.Path["storageAccounts"] - resourceGroupName := id.ResourceGroup - - // create the update object with the default values - alwaysEnabled := true - opts := storage.AccountUpdateParameters{ - AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ - Encryption: &storage.Encryption{ - Services: &storage.EncryptionServices{ - Blob: &storage.EncryptionService{ - Enabled: utils.Bool(alwaysEnabled), - }, - File: &storage.EncryptionService{ - Enabled: utils.Bool(alwaysEnabled), - }}, - KeySource: storage.MicrosoftStorage, - KeyVaultProperties: &storage.KeyVaultProperties{}, - }, - }, - } - - if keyVaultProperties := expandAzureRmStorageAccountKeyVaultProperties(d); keyVaultProperties.KeyName != utils.String("") { - if v, ok := d.GetOk("key_vault.0.key_vault_id"); ok { - // Get the key vault base URL from the key vault - keyVaultId := v.(string) - - kvId, err := azure.ParseAzureResourceID(keyVaultId) - if err != nil { - return err - } - - keyVaultAccountName := kvId.Path["vaults"] - keyVaultResourceGroupName := kvId.ResourceGroup - - pKeyVaultBaseURL, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - - if err != nil { - return fmt.Errorf("Error looking up Key Vault URI from id %q: %+v", keyVaultId, err) - } - - if !azure.KeyVaultIsSoftDeleteAndPurgeProtected(ctx, vaultClient, keyVaultId) { - return fmt.Errorf("Key Vault %q (Resource Group %q) is not configured correctly, please make sure that both 'soft_delete_enabled' and 'purge_protection_enabled' arguments are set to 'true'", keyVaultAccountName, keyVaultResourceGroupName) - } - - keyVaultProperties.KeyVaultURI = utils.String(pKeyVaultBaseURL) - opts.Encryption.KeyVaultProperties = keyVaultProperties - opts.Encryption.KeySource = storage.MicrosoftKeyvault - } - } - - _, err = storageClient.Update(ctx, resourceGroupName, storageAccountName, opts) - if err != nil { - return fmt.Errorf("Error updating Azure Storage Account Encryption %q: %+v", storageAccountName, err) - } - - resourceId := fmt.Sprintf("%s/encryptionSettings", storageAccountId) - d.SetId(resourceId) - - return resourceArmStorageAccountEncryptionSettingsRead(d, meta) -} - -func resourceArmStorageAccountEncryptionSettingsRead(d *schema.ResourceData, meta interface{}) error { - storageClient := meta.(*clients.Client).Storage.AccountsClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - storageAccountId := d.Get("storage_account_id").(string) - - id, err := azure.ParseAzureResourceID(storageAccountId) - if err != nil { - return err - } - name := id.Path["storageAccounts"] - resGroup := id.ResourceGroup - - resp, err := storageClient.GetProperties(ctx, resGroup, name, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error reading the state of AzureRM Storage Account %q: %+v", name, err) - } - - if props := resp.AccountProperties; props != nil { - if encryption := props.Encryption; encryption != nil { - if services := encryption.Services; services != nil { - if blob := services.Blob; blob != nil { - d.Set("enable_blob_encryption", blob.Enabled) - } - if file := services.File; file != nil { - d.Set("enable_file_encryption", file.Enabled) - } - } - - if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { - keyVaultId := d.Get("key_vault.0.key_vault_id").(string) - keyVaultPolicyId := d.Get("key_vault.0.key_vault_policy_id").(string) - - if err := d.Set("key_vault", flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties, keyVaultId, keyVaultPolicyId)); err != nil { - return fmt.Errorf("Error flattening `key_vault_properties`: %+v", err) - } - } - } - } - - return nil -} - -func resourceArmStorageAccountEncryptionSettingsDelete(d *schema.ResourceData, meta interface{}) error { - storageClient := meta.(*clients.Client).Storage.AccountsClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - storageAccountId := d.Get("storage_account_id").(string) - - id, err := azure.ParseAzureResourceID(storageAccountId) - if err != nil { - return err - } - - storageAccountName := id.Path["storageAccounts"] - resourceGroupName := id.ResourceGroup - - // Since this isn't a real object, just modifying an existing object - // "Delete" doesn't really make sense it should really be a "Revert to Default" - // So instead of the Delete func actually deleting the Storage Account I am - // making it reset the Storage Account to it's default state - opts := storage.AccountUpdateParameters{ - AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ - Encryption: &storage.Encryption{ - KeySource: storage.MicrosoftStorage, - }, - }, - } - - _, err = storageClient.Update(ctx, resourceGroupName, storageAccountName, opts) - if err != nil { - return fmt.Errorf("Error deleting Azure Storage Account Encryption %q: %+v", storageAccountName, err) - } - - return nil -} - -func resourceArmStorageAccountEncryptionSettingsImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - storageClient := meta.(*clients.Client).Storage.AccountsClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id := d.Id() - - d.Set("storage_account_id", id) - - saId, err := azure.ParseAzureResourceID(id) - if err != nil { - return nil, err - } - name := saId.Path["storageAccounts"] - resGroup := saId.ResourceGroup - - resp, err := storageClient.GetProperties(ctx, resGroup, name, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil, nil - } - return nil, fmt.Errorf("Error importing the state of AzureRM Storage Account %q: %+v", name, err) - } - - if props := resp.AccountProperties; props != nil { - if encryption := props.Encryption; encryption != nil { - if keyVaultProperties := encryption.KeyVaultProperties; keyVaultProperties != nil { - if err := d.Set("key_vault", flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties, "", "")); err != nil { - return nil, fmt.Errorf("Error flattening `key_vault_properties` on import: %+v", err) - } - } - } - } - - resourceId := fmt.Sprintf("%s/encryptionSettings", id) - d.SetId(resourceId) - - results := make([]*schema.ResourceData, 1) - - results[0] = d - return results, nil -} - -func expandAzureRmStorageAccountKeyVaultProperties(d *schema.ResourceData) *storage.KeyVaultProperties { - vs := d.Get("key_vault").([]interface{}) - if len(vs) == 0 { - return &storage.KeyVaultProperties{} - } - - v := vs[0].(map[string]interface{}) - keyName := v["key_name"].(string) - keyVersion := v["key_version"].(string) - - return &storage.KeyVaultProperties{ - KeyName: utils.String(keyName), - KeyVersion: utils.String(keyVersion), - } -} - -func flattenAzureRmStorageAccountKeyVaultProperties(keyVaultProperties *storage.KeyVaultProperties, keyVaultId string, keyVaultPolicyId string) []interface{} { - if keyVaultProperties == nil { - return make([]interface{}, 0) - } - - result := make(map[string]interface{}) - if keyVaultId != "" { - result["key_vault_id"] = keyVaultId - } - - if keyVaultPolicyId != "" { - result["key_vault_policy_id"] = keyVaultPolicyId - } - - if keyVaultProperties.KeyName != nil { - result["key_name"] = *keyVaultProperties.KeyName - } - if keyVaultProperties.KeyVersion != nil { - result["key_version"] = *keyVaultProperties.KeyVersion - } - if keyVaultProperties.KeyVaultURI != nil { - result["key_vault_uri"] = *keyVaultProperties.KeyVaultURI - } - - return []interface{}{result} -} diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_customer_managed_key_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_customer_managed_key_test.go new file mode 100644 index 0000000000000..5a735cf7ba5c6 --- /dev/null +++ b/azurerm/internal/services/storage/tests/resource_arm_storage_account_customer_managed_key_test.go @@ -0,0 +1,221 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccAzureRMStorageAccountCustomerManagedKey_basic(t *testing.T) { + parentResourceName := "azurerm_storage_account.testsa" + data := acceptance.BuildTestData(t, "azurerm_storage_account_customer_managed_key", "custom") + preConfig := testAccAzureRMStorageAccountCustomerManagedKey_basic(data) + postConfig := testAccAzureRMStorageAccountCustomerManagedKey_basicDelete(data) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountCustomerManagedKeyExists(data.ResourceName), + ), + }, + { + // Delete the encryption settings resource and verify it is gone + // Whilst making sure the encryption settings on the storage account + // have been reverted to their default state + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), + testCheckAzureRMStorageAccountCustomerManagedKeyDestroyed(data.ResourceName), + ), + }, + }, + }) +} + +func TestAccAzureRMStorageAccountCustomerManagedKey_disappears(t *testing.T) { + parentResourceName := "azurerm_storage_account.testsa" + data := acceptance.BuildTestData(t, "azurerm_storage_account_customer_managed_key", "custom") + preConfig := testAccAzureRMStorageAccountCustomerManagedKey_basic(data) + postConfig := testAccAzureRMStorageAccountCustomerManagedKey_basicDelete(data) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMStorageAccountDestroyed, + Steps: []resource.TestStep{ + { + Config: preConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountCustomerManagedKeyExists(data.ResourceName), + ), + }, + { + Config: postConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), + testCheckAzureRMStorageAccountCustomerManagedKeyDestroyed(data.ResourceName), + ), + }, + }, + }) +} + +func testCheckAzureRMStorageAccountExistsWithDefaultSettings(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) + } + + storageAccount := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + // Ensure resource group exists in API + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + conn := acceptance.AzureProvider.Meta().(*clients.Client).Storage.AccountsClient + + resp, err := conn.GetProperties(ctx, resourceGroup, storageAccount, "") + if err != nil { + return fmt.Errorf("Bad: Get on storageServiceClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: StorageAccount %q (resource group: %q) does not exist", storageAccount, resourceGroup) + } + + if props := resp.AccountProperties; props != nil { + if encryption := props.Encryption; encryption != nil { + if services := encryption.Services; services != nil { + if !*services.Blob.Enabled { + return fmt.Errorf("enable_blob_encryption not set to default: %s", resourceName) + } + if !*services.File.Enabled { + return fmt.Errorf("enable_file_encryption not set to default: %s", resourceName) + } + } + + if encryption.KeySource != storage.MicrosoftStorage { + return fmt.Errorf("%s keySource not set to default(storage.MicrosoftStorage): %s", resourceName, encryption.KeySource) + } + } else { + return fmt.Errorf("storage account encryption properties not found: %s", resourceName) + } + } + + return nil + } +} + +func testCheckAzureRMStorageAccountCustomerManagedKeyExists(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) + } + + if storageAccountId := rs.Primary.Attributes["storage_account_id"]; storageAccountId == "" { + return fmt.Errorf("Unable to read storageAccountId: %s", resourceName) + } + + return nil + } +} + +func testCheckAzureRMStorageAccountDestroyed(s *terraform.State) error { + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + conn := acceptance.AzureProvider.Meta().(*clients.Client).Storage.AccountsClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_storage_account" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.GetProperties(ctx, resourceGroup, name, "") + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Storage Account still exists:\n%#v", resp.AccountProperties) + } + } + + return nil +} + +func testCheckAzureRMStorageAccountCustomerManagedKeyDestroyed(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + _, ok := s.RootModule().Resources[resourceName] + if !ok { + return nil + } + + return fmt.Errorf("Found: %s", resourceName) + } +} + +func testAccAzureRMStorageAccountCustomerManagedKey_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags = { + environment = "production" + } +} + +resource "azurerm_storage_account_customer_managed_key" "custom" { + storage_account_id = "${azurerm_storage_account.testsa.id}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomStringOfLength(4)) +} + +func testAccAzureRMStorageAccountCustomerManagedKey_basicDelete(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "testrg" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_storage_account" "testsa" { + name = "unlikely23exst2acct%s" + resource_group_name = "${azurerm_resource_group.testrg.name}" + + location = "${azurerm_resource_group.testrg.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags = { + environment = "production" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomStringOfLength(4)) +} diff --git a/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go b/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go deleted file mode 100644 index cc994667f9407..0000000000000 --- a/azurerm/internal/services/storage/tests/resource_arm_storage_account_encryption_settings_test.go +++ /dev/null @@ -1,341 +0,0 @@ -package azurerm - -import ( - "fmt" - "net/http" - "os" - "testing" - - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" - "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" -) - -func TestAccAzureRMStorageAccountEncryptionSettings_basic(t *testing.T) { - parentResourceName := "azurerm_storage_account.testsa" - resourceName := "azurerm_storage_account_encryption_settings.custom" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(4) - location := testLocation() - preConfig := testAccAzureRMStorageAccountEncryptionSettings_basic(ri, rs, location) - postConfig := testAccAzureRMStorageAccountEncryptionSettings_basicDelete(ri, rs, location) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroyed, - Steps: []resource.TestStep{ - { - Config: preConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "true"), - resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "true"), - ), - }, - { - // Delete the encryption settings resource and verify it is gone - // Whilst making sure the encryption settings on the storage account - // have been reverted to their default state - Config: postConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), - testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName), - ), - }, - }, - }) -} - -func TestAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisable(t *testing.T) { - _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") - if !exists { - t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") - } - - resourceName := "azurerm_storage_account_encryption_settings.custom" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(4) - location := testLocation() - config := testAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisabled(ri, rs, location) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroyed, - Steps: []resource.TestStep{ - { - Config: config, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "false"), - ), - }, - }, - }) -} - -func TestAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisable(t *testing.T) { - _, exists := os.LookupEnv("TF_ACC_STORAGE_ENCRYPTION_DISABLE") - if !exists { - t.Skip("`TF_ACC_STORAGE_ENCRYPTION_DISABLE` isn't specified - skipping since disabling encryption is generally disabled") - } - - resourceName := "azurerm_storage_account_encryption_settings.custom" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(4) - location := testLocation() - config := testAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisabled(ri, rs, location) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroyed, - Steps: []resource.TestStep{ - { - Config: config, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "false"), - ), - }, - }, - }) -} - -func TestAccAzureRMStorageAccountEncryptionSettings_disappears(t *testing.T) { - parentResourceName := "azurerm_storage_account.testsa" - resourceName := "azurerm_storage_account_encryption_settings.custom" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(4) - preConfig := testAccAzureRMStorageAccountEncryptionSettings_basic(ri, rs, testLocation()) - postConfig := testAccAzureRMStorageAccountEncryptionSettings_basicDelete(ri, rs, testLocation()) - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMStorageAccountDestroyed, - Steps: []resource.TestStep{ - { - Config: preConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountEncryptionSettingsExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "enable_blob_encryption", "true"), - resource.TestCheckResourceAttr(resourceName, "enable_file_encryption", "true"), - ), - }, - { - Config: postConfig, - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMStorageAccountExistsWithDefaultSettings(parentResourceName), - testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName), - ), - }, - }, - }) -} - -func testCheckAzureRMStorageAccountExistsWithDefaultSettings(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) - } - - storageAccount := rs.Primary.Attributes["name"] - resourceGroup := rs.Primary.Attributes["resource_group_name"] - - // Ensure resource group exists in API - ctx := testAccProvider.Meta().(*ArmClient).StopContext - conn := testAccProvider.Meta().(*ArmClient).storageServiceClient - - resp, err := conn.GetProperties(ctx, resourceGroup, storageAccount) - if err != nil { - return fmt.Errorf("Bad: Get on storageServiceClient: %+v", err) - } - - if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: StorageAccount %q (resource group: %q) does not exist", storageAccount, resourceGroup) - } - - if props := resp.AccountProperties; props != nil { - if encryption := props.Encryption; encryption != nil { - if services := encryption.Services; services != nil { - if !*services.Blob.Enabled { - return fmt.Errorf("enable_blob_encryption not set to default: %s", resourceName) - } - if !*services.File.Enabled { - return fmt.Errorf("enable_file_encryption not set to default: %s", resourceName) - } - } - - if encryption.KeySource != storage.MicrosoftStorage { - return fmt.Errorf("%s keySource not set to default(storage.MicrosoftStorage): %s", resourceName, encryption.KeySource) - } - } else { - return fmt.Errorf("storage account encryption properties not found: %s", resourceName) - } - } - - return nil - } -} - -func testCheckAzureRMStorageAccountEncryptionSettingsExists(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) - } - - if storageAccountId := rs.Primary.Attributes["storage_account_id"]; storageAccountId == "" { - return fmt.Errorf("Unable to read storageAccountId: %s", resourceName) - } - - return nil - } -} - -func testCheckAzureRMStorageAccountDestroyed(s *terraform.State) error { - ctx := testAccProvider.Meta().(*ArmClient).StopContext - conn := testAccProvider.Meta().(*ArmClient).storageServiceClient - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_storage_account" { - continue - } - - name := rs.Primary.Attributes["name"] - resourceGroup := rs.Primary.Attributes["resource_group_name"] - - resp, err := conn.GetProperties(ctx, resourceGroup, name) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Storage Account still exists:\n%#v", resp.AccountProperties) - } - } - - return nil -} - -func testCheckAzureRMStorageAccountEncryptionSettingsDestroyed(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - _, ok := s.RootModule().Resources[resourceName] - if !ok { - return nil - } - - return fmt.Errorf("Found: %s", resourceName) - } -} - -func testAccAzureRMStorageAccountEncryptionSettings_basic(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_storage_account" "testsa" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.testrg.name}" - - location = "${azurerm_resource_group.testrg.location}" - account_tier = "Standard" - account_replication_type = "LRS" - - tags { - environment = "production" - } -} - -resource "azurerm_storage_account_encryption_settings" "custom" { - storage_account_id = "${azurerm_storage_account.testsa.id}" - enable_blob_encryption = true - enable_file_encryption = true -} -`, rInt, location, rString) -} - -func testAccAzureRMStorageAccountEncryptionSettings_basicDelete(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_storage_account" "testsa" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.testrg.name}" - - location = "${azurerm_resource_group.testrg.location}" - account_tier = "Standard" - account_replication_type = "LRS" - - tags { - environment = "production" - } -} -`, rInt, location, rString) -} - -func testAccAzureRMStorageAccountEncryptionSettings_fileEncryptionDisabled(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_storage_account" "testsa" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.testrg.name}" - - location = "${azurerm_resource_group.testrg.location}" - account_tier = "Standard" - account_replication_type = "LRS" - - tags { - environment = "production" - } -} - -resource "azurerm_storage_account_encryption_settings" "custom" { - storage_account_id = "${azurerm_storage_account.testsa.id} - enable_file_encryption = false" -} -`, rInt, location, rString) -} - -func testAccAzureRMStorageAccountEncryptionSettings_blobEncryptionDisabled(rInt int, rString string, location string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "testrg" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_storage_account" "testsa" { - name = "unlikely23exst2acct%s" - resource_group_name = "${azurerm_resource_group.testrg.name}" - - location = "${azurerm_resource_group.testrg.location}" - account_tier = "Standard" - account_replication_type = "LRS" - - tags { - environment = "production" - } -} - -resource "azurerm_storage_account_encryption_settings" "custom" { - storage_account_id = "${azurerm_storage_account.testsa.id} - enable_blob_encryption = false" -} -`, rInt, location, rString) -} diff --git a/website/docs/r/storage_account_encryption_settings.html.markdown b/website/docs/r/storage_account_customer_managed_key.html.markdown similarity index 58% rename from website/docs/r/storage_account_encryption_settings.html.markdown rename to website/docs/r/storage_account_customer_managed_key.html.markdown index 553bdcdfad954..abfb32696860a 100644 --- a/website/docs/r/storage_account_encryption_settings.html.markdown +++ b/website/docs/r/storage_account_customer_managed_key.html.markdown @@ -1,27 +1,24 @@ --- subcategory: "Storage" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_storage_account_encryption_settings" +page_title: "Azure Resource Manager: azurerm_storage_account_customer_managed_key" description: |- - Manages the encryption settings of an Azure Storage Account. + Manages the customer managed key of an Azure Storage Account. --- -# azurerm_storage_account_encryption_settings +# azurerm_storage_account_customer_managed_key -Manages the encryption settings of an Azure Storage Account. +Manages the customer managed key of an Azure Storage Account. ## Example Usage ```hcl -resource "azurerm_storage_account_encryption_settings" "tfex" { - storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.Storage/storageAccounts/tfexstorageaccount" - - key_vault { - key_vault_policy_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault/objectId/00000000-0000-0000-0000-000000000000" - key_vault_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault" - key_name = "tfex-key" - key_version = "955b9ad9579e4501a311df5493bacd02" - } +resource "azurerm_storage_account_customer_managed_key" "tfex" { + storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.Storage/storageAccounts/tfexstorageaccount" + key_vault_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault" + key_vault_access_policy_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault/objectId/00000000-0000-0000-0000-000000000000" + key_name = "tfex-key" + key_version = "955b9ad9579e4501a311df5493bacd02" } ``` @@ -33,7 +30,7 @@ provider "azurerm" { features { key_vault { - purge_soft_delete_on_destroy = true + purge_soft_delete_on_destroy = false } } } @@ -51,7 +48,7 @@ resource "azurerm_key_vault" "tfex" { tenant_id = "00000000-0000-0000-0000-000000000000" soft_delete_enabled = true - purge_protection_enabled = false + purge_protection_enabled = true sku_name = "standard" @@ -94,15 +91,12 @@ resource "azurerm_storage_account" "tfex" { } } -resource "azurerm_storage_account_encryption_settings" "tfex" { - storage_account_id = azurerm_storage_account.tfex.id - - key_vault { - key_vault_policy_id = azurerm_key_vault_access_policy.tfex.id - key_vault_id = azurerm_key_vault.tfex.id - key_name = azurerm_key_vault_key.tfex.name - key_version = azurerm_key_vault_key.tfex.version - } +resource "azurerm_storage_account_customer_managed_key" "tfex" { + storage_account_id = azurerm_storage_account.tfex.id + key_vault_id = azurerm_key_vault.tfex.id + key_vault_access_policy_id = azurerm_key_vault_access_policy.tfex.id + key_name = azurerm_key_vault_key.tfex.name + key_version = azurerm_key_vault_key.tfex.version } ``` @@ -111,15 +105,8 @@ resource "azurerm_storage_account_encryption_settings" "tfex" { The following arguments are supported: * `storage_account_id` - (Required) The id of the storage account to manage the encryption settings for. - -* `key_vault` - (Optional) A `key_vault` block as documented below. - ---- - -* `key_vault` supports the following: - * `key_vault_id` - (Required) The ID of the Key Vault. -* `key_vault_policy_id` - (Required) The resource ID of the `azurerm_key_vault_access_policy` granting the storage account access to the key vault. +* `key_vault_access_policy_id` - (Required) The resource ID of the `azurerm_key_vault_access_policy` granting the storage account access to the key vault. * `key_name` - (Required) The name of Key Vault key. * `key_version` - (Required) The version of Key Vault key. @@ -137,5 +124,5 @@ The following attributes are exported in addition to the arguments listed above: Storage Accounts Encryption Settings can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_storage_account_encryption_settings.tfex /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount +terraform import azurerm_storage_account_customer_managed_key.tfex /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myresourcegroup/providers/Microsoft.Storage/storageAccounts/myaccount ``` \ No newline at end of file From a86c893394a4784d66286fc6f1ca6c6355b6c46e Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 13 Feb 2020 15:04:28 -0800 Subject: [PATCH 095/498] Add SACMK doc to TOC --- website/azurerm.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/azurerm.erb b/website/azurerm.erb index 4301935ec7abe..e03d2a220a19b 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -2185,6 +2185,10 @@ azurerm_storage_account +
  • + azurerm_storage_account_customer_managed_key +
  • +
  • azurerm_storage_account_network_rules
  • From 08feb94a75739fb2bfd371f960f4eef0625ce100 Mon Sep 17 00:00:00 2001 From: John Kendall Date: Fri, 14 Feb 2020 10:11:53 +1100 Subject: [PATCH 096/498] remove synthentic delays --- .../services/bot/resource_arm_bot_channel_directline.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index 30b28aa95ed15..e33a7f534a303 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -149,8 +149,7 @@ func resourceArmBotChannelDirectlineCreate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } - // Create does not include sites properly, so we need to update as well - time.Sleep(10 * time.Second) + // Unable to create a new site with enhanced_authentication_enabled in the same operation, so we need to make two calls if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } @@ -230,8 +229,7 @@ func resourceArmBotChannelDirectlineUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } - // Create does not include sites properly, so we need to update as well - time.Sleep(10 * time.Second) + // Unable to create a new site with enhanced_authentication_enabled in the same operation, so we need to make two calls if _, err := client.Update(ctx, resourceGroup, botName, botservice.ChannelNameDirectLineChannel, channel); err != nil { return fmt.Errorf("Error issuing create request for Channel Directline for Bot %q (Resource Group %q): %+v", resourceGroup, botName, err) } From da671823b9722dc4e0bb9ef514106c9802c7f26a Mon Sep 17 00:00:00 2001 From: John Kendall Date: Fri, 14 Feb 2020 10:46:04 +1100 Subject: [PATCH 097/498] Fix whitespace --- .../internal/services/bot/resource_arm_bot_channel_directline.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go index e33a7f534a303..b84927665a03e 100644 --- a/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go +++ b/azurerm/internal/services/bot/resource_arm_bot_channel_directline.go @@ -358,7 +358,6 @@ func flattenDirectlineSites(input []botservice.DirectLineSite) []interface{} { // When creating a new directline channel, a Default Site is created // There is a race condition where this site is not removed before the create request is completed func filterSites(sites *[]botservice.DirectLineSite) []botservice.DirectLineSite { - filtered := make([]botservice.DirectLineSite, 0) for _, site := range *sites { if *site.SiteName == "Default Site" { From cf39a6e4617ec8e72b9ec7bcf0418a42c990c080 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 13 Feb 2020 15:52:52 -0800 Subject: [PATCH 098/498] Fixed import issue --- azurerm/helpers/azure/key_vault.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/azurerm/helpers/azure/key_vault.go b/azurerm/helpers/azure/key_vault.go index e5e68e8ec8ef8..d35fa9400c2ce 100644 --- a/azurerm/helpers/azure/key_vault.go +++ b/azurerm/helpers/azure/key_vault.go @@ -7,7 +7,6 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -195,7 +194,7 @@ func KeyVaultIsSoftDeleteAndPurgeProtected(ctx context.Context, client *keyvault } func KeyVaultGetResourceNameResource(resourceId string, namePathKey string) (resourceName interface{}, resourceGroup interface{}, err error) { - id, err := azure.ParseAzureResourceID(resourceId) + id, err := ParseAzureResourceID(resourceId) if err != nil { return nil, nil, err } From 5d7f77b76cca75916ae94f169bc7224ceff5c5b5 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Thu, 13 Feb 2020 18:50:46 -0800 Subject: [PATCH 099/498] Updates --- .../keyvault/data_source_key_vault_key.go | 46 ++++--------------- .../keyvault/resource_arm_key_vault_key.go | 4 +- ...rm_storage_account_customer_managed_key.go | 32 ++++++------- ...account_customer_managed_key.html.markdown | 11 ++--- 4 files changed, 31 insertions(+), 62 deletions(-) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault_key.go b/azurerm/internal/services/keyvault/data_source_key_vault_key.go index b1d672a650e0c..2632b6f015721 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault_key.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault_key.go @@ -5,7 +5,6 @@ import ( "time" "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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -29,21 +28,13 @@ func dataSourceArmKeyVaultKey() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, + Type: schema.TypeString, + Computed: true, }, - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + "key_vault_access_policy_id": { + Type: schema.TypeString, + Computed: true, }, "key_type": { @@ -90,33 +81,16 @@ func dataSourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) erro ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - keyVaultBaseUri := d.Get("vault_uri").(string) name := d.Get("name").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUri == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUri = pKeyVaultBaseUrl - d.Set("vault_uri", keyVaultBaseUri) - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUri) - if err != nil { - return fmt.Errorf("Error retrieving the Resource ID the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - if id == nil { - return fmt.Errorf("Unable to locate the Resource ID for the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - d.Set("key_vault_id", id) + keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) } + d.Set("key_vault_id", keyVaultId) + resp, err := client.GetKey(ctx, keyVaultBaseUri, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go index 454aaa8728d74..b48a213873dab 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go @@ -170,13 +170,11 @@ func resourceArmKeyVaultKeyCreate(d *schema.ResourceData, meta interface{}) erro name := d.Get("name").(string) keyVaultId := d.Get("key_vault_id").(string) - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) if err != nil { return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) } - keyVaultBaseUri := pKeyVaultBaseUrl - if features.ShouldResourcesBeImported() { existing, err := client.GetKey(ctx, keyVaultBaseUri, name, "") if err != nil { diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go index 280717be845a5..3291bc3ef832b 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go @@ -44,12 +44,6 @@ func resourceArmStorageAccountCustomerManagedKey() *schema.Resource { ValidateFunc: azure.ValidateResourceID, }, - "key_vault_access_policy_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - "key_name": { Type: schema.TypeString, Required: true, @@ -121,9 +115,9 @@ func resourceArmStorageAccountCustomerManagedKeyCreateUpdate(d *schema.ResourceD }, } - _, err = storageClient.Update(ctx, storageAccountResourceGroupName.(string), storageAccountName.(string), props) + _, err := storageClient.Update(ctx, storageAccountResourceGroupName.(string), storageAccountName.(string), props) if err != nil { - return fmt.Errorf("Error updating Azure Storage Account %q (Resource Group %q) Customer Managed Key : %+v", storageAccountName, storageAccountResourceGroupName, err) + return fmt.Errorf("Error updating Azure Storage Account %q (Resource Group %q) Customer Managed Key: %+v", storageAccountName, storageAccountResourceGroupName, err) } resourceId := fmt.Sprintf("%s/customerManagedKey", storageAccountId) @@ -139,11 +133,9 @@ func resourceArmStorageAccountCustomerManagedKeyRead(d *schema.ResourceData, met storageAccountId := d.Get("storage_account_id").(string) keyVaultId := d.Get("key_vault_id").(string) - keyVaultPolicy := d.Get("key_vault_access_policy_id").(string) d.Set("storage_account_id", storageAccountId) d.Set("key_vault_id", keyVaultId) - d.Set("key_vault_access_policy_id", keyVaultPolicy) name, resGroup, err := azure.KeyVaultGetResourceNameResource(storageAccountId, "storageAccounts") if err != nil { @@ -178,6 +170,7 @@ func resourceArmStorageAccountCustomerManagedKeyDelete(d *schema.ResourceData, m defer cancel() storageAccountId := d.Get("storage_account_id").(string) + encryptionServices := true storageAccountName, resourceGroupName, err := azure.KeyVaultGetResourceNameResource(storageAccountId, "storageAccounts") if err != nil { @@ -188,15 +181,23 @@ func resourceArmStorageAccountCustomerManagedKeyDelete(d *schema.ResourceData, m // "Delete" doesn't really make sense it should really be a "Revert to Default" // So instead of the Delete func actually deleting the Storage Account I am // making it reset the Storage Account to it's default state - opts := storage.AccountUpdateParameters{ + props := storage.AccountUpdateParameters{ AccountPropertiesUpdateParameters: &storage.AccountPropertiesUpdateParameters{ Encryption: &storage.Encryption{ + Services: &storage.EncryptionServices{ + Blob: &storage.EncryptionService{ + Enabled: utils.Bool(encryptionServices), + }, + File: &storage.EncryptionService{ + Enabled: utils.Bool(encryptionServices), + }, + }, KeySource: storage.MicrosoftStorage, }, }, } - _, err = storageClient.Update(ctx, resourceGroupName.(string), storageAccountName.(string), opts) + _, err = storageClient.Update(ctx, resourceGroupName.(string), storageAccountName.(string), props) if err != nil { return fmt.Errorf("Error deleting AzureRM Storage Account %q (Resource Group %q) %q: %+v", storageAccountName.(string), resourceGroupName.(string), err) } @@ -213,20 +214,19 @@ func resourceArmStorageAccountCustomerManagedKeyImportState(d *schema.ResourceDa d.Set("storage_account_id", id) d.Set("key_vault_id", "") - d.Set("key_vault_access_policy_id", "") - name, resGroup, err := azure.KeyVaultGetResourceNameResource(id, "storageAccounts") + name, resourceGroup, err := azure.KeyVaultGetResourceNameResource(id, "storageAccounts") if err != nil { return nil, err } - resp, err := storageClient.GetProperties(ctx, resGroup.(string), name.(string), "") + resp, err := storageClient.GetProperties(ctx, resourceGroup.(string), name.(string), "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil, nil } - return nil, fmt.Errorf("Error importing the state of AzureRM Storage Account %q (Resource Group %q): %+v", name.(string), resGroup.(string), err) + return nil, fmt.Errorf("Error importing the state of AzureRM Storage Account %q (Resource Group %q): %+v", name.(string), resourceGroup.(string), err) } if props := resp.AccountProperties; props != nil { diff --git a/website/docs/r/storage_account_customer_managed_key.html.markdown b/website/docs/r/storage_account_customer_managed_key.html.markdown index abfb32696860a..8210f51f5bafc 100644 --- a/website/docs/r/storage_account_customer_managed_key.html.markdown +++ b/website/docs/r/storage_account_customer_managed_key.html.markdown @@ -16,7 +16,6 @@ Manages the customer managed key of an Azure Storage Account. resource "azurerm_storage_account_customer_managed_key" "tfex" { storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.Storage/storageAccounts/tfexstorageaccount" key_vault_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault" - key_vault_access_policy_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault/objectId/00000000-0000-0000-0000-000000000000" key_name = "tfex-key" key_version = "955b9ad9579e4501a311df5493bacd02" } @@ -92,11 +91,10 @@ resource "azurerm_storage_account" "tfex" { } resource "azurerm_storage_account_customer_managed_key" "tfex" { - storage_account_id = azurerm_storage_account.tfex.id - key_vault_id = azurerm_key_vault.tfex.id - key_vault_access_policy_id = azurerm_key_vault_access_policy.tfex.id - key_name = azurerm_key_vault_key.tfex.name - key_version = azurerm_key_vault_key.tfex.version + storage_account_id = azurerm_storage_account.tfex.id + key_vault_id = azurerm_key_vault.tfex.id + key_name = azurerm_key_vault_key.tfex.name + key_version = azurerm_key_vault_key.tfex.version } ``` @@ -106,7 +104,6 @@ The following arguments are supported: * `storage_account_id` - (Required) The id of the storage account to manage the encryption settings for. * `key_vault_id` - (Required) The ID of the Key Vault. -* `key_vault_access_policy_id` - (Required) The resource ID of the `azurerm_key_vault_access_policy` granting the storage account access to the key vault. * `key_name` - (Required) The name of Key Vault key. * `key_version` - (Required) The version of Key Vault key. From 4021461eae82255e1dcd3304f163c4e2e8febc11 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Thu, 13 Feb 2020 20:12:42 -0800 Subject: [PATCH 100/498] Update mysql to 2.0 --- .../mysql/resource_arm_mysql_server.go | 148 +----------------- .../tests/resource_arm_mysql_server_test.go | 108 +------------ 2 files changed, 9 insertions(+), 247 deletions(-) diff --git a/azurerm/internal/services/mysql/resource_arm_mysql_server.go b/azurerm/internal/services/mysql/resource_arm_mysql_server.go index 1772bd255339e..831db404112ce 100644 --- a/azurerm/internal/services/mysql/resource_arm_mysql_server.go +++ b/azurerm/internal/services/mysql/resource_arm_mysql_server.go @@ -52,8 +52,7 @@ func resourceArmMySqlServer() *schema.Resource { "sku_name": { Type: schema.TypeString, - Optional: true, // required in 2.0 - Computed: true, // remove in 2.0 + Required: true, ConflictsWith: []string{"sku"}, ValidateFunc: validation.StringInSlice([]string{ "B_Gen4_1", @@ -79,82 +78,6 @@ func resourceArmMySqlServer() *schema.Resource { }, false), }, - // remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku_name"}, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "B_Gen4_1", - "B_Gen4_2", - "B_Gen5_1", - "B_Gen5_2", - "GP_Gen4_2", - "GP_Gen4_4", - "GP_Gen4_8", - "GP_Gen4_16", - "GP_Gen4_32", - "GP_Gen5_2", - "GP_Gen5_4", - "GP_Gen5_8", - "GP_Gen5_16", - "GP_Gen5_32", - "GP_Gen5_64", - "MO_Gen5_2", - "MO_Gen5_4", - "MO_Gen5_8", - "MO_Gen5_16", - "MO_Gen5_32", - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - - "capacity": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntInSlice([]int{ - 1, - 2, - 4, - 8, - 16, - 32, - 64, - }), - }, - - "tier": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(mysql.Basic), - string(mysql.GeneralPurpose), - string(mysql.MemoryOptimized), - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - - "family": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Gen4", - "Gen5", - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - }, - }, - }, - "administrator_login": { Type: schema.TypeString, Required: true, @@ -275,17 +198,9 @@ func resourceArmMySqlServerCreate(d *schema.ResourceData, meta interface{}) erro } } - var sku *mysql.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandServerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for MySQL Server %q (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandMySQLServerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for MySQL Server %q (Resource Group %q)", name, resourceGroup) + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding sku_name for MySQL Server %q (Resource Group %q): %v", name, resourceGroup, err) } properties := mysql.ServerForCreate{ @@ -335,17 +250,9 @@ func resourceArmMySqlServerUpdate(d *schema.ResourceData, meta interface{}) erro name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - var sku *mysql.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandServerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for MySQL Server %q (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandMySQLServerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for MySQL Server %q (Resource Group %q)", name, resourceGroup) + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding sku_name for MySQL Server %q (Resource Group %q): %v", name, resourceGroup, err) } properties := mysql.ServerUpdateParameters{ @@ -419,10 +326,6 @@ func resourceArmMySqlServerRead(d *schema.ResourceData, meta interface{}) error d.Set("version", string(resp.Version)) d.Set("ssl_enforcement", string(resp.SslEnforcement)) - if err := d.Set("sku", flattenMySQLServerSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - if err := d.Set("storage_profile", flattenMySQLStorageProfile(resp.StorageProfile)); err != nil { return fmt.Errorf("Error setting `storage_profile`: %+v", err) } @@ -488,23 +391,6 @@ func expandServerSkuName(skuName string) (*mysql.Sku, error) { }, nil } -func expandMySQLServerSku(d *schema.ResourceData) *mysql.Sku { - skus := d.Get("sku").([]interface{}) - sku := skus[0].(map[string]interface{}) - - name := sku["name"].(string) - capacity := sku["capacity"].(int) - tier := sku["tier"].(string) - family := sku["family"].(string) - - return &mysql.Sku{ - Name: utils.String(name), - Tier: mysql.SkuTier(tier), - Capacity: utils.Int32(int32(capacity)), - Family: utils.String(family), - } -} - func expandMySQLStorageProfile(d *schema.ResourceData) *mysql.StorageProfile { storageprofiles := d.Get("storage_profile").([]interface{}) storageprofile := storageprofiles[0].(map[string]interface{}) @@ -522,26 +408,6 @@ func expandMySQLStorageProfile(d *schema.ResourceData) *mysql.StorageProfile { } } -func flattenMySQLServerSku(resp *mysql.Sku) []interface{} { - values := map[string]interface{}{} - - if name := resp.Name; name != nil { - values["name"] = *name - } - - if capacity := resp.Capacity; capacity != nil { - values["capacity"] = *capacity - } - - values["tier"] = string(resp.Tier) - - if family := resp.Family; family != nil { - values["family"] = *family - } - - return []interface{}{values} -} - func flattenMySQLStorageProfile(resp *mysql.StorageProfile) []interface{} { values := map[string]interface{}{} diff --git a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go index b97425bd6887c..b2070f11645dd 100644 --- a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go +++ b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go @@ -31,25 +31,6 @@ func TestAccAzureRMMySQLServer_basicFiveSix(t *testing.T) { }) } -func TestAccAzureRMMySQLServer_basicFiveSixOldSku(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_mysql_server", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMySQLServerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMMySQLServer_basicFiveSixOldSku(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMySQLServerExists(data.ResourceName), - ), - }, - data.ImportStep("administrator_login_password"), // not returned as sensitive - }, - }) -} - func TestAccAzureRMMySQLServer_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -120,25 +101,6 @@ func TestAccAzureRMMySQLServer_basicEightZero(t *testing.T) { }) } -func TestAccAzureRMMySqlServer_generalPurpose(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_mysql_server", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMySQLServerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMMySQLServer_generalPurpose(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMySQLServerExists(data.ResourceName), - ), - }, - data.ImportStep("administrator_login_password"), // not returned as sensitive - }, - }) -} - func TestAccAzureRMMySqlServer_memoryOptimized(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mysql_server", "test") @@ -199,7 +161,7 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { CheckDestroy: testCheckAzureRMMySQLServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMySQLServer_generalPurpose(data), + Config: testAccAzureRMMySQLServer_basicEightZero(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_32"), @@ -211,7 +173,7 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { ), }, { - Config: testAccAzureRMMySQLServer_memoryOptimized(data), + Config: testAccAzureRMMySQLServer_basicFiveSevenUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "MO_Gen5_16"), @@ -337,39 +299,6 @@ resource "azurerm_mysql_server" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMMySQLServer_basicFiveSixOldSku(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_mysql_server" "test" { - name = "acctestmysqlsvr-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "GP_Gen5_2" - capacity = 2 - tier = "GeneralPurpose" - family = "Gen5" - } - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } - - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "5.6" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMMySQLServer_basicFiveSeven(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -479,39 +408,6 @@ resource "azurerm_mysql_server" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMMySQLServer_generalPurpose(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_mysql_server" "test" { - name = "acctestmysqlsvr-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "GP_Gen5_32" - capacity = 32 - tier = "GeneralPurpose" - family = "Gen5" - } - - storage_profile { - storage_mb = 640000 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } - - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "5.7" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMMySQLServer_memoryOptimized(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From fa31f3124006eeef630454379ca33aed84a4de59 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Thu, 13 Feb 2020 20:26:46 -0800 Subject: [PATCH 101/498] update mssql to 2.0 --- .../mssql/resource_arm_mssql_elasticpool.go | 61 ------------------- 1 file changed, 61 deletions(-) diff --git a/azurerm/internal/services/mssql/resource_arm_mssql_elasticpool.go b/azurerm/internal/services/mssql/resource_arm_mssql_elasticpool.go index 23c8b521d3d32..ab4603acac80c 100644 --- a/azurerm/internal/services/mssql/resource_arm_mssql_elasticpool.go +++ b/azurerm/internal/services/mssql/resource_arm_mssql_elasticpool.go @@ -129,45 +129,6 @@ func resourceArmMsSqlElasticPool() *schema.Resource { }, }, - "elastic_pool_properties": { - Type: schema.TypeList, - Computed: true, - Deprecated: "These properties herein have been moved to the top level or removed", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "state": { - Type: schema.TypeString, - Computed: true, - Deprecated: "This property has been removed", - }, - - "creation_date": { - Type: schema.TypeString, - Computed: true, - Deprecated: "This property has been removed", - }, - - "max_size_bytes": { - Type: schema.TypeInt, - Computed: true, - Deprecated: "This property has been moved to the top level", - }, - - "zone_redundant": { - Type: schema.TypeBool, - Computed: true, - Deprecated: "This property has been moved to the top level", - }, - - "license_type": { - Type: schema.TypeString, - Computed: true, - Deprecated: "This property has been removed", - }, - }, - }, - }, - "max_size_bytes": { Type: schema.TypeInt, Optional: true, @@ -320,11 +281,6 @@ func resourceArmMsSqlElasticPoolRead(d *schema.ResourceData, meta interface{}) e } d.Set("zone_redundant", properties.ZoneRedundant) - // todo remove in 2.0 - if err := d.Set("elastic_pool_properties", flattenAzureRmMsSqlElasticPoolProperties(resp.ElasticPoolProperties)); err != nil { - return fmt.Errorf("Error setting `elastic_pool_properties`: %+v", err) - } - if err := d.Set("per_database_settings", flattenAzureRmMsSqlElasticPoolPerDatabaseSettings(properties.PerDatabaseSettings)); err != nil { return fmt.Errorf("Error setting `per_database_settings`: %+v", err) } @@ -412,23 +368,6 @@ func flattenAzureRmMsSqlElasticPoolSku(input *sql.Sku) []interface{} { return []interface{}{values} } -func flattenAzureRmMsSqlElasticPoolProperties(resp *sql.ElasticPoolProperties) []interface{} { - elasticPoolProperty := map[string]interface{}{} - elasticPoolProperty["state"] = string(resp.State) - - if date := resp.CreationDate; date != nil { - elasticPoolProperty["creation_date"] = date.String() - } - - if zoneRedundant := resp.ZoneRedundant; zoneRedundant != nil { - elasticPoolProperty["zone_redundant"] = *zoneRedundant - } - - elasticPoolProperty["license_type"] = string(resp.LicenseType) - - return []interface{}{elasticPoolProperty} -} - func flattenAzureRmMsSqlElasticPoolPerDatabaseSettings(resp *sql.ElasticPoolPerDatabaseSettings) []interface{} { perDatabaseSettings := map[string]interface{}{} From 1ed30cf72d76d21b634c6e591d82fbc67850ae29 Mon Sep 17 00:00:00 2001 From: Narsi-1310 <55081590+Narsi-1310@users.noreply.github.com> Date: Fri, 14 Feb 2020 16:59:30 +1100 Subject: [PATCH 102/498] Update subnets options and add details for endpoint The following changes have been carried out: - renamed parameter to enforce_private_link_service_network_policies from disable_private_link_service_network_policy_enforcement for service and endpoint subnets - Include private service connection under azurerm_private_endpoint - to provide better view of example. --- website/docs/r/private_endpoint.html.markdown | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/website/docs/r/private_endpoint.html.markdown b/website/docs/r/private_endpoint.html.markdown index a6d8acdafdfb2..47ca392476af0 100644 --- a/website/docs/r/private_endpoint.html.markdown +++ b/website/docs/r/private_endpoint.html.markdown @@ -35,7 +35,7 @@ resource "azurerm_subnet" "service" { virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.0.1.0/24" - disable_private_link_service_network_policy_enforcement = true + enforce_private_link_service_network_policies = true } resource "azurerm_subnet" "endpoint" { @@ -44,7 +44,7 @@ resource "azurerm_subnet" "endpoint" { virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.0.2.0/24" - disable_private_link_endpoint_network_policy_enforcement = true + enforce_private_link_endpoint_network_policies = true } resource "azurerm_public_ip" "example" { @@ -88,6 +88,12 @@ resource "azurerm_private_endpoint" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name subnet_id = azurerm_subnet.endpoint.id + + private_service_connection { + name = "example-privateserviceconnection" + private_connection_resource_id = azurerm_private_link_service.example.id + is_manual_connection = false + } } ``` From 3850025c3304e2ae7a6ae44d05ac24f6bbb28c40 Mon Sep 17 00:00:00 2001 From: Narsi-1310 <55081590+Narsi-1310@users.noreply.github.com> Date: Fri, 14 Feb 2020 17:01:35 +1100 Subject: [PATCH 103/498] Format private service connection --- website/docs/r/private_endpoint.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/docs/r/private_endpoint.html.markdown b/website/docs/r/private_endpoint.html.markdown index 47ca392476af0..d590fd957bbc3 100644 --- a/website/docs/r/private_endpoint.html.markdown +++ b/website/docs/r/private_endpoint.html.markdown @@ -90,9 +90,9 @@ resource "azurerm_private_endpoint" "example" { subnet_id = azurerm_subnet.endpoint.id private_service_connection { - name = "example-privateserviceconnection" - private_connection_resource_id = azurerm_private_link_service.example.id - is_manual_connection = false + name = "example-privateserviceconnection" + private_connection_resource_id = azurerm_private_link_service.example.id + is_manual_connection = false } } ``` From 4c870410fca7b7143f5481c30f25cba47b14efd0 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 09:37:21 +0100 Subject: [PATCH 104/498] r/mysql_server: removing reference to the old field --- .../internal/services/mysql/resource_arm_mysql_server.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/azurerm/internal/services/mysql/resource_arm_mysql_server.go b/azurerm/internal/services/mysql/resource_arm_mysql_server.go index 831db404112ce..7dd5ba650553e 100644 --- a/azurerm/internal/services/mysql/resource_arm_mysql_server.go +++ b/azurerm/internal/services/mysql/resource_arm_mysql_server.go @@ -51,9 +51,8 @@ func resourceArmMySqlServer() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), "sku_name": { - Type: schema.TypeString, - Required: true, - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ "B_Gen4_1", "B_Gen4_2", @@ -162,10 +161,10 @@ func resourceArmMySqlServer() *schema.Resource { }, CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { - tier, _ := diff.GetOk("sku.0.tier") + tier, _ := diff.GetOk("sku_name") storageMB, _ := diff.GetOk("storage_profile.0.storage_mb") - if strings.ToLower(tier.(string)) == "basic" && storageMB.(int) > 1048576 { + if strings.HasPrefix(tier.(string), "B_") && storageMB.(int) > 1048576 { return fmt.Errorf("basic pricing tier only supports upto 1,048,576 MB (1TB) of storage") } From 3b9cc7f5497ec80b110522a076ca10d9d6aca8a4 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Fri, 14 Feb 2020 10:24:24 +0000 Subject: [PATCH 105/498] tweaked import acctests --- .../tests/resource_arm_api_management_api_operation_test.go | 3 ++- .../tests/resource_arm_api_management_api_schema_test.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go index 2902e271967e3..bf2fd8babfee4 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go @@ -239,7 +239,8 @@ resource "azurerm_api_management_api_operation" "test" { } func testAccAzureRMApiManagementApiOperation_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMApiManagementApiOperation_template(data) + //template := testAccAzureRMApiManagementApiOperation_template(data) + template := testAccAzureRMApiManagementApiOperation_basic(data) return fmt.Sprintf(` %s diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go index d71d224d70f96..cead65cccb6ad 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go @@ -133,7 +133,7 @@ func testAccAzureRMApiManagementApiSchema_requiresImport(data acceptance.TestDat return fmt.Sprintf(` %s -resource "azurerm_api_management_api_schema" "test" { +resource "azurerm_api_management_api_schema" "import" { api_name = "${azurerm_api_management_api.test.name}" api_management_name = "${azurerm_api_management.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" From f9a2a85a2dc938d365fba8e6512b7568b9708ffd Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 09:28:08 +0100 Subject: [PATCH 106/498] r/mssql_elasticpool: fixing the import tests --- .../resource_arm_mssql_elasticpool_test.go | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go b/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go index 5c4555b8bfba2..2d693a5b1dccd 100644 --- a/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go +++ b/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go @@ -329,18 +329,27 @@ func testAccAzureRMMsSqlElasticPool_basic_DTU(data acceptance.TestData) string { } func testAccAzureRMMsSqlElasticPool_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMMsSqlElasticPool_DTU_Template(data, "BasicPool", "Basic", 50, 5242880000, 0, 5, false) + template := testAccAzureRMMsSqlElasticPool_DTU_Template(data, "BasicPool", "Basic", 50, 4.8828125, 0, 5, false) return fmt.Sprintf(` %s resource "azurerm_mssql_elasticpool" "import" { - name = "${azurerm_mssql_elasticpool.test.name}" - resource_group_name = "${azurerm_mssql_elasticpool.test.resource_group_name}" - location = "${azurerm_mssql_elasticpool.test.location}" - server_name = "${azurerm_mssql_elasticpool.test.server_name}" - max_size_bytes = "${azurerm_mssql_elasticpool.test.max_size_bytes}" - sku = "${azurerm_mssql_elasticpool.test.sku}" - per_database_settings = "${azurerm_mssql_elasticpool.test.per_database_settings}" + name = "${azurerm_mssql_elasticpool.test.name}" + resource_group_name = "${azurerm_mssql_elasticpool.test.resource_group_name}" + location = "${azurerm_mssql_elasticpool.test.location}" + server_name = "${azurerm_mssql_elasticpool.test.server_name}" + max_size_gb = 4.8828125 + + sku { + name = "BasicPool" + tier = "Basic" + capacity = 50 + } + + per_database_settings { + min_capacity = 0 + max_capacity = 5 + } } `, template) } From 0476ebaec7b2ea29c9aaaf05fdd4cbec44c31793 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 11:56:44 +0100 Subject: [PATCH 107/498] iothub: removing the deprecated `azurerm_iot_dps` and `azurerm_iot_dps_certificate` resources Replacements for these resources is available in the form of `azurerm_iothub_..` resources --- .../internal/services/iothub/registration.go | 2 - .../services/iothub/resource_arm_iot_dps.go | 381 ------------------ .../resource_arm_iot_dps_certificate.go | 174 -------- .../resource_arm_iot_dps_certificate_test.go | 216 ---------- .../iothub/tests/resource_arm_iot_dps_test.go | 284 ------------- 5 files changed, 1057 deletions(-) delete mode 100644 azurerm/internal/services/iothub/resource_arm_iot_dps.go delete mode 100644 azurerm/internal/services/iothub/resource_arm_iot_dps_certificate.go delete mode 100644 azurerm/internal/services/iothub/tests/resource_arm_iot_dps_certificate_test.go delete mode 100644 azurerm/internal/services/iothub/tests/resource_arm_iot_dps_test.go diff --git a/azurerm/internal/services/iothub/registration.go b/azurerm/internal/services/iothub/registration.go index 5bdcfdd493122..62c25ce49a2f4 100644 --- a/azurerm/internal/services/iothub/registration.go +++ b/azurerm/internal/services/iothub/registration.go @@ -23,8 +23,6 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_iot_dps": resourceArmIotDPS(), - "azurerm_iot_dps_certificate": resourceArmIotDPSCertificate(), "azurerm_iothub_dps": resourceArmIotHubDPS(), "azurerm_iothub_dps_certificate": resourceArmIotHubDPSCertificate(), "azurerm_iothub_dps_shared_access_policy": resourceArmIotHubDPSSharedAccessPolicy(), diff --git a/azurerm/internal/services/iothub/resource_arm_iot_dps.go b/azurerm/internal/services/iothub/resource_arm_iot_dps.go deleted file mode 100644 index 31818c1d88e82..0000000000000 --- a/azurerm/internal/services/iothub/resource_arm_iot_dps.go +++ /dev/null @@ -1,381 +0,0 @@ -package iothub - -import ( - "context" - "fmt" - "log" - "regexp" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/iothub/mgmt/2018-12-01-preview/devices" - "github.com/Azure/azure-sdk-for-go/services/provisioningservices/mgmt/2018-01-22/iothub" - "github.com/hashicorp/go-azure-helpers/response" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "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/suppress" - "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/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmIotDPS() *schema.Resource { - return &schema.Resource{ - Create: resourceArmIotDPSCreateUpdate, - Read: resourceArmIotDPSRead, - Update: resourceArmIotDPSCreateUpdate, - Delete: resourceArmIotDPSDelete, - - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - DeprecationMessage: `The 'azurerm_iot_dps' resource is deprecated in favour of the renamed version 'azurerm_iothub_dps'. - -Information on migrating to the renamed resource can be found here: https://terraform.io/docs/providers/azurerm/guides/migrating-between-renamed-resources.html - -As such the existing 'azurerm_iot_dps' resource is deprecated and will be removed in the next major version of the AzureRM Provider (2.0). -`, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.IoTHubName, - }, - - "resource_group_name": azure.SchemaResourceGroupName(), // azure.SchemaResourceGroupNameDiffSuppress(), - - "location": azure.SchemaLocation(), - - "sku": { - Type: schema.TypeList, - MaxItems: 1, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(devices.B1), - string(devices.B2), - string(devices.B3), - string(devices.F1), - string(devices.S1), - string(devices.S2), - string(devices.S3), - }, true), - }, - - "tier": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property is no longer required and will be removed in version 2.0 of the provider", - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(devices.Basic), - string(devices.Free), - string(devices.Standard), - }, true), - }, - - "capacity": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntAtLeast(1), - }, - }, - }, - }, - - "linked_hub": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "connection_string": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - ForceNew: true, - // Azure returns the key as ****. We'll suppress that here. - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - secretKeyRegex := regexp.MustCompile("(SharedAccessKey)=[^;]+") - maskedNew := secretKeyRegex.ReplaceAllString(new, "$1=****") - return (new == d.Get(k).(string)) && (maskedNew == old) - }, - Sensitive: true, - }, - "location": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - StateFunc: azure.NormalizeLocation, - ForceNew: true, - }, - "apply_allocation_policy": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - "allocation_weight": { - Type: schema.TypeInt, - Optional: true, - Default: 0, - ValidateFunc: validation.IntBetween(0, 1000), - }, - "hostname": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - - "tags": tags.Schema(), - }, - } -} - -func resourceArmIotDPSCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSResourceClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, name, resourceGroup) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_iot_dps", *existing.ID) - } - } - - iotdps := iothub.ProvisioningServiceDescription{ - Location: utils.String(d.Get("location").(string)), - Name: utils.String(name), - Sku: expandIoTDPSSku(d), - Properties: &iothub.IotDpsPropertiesDescription{ - IotHubs: expandIoTDPSIoTHubs(d.Get("linked_hub").([]interface{})), - }, - Tags: tags.Expand(d.Get("tags").(map[string]interface{})), - } - - future, err := client.CreateOrUpdate(ctx, resourceGroup, name, iotdps) - if err != nil { - return fmt.Errorf("Error creating/updating IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for the completion of the creating/updating of IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - resp, err := client.Get(ctx, name, resourceGroup) - if err != nil { - return fmt.Errorf("Error retrieving IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - if resp.ID == nil { - return fmt.Errorf("Cannot read IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - d.SetId(*resp.ID) - - return resourceArmIotDPSRead(d, meta) -} - -func resourceArmIotDPSRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSResourceClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["provisioningServices"] - - resp, err := client.Get(ctx, name, resourceGroup) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - - return fmt.Errorf("Error retrieving IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", resp.Name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - sku := flattenIoTDPSSku(resp.Sku) - if err := d.Set("sku", sku); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - - if props := resp.Properties; props != nil { - if err := d.Set("linked_hub", flattenIoTDPSLinkedHub(props.IotHubs)); err != nil { - return fmt.Errorf("Error setting `linked_hub`: %+v", err) - } - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmIotDPSDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSResourceClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["provisioningServices"] - - future, err := client.Delete(ctx, name, resourceGroup) - if err != nil { - if !response.WasNotFound(future.Response()) { - return fmt.Errorf("Error deleting IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - } - - return waitForIotDPSToBeDeleted(ctx, client, resourceGroup, name, d) -} - -func waitForIotDPSToBeDeleted(ctx context.Context, client *iothub.IotDpsResourceClient, resourceGroup, name string, d *schema.ResourceData) error { - // we can't use the Waiter here since the API returns a 404 once it's deleted which is considered a polling status code.. - log.Printf("[DEBUG] Waiting for IoT Device Provisioning Service %q (Resource Group %q) to be deleted", name, resourceGroup) - stateConf := &resource.StateChangeConf{ - Pending: []string{"200"}, - Target: []string{"404"}, - Refresh: iotdpsStateStatusCodeRefreshFunc(ctx, client, resourceGroup, name), - Timeout: d.Timeout(schema.TimeoutDelete), - } - - if _, err := stateConf.WaitForState(); err != nil { - return fmt.Errorf("Error waiting for IoT Device Provisioning Service %q (Resource Group %q) to be deleted: %+v", name, resourceGroup, err) - } - - return nil -} - -func iotdpsStateStatusCodeRefreshFunc(ctx context.Context, client *iothub.IotDpsResourceClient, resourceGroup, name string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - res, err := client.Get(ctx, name, resourceGroup) - - log.Printf("Retrieving IoT Device Provisioning Service %q (Resource Group %q) returned Status %d", resourceGroup, name, res.StatusCode) - - if err != nil { - if utils.ResponseWasNotFound(res.Response) { - return res, strconv.Itoa(res.StatusCode), nil - } - return nil, "", fmt.Errorf("Error polling for the status of the IoT Device Provisioning Service %q (Resource Group %q): %+v", name, resourceGroup, err) - } - - return res, strconv.Itoa(res.StatusCode), nil - } -} - -func expandIoTDPSSku(d *schema.ResourceData) *iothub.IotDpsSkuInfo { - skuList := d.Get("sku").([]interface{}) - skuMap := skuList[0].(map[string]interface{}) - capacity := int64(skuMap["capacity"].(int)) - - name := skuMap["name"].(string) - tier := skuMap["tier"].(string) - - return &iothub.IotDpsSkuInfo{ - Name: iothub.IotDpsSku(name), - Tier: utils.String(tier), - Capacity: utils.Int64(capacity), - } -} - -func expandIoTDPSIoTHubs(input []interface{}) *[]iothub.DefinitionDescription { - linkedHubs := make([]iothub.DefinitionDescription, 0) - - for _, attr := range input { - linkedHubConfig := attr.(map[string]interface{}) - linkedHub := iothub.DefinitionDescription{ - ConnectionString: utils.String(linkedHubConfig["connection_string"].(string)), - AllocationWeight: utils.Int32(int32(linkedHubConfig["allocation_weight"].(int))), - ApplyAllocationPolicy: utils.Bool(linkedHubConfig["apply_allocation_policy"].(bool)), - Location: utils.String(linkedHubConfig["location"].(string)), - } - - linkedHubs = append(linkedHubs, linkedHub) - } - - return &linkedHubs -} - -func flattenIoTDPSSku(input *iothub.IotDpsSkuInfo) []interface{} { - output := make(map[string]interface{}) - - output["name"] = string(input.Name) - output["tier"] = input.Tier - if capacity := input.Capacity; capacity != nil { - output["capacity"] = int(*capacity) - } - - return []interface{}{output} -} - -func flattenIoTDPSLinkedHub(input *[]iothub.DefinitionDescription) []interface{} { - linkedHubs := make([]interface{}, 0) - if input == nil { - return linkedHubs - } - - for _, attr := range *input { - linkedHub := make(map[string]interface{}) - - if attr.Name != nil { - linkedHub["hostname"] = *attr.Name - } - if attr.ApplyAllocationPolicy != nil { - linkedHub["apply_allocation_policy"] = *attr.ApplyAllocationPolicy - } - if attr.AllocationWeight != nil { - linkedHub["allocation_weight"] = *attr.AllocationWeight - } - if attr.ConnectionString != nil { - linkedHub["connection_string"] = *attr.ConnectionString - } - if attr.Location != nil { - linkedHub["location"] = *attr.Location - } - - linkedHubs = append(linkedHubs, linkedHub) - } - - return linkedHubs -} diff --git a/azurerm/internal/services/iothub/resource_arm_iot_dps_certificate.go b/azurerm/internal/services/iothub/resource_arm_iot_dps_certificate.go deleted file mode 100644 index 694cbf1a8fe15..0000000000000 --- a/azurerm/internal/services/iothub/resource_arm_iot_dps_certificate.go +++ /dev/null @@ -1,174 +0,0 @@ -package iothub - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/provisioningservices/mgmt/2018-01-22/iothub" - "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/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" -) - -func resourceArmIotDPSCertificate() *schema.Resource { - return &schema.Resource{ - Create: resourceArmIotDPSCertificateCreateUpdate, - Read: resourceArmIotDPSCertificateRead, - Update: resourceArmIotDPSCertificateCreateUpdate, - Delete: resourceArmIotDPSCertificateDelete, - - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - DeprecationMessage: `The 'azurerm_iot_dps_certificate' resource is deprecated in favour of the renamed version 'azurerm_iothub_dps_certificate'. - -Information on migrating to the renamed resource can be found here: https://terraform.io/docs/providers/azurerm/guides/migrating-between-renamed-resources.html - -As such the existing 'azurerm_iot_dps_certificate' resource is deprecated and will be removed in the next major version of the AzureRM Provider (2.0). -`, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.IoTHubName, - }, - - "resource_group_name": azure.SchemaResourceGroupName(), - - "iot_dps_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.IoTHubName, - }, - - "certificate_content": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - Sensitive: true, - }, - }, - } -} - -func resourceArmIotDPSCertificateCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSCertificateClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - iotDPSName := d.Get("iot_dps_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_iot_dps_certificate", *existing.ID) - } - } - - certificate := iothub.CertificateBodyDescription{ - Certificate: utils.String(d.Get("certificate_content").(string)), - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, iotDPSName, name, certificate, ""); err != nil { - return fmt.Errorf("Error creating/updating IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - - resp, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - if err != nil { - return fmt.Errorf("Error retrieving IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - - if resp.ID == nil { - return fmt.Errorf("Cannot read IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - - d.SetId(*resp.ID) - - return resourceArmIotDPSCertificateRead(d, meta) -} - -func resourceArmIotDPSCertificateRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSCertificateClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - iotDPSName := id.Path["provisioningServices"] - name := id.Path["certificates"] - - resp, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error retrieving IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - - d.Set("name", resp.Name) - d.Set("resource_group_name", resourceGroup) - d.Set("iot_dps_name", iotDPSName) - // We are unable to set `certificate_content` since it is not returned from the API - - return nil -} - -func resourceArmIotDPSCertificateDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).IoTHub.DPSCertificateClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - iotDPSName := id.Path["provisioningServices"] - name := id.Path["certificates"] - - resp, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - return fmt.Errorf("Error retrieving IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - - if resp.Etag == nil { - return fmt.Errorf("Error deleting IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q) because Etag is nil", name, iotDPSName, resourceGroup) - } - - // TODO address this delete call if https://github.com/Azure/azure-rest-api-specs/pull/6311 get's merged - if _, err := client.Delete(ctx, resourceGroup, *resp.Etag, iotDPSName, name, "", nil, nil, iothub.ServerAuthentication, nil, nil, nil, ""); err != nil { - return fmt.Errorf("Error deleting IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q): %+v", name, iotDPSName, resourceGroup, err) - } - return nil -} diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_certificate_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_certificate_test.go deleted file mode 100644 index 03bf322e7f417..0000000000000 --- a/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_certificate_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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/internal/features" -) - -func TestAccAzureRMIotDPSCertificate_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_iot_dps_certificate", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSCertificateDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPSCertificate_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSCertificateExists(data.ResourceName), - ), - }, - data.ImportStep("certificate_content"), - }, - }) -} - -func TestAccAzureRMIotDPSCertificate_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - - data := acceptance.BuildTestData(t, "azurerm_iot_dps_certificate", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSCertificateDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPSCertificate_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSCertificateExists(data.ResourceName), - ), - }, - { - Config: testAccAzureRMIotDPSCertificate_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_iotdps"), - }, - }, - }) -} - -func TestAccAzureRMIotDPSCertificate_update(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_iot_dps_certificate", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSCertificateDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPSCertificate_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSCertificateExists(data.ResourceName), - ), - }, - data.ImportStep("certificate_content"), - { - Config: testAccAzureRMIotDPSCertificate_update(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSCertificateExists(data.ResourceName), - ), - }, - data.ImportStep("certificate_content"), - }, - }) -} - -func testCheckAzureRMIotDPSCertificateDestroy(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).IoTHub.DPSCertificateClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_iot_dps_certificate" { - continue - } - - name := rs.Primary.Attributes["name"] - resourceGroup := rs.Primary.Attributes["resource_group_name"] - iotDPSName := rs.Primary.Attributes["iot_dps_name"] - - resp, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("IoT Device Provisioning Service Certificate %s still exists in (device provisioning service %s / resource group %s)", name, iotDPSName, resourceGroup) - } - } - return nil -} - -func testCheckAzureRMIotDPSCertificateExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).IoTHub.DPSCertificateClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - name := rs.Primary.Attributes["name"] - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - iotDPSName := rs.Primary.Attributes["iot_dps_name"] - - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for IoT Device Provisioning Service Certificate: %s", name) - } - - resp, err := client.Get(ctx, name, resourceGroup, iotDPSName, "") - if err != nil { - if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: IoT Device Provisioning Service Certificate %q (Device Provisioning Service %q / Resource Group %q) does not exist", name, iotDPSName, resourceGroup) - } - - return fmt.Errorf("Bad: Get on iothubDPSCertificateClient: %+v", err) - } - - return nil - } -} - -func testAccAzureRMIotDPSCertificate_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } -} - -resource "azurerm_iot_dps_certificate" "test" { - name = "acctestIoTDPSCertificate-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - iot_dps_name = "${azurerm_iot_dps.test.name}" - - certificate_content = "${filebase64("testdata/batch_certificate.cer")}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMIotDPSCertificate_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMIotDPS_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_iot_dps_certificate" "test" { - name = "${azurerm_iot_dps_certificate.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - iot_dps_name = "${azurerm_iot_dps.test.name}" - - certificate_content = "${filebase64("testdata/batch_certificate.cer")}" -} -`, template) -} - -func testAccAzureRMIotDPSCertificate_update(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } - - tags = { - purpose = "testing" - } -} - -resource "azurerm_iot_dps_certificate" "test" { - name = "acctestIoTDPSCertificate-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - iot_dps_name = "${azurerm_iot_dps.test.name}" - - certificate_content = "${filebase64("testdata/application_gateway_test.cer")}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_test.go deleted file mode 100644 index 8283155704e49..0000000000000 --- a/azurerm/internal/services/iothub/tests/resource_arm_iot_dps_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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/internal/features" -) - -func TestAccAzureRMIotDPS_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_iot_dps", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPS_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMIotDPS_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - - data := acceptance.BuildTestData(t, "azurerm_iot_dps", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPS_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - { - Config: testAccAzureRMIotDPS_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_iotdps"), - }, - }, - }) -} - -func TestAccAzureRMIotDPS_update(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_iot_dps", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPS_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - data.ImportStep(), - { - Config: testAccAzureRMIotDPS_update(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMIotDPS_linkedHubs(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_iot_dps", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotDPS_linkedHubs(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - data.ImportStep(), - { - Config: testAccAzureRMIotDPS_linkedHubsUpdated(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotDPSExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testCheckAzureRMIotDPSDestroy(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).IoTHub.DPSResourceClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_iotdps" { - continue - } - - name := rs.Primary.Attributes["name"] - resourceGroup := rs.Primary.Attributes["resource_group_name"] - - resp, err := client.Get(ctx, resourceGroup, name) - - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("IoT Device Provisioning Service %s still exists in resource group %s", name, resourceGroup) - } - } - return nil -} - -func testCheckAzureRMIotDPSExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - client := acceptance.AzureProvider.Meta().(*clients.Client).IoTHub.DPSResourceClient - - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - iotdpsName := 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 IoT Device Provisioning Service: %s", iotdpsName) - } - - resp, err := client.Get(ctx, iotdpsName, resourceGroup) - if err != nil { - if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: IoT Device Provisioning Service %q (Resource Group %q) does not exist", iotdpsName, resourceGroup) - } - - return fmt.Errorf("Bad: Get on iothubDPSResourceClient: %+v", err) - } - - return nil - } -} - -func testAccAzureRMIotDPS_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMIotDPS_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMIotDPS_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_iot_dps" "import" { - name = "${azurerm_iot_dps.test.name}" - resource_group_name = "${azurerm_iot_dps.test.resource_group_name}" - location = "${azurerm_iot_dps.test.location}" - - sku { - name = "S1" - capacity = "1" - } -} -`, template) -} - -func testAccAzureRMIotDPS_update(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } - - tags = { - purpose = "testing" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMIotDPS_linkedHubs(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } - - linked_hub { - connection_string = "HostName=test.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=booo" - location = "${azurerm_resource_group.test.location}" - allocation_weight = 15 - apply_allocation_policy = true - } - - linked_hub { - connection_string = "HostName=test2.azure-devices.net;SharedAccessKeyName=iothubowner2;SharedAccessKey=key2" - location = "${azurerm_resource_group.test.location}" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMIotDPS_linkedHubsUpdated(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_iot_dps" "test" { - name = "acctestIoTDPS-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - - sku { - name = "S1" - capacity = "1" - } - - linked_hub { - connection_string = "HostName=test.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=booo" - location = "${azurerm_resource_group.test.location}" - allocation_weight = 150 - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} From 514b6562ac0d1dfb09ca1ee6a8837cccfe4bfeb9 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Fri, 14 Feb 2020 13:20:35 +0000 Subject: [PATCH 108/498] Minor formatting update. Added azurerm_role_definition data source note --- website/docs/guides/2.0-upgrade-guide.html.markdown | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index 6382c36896385..b70630ce6bb6d 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -169,6 +169,10 @@ The deprecated field `internal_fqdn` will be removed. The deprecated field `network_interface_ids` will be removed. +### Date Source: `azurerm_role_definition` + +The Data Source no longer supports the alias `VirtualMachineContributor` for the Built-in role `Virtual Machine Contributor`. + ### Data Source: `azurerm_scheduler_job_collection` Azure Scheduler is being retired in favour of Logic Apps ([more information can be found here](https://docs.microsoft.com/en-us/azure/scheduler/migrate-from-scheduler-to-logic-apps)) - as such this Data Source will be removed. @@ -287,15 +291,15 @@ The deprecated `zone_type` field will be removed. This has been replaced by the The deprecated `location` field will be removed, since this is no longer used. -## Resource: `azurerm_eventhub_authorization_rule` +### Resource: `azurerm_eventhub_authorization_rule` The deprecated `location` field will be removed, since this is no longer used. -## Resource: `azurerm_eventhub_consumer_group` +### Resource: `azurerm_eventhub_consumer_group` The deprecated `location` field will be removed, since this is no longer used. -## Resource: `azurerm_eventhub_namespace` +^### Resource: `azurerm_eventhub_namespace` The deprecated `kafka_enabled` field will be removed, since this is no longer used. @@ -383,7 +387,7 @@ The `load_balancer_backend_address_pools_ids` field in the `ip_configuration` bl The `load_balancer_inbound_nat_rules_ids` field in the `ip_configuration` block will been removed. This has been replaced by the `azurerm_network_interface_nat_rule_association` resource. -## Resource: `azurerm_notification_hub_namespace` +^### Resource: `azurerm_notification_hub_namespace` The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. From f5a4293b4a886deea7b16e959babd384c4586297 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Fri, 14 Feb 2020 13:23:45 +0000 Subject: [PATCH 109/498] removed unintended carets --- website/docs/guides/2.0-upgrade-guide.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index b70630ce6bb6d..cbcfc6a085892 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -299,7 +299,7 @@ The deprecated `location` field will be removed, since this is no longer used. The deprecated `location` field will be removed, since this is no longer used. -^### Resource: `azurerm_eventhub_namespace` +### Resource: `azurerm_eventhub_namespace` The deprecated `kafka_enabled` field will be removed, since this is no longer used. @@ -387,7 +387,7 @@ The `load_balancer_backend_address_pools_ids` field in the `ip_configuration` bl The `load_balancer_inbound_nat_rules_ids` field in the `ip_configuration` block will been removed. This has been replaced by the `azurerm_network_interface_nat_rule_association` resource. -^### Resource: `azurerm_notification_hub_namespace` +### Resource: `azurerm_notification_hub_namespace` The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. From 9f487ee9670b8888caa67e8c605a8ebdec4750c8 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 14:25:15 +0100 Subject: [PATCH 110/498] linting --- .../services/mssql/tests/resource_arm_mssql_elasticpool_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go b/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go index 2d693a5b1dccd..f131eaa6c2377 100644 --- a/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go +++ b/azurerm/internal/services/mssql/tests/resource_arm_mssql_elasticpool_test.go @@ -339,7 +339,7 @@ resource "azurerm_mssql_elasticpool" "import" { location = "${azurerm_mssql_elasticpool.test.location}" server_name = "${azurerm_mssql_elasticpool.test.server_name}" max_size_gb = 4.8828125 - + sku { name = "BasicPool" tier = "Basic" From 976f85ee48cee04f4c155fd287fe6203829cc771 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 14:26:19 +0100 Subject: [PATCH 111/498] removing dead code --- .../resource_arm_postgresql_server_test.go | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go index b6a6ad04b8ea9..a02ee21b42dd4 100644 --- a/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go +++ b/azurerm/internal/services/postgres/tests/resource_arm_postgresql_server_test.go @@ -353,35 +353,6 @@ resource "azurerm_postgresql_server" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMPostgreSQLServer_basicNinePointFiveOldSku(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-psql-%d" - location = "%s" -} - -resource "azurerm_postgresql_server" "test" { - name = "acctest-psql-server-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku_name = "GP_Gen5_2" - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - auto_grow = "Disabled" - } - - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "%s" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, "9.5") -} - func testAccAzureRMPostgreSQLServer_basicNinePointFive(data acceptance.TestData) string { return testAccAzureRMPostgreSQLServer_basic(data, "9.5") } From adb6f592e49249dd5092dca1b7095a382e671ee2 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 13:49:10 +0100 Subject: [PATCH 112/498] r/network_interface: introducing a separate update method --- azurerm/helpers/azure/contains.go | 11 + .../keyvault/resource_arm_key_vault.go | 4 +- .../network/network_interface_locking.go | 61 ++ .../resource_arm_ddos_protection_plan.go | 2 +- .../services/network/resource_arm_firewall.go | 8 +- ...source_arm_network_ddos_protection_plan.go | 2 +- .../network/resource_arm_network_interface.go | 639 ++++++++++-------- .../network/resource_arm_network_profile.go | 4 +- .../network/resource_arm_virtual_network.go | 4 +- 9 files changed, 446 insertions(+), 289 deletions(-) create mode 100644 azurerm/helpers/azure/contains.go create mode 100644 azurerm/internal/services/network/network_interface_locking.go diff --git a/azurerm/helpers/azure/contains.go b/azurerm/helpers/azure/contains.go new file mode 100644 index 0000000000000..d6357dc3cc5bb --- /dev/null +++ b/azurerm/helpers/azure/contains.go @@ -0,0 +1,11 @@ +package azure + +func SliceContainsValue(input []string, value string) bool { + for _, v := range input { + if v == value { + return true + } + } + + return false +} diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 62d559c4d2f13..b8794993e092a 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -290,7 +290,7 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e } virtualNetworkName := id.Path["virtualNetworks"] - if !network.SliceContainsValue(virtualNetworkNames, virtualNetworkName) { + if !azure.SliceContainsValue(virtualNetworkNames, virtualNetworkName) { virtualNetworkNames = append(virtualNetworkNames, virtualNetworkName) } } @@ -437,7 +437,7 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { } virtualNetworkName := id.Path["virtualNetworks"] - if !network.SliceContainsValue(virtualNetworkNames, virtualNetworkName) { + if !azure.SliceContainsValue(virtualNetworkNames, virtualNetworkName) { virtualNetworkNames = append(virtualNetworkNames, virtualNetworkName) } } diff --git a/azurerm/internal/services/network/network_interface_locking.go b/azurerm/internal/services/network/network_interface_locking.go new file mode 100644 index 0000000000000..9e599ce482b8b --- /dev/null +++ b/azurerm/internal/services/network/network_interface_locking.go @@ -0,0 +1,61 @@ +package network + +import ( + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" +) + +type networkInterfaceIPConfigurationLockingDetails struct { + subnetNamesToLock []string + virtualNetworkNamesToLock []string +} + +func (details networkInterfaceIPConfigurationLockingDetails) lock() { + locks.MultipleByName(&details.subnetNamesToLock, SubnetResourceName) + locks.MultipleByName(&details.virtualNetworkNamesToLock, VirtualNetworkResourceName) +} + +func (details networkInterfaceIPConfigurationLockingDetails) unlock() { + locks.UnlockMultipleByName(&details.subnetNamesToLock, SubnetResourceName) + locks.UnlockMultipleByName(&details.virtualNetworkNamesToLock, VirtualNetworkResourceName) +} + +func determineResourcesToLockFromIPConfiguration(input *[]network.InterfaceIPConfiguration) (*networkInterfaceIPConfigurationLockingDetails, error) { + if input == nil { + return &networkInterfaceIPConfigurationLockingDetails{ + subnetNamesToLock: []string{}, + virtualNetworkNamesToLock: []string{}, + }, nil + } + + subnetNamesToLock := make([]string, 0) + virtualNetworkNamesToLock := make([]string, 0) + + for _, config := range *input { + if config.Subnet == nil || config.Subnet.ID == nil { + continue + } + + id, err := azure.ParseAzureResourceID(*config.Subnet.ID) + if err != nil { + return nil, err + } + + virtualNetworkName := id.Path["virtualNetworks"] + subnetName := id.Path["subnets"] + + if !azure.SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { + virtualNetworkNamesToLock = append(virtualNetworkNamesToLock, virtualNetworkName) + } + + if !azure.SliceContainsValue(subnetNamesToLock, subnetName) { + subnetNamesToLock = append(subnetNamesToLock, subnetName) + } + } + + return &networkInterfaceIPConfigurationLockingDetails{ + subnetNamesToLock: subnetNamesToLock, + virtualNetworkNamesToLock: virtualNetworkNamesToLock, + }, nil +} diff --git a/azurerm/internal/services/network/resource_arm_ddos_protection_plan.go b/azurerm/internal/services/network/resource_arm_ddos_protection_plan.go index 29edffb05e505..10c5377ba10e7 100644 --- a/azurerm/internal/services/network/resource_arm_ddos_protection_plan.go +++ b/azurerm/internal/services/network/resource_arm_ddos_protection_plan.go @@ -229,7 +229,7 @@ func extractVnetNames(d *schema.ResourceData) (*[]string, error) { vnetName := vnetResourceID.Path["virtualNetworks"] - if !SliceContainsValue(vnetNames, vnetName) { + if !azure.SliceContainsValue(vnetNames, vnetName) { vnetNames = append(vnetNames, vnetName) } } diff --git a/azurerm/internal/services/network/resource_arm_firewall.go b/azurerm/internal/services/network/resource_arm_firewall.go index 9b4ac25596ad5..c825d2e914d8d 100644 --- a/azurerm/internal/services/network/resource_arm_firewall.go +++ b/azurerm/internal/services/network/resource_arm_firewall.go @@ -267,12 +267,12 @@ func resourceArmFirewallDelete(d *schema.ResourceData, meta interface{}) error { } subnetName := parsedSubnetId.Path["subnets"] - if !SliceContainsValue(subnetNamesToLock, subnetName) { + if !azure.SliceContainsValue(subnetNamesToLock, subnetName) { subnetNamesToLock = append(subnetNamesToLock, subnetName) } virtualNetworkName := parsedSubnetId.Path["virtualNetworks"] - if !SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { + if !azure.SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { virtualNetworkNamesToLock = append(virtualNetworkNamesToLock, virtualNetworkName) } } @@ -338,11 +338,11 @@ func expandArmFirewallIPConfigurations(d *schema.ResourceData) (*[]network.Azure subnetName := subnetID.Path["subnets"] virtualNetworkName := subnetID.Path["virtualNetworks"] - if !SliceContainsValue(subnetNamesToLock, subnetName) { + if !azure.SliceContainsValue(subnetNamesToLock, subnetName) { subnetNamesToLock = append(subnetNamesToLock, subnetName) } - if !SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { + if !azure.SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { virtualNetworkNamesToLock = append(virtualNetworkNamesToLock, virtualNetworkName) } diff --git a/azurerm/internal/services/network/resource_arm_network_ddos_protection_plan.go b/azurerm/internal/services/network/resource_arm_network_ddos_protection_plan.go index f8c8b7131d434..3f8f2f8dfb534 100644 --- a/azurerm/internal/services/network/resource_arm_network_ddos_protection_plan.go +++ b/azurerm/internal/services/network/resource_arm_network_ddos_protection_plan.go @@ -223,7 +223,7 @@ func expandArmNetworkDDoSProtectionPlanVnetNames(d *schema.ResourceData) (*[]str vnetName := vnetResourceID.Path["virtualNetworks"] - if !SliceContainsValue(vnetNames, vnetName) { + if !azure.SliceContainsValue(vnetNames, vnetName) { vnetNames = append(vnetNames, vnetName) } } diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 67d9a448b7fb1..108413b84da73 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -3,7 +3,6 @@ package network import ( "fmt" "log" - "strings" "time" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" @@ -12,7 +11,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "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/locks" @@ -26,9 +24,9 @@ var networkInterfaceResourceName = "azurerm_network_interface" func resourceArmNetworkInterface() *schema.Resource { return &schema.Resource{ - Create: resourceArmNetworkInterfaceCreateUpdate, + Create: resourceArmNetworkInterfaceCreate, Read: resourceArmNetworkInterfaceRead, - Update: resourceArmNetworkInterfaceCreateUpdate, + Update: resourceArmNetworkInterfaceUpdate, Delete: resourceArmNetworkInterfaceDelete, Importer: &schema.ResourceImporter{ @@ -53,26 +51,13 @@ func resourceArmNetworkInterface() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), + // NOTE: does this want it's own association resource? "network_security_group_id": { Type: schema.TypeString, Optional: true, ValidateFunc: azure.ValidateResourceIDOrEmpty, }, - "mac_address": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validate.MACAddress, - }, - - "virtual_machine_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: azure.ValidateResourceID, - }, - "ip_configuration": { Type: schema.TypeList, Required: true, @@ -107,7 +92,6 @@ func resourceArmNetworkInterface() *schema.Resource { }, false), }, - //TODO: should this be renamed to private_ip_address_allocation_method or private_ip_allocation_method ? "private_ip_address_allocation": { Type: schema.TypeString, Required: true, @@ -193,6 +177,18 @@ func resourceArmNetworkInterface() *schema.Resource { Set: schema.HashString, }, + "enable_accelerated_networking": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "enable_ip_forwarding": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "internal_dns_name_label": { Type: schema.TypeString, Optional: true, @@ -200,45 +196,22 @@ func resourceArmNetworkInterface() *schema.Resource { ValidateFunc: validation.StringIsNotEmpty, }, + "tags": tags.Schema(), + + // Computed "applied_dns_servers": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeList, Computed: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringIsNotEmpty, + Type: schema.TypeString, }, - Set: schema.HashString, }, - "internal_fqdn": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This field has been removed by Azure", - }, - - /** - * As of 2018-01-06: AN (aka. SR-IOV) on Azure is GA on Windows and Linux. - * - * Refer to: https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/ - * - * Refer to: https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli - * For details, VM configuration and caveats. - */ - "enable_accelerated_networking": { - Type: schema.TypeBool, - Optional: true, - Default: false, - }, - - "enable_ip_forwarding": { - Type: schema.TypeBool, - Optional: true, - Default: false, + "mac_address": { + Type: schema.TypeString, + Computed: true, }, - // todo consider removing this one day as it is exposed in `private_ip_addresses.0` "private_ip_address": { Type: schema.TypeString, Computed: true, @@ -252,26 +225,27 @@ func resourceArmNetworkInterface() *schema.Resource { }, }, - "tags": tags.Schema(), + "virtual_machine_id": { + Type: schema.TypeString, + Computed: true, + }, }, } } -func resourceArmNetworkInterfaceCreateUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Network.InterfacesClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - log.Printf("[INFO] preparing arguments for AzureRM Network Interface creation.") - name := d.Get("name").(string) - resGroup := d.Get("resource_group_name").(string) + resourceGroup := d.Get("resource_group_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resGroup, name, "") + existing, err := client.Get(ctx, resourceGroup, name, "") if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Network Interface %q (Resource Group %q): %s", name, resGroup, err) + return fmt.Errorf("Error checking for presence of existing Network Interface %q (Resource Group %q): %s", name, resourceGroup, err) } } @@ -313,70 +287,176 @@ func resourceArmNetworkInterfaceCreateUpdate(d *schema.ResourceData, meta interf dns, hasDns := d.GetOk("dns_servers") nameLabel, hasNameLabel := d.GetOk("internal_dns_name_label") if hasDns || hasNameLabel { - ifaceDnsSettings := network.InterfaceDNSSettings{} + dnsSettings := network.InterfaceDNSSettings{} if hasDns { - var dnsServers []string - dns := dns.(*schema.Set).List() - for _, v := range dns { - str := v.(string) - dnsServers = append(dnsServers, str) - } - ifaceDnsSettings.DNSServers = &dnsServers + dnsRaw := dns.(*schema.Set).List() + dns := expandNetworkInterfaceDnsServers(dnsRaw) + dnsSettings.DNSServers = &dns } if hasNameLabel { name_label := nameLabel.(string) - ifaceDnsSettings.InternalDNSNameLabel = &name_label + dnsSettings.InternalDNSNameLabel = &name_label } - properties.DNSSettings = &ifaceDnsSettings + properties.DNSSettings = &dnsSettings } - ipConfigs, subnetnToLock, vnnToLock, sgErr := expandAzureRmNetworkInterfaceIpConfigurations(d) - if sgErr != nil { - return fmt.Errorf("Error Building list of Network Interface IP Configurations: %+v", sgErr) + ipConfigsRaw := d.Get("ip_configuration").([]interface{}) + ipConfigs, err := expandNetworkInterfaceIPConfigurations(ipConfigsRaw) + if err != nil { + return fmt.Errorf("Error expanding `ip_configuration`: %+v", err) + } + lockingDetails, err := determineResourcesToLockFromIPConfiguration(&ipConfigs) + if err != nil { + return fmt.Errorf("Error determing locking details: %+v", err) } - locks.MultipleByName(subnetnToLock, SubnetResourceName) - defer locks.UnlockMultipleByName(subnetnToLock, SubnetResourceName) - - locks.MultipleByName(vnnToLock, VirtualNetworkResourceName) - defer locks.UnlockMultipleByName(vnnToLock, VirtualNetworkResourceName) + lockingDetails.lock() + defer lockingDetails.unlock() if len(ipConfigs) > 0 { properties.IPConfigurations = &ipConfigs } iface := network.Interface{ - Name: &name, - Location: &location, + Name: utils.String(name), + Location: utils.String(location), InterfacePropertiesFormat: &properties, Tags: tags.Expand(t), } - future, err := client.CreateOrUpdate(ctx, resGroup, name, iface) + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, iface) if err != nil { - return err + return fmt.Errorf("Error creating Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return err + return fmt.Errorf("Error waiting for creation of Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } - read, err := client.Get(ctx, resGroup, name, "") + read, err := client.Get(ctx, resourceGroup, name, "") if err != nil { - return err + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } if read.ID == nil { - return fmt.Errorf("Cannot read NIC %q (resource group %q) ID", name, resGroup) + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): ID was nil", name, resourceGroup) } - d.SetId(*read.ID) return resourceArmNetworkInterfaceRead(d, meta) } +func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.InterfacesClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["networkInterfaces"] + + locks.ByName(name, networkInterfaceResourceName) + defer locks.UnlockByName(name, networkInterfaceResourceName) + + location := azure.NormalizeLocation(d.Get("location").(string)) + update := network.Interface{ + Name: utils.String(name), + Location: utils.String(location), + } + + if d.HasChange("dns_servers") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + if update.InterfacePropertiesFormat.DNSSettings == nil { + update.InterfacePropertiesFormat.DNSSettings = &network.InterfaceDNSSettings{} + } + + dnsServersRaw := d.Get("dns_servers").(*schema.Set).List() + dnsServers := expandNetworkInterfaceDnsServers(dnsServersRaw) + + update.InterfacePropertiesFormat.DNSSettings.DNSServers = &dnsServers + } + + if d.HasChange("enable_accelerated_networking") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + + update.InterfacePropertiesFormat.EnableAcceleratedNetworking = utils.Bool(d.Get("enable_accelerated_networking").(bool)) + } + + if d.HasChange("enable_ip_forwarding") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + + update.InterfacePropertiesFormat.EnableIPForwarding = utils.Bool(d.Get("enable_ip_forwarding").(bool)) + } + + if d.HasChange("internal_dns_name_label") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + if update.InterfacePropertiesFormat.DNSSettings == nil { + update.InterfacePropertiesFormat.DNSSettings = &network.InterfaceDNSSettings{} + } + + update.InterfacePropertiesFormat.DNSSettings.InternalDNSNameLabel = utils.String(d.Get("internal_dns_name_label").(string)) + } + + if d.HasChange("ip_configuration") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + + ipConfigsRaw := d.Get("ip_configuration").([]interface{}) + ipConfigs, err := expandNetworkInterfaceIPConfigurations(ipConfigsRaw) + if err != nil { + return fmt.Errorf("Error expanding `ip_configuration`: %+v", err) + } + lockingDetails, err := determineResourcesToLockFromIPConfiguration(&ipConfigs) + if err != nil { + return fmt.Errorf("Error determing locking details: %+v", err) + } + + lockingDetails.lock() + defer lockingDetails.unlock() + + update.InterfacePropertiesFormat.IPConfigurations = &ipConfigs + } + + if d.HasChange("network_security_group_id") { + if update.InterfacePropertiesFormat == nil { + update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} + } + + update.InterfacePropertiesFormat.NetworkSecurityGroup = &network.SecurityGroup{ + ID: utils.String(d.Get("network_security_group_id").(string)), + } + } + + if d.HasChange("tags") { + tagsRaw := d.Get("tags").(map[string]interface{}) + update.Tags = tags.Expand(tagsRaw) + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, update) + if err != nil { + return fmt.Errorf("Error updating Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for update of Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + return nil +} + func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Network.InterfacesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) @@ -386,80 +466,88 @@ func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) e if err != nil { return err } - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup name := id.Path["networkInterfaces"] - resp, err := client.Get(ctx, resGroup, name, "") + resp, err := client.Get(ctx, resourceGroup, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Azure Network Interface %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error making Read request on Azure Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) + d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } if props := resp.InterfacePropertiesFormat; props != nil { - d.Set("mac_address", props.MacAddress) - addresses := make([]interface{}, 0) + primaryPrivateIPAddress := "" + privateIPAddresses := make([]interface{}, 0) if configs := props.IPConfigurations; configs != nil { for i, config := range *props.IPConfigurations { if ipProps := config.InterfaceIPConfigurationPropertiesFormat; ipProps != nil { - if v := ipProps.PrivateIPAddress; v != nil { - if i == 0 { - d.Set("private_ip_address", v) - } - addresses = append(addresses, *v) + v := ipProps.PrivateIPAddress + if v == nil { + continue } - } - } - } - if err := d.Set("private_ip_addresses", addresses); err != nil { - return err - } - if props.IPConfigurations != nil { - configs := flattenNetworkInterfaceIPConfigurations(props.IPConfigurations) - if err := d.Set("ip_configuration", configs); err != nil { - return fmt.Errorf("Error setting `ip_configuration`: %+v", err) - } - } + if i == 0 { + primaryPrivateIPAddress = *v + } - if vm := props.VirtualMachine; vm != nil { - d.Set("virtual_machine_id", vm.ID) + privateIPAddresses = append(privateIPAddresses, *v) + } + } } - var appliedDNSServers []string - var dnsServers []string + appliedDNSServers := make([]string, 0) + dnsServers := make([]string, 0) + internalDnsNameLabel := "" if dnsSettings := props.DNSSettings; dnsSettings != nil { - if s := dnsSettings.AppliedDNSServers; s != nil { - appliedDNSServers = *s - } + appliedDNSServers = flattenNetworkInterfaceDnsServers(dnsSettings.AppliedDNSServers) + dnsServers = flattenNetworkInterfaceDnsServers(dnsSettings.DNSServers) - if s := dnsSettings.DNSServers; s != nil { - dnsServers = *s + if dnsSettings.InternalDNSNameLabel != nil { + internalDnsNameLabel = *dnsSettings.InternalDNSNameLabel } + } - d.Set("internal_fqdn", dnsSettings.InternalFqdn) - d.Set("internal_dns_name_label", dnsSettings.InternalDNSNameLabel) + networkSecurityGroupId := "" + if props.NetworkSecurityGroup != nil && props.NetworkSecurityGroup.ID != nil { + networkSecurityGroupId = *props.NetworkSecurityGroup.ID + } + virtualMachineId := "" + if props.VirtualMachine != nil && props.VirtualMachine.ID != nil { + virtualMachineId = *props.VirtualMachine.ID } - d.Set("applied_dns_servers", appliedDNSServers) - d.Set("dns_servers", dnsServers) + if err := d.Set("applied_dns_servers", appliedDNSServers); err != nil { + return fmt.Errorf("Error setting `applied_dns_servers`: %+v", err) + } - if nsg := props.NetworkSecurityGroup; nsg != nil { - d.Set("network_security_group_id", nsg.ID) - } else { - d.Set("network_security_group_id", "") + if err := d.Set("dns_servers", dnsServers); err != nil { + return fmt.Errorf("Error setting `applied_dns_servers`: %+v", err) } d.Set("enable_ip_forwarding", resp.EnableIPForwarding) d.Set("enable_accelerated_networking", resp.EnableAcceleratedNetworking) + d.Set("internal_dns_name_label", internalDnsNameLabel) + d.Set("mac_address", props.MacAddress) + d.Set("network_security_group_id", networkSecurityGroupId) + d.Set("private_ip_address", primaryPrivateIPAddress) + d.Set("virtual_machine_id", virtualMachineId) + + if err := d.Set("ip_configuration", flattenNetworkInterfaceIPConfigurations(props.IPConfigurations)); err != nil { + return fmt.Errorf("Error setting `ip_configuration`: %+v", err) + } + + if err := d.Set("private_ip_addresses", privateIPAddresses); err != nil { + return fmt.Errorf("Error setting `private_ip_addresses`: %+v", err) + } } return tags.FlattenAndSet(d, resp.Tags) @@ -474,14 +562,30 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) if err != nil { return err } - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup name := id.Path["networkInterfaces"] locks.ByName(name, networkInterfaceResourceName) defer locks.UnlockByName(name, networkInterfaceResourceName) - if v, ok := d.GetOk("network_security_group_id"); ok { - networkSecurityGroupId := v.(string) + existing, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(existing.Response) { + log.Printf("[DEBUG] Network Interface %q was not found in Resource Group %q - removing from state", name, resourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if existing.InterfacePropertiesFormat == nil { + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): `properties` was nil", name, resourceGroup) + } + props := *existing.InterfacePropertiesFormat + + if props.NetworkSecurityGroup != nil && props.NetworkSecurityGroup.ID != nil { + networkSecurityGroupId := *props.NetworkSecurityGroup.ID parsedNsgID, err := azure.ParseAzureResourceID(networkSecurityGroupId) if err != nil { return fmt.Errorf("Error parsing Network Security Group ID %q: %+v", networkSecurityGroupId, err) @@ -493,159 +597,49 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) defer locks.UnlockByName(networkSecurityGroupName, networkSecurityGroupResourceName) } - configs := d.Get("ip_configuration").([]interface{}) - subnetNamesToLock := make([]string, 0) - virtualNetworkNamesToLock := make([]string, 0) - - for _, configRaw := range configs { - data := configRaw.(map[string]interface{}) - - subnet_id := data["subnet_id"].(string) - if subnet_id != "" { - subnetId, err2 := azure.ParseAzureResourceID(subnet_id) - if err2 != nil { - return err2 - } - subnetName := subnetId.Path["subnets"] - if !SliceContainsValue(subnetNamesToLock, subnetName) { - subnetNamesToLock = append(subnetNamesToLock, subnetName) - } - - virtualNetworkName := subnetId.Path["virtualNetworks"] - if !SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { - virtualNetworkNamesToLock = append(virtualNetworkNamesToLock, virtualNetworkName) - } - } + lockingDetails, err := determineResourcesToLockFromIPConfiguration(props.IPConfigurations) + if err != nil { + return fmt.Errorf("Error determing locking details: %+v", err) } - locks.MultipleByName(&subnetNamesToLock, SubnetResourceName) - defer locks.UnlockMultipleByName(&subnetNamesToLock, SubnetResourceName) - - locks.MultipleByName(&virtualNetworkNamesToLock, VirtualNetworkResourceName) - defer locks.UnlockMultipleByName(&virtualNetworkNamesToLock, VirtualNetworkResourceName) + lockingDetails.lock() + defer lockingDetails.unlock() - future, err := client.Delete(ctx, resGroup, name) + future, err := client.Delete(ctx, resourceGroup, name) if err != nil { - return fmt.Errorf("Error deleting Network Interface %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error deleting Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for the deletion of Network Interface %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("Error waiting for the deletion of Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } - return err -} - -func flattenNetworkInterfaceIPConfigurations(ipConfigs *[]network.InterfaceIPConfiguration) []interface{} { - result := make([]interface{}, 0, len(*ipConfigs)) - for _, ipConfig := range *ipConfigs { - niIPConfig := make(map[string]interface{}) - - props := ipConfig.InterfaceIPConfigurationPropertiesFormat - - niIPConfig["name"] = *ipConfig.Name - - if props.Subnet != nil && props.Subnet.ID != nil { - niIPConfig["subnet_id"] = *props.Subnet.ID - } - - niIPConfig["private_ip_address_allocation"] = strings.ToLower(string(props.PrivateIPAllocationMethod)) - - if props.PrivateIPAddress != nil { - niIPConfig["private_ip_address"] = *props.PrivateIPAddress - } - - if props.PrivateIPAddressVersion != "" { - niIPConfig["private_ip_address_version"] = string(props.PrivateIPAddressVersion) - } - - if props.PublicIPAddress != nil { - niIPConfig["public_ip_address_id"] = *props.PublicIPAddress.ID - } - - if props.Primary != nil { - niIPConfig["primary"] = *props.Primary - } - - var poolsAG []interface{} - if props.ApplicationGatewayBackendAddressPools != nil { - for _, pool := range *props.ApplicationGatewayBackendAddressPools { - poolsAG = append(poolsAG, *pool.ID) - } - } - niIPConfig["application_gateway_backend_address_pools_ids"] = schema.NewSet(schema.HashString, poolsAG) - - var pools []interface{} - if props.LoadBalancerBackendAddressPools != nil { - for _, pool := range *props.LoadBalancerBackendAddressPools { - pools = append(pools, *pool.ID) - } - } - niIPConfig["load_balancer_backend_address_pools_ids"] = schema.NewSet(schema.HashString, pools) - - var rules []interface{} - if props.LoadBalancerInboundNatRules != nil { - for _, rule := range *props.LoadBalancerInboundNatRules { - rules = append(rules, *rule.ID) - } - } - niIPConfig["load_balancer_inbound_nat_rules_ids"] = schema.NewSet(schema.HashString, rules) - - securityGroups := make([]interface{}, 0) - if sgs := props.ApplicationSecurityGroups; sgs != nil { - for _, sg := range *sgs { - securityGroups = append(securityGroups, *sg.ID) - } - } - niIPConfig["application_security_group_ids"] = schema.NewSet(schema.HashString, securityGroups) - - result = append(result, niIPConfig) - } - return result + return nil } -func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]network.InterfaceIPConfiguration, *[]string, *[]string, error) { - configs := d.Get("ip_configuration").([]interface{}) - ipConfigs := make([]network.InterfaceIPConfiguration, 0, len(configs)) - subnetNamesToLock := make([]string, 0) - virtualNetworkNamesToLock := make([]string, 0) +func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.InterfaceIPConfiguration, error) { + ipConfigs := make([]network.InterfaceIPConfiguration, 0) - for _, configRaw := range configs { + for _, configRaw := range input { data := configRaw.(map[string]interface{}) - subnet_id := data["subnet_id"].(string) - private_ip_allocation_method := data["private_ip_address_allocation"].(string) - private_ip_address_version := network.IPVersion(data["private_ip_address_version"].(string)) + subnetId := data["subnet_id"].(string) + privateIpAllocationMethod := data["private_ip_address_allocation"].(string) + privateIpAddressVersion := network.IPVersion(data["private_ip_address_version"].(string)) - allocationMethod := network.IPAllocationMethod(private_ip_allocation_method) + allocationMethod := network.IPAllocationMethod(privateIpAllocationMethod) properties := network.InterfaceIPConfigurationPropertiesFormat{ PrivateIPAllocationMethod: allocationMethod, - PrivateIPAddressVersion: private_ip_address_version, + PrivateIPAddressVersion: privateIpAddressVersion, } - if private_ip_address_version == network.IPv4 && subnet_id == "" { - return nil, nil, nil, fmt.Errorf("A Subnet ID must be specified for an IPv4 Network Interface.") + if privateIpAddressVersion == network.IPv4 && subnetId == "" { + return nil, fmt.Errorf("A Subnet ID must be specified for an IPv4 Network Interface.") } - if subnet_id != "" { + if subnetId != "" { properties.Subnet = &network.Subnet{ - ID: &subnet_id, - } - - subnetId, err := azure.ParseAzureResourceID(subnet_id) - if err != nil { - return []network.InterfaceIPConfiguration{}, nil, nil, err - } - - subnetName := subnetId.Path["subnets"] - virtualNetworkName := subnetId.Path["virtualNetworks"] - - if !SliceContainsValue(subnetNamesToLock, subnetName) { - subnetNamesToLock = append(subnetNamesToLock, subnetName) - } - - if !SliceContainsValue(virtualNetworkNamesToLock, virtualNetworkName) { - virtualNetworkNamesToLock = append(virtualNetworkNamesToLock, virtualNetworkName) + ID: &subnetId, } } @@ -660,17 +654,16 @@ func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]ne } if v, ok := data["primary"]; ok { - b := v.(bool) - properties.Primary = &b + properties.Primary = utils.Bool(v.(bool)) } if v, ok := data["application_gateway_backend_address_pools_ids"]; ok { var ids []network.ApplicationGatewayBackendAddressPool pools := v.(*schema.Set).List() for _, p := range pools { - pool_id := p.(string) + poolId := p.(string) id := network.ApplicationGatewayBackendAddressPool{ - ID: &pool_id, + ID: &poolId, } ids = append(ids, id) @@ -683,9 +676,9 @@ func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]ne var ids []network.BackendAddressPool pools := v.(*schema.Set).List() for _, p := range pools { - pool_id := p.(string) + poolId := p.(string) id := network.BackendAddressPool{ - ID: &pool_id, + ID: &poolId, } ids = append(ids, id) @@ -698,9 +691,9 @@ func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]ne var natRules []network.InboundNatRule rules := v.(*schema.Set).List() for _, r := range rules { - rule_id := r.(string) + ruleId := r.(string) rule := network.InboundNatRule{ - ID: &rule_id, + ID: &ruleId, } natRules = append(natRules, rule) @@ -725,12 +718,10 @@ func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]ne } name := data["name"].(string) - ipConfig := network.InterfaceIPConfiguration{ + ipConfigs = append(ipConfigs, network.InterfaceIPConfiguration{ Name: &name, InterfaceIPConfigurationPropertiesFormat: &properties, - } - - ipConfigs = append(ipConfigs, ipConfig) + }) } // if we've got multiple IP Configurations - one must be designated Primary @@ -744,19 +735,113 @@ func expandAzureRmNetworkInterfaceIpConfigurations(d *schema.ResourceData) ([]ne } if !hasPrimary { - return nil, nil, nil, fmt.Errorf("If multiple `ip_configurations` are specified - one must be designated as `primary`.") + return nil, fmt.Errorf("If multiple `ip_configurations` are specified - one must be designated as `primary`.") } } - return ipConfigs, &subnetNamesToLock, &virtualNetworkNamesToLock, nil + return ipConfigs, nil } -func SliceContainsValue(input []string, value string) bool { - for _, v := range input { - if v == value { - return true +func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfiguration) []interface{} { + if input == nil { + return []interface{}{} + } + + result := make([]interface{}, 0) + for _, ipConfig := range *input { + props := ipConfig.InterfaceIPConfigurationPropertiesFormat + + name := "" + if ipConfig.Name != nil { + name = *ipConfig.Name + } + + subnetId := "" + if props.Subnet != nil && props.Subnet.ID != nil { + subnetId = *props.Subnet.ID + } + + privateIPAddress := "" + if props.PrivateIPAddress != nil { + privateIPAddress = *props.PrivateIPAddress + } + + privateIPAddressVersion := "" + if props.PrivateIPAddressVersion != "" { + privateIPAddressVersion = string(props.PrivateIPAddressVersion) + } + + publicIPAddressId := "" + if props.PublicIPAddress != nil && props.PublicIPAddress.ID != nil { + publicIPAddressId = *props.PublicIPAddress.ID + } + + var appGatewayBackendPools []interface{} + if props.ApplicationGatewayBackendAddressPools != nil { + for _, pool := range *props.ApplicationGatewayBackendAddressPools { + appGatewayBackendPools = append(appGatewayBackendPools, *pool.ID) + } } + + var lbBackendAddressPools []interface{} + if props.LoadBalancerBackendAddressPools != nil { + for _, pool := range *props.LoadBalancerBackendAddressPools { + lbBackendAddressPools = append(lbBackendAddressPools, *pool.ID) + } + } + + var lbInboundNatRules []interface{} + if props.LoadBalancerInboundNatRules != nil { + for _, rule := range *props.LoadBalancerInboundNatRules { + lbInboundNatRules = append(lbInboundNatRules, *rule.ID) + } + } + + primary := false + if props.Primary != nil { + primary = *props.Primary + } + + securityGroups := make([]interface{}, 0) + if sgs := props.ApplicationSecurityGroups; sgs != nil { + for _, sg := range *sgs { + securityGroups = append(securityGroups, *sg.ID) + } + } + + result = append(result, map[string]interface{}{ + "application_gateway_backend_address_pools_ids": schema.NewSet(schema.HashString, appGatewayBackendPools), + "application_security_group_ids": schema.NewSet(schema.HashString, securityGroups), + "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), + "load_balancer_inbound_nat_rules_ids": schema.NewSet(schema.HashString, lbInboundNatRules), + "name": name, + "primary": primary, + "private_ip_address": privateIPAddress, + "private_ip_address_allocation": string(props.PrivateIPAllocationMethod), + "private_ip_address_version": privateIPAddressVersion, + "public_ip_address_id": publicIPAddressId, + "subnet_id": subnetId, + }) + } + return result +} + +func expandNetworkInterfaceDnsServers(input []interface{}) []string { + dnsServers := make([]string, 0) + for _, v := range input { + dnsServers = append(dnsServers, v.(string)) + } + return dnsServers +} + +func flattenNetworkInterfaceDnsServers(input *[]string) []string { + output := make([]string, 0) + if input == nil { + return output } - return false + for _, v := range *input { + output = append(output, v) + } + return output } diff --git a/azurerm/internal/services/network/resource_arm_network_profile.go b/azurerm/internal/services/network/resource_arm_network_profile.go index 40c8bd3593e0c..f3338e0dc9721 100644 --- a/azurerm/internal/services/network/resource_arm_network_profile.go +++ b/azurerm/internal/services/network/resource_arm_network_profile.go @@ -315,11 +315,11 @@ func expandNetworkProfileVirtualNetworkSubnetNames(d *schema.ResourceData) (*[]s subnetName := subnetResourceID.Path["subnets"] vnetName := subnetResourceID.Path["virtualNetworks"] - if !SliceContainsValue(subnetNames, subnetName) { + if !azure.SliceContainsValue(subnetNames, subnetName) { subnetNames = append(subnetNames, subnetName) } - if !SliceContainsValue(vnetNames, vnetName) { + if !azure.SliceContainsValue(vnetNames, vnetName) { vnetNames = append(vnetNames, vnetName) } } diff --git a/azurerm/internal/services/network/resource_arm_virtual_network.go b/azurerm/internal/services/network/resource_arm_virtual_network.go index 3bc5e00805675..3b7ce65bf6640 100644 --- a/azurerm/internal/services/network/resource_arm_virtual_network.go +++ b/azurerm/internal/services/network/resource_arm_virtual_network.go @@ -178,7 +178,7 @@ func resourceArmVirtualNetworkCreateUpdate(d *schema.ResourceData, meta interfac networkSecurityGroupName := parsedNsgID.Path["networkSecurityGroups"] - if !SliceContainsValue(networkSecurityGroupNames, networkSecurityGroupName) { + if !azure.SliceContainsValue(networkSecurityGroupNames, networkSecurityGroupName) { networkSecurityGroupNames = append(networkSecurityGroupNames, networkSecurityGroupName) } } @@ -480,7 +480,7 @@ func expandAzureRmVirtualNetworkVirtualNetworkSecurityGroupNames(d *schema.Resou networkSecurityGroupName := parsedNsgID.Path["networkSecurityGroups"] - if !SliceContainsValue(nsgNames, networkSecurityGroupName) { + if !azure.SliceContainsValue(nsgNames, networkSecurityGroupName) { nsgNames = append(nsgNames, networkSecurityGroupName) } } From 9ea66209d490b0ac5c6e7192c6a51a6a28a04695 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 14:43:15 +0100 Subject: [PATCH 113/498] r/network_interface: removing the `application_gateway_backend_address_pool_ids` field --- .../network/resource_arm_network_interface.go | 55 ++------ ...ce_application_gateway_association_test.go | 130 +++++++++++++----- .../resource_arm_network_interface_test.go | 130 ------------------ .../docs/r/network_interface.html.markdown | 4 - 4 files changed, 108 insertions(+), 211 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 108413b84da73..d137973c4c67f 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -109,18 +109,6 @@ func resourceArmNetworkInterface() *schema.Resource { ValidateFunc: azure.ValidateResourceIDOrEmpty, }, - "application_gateway_backend_address_pools_ids": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Deprecated: "This field has been deprecated in favour of the `azurerm_network_interface_application_gateway_backend_address_pool_association` resource.", - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: azure.ValidateResourceID, - }, - Set: schema.HashString, - }, - "load_balancer_backend_address_pools_ids": { Type: schema.TypeSet, Optional: true, @@ -657,21 +645,6 @@ func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.Inte properties.Primary = utils.Bool(v.(bool)) } - if v, ok := data["application_gateway_backend_address_pools_ids"]; ok { - var ids []network.ApplicationGatewayBackendAddressPool - pools := v.(*schema.Set).List() - for _, p := range pools { - poolId := p.(string) - id := network.ApplicationGatewayBackendAddressPool{ - ID: &poolId, - } - - ids = append(ids, id) - } - - properties.ApplicationGatewayBackendAddressPools = &ids - } - if v, ok := data["load_balancer_backend_address_pools_ids"]; ok { var ids []network.BackendAddressPool pools := v.(*schema.Set).List() @@ -776,13 +749,6 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu publicIPAddressId = *props.PublicIPAddress.ID } - var appGatewayBackendPools []interface{} - if props.ApplicationGatewayBackendAddressPools != nil { - for _, pool := range *props.ApplicationGatewayBackendAddressPools { - appGatewayBackendPools = append(appGatewayBackendPools, *pool.ID) - } - } - var lbBackendAddressPools []interface{} if props.LoadBalancerBackendAddressPools != nil { for _, pool := range *props.LoadBalancerBackendAddressPools { @@ -810,17 +776,16 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu } result = append(result, map[string]interface{}{ - "application_gateway_backend_address_pools_ids": schema.NewSet(schema.HashString, appGatewayBackendPools), - "application_security_group_ids": schema.NewSet(schema.HashString, securityGroups), - "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), - "load_balancer_inbound_nat_rules_ids": schema.NewSet(schema.HashString, lbInboundNatRules), - "name": name, - "primary": primary, - "private_ip_address": privateIPAddress, - "private_ip_address_allocation": string(props.PrivateIPAllocationMethod), - "private_ip_address_version": privateIPAddressVersion, - "public_ip_address_id": publicIPAddressId, - "subnet_id": subnetId, + "application_security_group_ids": schema.NewSet(schema.HashString, securityGroups), + "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), + "load_balancer_inbound_nat_rules_ids": schema.NewSet(schema.HashString, lbInboundNatRules), + "name": name, + "primary": primary, + "private_ip_address": privateIPAddress, + "private_ip_address_allocation": string(props.PrivateIPAllocationMethod), + "private_ip_address_version": privateIPAddressVersion, + "public_ip_address_id": publicIPAddressId, + "subnet_id": subnetId, }) } return result diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go index 3fc2b0d855eb1..f2dad35421cd7 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go @@ -27,6 +27,7 @@ func TestAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociati testCheckAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociationExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } @@ -79,6 +80,32 @@ func TestAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociati }) } +func TestAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_updateNIC(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_application_gateway_backend_address_pool_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_updateNIC(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociationExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient @@ -185,6 +212,76 @@ func testCheckAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssocia } func testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.frontend.id}" + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + backend_address_pool_id = azurerm_application_gateway.test.backend_address_pool.0.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "import" { + network_interface_id = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.network_interface_id}" + ip_configuration_name = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.ip_configuration_name}" + backend_address_pool_id = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.backend_address_pool_id}" +} +`, template) +} + +func testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_updateNIC(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfiguration1" + subnet_id = "${azurerm_subnet.frontend.id}" + private_ip_address_allocation = "Dynamic" + primary = true + } + + ip_configuration { + name = "testconfiguration2" + private_ip_address_version = "IPv6" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + backend_address_pool_id = azurerm_application_gateway.test.backend_address_pool.0.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -282,36 +379,5 @@ resource "azurerm_application_gateway" "test" { backend_http_settings_name = "${local.http_setting_name}" } } - -resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.frontend.id}" - private_ip_address_allocation = "Dynamic" - } -} - -resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "test" { - network_interface_id = "${azurerm_network_interface.test.id}" - ip_configuration_name = "testconfiguration1" - backend_address_pool_id = "${azurerm_application_gateway.test.backend_address_pool.0.id}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMNetworkInterfaceApplicationGatewayBackendAddressPoolAssociation_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "import" { - network_interface_id = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.network_interface_id}" - ip_configuration_name = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.ip_configuration_name}" - backend_address_pool_id = "${azurerm_network_interface_application_gateway_backend_address_pool_association.test.backend_address_pool_id}" -} -`, template) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go index 468f031e32375..8d35f133cbac6 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go @@ -231,24 +231,6 @@ func TestAccAzureRMNetworkInterface_multipleLoadBalancers(t *testing.T) { }) } -func TestAccAzureRMNetworkInterface_applicationGateway(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMNetworkInterface_applicationGatewayBackendPool(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists("azurerm_network_interface.test"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.application_gateway_backend_address_pools_ids.#", "1"), - ), - }, - }, - }) -} - func TestAccAzureRMNetworkInterface_withTags(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ @@ -1067,118 +1049,6 @@ resource "azurerm_network_interface" "test2" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMNetworkInterface_applicationGatewayBackendPool(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctest-vnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["10.254.0.0/16"] - location = "${azurerm_resource_group.test.location}" -} - -resource "azurerm_subnet" "gateway" { - name = "subnet-gateway-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.254.0.0/24" -} - -resource "azurerm_subnet" "test" { - name = "subnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.254.1.0/24" -} - -resource "azurerm_public_ip" "test" { - name = "acctest-pubip-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Dynamic" -} - -resource "azurerm_application_gateway" "test" { - name = "acctestgw-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Standard_Medium" - tier = "Standard" - capacity = 1 - } - - gateway_ip_configuration { - name = "gw-ip-config1" - subnet_id = "${azurerm_subnet.gateway.id}" - } - - frontend_port { - name = "port-8080" - port = 8080 - } - - frontend_ip_configuration { - name = "ip-config-public" - public_ip_address_id = "${azurerm_public_ip.test.id}" - } - - backend_address_pool { - name = "pool-1" - } - - backend_http_settings { - name = "backend-http-1" - port = 8080 - protocol = "Http" - cookie_based_affinity = "Enabled" - request_timeout = 30 - } - - http_listener { - name = "listener-1" - frontend_ip_configuration_name = "ip-config-public" - frontend_port_name = "port-8080" - protocol = "Http" - } - - request_routing_rule { - name = "rule-basic-1" - rule_type = "Basic" - http_listener_name = "listener-1" - backend_address_pool_name = "pool-1" - backend_http_settings_name = "backend-http-1" - } - - tags = { - environment = "tf01" - } -} - -resource "azurerm_network_interface" "test" { - name = "acctestnic-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - enable_ip_forwarding = true - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - - application_gateway_backend_address_pools_ids = [ - "${azurerm_application_gateway.test.backend_address_pool.0.id}", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testAccAzureRMNetworkInterface_bug7986(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index 45f5f6bfddcec..ccd50c5460126 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -90,10 +90,6 @@ The `ip_configuration` block supports: * `public_ip_address_id` - (Optional) Reference to a Public IP Address to associate with this NIC -* `application_gateway_backend_address_pools_ids` - (Optional / **Deprecated**) List of Application Gateway Backend Address Pool IDs references to which this NIC belongs - --> **NOTE:** At this time Network Interface <-> Application Gateway Backend Address Pool associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_application_gateway_backend_address_pool_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - * `load_balancer_backend_address_pools_ids` - (Optional / **Deprecated**) List of Load Balancer Backend Address Pool IDs references to which this NIC belongs -> **NOTE:** At this time Network Interface <-> Load Balancer Backend Address Pool associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_backend_address_pool_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. From bf5cf315c9fe54f65f245213a561c69ec48bb88f Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 14:55:32 +0100 Subject: [PATCH 114/498] r/network_interface: removing the deprecated `application_security_group_ids` field --- .../network/resource_arm_network_interface.go | 35 ----- ...ication_security_group_association_test.go | 131 +++++++++++++----- .../resource_arm_network_interface_test.go | 60 -------- .../docs/r/network_interface.html.markdown | 4 - 4 files changed, 98 insertions(+), 132 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index d137973c4c67f..1c9ebd3dd1062 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -133,18 +133,6 @@ func resourceArmNetworkInterface() *schema.Resource { Set: schema.HashString, }, - "application_security_group_ids": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Deprecated: "This field has been deprecated in favour of the `azurerm_network_interface_application_security_group_association` resource.", - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: azure.ValidateResourceID, - }, - Set: schema.HashString, - }, - "primary": { Type: schema.TypeBool, Optional: true, @@ -675,21 +663,6 @@ func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.Inte properties.LoadBalancerInboundNatRules = &natRules } - if v, ok := data["application_security_group_ids"]; ok { - var securityGroups []network.ApplicationSecurityGroup - rules := v.(*schema.Set).List() - for _, r := range rules { - groupId := r.(string) - group := network.ApplicationSecurityGroup{ - ID: &groupId, - } - - securityGroups = append(securityGroups, group) - } - - properties.ApplicationSecurityGroups = &securityGroups - } - name := data["name"].(string) ipConfigs = append(ipConfigs, network.InterfaceIPConfiguration{ Name: &name, @@ -768,15 +741,7 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu primary = *props.Primary } - securityGroups := make([]interface{}, 0) - if sgs := props.ApplicationSecurityGroups; sgs != nil { - for _, sg := range *sgs { - securityGroups = append(securityGroups, *sg.ID) - } - } - result = append(result, map[string]interface{}{ - "application_security_group_ids": schema.NewSet(schema.HashString, securityGroups), "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), "load_balancer_inbound_nat_rules_ids": schema.NewSet(schema.HashString, lbInboundNatRules), "name": name, diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_security_group_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_security_group_association_test.go index 563976476bbf9..bd544711f3e11 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_security_group_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_security_group_association_test.go @@ -27,6 +27,7 @@ func TestAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_basic(t * testCheckAzureRMNetworkInterfaceApplicationSecurityGroupAssociationExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } @@ -79,6 +80,32 @@ func TestAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_deleted(t }) } +func TestAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_updateNIC(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_application_security_group_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceApplicationSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_updateNIC(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceApplicationSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMNetworkInterfaceApplicationSecurityGroupAssociationExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient @@ -185,51 +212,28 @@ func testCheckAzureRMNetworkInterfaceApplicationSecurityGroupAssociationDisappea } func testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "internal" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" -} - -resource "azurerm_application_security_group" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - application_security_group_ids = ["${azurerm_application_security_group.test.id}"] + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" } } resource "azurerm_network_interface_application_security_group_association" "test" { - network_interface_id = "${azurerm_network_interface.test.id}" + network_interface_id = azurerm_network_interface.test.id ip_configuration_name = "testconfiguration1" - application_security_group_id = "${azurerm_application_security_group.test.id}" + application_security_group_id = azurerm_application_security_group.test.id } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } func testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_requiresImport(data acceptance.TestData) string { @@ -244,3 +248,64 @@ resource "azurerm_network_interface_application_security_group_association" "imp } `, template) } + +func testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_updateNIC(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + primary = true + } + + ip_configuration { + name = "testconfiguration2" + private_ip_address_version = "IPv6" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_network_interface_application_security_group_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + application_security_group_id = azurerm_application_security_group.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceApplicationSecurityGroupAssociation_template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvn-%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_application_security_group" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go index 8d35f133cbac6..3dfa3f73ea013 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go @@ -326,24 +326,6 @@ func TestAccAzureRMNetworkInterface_bug7986(t *testing.T) { }) } -func TestAccAzureRMNetworkInterface_applicationSecurityGroups(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMNetworkInterface_applicationSecurityGroup(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.application_security_group_ids.#", "1"), - ), - }, - }, - }) -} - func TestAccAzureRMNetworkInterface_importPublicIP(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") @@ -1195,45 +1177,3 @@ resource "azurerm_network_interface" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } - -func testAccAzureRMNetworkInterface_applicationSecurityGroup(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} - -resource "azurerm_application_security_group" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_network_interface" "test" { - name = "acctestnic-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - application_security_group_ids = ["${azurerm_application_security_group.test.id}"] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index ccd50c5460126..25af5192cf89f 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -98,10 +98,6 @@ The `ip_configuration` block supports: -> **NOTE:** At this time Network Interface <-> Load Balancer Inbound NAT Rule associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_nat_rule_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. -* `application_security_group_ids` - (Optional / **Deprecated**) List of Application Security Group IDs which should be attached to this NIC - --> **NOTE:** At this time Network Interface <-> Application Security Group associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_application_security_group_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - * `primary` - (Optional) Is this the Primary Network Interface? If set to `true` this should be the first `ip_configuration` in the array. ## Attributes Reference From a024810d55ab9030b489d7f1b467bfe27f6917f9 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 15:16:52 +0100 Subject: [PATCH 115/498] r/network_interface: removing the deprecated `load_balancer_inbound_nat_rules_ids` field --- .../network/resource_arm_network_interface.go | 49 ++-------- ...ork_interface_nat_rule_association_test.go | 98 +++++++++++++------ .../docs/r/network_interface.html.markdown | 4 - 3 files changed, 73 insertions(+), 78 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 1c9ebd3dd1062..70f7246ead853 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -121,18 +121,6 @@ func resourceArmNetworkInterface() *schema.Resource { Set: schema.HashString, }, - "load_balancer_inbound_nat_rules_ids": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Deprecated: "This field has been deprecated in favour of the `azurerm_network_interface_nat_rule_association` resource.", - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: azure.ValidateResourceID, - }, - Set: schema.HashString, - }, - "primary": { Type: schema.TypeBool, Optional: true, @@ -648,21 +636,6 @@ func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.Inte properties.LoadBalancerBackendAddressPools = &ids } - if v, ok := data["load_balancer_inbound_nat_rules_ids"]; ok { - var natRules []network.InboundNatRule - rules := v.(*schema.Set).List() - for _, r := range rules { - ruleId := r.(string) - rule := network.InboundNatRule{ - ID: &ruleId, - } - - natRules = append(natRules, rule) - } - - properties.LoadBalancerInboundNatRules = &natRules - } - name := data["name"].(string) ipConfigs = append(ipConfigs, network.InterfaceIPConfiguration{ Name: &name, @@ -729,13 +702,6 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu } } - var lbInboundNatRules []interface{} - if props.LoadBalancerInboundNatRules != nil { - for _, rule := range *props.LoadBalancerInboundNatRules { - lbInboundNatRules = append(lbInboundNatRules, *rule.ID) - } - } - primary := false if props.Primary != nil { primary = *props.Primary @@ -743,14 +709,13 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu result = append(result, map[string]interface{}{ "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), - "load_balancer_inbound_nat_rules_ids": schema.NewSet(schema.HashString, lbInboundNatRules), - "name": name, - "primary": primary, - "private_ip_address": privateIPAddress, - "private_ip_address_allocation": string(props.PrivateIPAllocationMethod), - "private_ip_address_version": privateIPAddressVersion, - "public_ip_address_id": publicIPAddressId, - "subnet_id": subnetId, + "name": name, + "primary": primary, + "private_ip_address": privateIPAddress, + "private_ip_address_allocation": string(props.PrivateIPAllocationMethod), + "private_ip_address_version": privateIPAddressVersion, + "public_ip_address_id": publicIPAddressId, + "subnet_id": subnetId, }) } return result diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go index e10f617bfe017..2585bea6c433c 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go @@ -27,6 +27,7 @@ func TestAccAzureRMNetworkInterfaceNATRuleAssociation_basic(t *testing.T) { testCheckAzureRMNetworkInterfaceNATRuleAssociationExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } @@ -79,6 +80,32 @@ func TestAccAzureRMNetworkInterfaceNATRuleAssociation_deleted(t *testing.T) { }) } +func TestAccAzureRMNetworkInterfaceNATRuleAssociation_updateNIC(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_nat_rule_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceNATRuleAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceNATRuleAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterfaceNATRuleAssociation_updateNIC(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceNATRuleAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMNetworkInterfaceNATRuleAssociationExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient @@ -185,6 +212,44 @@ func testCheckAzureRMNetworkInterfaceNATRuleAssociationDisappears(resourceName s } func testAccAzureRMNetworkInterfaceNATRuleAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceNATRuleAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_network_interface_nat_rule_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + nat_rule_id = azurerm_lb_nat_rule.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceNATRuleAssociation_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceNATRuleAssociation_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface_nat_rule_association" "import" { + network_interface_id = "${azurerm_network_interface_nat_rule_association.test.network_interface_id}" + ip_configuration_name = "${azurerm_network_interface_nat_rule_association.test.ip_configuration_name}" + nat_rule_id = "${azurerm_network_interface_nat_rule_association.test.nat_rule_id}" +} +`, template) +} + +func testAccAzureRMNetworkInterfaceNATRuleAssociation_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -232,36 +297,5 @@ resource "azurerm_lb_nat_rule" "test" { backend_port = 3389 frontend_ip_configuration_name = "primary" } - -resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - } -} - -resource "azurerm_network_interface_nat_rule_association" "test" { - network_interface_id = "${azurerm_network_interface.test.id}" - ip_configuration_name = "testconfiguration1" - nat_rule_id = "${azurerm_lb_nat_rule.test.id}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMNetworkInterfaceNATRuleAssociation_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMNetworkInterfaceNATRuleAssociation_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_network_interface_nat_rule_association" "import" { - network_interface_id = "${azurerm_network_interface_nat_rule_association.test.network_interface_id}" - ip_configuration_name = "${azurerm_network_interface_nat_rule_association.test.ip_configuration_name}" - nat_rule_id = "${azurerm_network_interface_nat_rule_association.test.nat_rule_id}" -} -`, template) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index 25af5192cf89f..8c7d9542c57ab 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -94,10 +94,6 @@ The `ip_configuration` block supports: -> **NOTE:** At this time Network Interface <-> Load Balancer Backend Address Pool associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_backend_address_pool_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. -* `load_balancer_inbound_nat_rules_ids` - (Optional / **Deprecated**) List of Load Balancer Inbound Nat Rules IDs involving this NIC - --> **NOTE:** At this time Network Interface <-> Load Balancer Inbound NAT Rule associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_nat_rule_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - * `primary` - (Optional) Is this the Primary Network Interface? If set to `true` this should be the first `ip_configuration` in the array. ## Attributes Reference From 380f32c3cba42124866000e55492e642056483f5 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 15:19:32 +0100 Subject: [PATCH 116/498] r/network_interface: removing the deprecated `load_balancer_backend_address_pools_ids` field --- .../network/resource_arm_network_interface.go | 35 ---- ...e_backend_address_pool_association_test.go | 130 +++++++++++---- .../resource_arm_network_interface_test.go | 151 ------------------ .../docs/r/network_interface.html.markdown | 4 - 4 files changed, 98 insertions(+), 222 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 70f7246ead853..135ed6669a659 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -109,18 +109,6 @@ func resourceArmNetworkInterface() *schema.Resource { ValidateFunc: azure.ValidateResourceIDOrEmpty, }, - "load_balancer_backend_address_pools_ids": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Deprecated: "This field has been deprecated in favour of the `azurerm_network_interface_backend_address_pool_association` resource.", - Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: azure.ValidateResourceID, - }, - Set: schema.HashString, - }, - "primary": { Type: schema.TypeBool, Optional: true, @@ -621,21 +609,6 @@ func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.Inte properties.Primary = utils.Bool(v.(bool)) } - if v, ok := data["load_balancer_backend_address_pools_ids"]; ok { - var ids []network.BackendAddressPool - pools := v.(*schema.Set).List() - for _, p := range pools { - poolId := p.(string) - id := network.BackendAddressPool{ - ID: &poolId, - } - - ids = append(ids, id) - } - - properties.LoadBalancerBackendAddressPools = &ids - } - name := data["name"].(string) ipConfigs = append(ipConfigs, network.InterfaceIPConfiguration{ Name: &name, @@ -695,20 +668,12 @@ func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfigu publicIPAddressId = *props.PublicIPAddress.ID } - var lbBackendAddressPools []interface{} - if props.LoadBalancerBackendAddressPools != nil { - for _, pool := range *props.LoadBalancerBackendAddressPools { - lbBackendAddressPools = append(lbBackendAddressPools, *pool.ID) - } - } - primary := false if props.Primary != nil { primary = *props.Primary } result = append(result, map[string]interface{}{ - "load_balancer_backend_address_pools_ids": schema.NewSet(schema.HashString, lbBackendAddressPools), "name": name, "primary": primary, "private_ip_address": privateIPAddress, diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_backend_address_pool_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_backend_address_pool_association_test.go index 635796cfc4267..ae067fb3fb8c8 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_backend_address_pool_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_backend_address_pool_association_test.go @@ -27,6 +27,7 @@ func TestAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_basic(t *testin testCheckAzureRMNetworkInterfaceBackendAddressPoolAssociationExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } @@ -79,6 +80,32 @@ func TestAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_deleted(t *test }) } +func TestAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_updateNIC(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_backend_address_pool_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceBackendAddressPoolAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_updateNIC(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceBackendAddressPoolAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMNetworkInterfaceBackendAddressPoolAssociationExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient @@ -185,6 +212,76 @@ func testCheckAzureRMNetworkInterfaceBackendAddressPoolAssociationDisappears(res } func testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_network_interface_backend_address_pool_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + backend_address_pool_id = azurerm_lb_backend_address_pool.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface_backend_address_pool_association" "import" { + network_interface_id = "${azurerm_network_interface_backend_address_pool_association.test.network_interface_id}" + ip_configuration_name = "${azurerm_network_interface_backend_address_pool_association.test.ip_configuration_name}" + backend_address_pool_id = "${azurerm_network_interface_backend_address_pool_association.test.backend_address_pool_id}" +} +`, template) +} + +func testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_updateNIC(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + primary = true + } + + ip_configuration { + name = "testconfiguration2" + private_ip_address_version = "IPv6" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_network_interface_backend_address_pool_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + backend_address_pool_id = azurerm_lb_backend_address_pool.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -229,36 +326,5 @@ resource "azurerm_lb_backend_address_pool" "test" { loadbalancer_id = "${azurerm_lb.test.id}" name = "acctestpool" } - -resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - } -} - -resource "azurerm_network_interface_backend_address_pool_association" "test" { - network_interface_id = "${azurerm_network_interface.test.id}" - ip_configuration_name = "testconfiguration1" - backend_address_pool_id = "${azurerm_lb_backend_address_pool.test.id}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMNetworkInterfaceBackendAddressPoolAssociation_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_network_interface_backend_address_pool_association" "import" { - network_interface_id = "${azurerm_network_interface_backend_address_pool_association.test.network_interface_id}" - ip_configuration_name = "${azurerm_network_interface_backend_address_pool_association.test.ip_configuration_name}" - backend_address_pool_id = "${azurerm_network_interface_backend_address_pool_association.test.backend_address_pool_id}" -} -`, template) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go index 3dfa3f73ea013..05170566f5b45 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go @@ -212,25 +212,6 @@ func TestAccAzureRMNetworkInterface_enableAcceleratedNetworking(t *testing.T) { }) } -func TestAccAzureRMNetworkInterface_multipleLoadBalancers(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_network_interface", "test1") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMNetworkInterface_multipleLoadBalancers(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists("azurerm_network_interface.test1"), - testCheckAzureRMNetworkInterfaceExists("azurerm_network_interface.test2"), - ), - }, - }, - }) -} - func TestAccAzureRMNetworkInterface_withTags(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ @@ -899,138 +880,6 @@ resource "azurerm_network_interface" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMNetworkInterface_multipleLoadBalancers(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} - -resource "azurerm_public_ip" "testext" { - name = "acctestpip-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Static" -} - -resource "azurerm_lb" "testext" { - name = "acctestlb-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - frontend_ip_configuration { - name = "publicipext" - public_ip_address_id = "${azurerm_public_ip.testext.id}" - } -} - -resource "azurerm_lb_backend_address_pool" "testext" { - name = "testbackendpoolext" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - loadbalancer_id = "${azurerm_lb.testext.id}" -} - -resource "azurerm_lb_nat_rule" "testext" { - name = "testnatruleext" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - loadbalancer_id = "${azurerm_lb.testext.id}" - protocol = "Tcp" - frontend_port = 3389 - backend_port = 3390 - frontend_ip_configuration_name = "publicipext" -} - -resource "azurerm_public_ip" "testint" { - name = "testpublicipint" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Static" -} - -resource "azurerm_lb" "testint" { - name = "testlbint" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - frontend_ip_configuration { - name = "publicipint" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - } -} - -resource "azurerm_lb_backend_address_pool" "testint" { - name = "testbackendpoolint" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - loadbalancer_id = "${azurerm_lb.testint.id}" -} - -resource "azurerm_lb_nat_rule" "testint" { - name = "testnatruleint" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - loadbalancer_id = "${azurerm_lb.testint.id}" - protocol = "Tcp" - frontend_port = 3389 - backend_port = 3391 - frontend_ip_configuration_name = "publicipint" -} - -resource "azurerm_network_interface" "test1" { - name = "acctestnic1-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - enable_ip_forwarding = true - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - - load_balancer_backend_address_pools_ids = [ - "${azurerm_lb_backend_address_pool.testext.id}", - "${azurerm_lb_backend_address_pool.testint.id}", - ] - } -} - -resource "azurerm_network_interface" "test2" { - name = "acctestnic2-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - enable_ip_forwarding = true - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - - load_balancer_inbound_nat_rules_ids = [ - "${azurerm_lb_nat_rule.testext.id}", - "${azurerm_lb_nat_rule.testint.id}", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testAccAzureRMNetworkInterface_bug7986(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index 8c7d9542c57ab..d2045d5c50d6b 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -90,10 +90,6 @@ The `ip_configuration` block supports: * `public_ip_address_id` - (Optional) Reference to a Public IP Address to associate with this NIC -* `load_balancer_backend_address_pools_ids` - (Optional / **Deprecated**) List of Load Balancer Backend Address Pool IDs references to which this NIC belongs - --> **NOTE:** At this time Network Interface <-> Load Balancer Backend Address Pool associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_network_interface_backend_address_pool_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - * `primary` - (Optional) Is this the Primary Network Interface? If set to `true` this should be the first `ip_configuration` in the array. ## Attributes Reference From 367ca5b1a04d938b021c5147cd1f677499aa2893 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 15:26:05 +0100 Subject: [PATCH 117/498] r/network_interface_nat_rule_association: commiting the missing method --- ...ork_interface_nat_rule_association_test.go | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go index 2585bea6c433c..57c369aa6ce71 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_nat_rule_association_test.go @@ -249,6 +249,38 @@ resource "azurerm_network_interface_nat_rule_association" "import" { `, template) } +func testAccAzureRMNetworkInterfaceNATRuleAssociation_updateNIC(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceNATRuleAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + primary = true + } + + ip_configuration { + name = "testconfiguration2" + private_ip_address_version = "IPv6" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_network_interface_nat_rule_association" "test" { + network_interface_id = azurerm_network_interface.test.id + ip_configuration_name = "testconfiguration1" + nat_rule_id = azurerm_lb_nat_rule.test.id +} +`, template, data.RandomInteger) +} + func testAccAzureRMNetworkInterfaceNATRuleAssociation_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From f50eb8d9341deeb7c57d3bd3b591960d78304ebd Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 17:59:29 +0100 Subject: [PATCH 118/498] r/network_interface: loading the existing nic details during a delta update --- .../network/resource_arm_network_interface.go | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 135ed6669a659..0789e212bfea3 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -51,7 +51,6 @@ func resourceArmNetworkInterface() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // NOTE: does this want it's own association resource? "network_security_group_id": { Type: schema.TypeString, Optional: true, @@ -315,16 +314,20 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) locks.ByName(name, networkInterfaceResourceName) defer locks.UnlockByName(name, networkInterfaceResourceName) + // first get the existing one so that we can pull things as needed + existing, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + location := azure.NormalizeLocation(d.Get("location").(string)) update := network.Interface{ - Name: utils.String(name), - Location: utils.String(location), + Name: utils.String(name), + Location: utils.String(location), + InterfacePropertiesFormat: &network.InterfacePropertiesFormat{}, } if d.HasChange("dns_servers") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } if update.InterfacePropertiesFormat.DNSSettings == nil { update.InterfacePropertiesFormat.DNSSettings = &network.InterfaceDNSSettings{} } @@ -336,25 +339,14 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) } if d.HasChange("enable_accelerated_networking") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } - update.InterfacePropertiesFormat.EnableAcceleratedNetworking = utils.Bool(d.Get("enable_accelerated_networking").(bool)) } if d.HasChange("enable_ip_forwarding") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } - update.InterfacePropertiesFormat.EnableIPForwarding = utils.Bool(d.Get("enable_ip_forwarding").(bool)) } if d.HasChange("internal_dns_name_label") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } if update.InterfacePropertiesFormat.DNSSettings == nil { update.InterfacePropertiesFormat.DNSSettings = &network.InterfaceDNSSettings{} } @@ -363,10 +355,6 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) } if d.HasChange("ip_configuration") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } - ipConfigsRaw := d.Get("ip_configuration").([]interface{}) ipConfigs, err := expandNetworkInterfaceIPConfigurations(ipConfigsRaw) if err != nil { @@ -381,16 +369,19 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) defer lockingDetails.unlock() update.InterfacePropertiesFormat.IPConfigurations = &ipConfigs + } else { + update.InterfacePropertiesFormat.IPConfigurations = existing.InterfacePropertiesFormat.IPConfigurations } if d.HasChange("network_security_group_id") { - if update.InterfacePropertiesFormat == nil { - update.InterfacePropertiesFormat = &network.InterfacePropertiesFormat{} - } - - update.InterfacePropertiesFormat.NetworkSecurityGroup = &network.SecurityGroup{ - ID: utils.String(d.Get("network_security_group_id").(string)), - } + update.InterfacePropertiesFormat.NetworkSecurityGroup = &network.SecurityGroup{} + if networkSecurityGroupId := d.Get("network_security_group_id").(string); networkSecurityGroupId != "" { + update.InterfacePropertiesFormat.NetworkSecurityGroup.ID = utils.String(networkSecurityGroupId) + } else { + update.InterfacePropertiesFormat.NetworkSecurityGroup = nil + } + } else { + update.InterfacePropertiesFormat.NetworkSecurityGroup = existing.InterfacePropertiesFormat.NetworkSecurityGroup } if d.HasChange("tags") { From 6fa556476efa01c0efde883395460e7c3ffae905 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Fri, 14 Feb 2020 17:43:27 +0000 Subject: [PATCH 119/498] Tweaked boolean logic for checkForNonDefaultStorageAccountNetworkRule --- .../storage/resource_arm_storage_account_network_rules.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go index 6e987f0f79b87..81fefac044d3a 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go @@ -251,8 +251,8 @@ func checkForNonDefaultStorageAccountNetworkRule(rule *storage.NetworkRuleSet) b return false } - if rule.IPRules != nil || len(*rule.IPRules) != 0 || - rule.VirtualNetworkRules != nil || len(*rule.VirtualNetworkRules) == 0 || + if (rule.IPRules != nil && len(*rule.IPRules) != 0) || + (rule.VirtualNetworkRules != nil && len(*rule.VirtualNetworkRules) != 0) || rule.Bypass != "AzureServices" || rule.DefaultAction != "Allow" { return true } From dd57fb27188d8d53b7ccb177405f511ca87a7f8b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 14 Feb 2020 20:10:47 +0100 Subject: [PATCH 120/498] r/(linux|windows)_virtual_machine: using the Delete timeout during Deletion --- .../internal/services/compute/linux_virtual_machine_resource.go | 2 +- .../services/compute/windows_virtual_machine_resource.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/compute/linux_virtual_machine_resource.go b/azurerm/internal/services/compute/linux_virtual_machine_resource.go index acb2ed83ebd0f..702b9f0ce07a5 100644 --- a/azurerm/internal/services/compute/linux_virtual_machine_resource.go +++ b/azurerm/internal/services/compute/linux_virtual_machine_resource.go @@ -892,7 +892,7 @@ func resourceLinuxVirtualMachineUpdate(d *schema.ResourceData, meta interface{}) func resourceLinuxVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Compute.VMClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() id, err := ParseVirtualMachineID(d.Id()) diff --git a/azurerm/internal/services/compute/windows_virtual_machine_resource.go b/azurerm/internal/services/compute/windows_virtual_machine_resource.go index 28324b4b26f12..2da51519cb9d4 100644 --- a/azurerm/internal/services/compute/windows_virtual_machine_resource.go +++ b/azurerm/internal/services/compute/windows_virtual_machine_resource.go @@ -917,7 +917,7 @@ func resourceWindowsVirtualMachineUpdate(d *schema.ResourceData, meta interface{ func resourceWindowsVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Compute.VMClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() id, err := ParseVirtualMachineID(d.Id()) From 3a45d8e6dcce3a2174de7d5b7d30aa6dc664a56c Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 14 Feb 2020 12:57:55 -0800 Subject: [PATCH 121/498] Updated doc --- ...account_customer_managed_key.html.markdown | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/website/docs/r/storage_account_customer_managed_key.html.markdown b/website/docs/r/storage_account_customer_managed_key.html.markdown index 8210f51f5bafc..6c855704bb510 100644 --- a/website/docs/r/storage_account_customer_managed_key.html.markdown +++ b/website/docs/r/storage_account_customer_managed_key.html.markdown @@ -13,17 +13,8 @@ Manages the customer managed key of an Azure Storage Account. ## Example Usage ```hcl -resource "azurerm_storage_account_customer_managed_key" "tfex" { - storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.Storage/storageAccounts/tfexstorageaccount" - key_vault_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-RG/providers/Microsoft.KeyVault/vaults/tfex-key-vault" - key_name = "tfex-key" - key_version = "955b9ad9579e4501a311df5493bacd02" -} -``` +data "azurerm_client_config" "current" {} -## Example Usage with User Managed Key Vault Key - -```hcl provider "azurerm" { alias = "keyVault" @@ -44,7 +35,7 @@ resource "azurerm_key_vault" "tfex" { provider = azurerm.keyVault location = azurerm_resource_group.tfex.location resource_group_name = azurerm_resource_group.tfex.name - tenant_id = "00000000-0000-0000-0000-000000000000" + tenant_id = data.azurerm_client_config.current.tenant_id soft_delete_enabled = true purge_protection_enabled = true @@ -59,15 +50,24 @@ resource "azurerm_key_vault" "tfex" { resource "azurerm_key_vault_key" "tfex" { name = "tfex-key" key_vault_id = azurerm_key_vault.tfex.id - key_vault_access_policy_id = azurerm_key_vault_access_policy.tfex.id + key_vault_access_policy_id = azurerm_key_vault_access_policy.storage.id key_type = "RSA" key_size = 2048 key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] } -resource "azurerm_key_vault_access_policy" "tfex" { +resource "azurerm_key_vault_access_policy" "storage" { + key_vault_id = azurerm_key_vault.tfex.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = azurerm_storage_account.tfex.identity.0.principal_id + + key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_access_policy" "client" { key_vault_id = azurerm_key_vault.tfex.id - tenant_id = "00000000-0000-0000-0000-000000000000" + tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_storage_account.tfex.identity.0.principal_id key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] From 1668aa3be036ee992cbf8eaa25df908592c299aa Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Fri, 14 Feb 2020 13:56:15 -0800 Subject: [PATCH 122/498] Format doc hcl blocks --- ...rm_storage_account_customer_managed_key.go | 2 +- website/docs/r/key_vault.html.markdown | 21 +++++-------- ...account_customer_managed_key.html.markdown | 30 +++++++++---------- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go index 3291bc3ef832b..f56c98db9a7a6 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_customer_managed_key.go @@ -115,7 +115,7 @@ func resourceArmStorageAccountCustomerManagedKeyCreateUpdate(d *schema.ResourceD }, } - _, err := storageClient.Update(ctx, storageAccountResourceGroupName.(string), storageAccountName.(string), props) + _, err = storageClient.Update(ctx, storageAccountResourceGroupName.(string), storageAccountName.(string), props) if err != nil { return fmt.Errorf("Error updating Azure Storage Account %q (Resource Group %q) Customer Managed Key: %+v", storageAccountName, storageAccountResourceGroupName, err) } diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index 3726d985fa135..9da136c4273ef 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -33,14 +33,14 @@ resource "azurerm_resource_group" "example" { } resource "azurerm_key_vault" "example" { - name = "testvault" - provider = azurerm.keyVault - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = "testvault" + provider = azurerm.keyVault + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name - tenant_id = data.azurerm_client_config.current.tenant_id - soft_delete_enabled = true - purge_protection_enabled = false + tenant_id = data.azurerm_client_config.current.tenant_id + soft_delete_enabled = true + purge_protection_enabled = false sku_name = "standard" @@ -82,8 +82,6 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which to create the Key Vault. Changing this forces a new resource to be created. -* `sku` - (Optional **Deprecated**)) A `sku` block as described below. - * `sku_name` - (Optional) The Name of the SKU used for this Key Vault. Possible values are `standard` and `premium`. * `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. @@ -110,11 +108,6 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. ---- -A `sku` block supports the following: - -* `name` - (Required) The Name of the SKU used for this Key Vault. Possible values are `standard` and `premium`. - --- A `access_policy` block supports the following: diff --git a/website/docs/r/storage_account_customer_managed_key.html.markdown b/website/docs/r/storage_account_customer_managed_key.html.markdown index 6c855704bb510..74058b8101a9f 100644 --- a/website/docs/r/storage_account_customer_managed_key.html.markdown +++ b/website/docs/r/storage_account_customer_managed_key.html.markdown @@ -31,14 +31,14 @@ resource "azurerm_resource_group" "tfex" { } resource "azurerm_key_vault" "tfex" { - name = "tfex-key-vault" - provider = azurerm.keyVault - location = azurerm_resource_group.tfex.location - resource_group_name = azurerm_resource_group.tfex.name - tenant_id = data.azurerm_client_config.current.tenant_id - - soft_delete_enabled = true - purge_protection_enabled = true + name = "tfex-key-vault" + provider = azurerm.keyVault + location = azurerm_resource_group.tfex.location + resource_group_name = azurerm_resource_group.tfex.name + tenant_id = data.azurerm_client_config.current.tenant_id + + soft_delete_enabled = true + purge_protection_enabled = true sku_name = "standard" @@ -61,7 +61,7 @@ resource "azurerm_key_vault_access_policy" "storage" { tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_storage_account.tfex.identity.0.principal_id - key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] + key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] secret_permissions = ["get"] } @@ -70,16 +70,16 @@ resource "azurerm_key_vault_access_policy" "client" { tenant_id = data.azurerm_client_config.current.tenant_id object_id = azurerm_storage_account.tfex.identity.0.principal_id - key_permissions = ["get","create","delete","list","restore","recover","unwrapkey","wrapkey","purge","encrypt","decrypt","sign","verify"] + key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] secret_permissions = ["get"] } resource "azurerm_storage_account" "tfex" { - name = "tfexstorageaccount" - resource_group_name = azurerm_resource_group.tfex.name - location = azurerm_resource_group.tfex.location - account_tier = "Standard" - account_replication_type = "GRS" + name = "tfexstorageaccount" + resource_group_name = azurerm_resource_group.tfex.name + location = azurerm_resource_group.tfex.location + account_tier = "Standard" + account_replication_type = "GRS" identity { type = "SystemAssigned" From 146a82ea26276829181298a0142d6248d4320e96 Mon Sep 17 00:00:00 2001 From: Tracy Holmes Date: Fri, 14 Feb 2020 20:49:24 -0600 Subject: [PATCH 123/498] r/compute - adds support for additional dedicated host SKUs Validation added for two additional SKUs: DSv3-Type2 and ESv3-Type2 Fixes #5700 --- .../internal/services/compute/resource_arm_dedicated_host.go | 2 ++ website/docs/r/dedicated_host.html.markdown | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/compute/resource_arm_dedicated_host.go b/azurerm/internal/services/compute/resource_arm_dedicated_host.go index 11031012f6229..d2d42cb804c93 100644 --- a/azurerm/internal/services/compute/resource_arm_dedicated_host.go +++ b/azurerm/internal/services/compute/resource_arm_dedicated_host.go @@ -68,7 +68,9 @@ func resourceArmDedicatedHost() *schema.Resource { Required: true, ValidateFunc: validation.StringInSlice([]string{ "DSv3-Type1", + "DSv3-Type2", "ESv3-Type1", + "ESv3-Type2", "FSv2-Type2", }, false), }, diff --git a/website/docs/r/dedicated_host.html.markdown b/website/docs/r/dedicated_host.html.markdown index 00af08790d591..fda61f4ec235d 100644 --- a/website/docs/r/dedicated_host.html.markdown +++ b/website/docs/r/dedicated_host.html.markdown @@ -44,7 +44,7 @@ The following arguments are supported: * `location` - (Required) Specify the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `sku_name` - (Required) Specify the sku name of the Dedicated Host. Possible values are `DSv3-Type1`, `ESv3-Type1`, `FSv2-Type2`. Changing this forces a new resource to be created. +* `sku_name` - (Required) Specify the sku name of the Dedicated Host. Possible values are `DSv3-Type1`, `DSv3-Type2`, `ESv3-Type1`, `ESv3-Type2`,`FSv2-Type2`. Changing this forces a new resource to be created. * `platform_fault_domain` - (Required) Specify the fault domain of the Dedicated Host Group in which to create the Dedicated Host. Changing this forces a new resource to be created. @@ -64,8 +64,6 @@ The following attributes are exported: ## Timeouts - - The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: * `create` - (Defaults to 30 minutes) Used when creating the Dedicated Host. From 651c41fe20749876087ada46c328c5d33201fb8c Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 15 Feb 2020 15:07:37 -0600 Subject: [PATCH 124/498] Address review comments - Fix test crash - Move common functions to helpers - Add more schema validations - Add Update tests --- azurerm/helpers/azure/monitor.go | 116 ++++++++++++++ ...rce_monitor_scheduled_query_rules_alert.go | 14 +- ...ource_monitor_scheduled_query_rules_log.go | 17 +- ...arm_monitor_scheduled_query_rules_alert.go | 101 +++--------- ...e_arm_monitor_scheduled_query_rules_log.go | 75 ++------- ...onitor_scheduled_query_rules_alert_test.go | 127 ++------------- ..._monitor_scheduled_query_rules_log_test.go | 44 +---- ...onitor_scheduled_query_rules_alert_test.go | 150 +++++++++++++++++- ..._monitor_scheduled_query_rules_log_test.go | 131 ++++++++++++++- ..._scheduled_query_rules_alert.html.markdown | 3 +- ...or_scheduled_query_rules_log.html.markdown | 1 - ..._scheduled_query_rules_alert.html.markdown | 5 +- ...or_scheduled_query_rules_log.html.markdown | 4 +- 13 files changed, 450 insertions(+), 338 deletions(-) diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go index f5bf82a5bcf26..0560c1f027863 100644 --- a/azurerm/helpers/azure/monitor.go +++ b/azurerm/helpers/azure/monitor.go @@ -2,8 +2,124 @@ package azure import ( "fmt" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +func FlattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func ExpandMonitorScheduledQueryRulesCommonSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query, ok := d.GetOk("query") + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + if ok { + source.Query = utils.String(query.(string)) + } + + return &source +} + +func FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func FlattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} + +func FlattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + v["dimension"] = FlattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func FlattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} + // ValidateThreshold checks that a threshold value is between 0 and 10000 // and is a whole number. The azure-sdk-for-go expects this value to be a float64 // but the user validation rules want an integer. diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go index cc535fed14527..c7089ad132da9 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -149,18 +149,20 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + return fmt.Errorf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q: %+v", name, resourceGroup, err) } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.SetId(*resp.ID) + + d.Set("name", name) d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) @@ -175,9 +177,9 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me action, ok := resp.Action.(insights.AlertingAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -186,7 +188,7 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index bad7e1f79797b..ce22485f3879f 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -85,10 +85,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "query_type": { - Type: schema.TypeString, - Computed: true, - }, "tags": tags.SchemaDataSource(), }, @@ -100,18 +96,20 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + return fmt.Errorf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q: %+v", name, resourceGroup, err) } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.SetId(*resp.ID) + + d.Set("name", name) d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) @@ -126,9 +124,9 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta action, ok := resp.Action.(insights.LogToMetricAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } @@ -148,7 +146,6 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta if source.DataSourceID != nil { d.Set("data_source_id", source.DataSourceID) } - d.Set("query_type", string(source.QueryType)) } return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 6ea171c6cd89a..25ede04fd1690 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -58,8 +58,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, }, "action": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeList, + Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "action_group": { @@ -133,13 +134,15 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: validation.IntBetween(5, 2880), }, "trigger": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_trigger": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_column": { @@ -214,7 +217,9 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa query := d.Get("query").(string) _, ok := d.GetOk("metric_trigger") if ok { - if !(strings.Contains(query, "summarize") && strings.Contains(query, "AggregatedValue") && strings.Contains(query, "bin")) { + if !(strings.Contains(query, "summarize") && + strings.Contains(query, "AggregatedValue") && + strings.Contains(query, "bin")) { return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): query must contain summarize, AggregatedValue, and bin when metric_trigger is specified", name, resourceGroup) } } @@ -242,7 +247,7 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa location := azure.NormalizeLocation(d.Get("location")) - source := expandMonitorScheduledQueryRulesAlertSource(d) + source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -260,7 +265,7 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa } if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error creating or updating Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } read, err := client.Get(ctx, resourceGroup, name) @@ -290,11 +295,11 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q", name, resourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.Set("name", name) @@ -303,19 +308,18 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta d.Set("location", azure.NormalizeLocation(*location)) } + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { d.Set("enabled", false) } - d.Set("description", resp.Description) - action, ok := resp.Action.(insights.AlertingAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -324,7 +328,7 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } @@ -367,7 +371,7 @@ func resourceArmMonitorScheduledQueryRulesAlertDelete(d *schema.ResourceData, me if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } } @@ -454,20 +458,6 @@ func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insi return &schedule } -func expandMonitorScheduledQueryRulesAlertSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query := d.Get("query").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - Query: utils.String(query), - QueryType: insights.ResultCount, - } - - return &source -} - func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} if len(input) == 0 { @@ -491,56 +481,3 @@ func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights return &result } - -func flattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { - result := make([]interface{}, 0) - v := make(map[string]interface{}) - - if input != nil { - if input.ActionGroup != nil { - v["action_group"] = *input.ActionGroup - } - v["email_subject"] = input.EmailSubject - v["custom_webhook_payload"] = input.CustomWebhookPayload - } - result = append(result, v) - - return result -} - -func flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - result["metric_trigger_type"] = string(input.MetricTriggerType) - - if input.MetricColumn != nil { - result["metric_column"] = *input.MetricColumn - } - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { - result := make(map[string]interface{}) - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) - } - - return []interface{}{result} -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index f9537f6a7306e..1ff8e7ca63ae2 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -57,8 +57,9 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { }, "criteria": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dimension": { @@ -152,7 +153,7 @@ func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData location := azure.NormalizeLocation(d.Get("location")) - source := expandMonitorScheduledQueryRulesLogSource(d) + source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -169,7 +170,7 @@ func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData } if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error creating or updating Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } read, err := client.Get(ctx, resourceGroup, name) @@ -199,11 +200,11 @@ func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta i resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q", name, resourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.Set("name", name) @@ -212,19 +213,18 @@ func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta i d.Set("location", azure.NormalizeLocation(*location)) } + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { d.Set("enabled", false) } - d.Set("description", resp.Description) - action, ok := resp.Action.(insights.LogToMetricAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } @@ -254,7 +254,7 @@ func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } } @@ -311,58 +311,3 @@ func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) * return &action } - -func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - - return &source -} - -func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, criteria := range *input { - v := make(map[string]interface{}) - - v["dimension"] = flattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) - v["metric_name"] = *criteria.MetricName - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, dimension := range *input { - v := make(map[string]interface{}) - - if dimension.Name != nil { - v["name"] = *dimension.Name - } - - if dimension.Operator != nil { - v["operator"] = *dimension.Operator - } - - if dimension.Values != nil { - v["values"] = *dimension.Values - } - - result = append(result, v) - } - } - - return result -} diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 4f41939128074..e1955393eb102 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -9,7 +9,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -26,7 +26,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin }) } -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingActionCrossResource(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -45,133 +45,26 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) + template := testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - - frequency = 60 - time_window = 60 - - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_alert.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +`, template) } func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - + template := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_log_analytics_workspace" "test2" { - name = "acctestWorkspace2-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "acctestSqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - - frequency = 60 - time_window = 60 - - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_alert.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +`, template) } diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index d25c6a7de3558..4d17e1662fb1e 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -8,7 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesLogToMetricAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ @@ -26,47 +26,13 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes } func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { + template := testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_log.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index a558a53593667..3ecf0a52bb0a0 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -12,8 +12,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + ts := time.Now().Format(time.RFC3339) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -21,7 +22,53 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + ts := time.Now().Format(time.RFC3339) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), @@ -40,7 +87,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), + Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), @@ -50,7 +97,95 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }) } -func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data acceptance.TestData, ts string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + + frequency = 60 + time_window = 60 + + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data acceptance.TestData, ts string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + enabled = false + description = "test description" + + frequency = 30 + time_window = 30 + + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + } + + trigger { + operator = "GreaterThan" + threshold = 1000 + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -81,12 +216,12 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - query_type = "ResultCount" frequency = 60 time_window = 60 - severity = 3 + severity = 3 + throttling = 5 action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" @@ -107,7 +242,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -145,7 +280,6 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" frequency = 60 time_window = 60 diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 0706ca5810786..fb742cd513ee2 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -11,7 +11,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ @@ -20,7 +20,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), @@ -30,7 +30,132 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "Computer" + operator = "Include" + values = ["25"] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 7e513bf3c885a..a48871a910b7b 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -35,10 +35,9 @@ output "query_rule_id" { * `authorized_resource_ids` - List of Resource IDs referred into query. * `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this scheduled query rule is enabled. +* `enabled` - Whether this Scheduled Query Rule is enabled. * `frequency` - Frequency at which rule condition should be evaluated. * `query` - Log search query. -* `query_type` - Must equal "ResultCount". * `time_window` - Time window for which data needs to be fetched for query. * `severity` - Severity of the alert. * `throttling` - Time for which alerts should be throttled or suppressed. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index af8890e478d20..47cb9bdbdd236 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -35,7 +35,6 @@ output "query_rule_id" { * `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this Scheduled Query Rule is enabled. -* `throttling` - Time for which alerts should be throttled or suppressed. --- diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 09cc587790910..d00a1f636a4f0 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -127,12 +127,13 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. * `data_source_id` - (Required) The resource URI over which log search query is to be run. * `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. Values must be between 5 and 1440 (inclusive). +* `query` - (Required) Log search query. * `time_window` - (Required) Time window for which data needs to be fetched for query (must be greater than or equal to `frequency`). Values must be between 5 and 2880 (inclusive). * `trigger` - (Required) The condition that results in the alert rule being run. +* `action` - (Required) An `action` block as defined below. * `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. -* `action` - (Optional) An `action` block as defined below. * `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. * `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 (inclusive). diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 48beb3b33359c..d804aa2180d2d 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -53,9 +53,7 @@ The following arguments are supported: * `criteria` - (Required) A `criteria` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 ( -inclusive). +* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. --- From 3c4d40d08e644deb5aba7f5a6bcc5651b5dbb7b5 Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Sat, 15 Feb 2020 15:54:16 -0800 Subject: [PATCH 125/498] add zone_redundant to azurerm_sql_database --- .../services/sql/resource_arm_sql_database.go | 14 +++++ .../tests/resource_arm_sql_database_test.go | 55 +++++++++++++++++++ website/docs/r/sql_database.html.markdown | 2 + 3 files changed, 71 insertions(+) diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 34ef8acfea751..1f65c65fa817e 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -318,6 +318,12 @@ func resourceArmSqlDatabase() *schema.Resource { Default: false, }, + "zone_redundant": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + "tags": tags.Schema(), }, @@ -449,6 +455,10 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} properties.DatabaseProperties.ReadScale = sql.ReadScaleDisabled } + if v, ok := d.GetOkExists("zone_redundant"); ok { + properties.DatabaseProperties.ZoneRedundant = utils.Bool(v.(bool)) + } + // The requested Service Objective Name does not match the requested Service Objective Id. if d.HasChange("requested_service_objective_name") && !d.HasChange("requested_service_objective_id") { properties.DatabaseProperties.RequestedServiceObjectiveID = nil @@ -570,6 +580,10 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error } else { d.Set("read_scale", false) } + + if zoneRedundant := props.ZoneRedundant; zoneRedundant != nil { + d.Set("zone_redundant", zoneRedundant) + } } return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go b/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go index c1c58164693a1..887b9daf1c323 100644 --- a/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go +++ b/azurerm/internal/services/sql/tests/resource_arm_sql_database_test.go @@ -296,6 +296,32 @@ func TestAccAzureRMSqlDatabase_readScale(t *testing.T) { }) } +func TestAccAzureRMSqlDatabase_zoneRedundant(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_sql_database", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMSqlDatabaseDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSqlDatabase_zoneRedundant(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "zone_redundant", "true"), + ), + }, + { + Config: testAccAzureRMSqlDatabase_zoneRedundant(data, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSqlDatabaseExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "zone_redundant", "false"), + ), + }, + }, + }) +} + func testCheckAzureRMSqlDatabaseExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Sql.DatabasesClient @@ -814,3 +840,32 @@ resource "azurerm_sql_database" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, readScale) } + +func testAccAzureRMSqlDatabase_zoneRedundant(data acceptance.TestData, zoneRedundant bool) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_sql_server" "test" { + name = "acctestsqlserver%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + version = "12.0" + administrator_login = "mradministrator" + administrator_login_password = "thisIsDog11" +} + +resource "azurerm_sql_database" "test" { + name = "acctestdb%d" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_sql_server.test.name}" + location = "${azurerm_resource_group.test.location}" + edition = "Premium" + collation = "SQL_Latin1_General_CP1_CI_AS" + max_size_bytes = "1073741824" + zone_redundant = %t +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, zoneRedundant) +} diff --git a/website/docs/r/sql_database.html.markdown b/website/docs/r/sql_database.html.markdown index 912454fc1b979..2d740c064440e 100644 --- a/website/docs/r/sql_database.html.markdown +++ b/website/docs/r/sql_database.html.markdown @@ -76,6 +76,8 @@ The following arguments are supported: * `read_scale` - (Optional) Read-only connections will be redirected to a high-available replica. Please see [Use read-only replicas to load-balance read-only query workloads](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-read-scale-out). +* `zone_redundant` - (Optional) Whether or not this database is zone redundant, which means the replicas of this database will be spread across multiple availability zones. + * `tags` - (Optional) A mapping of tags to assign to the resource. `import` supports the following: From 8e350e6fe4fa9e8b604d7e6bc9b6041a647022cc Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Sun, 16 Feb 2020 08:17:41 +0100 Subject: [PATCH 126/498] Update website/docs/guides/2.0-upgrade-guide.html.markdown --- website/docs/guides/2.0-upgrade-guide.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index cbcfc6a085892..75886b011ee70 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -169,7 +169,7 @@ The deprecated field `internal_fqdn` will be removed. The deprecated field `network_interface_ids` will be removed. -### Date Source: `azurerm_role_definition` +### Data Source: `azurerm_role_definition` The Data Source no longer supports the alias `VirtualMachineContributor` for the Built-in role `Virtual Machine Contributor`. From 33dfa98a7311830a15c03d505ee8670eae06382e Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Sun, 16 Feb 2020 08:30:14 +0100 Subject: [PATCH 127/498] updating to include #5768 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e990219aceb41..2e3119e57147e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ BREAKING CHANGES: IMPROVEMENTS: * Data Source: `azurerm_kubernetes_service_version` - support for filtering of preview releases [GH-5662] +* `azurerm_dedicated_host` - support for setting `sku_name` to `DSv3-Type2` and `ESv3-Type2` [GH-5768] * `azurerm_storage_account` - support for configuring `cors_rules` within the `blob_properties` block [GH-5425] * `azurerm_windows_virtual_machine` - fixing a bug when provisioning from a Shared Gallery image [GH-5661] From bd400bc2dd323211e0bcbb6b8ced297c493a321e Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Sun, 16 Feb 2020 08:48:59 +0100 Subject: [PATCH 128/498] updating to include #5744 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e3119e57147e..7404898508b82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ BREAKING CHANGES: * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_kubernetes_cluster` - updating the default value for `load_balancer_sku` to `Standard` from `Basic` [GH-5747] * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] +* `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] * `azurerm_notification_hub_namesapce` - removing the `sku` block in favour of the `sku_name` argument [GH-5722] * `azurerm_relay_namespace` - removing the `sku` block in favour of the `sku_name` field [GH-5719] * `azurerm_scheduler_job` - This resource has been removed since it was deprecated [GH-5712] From ab5070dfc936df71d9130ab7eb27bddb2ba2ddc1 Mon Sep 17 00:00:00 2001 From: Sivan Guetta Date: Sun, 16 Feb 2020 17:17:59 +0200 Subject: [PATCH 129/498] On metric alert rule creation, the 'autoMitigate' property should be set to true by default --- .../monitor/resource_arm_monitor_metric_alert.go | 2 +- .../tests/resource_arm_monitor_metric_alert_test.go | 10 +++++----- website/docs/r/monitor_metric_alert.html.markdown | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_metric_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_metric_alert.go index 63983794a554b..c9eed84502a38 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_metric_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_metric_alert.go @@ -166,7 +166,7 @@ func resourceArmMonitorMetricAlert() *schema.Resource { "auto_mitigate": { Type: schema.TypeBool, Optional: true, - Default: false, + Default: true, }, "description": { diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_metric_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_metric_alert_test.go index 3e94e9972d150..0a6c0ccccd2af 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_metric_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_metric_alert_test.go @@ -80,7 +80,7 @@ func TestAccAzureRMMonitorMetricAlert_complete(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorMetricAlertExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "false"), resource.TestCheckResourceAttr(data.ResourceName, "severity", "4"), resource.TestCheckResourceAttr(data.ResourceName, "description", "This is a complete metric alert resource."), resource.TestCheckResourceAttr(data.ResourceName, "frequency", "PT30M"), @@ -128,7 +128,7 @@ func TestAccAzureRMMonitorMetricAlert_basicAndCompleteUpdate(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorMetricAlertExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "true"), resource.TestCheckResourceAttr(data.ResourceName, "severity", "3"), resource.TestCheckResourceAttr(data.ResourceName, "description", ""), resource.TestCheckResourceAttr(data.ResourceName, "frequency", "PT1M"), @@ -149,7 +149,7 @@ func TestAccAzureRMMonitorMetricAlert_basicAndCompleteUpdate(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorMetricAlertExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "true"), + resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "false"), resource.TestCheckResourceAttr(data.ResourceName, "severity", "4"), resource.TestCheckResourceAttr(data.ResourceName, "description", "This is a complete metric alert resource."), resource.TestCheckResourceAttr(data.ResourceName, "frequency", "PT30M"), @@ -184,7 +184,7 @@ func TestAccAzureRMMonitorMetricAlert_basicAndCompleteUpdate(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorMetricAlertExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "enabled", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "false"), + resource.TestCheckResourceAttr(data.ResourceName, "auto_mitigate", "true"), resource.TestCheckResourceAttr(data.ResourceName, "severity", "3"), resource.TestCheckResourceAttr(data.ResourceName, "description", ""), resource.TestCheckResourceAttr(data.ResourceName, "frequency", "PT1M"), @@ -288,7 +288,7 @@ resource "azurerm_monitor_metric_alert" "test" { resource_group_name = "${azurerm_resource_group.test.name}" scopes = ["${azurerm_storage_account.test.id}"] enabled = true - auto_mitigate = true + auto_mitigate = false severity = 4 description = "This is a complete metric alert resource." frequency = "PT30M" diff --git a/website/docs/r/monitor_metric_alert.html.markdown b/website/docs/r/monitor_metric_alert.html.markdown index 7baf7b06d2ab9..3947465d4bf13 100644 --- a/website/docs/r/monitor_metric_alert.html.markdown +++ b/website/docs/r/monitor_metric_alert.html.markdown @@ -73,7 +73,7 @@ The following arguments are supported: * `criteria` - (Required) One or more `criteria` blocks as defined below. * `action` - (Optional) One or more `action` blocks as defined below. * `enabled` - (Optional) Should this Metric Alert be enabled? Defaults to `true`. -* `auto_mitigate` - (Optional) Should the alerts in this Metric Alert be auto resolved? Defaults to `false`. +* `auto_mitigate` - (Optional) Should the alerts in this Metric Alert be auto resolved? Defaults to `true`. * `description` - (Optional) The description of this Metric Alert. * `frequency` - (Optional) The evaluation frequency of this Metric Alert, represented in ISO 8601 duration format. Possible values are `PT1M`, `PT5M`, `PT15M`, `PT30M` and `PT1H`. Defaults to `PT1M`. * `severity` - (Optional) The severity of this Metric Alert. Possible values are `0`, `1`, `2`, `3` and `4`. Defaults to `3`. From 277e7c334ddc0fee3a4cfec9b930123aaca9231b Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Sun, 16 Feb 2020 09:05:20 -0700 Subject: [PATCH 130/498] Update mariadb to 2.0 --- .../mariadb/resource_arm_mariadb_server.go | 124 +----------------- 1 file changed, 4 insertions(+), 120 deletions(-) diff --git a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go index 1300051621fa5..51fc54a56fc8a 100644 --- a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go +++ b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go @@ -55,8 +55,7 @@ func resourceArmMariaDbServer() *schema.Resource { "sku_name": { Type: schema.TypeString, - Optional: true, // required in 2.0 - Computed: true, // remove in 2.0 + Required: true, ConflictsWith: []string{"sku"}, ValidateFunc: validation.StringInSlice([]string{ "B_Gen5_1", @@ -73,68 +72,6 @@ func resourceArmMariaDbServer() *schema.Resource { }, false), }, - // remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku_name"}, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "B_Gen5_1", - "B_Gen5_2", - "GP_Gen5_2", - "GP_Gen5_4", - "GP_Gen5_8", - "GP_Gen5_16", - "GP_Gen5_32", - "MO_Gen5_2", - "MO_Gen5_4", - "MO_Gen5_8", - "MO_Gen5_16", - }, false), - }, - - "capacity": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntInSlice([]int{ - 1, - 2, - 4, - 8, - 16, - 32, - }), - }, - - "tier": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(mariadb.Basic), - string(mariadb.GeneralPurpose), - string(mariadb.MemoryOptimized), - }, false), - }, - - "family": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Gen5", - }, false), - }, - }, - }, - }, - "administrator_login": { Type: schema.TypeString, Required: true, @@ -248,17 +185,9 @@ func resourceArmMariaDbServerCreateUpdate(d *schema.ResourceData, meta interface storageProfile := expandAzureRmMariaDbStorageProfile(d) - var sku *mariadb.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandServerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for PostgreSQL Server %q (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandAzureRmMariaDbServerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for PostgreSQL Server %q (Resource Group %q)", name, resourceGroup) + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding sku_name for PostgreSQL Server %q (Resource Group %q): %v", name, resourceGroup, err) } skuName := sku.Name @@ -396,10 +325,6 @@ func resourceArmMariaDbServerRead(d *schema.ResourceData, meta interface{}) erro } } - if err := d.Set("sku", flattenMariaDbServerSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - return tags.FlattenAndSet(d, resp.Tags) } @@ -466,23 +391,6 @@ func expandServerSkuName(skuName string) (*mariadb.Sku, error) { }, nil } -func expandAzureRmMariaDbServerSku(d *schema.ResourceData) *mariadb.Sku { - skus := d.Get("sku").([]interface{}) - sku := skus[0].(map[string]interface{}) - - name := sku["name"].(string) - capacity := sku["capacity"].(int) - tier := sku["tier"].(string) - family := sku["family"].(string) - - return &mariadb.Sku{ - Name: utils.String(name), - Tier: mariadb.SkuTier(tier), - Capacity: utils.Int32(int32(capacity)), - Family: utils.String(family), - } -} - func expandAzureRmMariaDbStorageProfile(d *schema.ResourceData) *mariadb.StorageProfile { storageprofiles := d.Get("storage_profile").([]interface{}) storageprofile := storageprofiles[0].(map[string]interface{}) @@ -500,30 +408,6 @@ func expandAzureRmMariaDbStorageProfile(d *schema.ResourceData) *mariadb.Storage } } -func flattenMariaDbServerSku(sku *mariadb.Sku) []interface{} { - values := map[string]interface{}{} - - if sku == nil { - return []interface{}{} - } - - if name := sku.Name; name != nil { - values["name"] = *name - } - - if capacity := sku.Capacity; capacity != nil { - values["capacity"] = *capacity - } - - values["tier"] = string(sku.Tier) - - if family := sku.Family; family != nil { - values["family"] = *family - } - - return []interface{}{values} -} - func flattenMariaDbStorageProfile(storage *mariadb.StorageProfile) []interface{} { values := map[string]interface{}{} From 7bcea7f3a4a262fbdae85868ad9f6477557eb9cc Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Sun, 16 Feb 2020 09:08:18 -0700 Subject: [PATCH 131/498] upgrade maps to 2.0 --- azurerm/internal/services/maps/resource_arm_maps_account.go | 3 +-- website/docs/guides/2.0-upgrade-guide.html.markdown | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/maps/resource_arm_maps_account.go b/azurerm/internal/services/maps/resource_arm_maps_account.go index 6b8eec8e510da..96380765ad5f0 100644 --- a/azurerm/internal/services/maps/resource_arm_maps_account.go +++ b/azurerm/internal/services/maps/resource_arm_maps_account.go @@ -55,8 +55,7 @@ func resourceArmMapsAccount() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{ "s0", "s1", - // TODO: revert this in 2.0 - }, true), + }, false), }, "tags": tags.Schema(), diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index 3c3fc2955605c..bda4ba8293d81 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -361,6 +361,10 @@ This resource has been renamed to `azurerm_log_analytics_linked_service` which i The deprecated field `linked_service_properties` will be removed. This has been replaced by the `resource_id` resource. +### Resource: `azurerm_maps_account` + +The `sku_name` field is now case sensitive. + ### Resource: `azurerm_mariadb_server` The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. From 30c58c58b40026c0039bc1a3a5987b77b6e093b8 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Sun, 16 Feb 2020 09:14:55 -0700 Subject: [PATCH 132/498] remove conflictswith --- .../internal/services/mariadb/resource_arm_mariadb_server.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go index 51fc54a56fc8a..0b8fefbcd8847 100644 --- a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go +++ b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go @@ -54,9 +54,8 @@ func resourceArmMariaDbServer() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), "sku_name": { - Type: schema.TypeString, - Required: true, - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ "B_Gen5_1", "B_Gen5_2", From 5f3fae24d3b404e7e83e976e4445af68bbf33091 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Sun, 16 Feb 2020 09:56:19 -0700 Subject: [PATCH 133/498] Upgrade keyvault to 2.0 --- .../keyvault/data_source_key_vault.go | 19 --- .../keyvault/data_source_key_vault_key.go | 46 ++----- .../keyvault/data_source_key_vault_secret.go | 47 +------ .../keyvault/resource_arm_key_vault.go | 66 +--------- .../resource_arm_key_vault_access_policy.go | 77 ++--------- .../resource_arm_key_vault_certificate.go | 43 +------ .../keyvault/resource_arm_key_vault_key.go | 43 +------ .../keyvault/resource_arm_key_vault_secret.go | 44 +------ .../tests/data_source_key_vault_test.go | 6 +- ...source_arm_key_vault_access_policy_test.go | 49 +------ ...resource_arm_key_vault_certificate_test.go | 120 +++--------------- .../tests/resource_arm_key_vault_key_test.go | 118 +++++------------ .../resource_arm_key_vault_secret_test.go | 93 +++----------- .../tests/resource_arm_key_vault_test.go | 64 +--------- website/docs/d/key_vault.html.markdown | 10 +- .../guides/2.0-upgrade-guide.html.markdown | 37 ++++++ website/docs/r/key_vault.html.markdown | 10 +- .../r/key_vault_access_policy.html.markdown | 8 -- 18 files changed, 170 insertions(+), 730 deletions(-) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault.go b/azurerm/internal/services/keyvault/data_source_key_vault.go index 6ff4ad35b13af..f99387eb327e7 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault.go @@ -33,20 +33,6 @@ func dataSourceArmKeyVault() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "sku_name": { Type: schema.TypeString, Computed: true, @@ -192,11 +178,6 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenKeyVaultDataSourceSku(sku)); err != nil { - return fmt.Errorf("Error setting `sku` for KeyVault %q: %+v", *resp.Name, err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting `sku_name` for KeyVault %q: %+v", *resp.Name, err) } diff --git a/azurerm/internal/services/keyvault/data_source_key_vault_key.go b/azurerm/internal/services/keyvault/data_source_key_vault_key.go index b1d672a650e0c..3b1277b7d91fe 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault_key.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault_key.go @@ -5,7 +5,6 @@ import ( "time" "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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -29,21 +28,9 @@ func dataSourceArmKeyVaultKey() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, - }, - - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, }, "key_type": { @@ -90,31 +77,12 @@ func dataSourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) erro ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - keyVaultBaseUri := d.Get("vault_uri").(string) name := d.Get("name").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUri == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUri = pKeyVaultBaseUrl - d.Set("vault_uri", keyVaultBaseUri) - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUri) - if err != nil { - return fmt.Errorf("Error retrieving the Resource ID the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - if id == nil { - return fmt.Errorf("Unable to locate the Resource ID for the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - d.Set("key_vault_id", id) + keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) } resp, err := client.GetKey(ctx, keyVaultBaseUri, name, "") @@ -133,6 +101,8 @@ func dataSourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) erro } d.SetId(id) + d.Set("key_vault_id", keyVaultId) + if key := resp.Key; key != nil { d.Set("key_type", string(key.Kty)) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault_secret.go b/azurerm/internal/services/keyvault/data_source_key_vault_secret.go index 7ce9f365f68c3..0f9c305038337 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault_secret.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault_secret.go @@ -5,7 +5,6 @@ import ( "time" "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/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" @@ -29,21 +28,9 @@ func dataSourceArmKeyVaultSecret() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, - }, - - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, }, "value": { @@ -74,31 +61,11 @@ func dataSourceArmKeyVaultSecretRead(d *schema.ResourceData, meta interface{}) e defer cancel() name := d.Get("name").(string) - keyVaultBaseUri := d.Get("vault_uri").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUri == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUri = pKeyVaultBaseUrl - d.Set("vault_uri", keyVaultBaseUri) - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUri) - if err != nil { - return fmt.Errorf("Error retrieving the Resource ID the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - if id == nil { - return fmt.Errorf("Unable to locate the Resource ID for the Key Vault at URL %q: %s", keyVaultBaseUri, err) - } - - d.Set("key_vault_id", id) + keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) } // we always want to get the latest version @@ -119,7 +86,7 @@ func dataSourceArmKeyVaultSecretRead(d *schema.ResourceData, meta interface{}) e d.SetId(*resp.ID) d.Set("name", respID.Name) - d.Set("vault_uri", respID.KeyVaultBaseUrl) + d.Set("key_vault_id", keyVaultId) d.Set("value", resp.Value) d.Set("version", respID.Version) d.Set("content_type", resp.ContentType) diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault.go b/azurerm/internal/services/keyvault/resource_arm_key_vault.go index 62d559c4d2f13..331fab188ef81 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault.go @@ -66,37 +66,13 @@ func resourceArmKeyVault() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - ConflictsWith: []string{"sku_name"}, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - string(keyvault.Standard), - string(keyvault.Premium), - }, false), - }, - }, - }, - }, - "sku_name": { Type: schema.TypeString, - Optional: true, - Computed: true, + Required: true, ValidateFunc: validation.StringInSlice([]string{ string(keyvault.Standard), string(keyvault.Premium), - // TODO: revert this in 2.0 - }, true), + }, false), }, "vault_uri": { @@ -205,27 +181,9 @@ func resourceArmKeyVaultCreateUpdate(d *schema.ResourceData, meta interface{}) e ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - // Remove in 2.0 - var sku keyvault.Sku - - if inputs := d.Get("sku").([]interface{}); len(inputs) != 0 { - input := inputs[0].(map[string]interface{}) - v := input["name"].(string) - - sku = keyvault.Sku{ - Family: &armKeyVaultSkuFamily, - Name: keyvault.SkuName(v), - } - } else { - // Keep in 2.0 - sku = keyvault.Sku{ - Family: &armKeyVaultSkuFamily, - Name: keyvault.SkuName(d.Get("sku_name").(string)), - } - } - - if sku.Name == "" { - return fmt.Errorf("either 'sku_name' or 'sku' must be defined in the configuration file") + sku := keyvault.Sku{ + Family: &armKeyVaultSkuFamily, + Name: keyvault.SkuName(d.Get("sku_name").(string)), } log.Printf("[INFO] preparing arguments for Azure ARM KeyVault creation.") @@ -372,11 +330,6 @@ func resourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { d.Set("vault_uri", props.VaultURI) if sku := props.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenKeyVaultSku(sku)); err != nil { - return fmt.Errorf("Error setting 'sku' for KeyVault %q: %+v", *resp.Name, err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting 'sku_name' for KeyVault %q: %+v", *resp.Name, err) } @@ -458,15 +411,6 @@ func resourceArmKeyVaultDelete(d *schema.ResourceData, meta interface{}) error { return nil } -// Remove in 2.0 -func flattenKeyVaultSku(sku *keyvault.Sku) []interface{} { - result := map[string]interface{}{ - "name": string(sku.Name), - } - - return []interface{}{result} -} - func flattenKeyVaultNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{ diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go index e22f0f7ed3579..61023c81a1ab9 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go @@ -3,7 +3,6 @@ package keyvault import ( "fmt" "log" - "regexp" "strings" "time" @@ -39,50 +38,10 @@ func resourceArmKeyVaultAccessPolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_name"}, - }, - - // todo remove in 2.0 - "vault_name": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.StringIsNotEmpty, - ConflictsWith: []string{"key_vault_id"}, - }, - - // todo remove in 2.0 - "resource_group_name": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated as the resource group is now pulled from the vault ID and will be removed in version 2.0 of the provider", - ValidateFunc: func(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - - if len(value) > 80 { - errors = append(errors, fmt.Errorf("%q may not exceed 80 characters in length", k)) - } - - if strings.HasSuffix(value, ".") { - errors = append(errors, fmt.Errorf("%q may not end with a period", k)) - } - - // regex pulled from https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/createorupdate - if matched := regexp.MustCompile(`^[-\w\._\(\)]+$`).Match([]byte(value)); !matched { - errors = append(errors, fmt.Errorf("%q may only contain alphanumeric characters, dash, underscores, parentheses and periods", k)) - } - - return warnings, errors - }, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, "tenant_id": { @@ -124,7 +83,6 @@ func resourceArmKeyVaultAccessPolicyCreateOrDelete(d *schema.ResourceData, meta log.Printf("[INFO] Preparing arguments for Key Vault Access Policy: %s.", action) vaultId := d.Get("key_vault_id").(string) - vaultName := d.Get("vault_name").(string) resourceGroup := d.Get("resource_group_name").(string) tenantIdRaw := d.Get("tenant_id").(string) @@ -136,24 +94,15 @@ func resourceArmKeyVaultAccessPolicyCreateOrDelete(d *schema.ResourceData, meta applicationIdRaw := d.Get("application_id").(string) objectId := d.Get("object_id").(string) - if vaultName == "" { - if vaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_name` must be set") - } - id, err2 := azure.ParseAzureResourceID(vaultId) - if err2 != nil { - return err2 - } - - resourceGroup = id.ResourceGroup + id, err := azure.ParseAzureResourceID(vaultId) + if err != nil { + return err + } - vaultNameTemp, ok := id.Path["vaults"] - if !ok { - return fmt.Errorf("key_value_id does not contain `vaults`: %q", vaultId) - } - vaultName = vaultNameTemp - } else if resourceGroup == "" { - return fmt.Errorf("one of `resource_group_name` must be set when `vault_name` is used") + resourceGroup = id.ResourceGroup + vaultName, ok := id.Path["vaults"] + if !ok { + return fmt.Errorf("key_value_id does not contain `vaults`: %q", vaultId) } keyVault, err := client.Get(ctx, resourceGroup, vaultName) @@ -323,8 +272,6 @@ func resourceArmKeyVaultAccessPolicyRead(d *schema.ResourceData, meta interface{ } d.Set("key_vault_id", resp.ID) - d.Set("vault_name", resp.Name) - d.Set("resource_group_name", resGroup) d.Set("object_id", objectId) if tid := policy.TenantID; tid != nil { diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_certificate.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_certificate.go index 0355f164ba80f..6219533d02b24 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_certificate.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_certificate.go @@ -70,23 +70,10 @@ func resourceArmKeyVaultCertificate() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, - }, - - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, "certificate": { @@ -356,25 +343,10 @@ func resourceArmKeyVaultCertificateCreate(d *schema.ResourceData, meta interface name := d.Get("name").(string) keyVaultId := d.Get("key_vault_id").(string) - keyVaultBaseUrl := d.Get("vault_uri").(string) - - if keyVaultBaseUrl == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Certificate %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUrl = pKeyVaultBaseUrl - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUrl) - if err != nil { - return fmt.Errorf("Error unable to find key vault ID from URL %q for certificate %q: %+v", keyVaultBaseUrl, name, err) - } - d.Set("key_vault_id", id) + keyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Certificate %q vault url from id %q: %+v", name, keyVaultId, err) } if features.ShouldResourcesBeImported() { @@ -497,7 +469,6 @@ func resourceArmKeyVaultCertificateRead(d *schema.ResourceData, meta interface{} } d.Set("name", id.Name) - d.Set("vault_uri", id.KeyVaultBaseUrl) certificatePolicy := flattenKeyVaultCertificatePolicy(cert.Policy) if err := d.Set("certificate_policy", certificatePolicy); err != nil { diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go index 73dc13da185ef..3e1ca20609880 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_key.go @@ -46,23 +46,10 @@ func resourceArmKeyVaultKey() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, - }, - - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, "key_type": { @@ -174,26 +161,11 @@ func resourceArmKeyVaultKeyCreate(d *schema.ResourceData, meta interface{}) erro log.Print("[INFO] preparing arguments for AzureRM KeyVault Key creation.") name := d.Get("name").(string) - keyVaultBaseUri := d.Get("vault_uri").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUri == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUri = pKeyVaultBaseUrl - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUri) - if err != nil { - return fmt.Errorf("Error unable to find key vault ID from URL %q for certificate %q: %+v", keyVaultBaseUri, name, err) - } - d.Set("key_vault_id", id) + keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) } if features.ShouldResourcesBeImported() { @@ -367,7 +339,6 @@ func resourceArmKeyVaultKeyRead(d *schema.ResourceData, meta interface{}) error } d.Set("name", id.Name) - d.Set("vault_uri", id.KeyVaultBaseUrl) if key := resp.Key; key != nil { d.Set("key_type", string(key.Kty)) diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_secret.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_secret.go index 1cc2f655ab7e1..7e4508bfca17b 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_secret.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_secret.go @@ -8,7 +8,6 @@ import ( "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" "github.com/Azure/go-autorest/autorest/date" "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" @@ -45,23 +44,10 @@ func resourceArmKeyVaultSecret() *schema.Resource { }, "key_vault_id": { - Type: schema.TypeString, - Optional: true, //todo required in 2.0 - Computed: true, //todo removed in 2.0 - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"vault_uri"}, - }, - - // todo remove in 2.0 - "vault_uri": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the key_vault_id property. This will prevent a class of bugs as described in https://github.com/terraform-providers/terraform-provider-azurerm/issues/2396 and will be removed in version 2.0 of the provider", - ValidateFunc: validation.IsURLWithHTTPS, - ConflictsWith: []string{"key_vault_id"}, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, }, "value": { @@ -106,26 +92,11 @@ func resourceArmKeyVaultSecretCreate(d *schema.ResourceData, meta interface{}) e log.Print("[INFO] preparing arguments for AzureRM KeyVault Secret creation.") name := d.Get("name").(string) - keyVaultBaseUrl := d.Get("vault_uri").(string) keyVaultId := d.Get("key_vault_id").(string) - if keyVaultBaseUrl == "" { - if keyVaultId == "" { - return fmt.Errorf("one of `key_vault_id` or `vault_uri` must be set") - } - - pKeyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) - if err != nil { - return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) - } - - keyVaultBaseUrl = pKeyVaultBaseUrl - } else { - id, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultClient, keyVaultBaseUrl) - if err != nil { - return fmt.Errorf("Error unable to find key vault ID from URL %q for certificate %q: %+v", keyVaultBaseUrl, name, err) - } - d.Set("key_vault_id", id) + keyVaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) } if features.ShouldResourcesBeImported() { @@ -319,7 +290,6 @@ func resourceArmKeyVaultSecretRead(d *schema.ResourceData, meta interface{}) err } d.Set("name", respID.Name) - d.Set("vault_uri", respID.KeyVaultBaseUrl) d.Set("value", resp.Value) d.Set("version", respID.Version) d.Set("content_type", resp.ContentType) diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 8953c5d82eff8..1330457be7a0c 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -46,7 +46,7 @@ func TestAccDataSourceAzureRMKeyVault_basicClassic(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), @@ -71,7 +71,7 @@ func TestAccDataSourceAzureRMKeyVault_complete(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "get"), @@ -97,7 +97,7 @@ func TestAccDataSourceAzureRMKeyVault_networkAcls(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "sku.0.name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_access_policy_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_access_policy_test.go index 41161a553330b..788ff00d413bc 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_access_policy_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_access_policy_test.go @@ -37,28 +37,6 @@ func TestAccAzureRMKeyVaultAccessPolicy_basic(t *testing.T) { }) } -func TestAccAzureRMKeyVaultAccessPolicy_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault_access_policy", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVaultAccessPolicy_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultAccessPolicyExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "key_permissions.0", "get"), - resource.TestCheckResourceAttr(data.ResourceName, "secret_permissions.0", "get"), - resource.TestCheckResourceAttr(data.ResourceName, "secret_permissions.1", "set"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMKeyVaultAccessPolicy_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -240,30 +218,6 @@ resource "azurerm_key_vault_access_policy" "test" { `, template) } -func testAccAzureRMKeyVaultAccessPolicy_basicClassic(data acceptance.TestData) string { - template := testAccAzureRMKeyVaultAccessPolicy_template(data) - return fmt.Sprintf(` -%s - -resource "azurerm_key_vault_access_policy" "test" { - vault_name = "${azurerm_key_vault.test.name}" - resource_group_name = "${azurerm_key_vault.test.resource_group_name}" - - key_permissions = [ - "get", - ] - - secret_permissions = [ - "get", - "set", - ] - - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.service_principal_object_id}" -} -`, template) -} - func testAccAzureRMKeyVaultAccessPolicy_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVaultAccessPolicy_basic(data) return fmt.Sprintf(` @@ -361,8 +315,7 @@ func testAccAzureRMKeyVaultAccessPolicy_update(data acceptance.TestData) string %s resource "azurerm_key_vault_access_policy" "test" { - vault_name = "${azurerm_key_vault.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + key_vault_id = "${azurerm_key_vault.test.id}" key_permissions = [ "list", diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go index 41d67eb2af812..59a2079005c5e 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go @@ -35,26 +35,6 @@ func TestAccAzureRMKeyVaultCertificate_basicImportPFX(t *testing.T) { }) } -func TestAccAzureRMKeyVaultCertificate_basicImportPFXClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault_certificate", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultCertificateDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVaultCertificate_basicImportPFXClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultCertificateExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "certificate_data"), - ), - }, - data.ImportStep("certificate"), - }, - }) -} - func TestAccAzureRMKeyVaultCertificate_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -233,6 +213,7 @@ func TestAccAzureRMKeyVaultCertificate_emptyExtendedKeyUsage(t *testing.T) { func testCheckAzureRMKeyVaultCertificateDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { @@ -241,8 +222,11 @@ func testCheckAzureRMKeyVaultCertificateDestroy(s *terraform.State) error { } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { @@ -271,6 +255,7 @@ func testCheckAzureRMKeyVaultCertificateDestroy(s *terraform.State) error { func testCheckAzureRMKeyVaultCertificateExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -280,10 +265,13 @@ func testCheckAzureRMKeyVaultCertificateExists(resourceName string) resource.Tes } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Certificate %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -308,6 +296,7 @@ func testCheckAzureRMKeyVaultCertificateExists(resourceName string) resource.Tes func testCheckAzureRMKeyVaultCertificateDisappears(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -316,10 +305,13 @@ func testCheckAzureRMKeyVaultCertificateDisappears(resourceName string) resource return fmt.Errorf("Not found: %s", resourceName) } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Certificate %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -407,76 +399,6 @@ resource "azurerm_key_vault_certificate" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } -func testAccAzureRMKeyVaultCertificate_basicImportPFXClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkeyvault%s" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku_name = "standard" - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.service_principal_object_id}" - - certificate_permissions = [ - "delete", - "import", - "get", - ] - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - - storage_permissions = [ - "set", - ] - } -} - -resource "azurerm_key_vault_certificate" "test" { - name = "acctestcert%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" - - certificate { - contents = "${filebase64("testdata/keyvaultcert.pfx")}" - password = "" - } - - certificate_policy { - issuer_parameters { - name = "Self" - } - - key_properties { - exportable = true - key_size = 2048 - key_type = "RSA" - reuse_key = false - } - - secret_properties { - content_type = "application/x-pkcs12" - } - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - func testAccAzureRMKeyVaultCertificate_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVaultCertificate_basicImportPFX(data) return fmt.Sprintf(` @@ -831,8 +753,8 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_certificate" "test" { - name = "acctestcert%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" + name = "acctestcert%s" + key_vault_id = "${azurerm_key_vault.test.id}" certificate_policy { issuer_parameters { @@ -927,8 +849,8 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_certificate" "test" { - name = "acctestcert%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" + name = "acctestcert%s" + key_vault_id = "${azurerm_key_vault.test.id}" certificate_policy { issuer_parameters { diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index ec3c7ffc8d9b5..b9cf42e1673b8 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -34,25 +34,6 @@ func TestAccAzureRMKeyVaultKey_basicEC(t *testing.T) { }) } -func TestAccAzureRMKeyVaultKey_basicECClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault_key", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultKeyDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVaultKey_basicECClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultKeyExists(data.ResourceName), - ), - }, - data.ImportStep("key_size"), - }, - }) -} - func TestAccAzureRMKeyVaultKey_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -248,6 +229,7 @@ func TestAccAzureRMKeyVaultKey_disappearsWhenParentKeyVaultDeleted(t *testing.T) func testCheckAzureRMKeyVaultKeyDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { @@ -256,8 +238,11 @@ func testCheckAzureRMKeyVaultKeyDestroy(s *terraform.State) error { } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { @@ -286,6 +271,7 @@ func testCheckAzureRMKeyVaultKeyDestroy(s *terraform.State) error { func testCheckAzureRMKeyVaultKeyExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -294,10 +280,13 @@ func testCheckAzureRMKeyVaultKeyExists(resourceName string) resource.TestCheckFu return fmt.Errorf("Not found: %s", resourceName) } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Key %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -322,6 +311,7 @@ func testCheckAzureRMKeyVaultKeyExists(resourceName string) resource.TestCheckFu func testCheckAzureRMKeyVaultKeyDisappears(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -331,10 +321,13 @@ func testCheckAzureRMKeyVaultKeyDisappears(resourceName string) resource.TestChe } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Key %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -409,59 +402,6 @@ resource "azurerm_key_vault_key" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } -func testAccAzureRMKeyVaultKey_basicECClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku_name = "premium" - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.service_principal_object_id}" - - key_permissions = [ - "create", - "delete", - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} - -resource "azurerm_key_vault_key" "test" { - name = "key-%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" - key_type = "EC" - key_size = 2048 - - key_opts = [ - "sign", - "verify", - ] -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - func testAccAzureRMKeyVaultKey_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVaultKey_basicEC(data) return fmt.Sprintf(` @@ -700,10 +640,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" - key_type = "RSA" - key_size = 2048 + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "RSA" + key_size = 2048 key_opts = [ "encrypt", @@ -758,10 +698,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" - key_type = "EC" - curve = "P-521" + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "EC" + curve = "P-521" key_opts = [ "sign", @@ -813,10 +753,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - vault_uri = "${azurerm_key_vault.test.vault_uri}" - key_type = "EC-HSM" - curve = "P-521" + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "EC-HSM" + curve = "P-521" key_opts = [ "sign", diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go index 5b2fd6a2d5964..693c1a0cccb61 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go @@ -35,26 +35,6 @@ func TestAccAzureRMKeyVaultSecret_basic(t *testing.T) { }) } -func TestAccAzureRMKeyVaultSecret_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault_secret", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVaultSecret_basicClasic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultSecretExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "value", "rick-and-morty"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMKeyVaultSecret_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -174,6 +154,7 @@ func TestAccAzureRMKeyVaultSecret_update(t *testing.T) { func testCheckAzureRMKeyVaultSecretDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { @@ -182,8 +163,11 @@ func testCheckAzureRMKeyVaultSecretDestroy(s *terraform.State) error { } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { @@ -212,6 +196,7 @@ func testCheckAzureRMKeyVaultSecretDestroy(s *terraform.State) error { func testCheckAzureRMKeyVaultSecretExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -220,10 +205,13 @@ func testCheckAzureRMKeyVaultSecretExists(resourceName string) resource.TestChec return fmt.Errorf("Not found: %s", resourceName) } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Secret %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -248,6 +236,7 @@ func testCheckAzureRMKeyVaultSecretExists(resourceName string) resource.TestChec func testCheckAzureRMKeyVaultSecretDisappears(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.ManagementClient + vaultClient := acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext // Ensure we have enough information in state to look up in API @@ -256,10 +245,13 @@ func testCheckAzureRMKeyVaultSecretDisappears(resourceName string) resource.Test return fmt.Errorf("Not found: %s", resourceName) } name := rs.Primary.Attributes["name"] - vaultBaseUrl := rs.Primary.Attributes["vault_uri"] keyVaultId := rs.Primary.Attributes["key_vault_id"] + vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) + if err != nil { + return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + } - ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) + ok, err = azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) if err != nil { return fmt.Errorf("Error checking if key vault %q for Secret %q in Vault at url %q exists: %v", keyVaultId, name, vaultBaseUrl, err) } @@ -326,51 +318,6 @@ resource "azurerm_key_vault_secret" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } -func testAccAzureRMKeyVaultSecret_basicClasic(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "acctestkv-%s" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku_name = "premium" - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.service_principal_object_id}" - - key_permissions = [ - "get", - ] - - secret_permissions = [ - "get", - "delete", - "set", - ] - } - - tags = { - environment = "Production" - } -} - -resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "rick-and-morty" - vault_uri = "${azurerm_key_vault.test.vault_uri}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) -} - func testAccAzureRMKeyVaultSecret_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVaultSecret_basic(data) return fmt.Sprintf(` @@ -474,9 +421,9 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "szechuan" - vault_uri = "${azurerm_key_vault.test.vault_uri}" + name = "secret-%s" + value = "szechuan" + key_vault_id = "${azurerm_key_vault.test.id}" } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index b4d595382d5ba..4fab60950554a 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -109,27 +109,6 @@ func TestAccAzureRMKeyVault_basicNotDefined(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMKeyVault_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVault_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMKeyVaultExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "premium"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMKeyVault_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -481,41 +460,6 @@ resource "azurerm_key_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMKeyVault_basicClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "vault%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku { - name = "premium" - } - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.client_id}" - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMKeyVault_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVault_basic(data) return fmt.Sprintf(` @@ -740,9 +684,7 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } + sku_name = "premium" enabled_for_deployment = true enabled_for_disk_encryption = true @@ -770,9 +712,7 @@ resource "azurerm_key_vault" "test" { resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - sku { - name = "premium" - } + sku_name = "premium" access_policy = [] diff --git a/website/docs/d/key_vault.html.markdown b/website/docs/d/key_vault.html.markdown index 429419f0eafba..0ffaf2d118621 100644 --- a/website/docs/d/key_vault.html.markdown +++ b/website/docs/d/key_vault.html.markdown @@ -41,10 +41,10 @@ The following attributes are exported: * `location` - The Azure Region in which the Key Vault exists. -* `sku` - A `sku` block as described below. - * `tenant_id` - The Azure Active Directory Tenant ID used for authenticating requests to the Key Vault. +* `sku_name` - The Name of the SKU used for this Key Vault. + * `access_policy` - One or more `access_policy` blocks as defined below. * `enabled_for_deployment` - Can Azure Virtual Machines retrieve certificates stored as secrets from the Key Vault? @@ -55,11 +55,7 @@ The following attributes are exported: * `tags` - A mapping of tags assigned to the Key Vault. -A `sku` block exports the following: - -* `name` - The name of the SKU used for this Key Vault. - -`access_policy` supports the following: +A `access_policy` block supports the following: * `tenant_id` - The Azure Active Directory Tenant ID used to authenticate requests for this Key Vault. diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index 3c3fc2955605c..e153aeb66919c 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -157,6 +157,18 @@ The deprecated fields `service_principal_object_id` and `service_principal_appli The deprecated field `zone_type` will be removed. Private DNS Zones are now a separate resource in both Azure and Terraform. +### Data Source: `azurerm_key_vault` + +The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. + +### Data Source: `azurerm_key_vault_key` + +The deprecated `vault_uri` field has been replaced by the `key_vault_id` field and will be removed. + +### Data Source: `azurerm_key_vault_secret` + +The deprecated `vault_uri` field has been replaced by the `key_vault_id` field and will be removed. + ### Data Source: `azurerm_kubernetes_cluster` The deprecated block `agent_pool_profile` will be removed. This has been replaced by the `default_node_pool` block. @@ -349,6 +361,31 @@ The deprecated `location` field will be removed, since this is no longer used. The deprecated `location` field will be removed, since this is no longer used. +### Resource: `azurerm_key_vault` + +The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. + +The `sku_name` field is now case sensitive. + +### Resource: `azurerm_key_vault_access_policy` + +The deprecated `vault_name` field has been replaced by the `key_vault_id` field and will be removed. + +The deprecated `resource_group_name` will be removed. + +### Resource: `azurerm_key_vault_certificate` + +The deprecated `vault_uri` field has been replaced by the `key_vault_id` field and will be removed. + +### Resource: `azurerm_key_vault_key` + +The deprecated `vault_uri` field has been replaced by the `key_vault_id` field and will be removed. + + +### Resource: `azurerm_key_vault_secret` + +The deprecated `vault_uri` field has been replaced by the `key_vault_id` field and will be removed. + ### Resource: `azurerm_log_analytics_linked_service` The `resource_id` field has been moved from the `linked_service_properties` block to the top-level. diff --git a/website/docs/r/key_vault.html.markdown b/website/docs/r/key_vault.html.markdown index fff01660246fd..a358cd62a4c61 100644 --- a/website/docs/r/key_vault.html.markdown +++ b/website/docs/r/key_vault.html.markdown @@ -67,9 +67,7 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which to create the Key Vault. Changing this forces a new resource to be created. -* `sku` - (Optional **Deprecated**)) A `sku` block as described below. - -* `sku_name` - (Optional) The Name of the SKU used for this Key Vault. Possible values are `standard` and `premium`. +* `sku_name` - (Required) The Name of the SKU used for this Key Vault. Possible values are `standard` and `premium`. * `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. @@ -88,11 +86,7 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. --- -A `sku` block supports the following: - -* `name` - (Required) The Name of the SKU used for this Key Vault. Possible values are `standard` and `premium`. ---- A `access_policy` block supports the following: Elements of `access_policy` support: @@ -133,8 +127,6 @@ The following attributes are exported: ## Timeouts - - The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: * `create` - (Defaults to 30 minutes) Used when creating the Key Vault. diff --git a/website/docs/r/key_vault_access_policy.html.markdown b/website/docs/r/key_vault_access_policy.html.markdown index c01f01cde5392..f4d9b171c1f12 100644 --- a/website/docs/r/key_vault_access_policy.html.markdown +++ b/website/docs/r/key_vault_access_policy.html.markdown @@ -61,14 +61,6 @@ The following arguments are supported: * `key_vault_id` - (Required) Specifies the id of the Key Vault resource. Changing this forces a new resource to be created. --> **NOTE:** At this time the Key Vault `<->` Key Vault Access Policy associations need to be configured using the field `key_vault_id` or using both fields `vault_name` and `resource_group_name`. These fields are now deprecated and will be removed in favour of `key_vault_id` in the next major version (2.0) of the AzureRM Provider. - -* `vault_name` - (Required / **Deprecated**) Specifies the name of the Key Vault resource. Changing this - forces a new resource to be created. - -* `resource_group_name` - (Required / **Deprecated**) The name of the resource group in which to - create the namespace. Changing this forces a new resource to be created. - * `tenant_id` - (Required) The Azure Active Directory tenant ID that should be used for authenticating requests to the key vault. Changing this forces a new resource to be created. From 576fa5b5b09f2e6567537e6be80395f79bf56128 Mon Sep 17 00:00:00 2001 From: aqche <39076898+aqche@users.noreply.github.com> Date: Sun, 16 Feb 2020 09:18:26 -0800 Subject: [PATCH 134/498] Update azurerm/internal/services/storage/resource_arm_storage_account.go Co-Authored-By: Tom Harvey --- .../internal/services/storage/resource_arm_storage_account.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 4c59eb4047750..5ea5ba80964ce 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -456,7 +456,6 @@ func resourceArmStorageAccount() *schema.Resource { "static_website": { Type: schema.TypeList, Optional: true, - Computed: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ From 525ec02e479259987cb7448aafdac1553547d45f Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 06:27:43 +0100 Subject: [PATCH 135/498] updating to include #5721 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7404898508b82..25c81191e38a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ BREAKING CHANGES: * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] * `azurerm_notification_hub_namesapce` - removing the `sku` block in favour of the `sku_name` argument [GH-5722] +* `azurerm_postgresql_server` - removing the `sku` block which has been deprecated in favour of the `sku_name` field [GH-5721] * `azurerm_relay_namespace` - removing the `sku` block in favour of the `sku_name` field [GH-5719] * `azurerm_scheduler_job` - This resource has been removed since it was deprecated [GH-5712] * `azurerm_scheduler_job_collection` - This resource has been removed since it was deprecated [GH-5712] From 5c6975b8be6c3e19debfa5fcc7f3f7d399a7b675 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 06:45:09 +0100 Subject: [PATCH 136/498] r/iothub_dps: fixing the test --- .../services/iothub/tests/resource_arm_iothub_dps_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go index 2219458d2d30e..d56e7fa952b27 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go @@ -46,7 +46,7 @@ func TestAccAzureRMIotHubDPS_requiresImport(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, + CheckDestroy: testCheckAzureRMIotHubDPSDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMIotHubDPS_basic(data), @@ -68,7 +68,7 @@ func TestAccAzureRMIotHubDPS_update(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotDPSDestroy, + CheckDestroy: testCheckAzureRMIotHubDPSDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMIotHubDPS_basic(data), From c4cf372975f829688747a6762cc45a972c2d45a4 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 06:47:54 +0100 Subject: [PATCH 137/498] updating to include #5776 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c81191e38a8..019d9c0b929bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ BREAKING CHANGES: * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_kubernetes_cluster` - updating the default value for `load_balancer_sku` to `Standard` from `Basic` [GH-5747] * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] +* `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] * `azurerm_notification_hub_namesapce` - removing the `sku` block in favour of the `sku_name` argument [GH-5722] * `azurerm_postgresql_server` - removing the `sku` block which has been deprecated in favour of the `sku_name` field [GH-5721] From b854b1606f3bf5b36dc7c808e17d1c712cf32258 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 07:15:51 +0100 Subject: [PATCH 138/498] updating to include #5649 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 019d9c0b929bc..77ffcd60a6490 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ IMPROVEMENTS: * Data Source: `azurerm_kubernetes_service_version` - support for filtering of preview releases [GH-5662] * `azurerm_dedicated_host` - support for setting `sku_name` to `DSv3-Type2` and `ESv3-Type2` [GH-5768] +* `azurerm_storage_account` - support for configuring the `static_website` block [GH-5649] * `azurerm_storage_account` - support for configuring `cors_rules` within the `blob_properties` block [GH-5425] * `azurerm_windows_virtual_machine` - fixing a bug when provisioning from a Shared Gallery image [GH-5661] From f3b56ac1a6a80de1b9fd65fe0b3c8cbc38874cb4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 07:22:19 +0100 Subject: [PATCH 139/498] r/app_service_plan: fixing a merge conflict --- .../web/resource_arm_app_service_plan.go | 56 +++---------------- 1 file changed, 7 insertions(+), 49 deletions(-) diff --git a/azurerm/internal/services/web/resource_arm_app_service_plan.go b/azurerm/internal/services/web/resource_arm_app_service_plan.go index 70ced7d9b7328..db32dd0b5efde 100644 --- a/azurerm/internal/services/web/resource_arm_app_service_plan.go +++ b/azurerm/internal/services/web/resource_arm_app_service_plan.go @@ -94,63 +94,21 @@ func resourceArmAppServicePlan() *schema.Resource { }, }, - "properties": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Deprecated: "These properties have been moved to the top level", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "app_service_environment_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - Deprecated: "This property has been moved to the top level", - ConflictsWith: []string{"app_service_environment_id"}, - }, - - "reserved": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Deprecated: "This property has been moved to the top level", - ConflictsWith: []string{"reserved"}, - }, - - "per_site_scaling": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Deprecated: "This property has been moved to the top level", - ConflictsWith: []string{"per_site_scaling"}, - }, - }, - }, - }, - /// AppServicePlanProperties "app_service_environment_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - ConflictsWith: []string{"properties.0.app_service_environment_id"}, + Type: schema.TypeString, + Optional: true, + ForceNew: true, }, "per_site_scaling": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"properties.0.per_site_scaling"}, + Type: schema.TypeBool, + Optional: true, }, "reserved": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - ConflictsWith: []string{"properties.0.reserved"}, + Type: schema.TypeBool, + Optional: true, }, "maximum_elastic_worker_count": { From 67700c6aa4f418846fdad5feb13e44152df93709 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 08:00:17 +0100 Subject: [PATCH 140/498] updating to include #5753 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77ffcd60a6490..8f236b32c3df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ BREAKING CHANGES: * `azurerm_azuread_service_principal_password` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_azuread_service_principal` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] +* `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] +* `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_kubernetes_cluster` - updating the default value for `load_balancer_sku` to `Standard` from `Basic` [GH-5747] * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] From 3e6929666a356882a6e816d140299d59cf5320a9 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 07:18:45 +0000 Subject: [PATCH 141/498] Fix for update --- .../storage/resource_arm_storage_account_network_rules.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go index 81fefac044d3a..7bbfda7558ce8 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account_network_rules.go @@ -118,7 +118,7 @@ func resourceArmStorageAccountNetworkRulesCreateUpdate(d *schema.ResourceData, m return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): %+v", storageAccountName, resourceGroup, err) } - if features.ShouldResourcesBeImported() { + if features.ShouldResourcesBeImported() && d.IsNewResource() { if storageAccount.AccountProperties == nil { return fmt.Errorf("Error retrieving Storage Account %q (Resource Group %q): `properties` was nil", storageAccountName, resourceGroup) } From 56051b864940a700cce301da60b78a1e7d4d0a11 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 08:25:59 +0100 Subject: [PATCH 142/498] updating to include #5764 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f236b32c3df7..1804f23113323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,8 @@ IMPROVEMENTS: BUG FIXES: +* `azurerm_linux_virtual_machine` - using the delete custom timeout during deletion [GH-5764] +* `azurerm_windows_virtual_machine` - using the delete custom timeout during deletion [GH-5764] * `azurerm_signalr_service` - ensuring the SignalR segment is parsed in the correct case [GH-5737] --- From 34340db17924ea5709f2d174ca5a1f1240496cf3 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 08:37:55 +0100 Subject: [PATCH 143/498] New Resource: `azurerm_network_interface_security_group_association` This commit introduces a new resource for linking a Network Interface and a Network Security Group which is required to work around a dependency issue in the Azure API where the NSG must be detached in order to be able to delete dependent resources. --- .../azuresdkhacks/network_interface.go | 105 +++++++ azurerm/internal/azuresdkhacks/notes.go | 15 + ...ork_security_group_association_resource.go | 218 ++++++++++++++ .../internal/services/network/registration.go | 1 + ...ecurity_group_association_resource_test.go | 281 ++++++++++++++++++ ...e_security_group_association.html.markdown | 91 ++++++ 6 files changed, 711 insertions(+) create mode 100644 azurerm/internal/azuresdkhacks/network_interface.go create mode 100644 azurerm/internal/azuresdkhacks/notes.go create mode 100644 azurerm/internal/services/network/network_interface_network_security_group_association_resource.go create mode 100644 azurerm/internal/services/network/tests/network_interface_network_security_group_association_resource_test.go create mode 100644 website/docs/r/network_interface_security_group_association.html.markdown diff --git a/azurerm/internal/azuresdkhacks/network_interface.go b/azurerm/internal/azuresdkhacks/network_interface.go new file mode 100644 index 0000000000000..8f4c849d71dec --- /dev/null +++ b/azurerm/internal/azuresdkhacks/network_interface.go @@ -0,0 +1,105 @@ +package azuresdkhacks + +import ( + "bytes" + "context" + "encoding/json" + "io/ioutil" + "net/http" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/Azure/go-autorest/autorest" +) + +// UpdateNetworkInterfaceAllowingRemovalOfNSG patches our way around a design flaw in the Azure +// Resource Manager API <-> Azure SDK for Go where it's not possible to remove a Network Security Group +func UpdateNetworkInterfaceAllowingRemovalOfNSG(ctx context.Context, client *network.InterfacesClient, resourceGroupName string, networkInterfaceName string, parameters network.Interface) (result network.InterfacesCreateOrUpdateFuture, err error) { + req, err := updateNetworkInterfaceAllowingRemovalOfNSGPreparer(ctx, client, resourceGroupName, networkInterfaceName, parameters) + if err != nil { + err = autorest.NewErrorWithError(err, "network.InterfacesClient", "CreateOrUpdate", nil, "Failure preparing request") + return + } + + result, err = client.CreateOrUpdateSender(req) + if err != nil { + err = autorest.NewErrorWithError(err, "network.InterfacesClient", "CreateOrUpdate", result.Response(), "Failure sending request") + return + } + + return +} + +// updateNetworkInterfaceAllowingRemovalOfNSGPreparer prepares the CreateOrUpdate request but applies the +// necessary patches to be able to remove the NSG if required +func updateNetworkInterfaceAllowingRemovalOfNSGPreparer(ctx context.Context, client *network.InterfacesClient, resourceGroupName string, networkInterfaceName string, parameters network.Interface) (*http.Request, error) { + pathParameters := map[string]interface{}{ + "networkInterfaceName": autorest.Encode("path", networkInterfaceName), + "resourceGroupName": autorest.Encode("path", resourceGroupName), + "subscriptionId": autorest.Encode("path", client.SubscriptionID), + } + + const APIVersion = "2019-09-01" + queryParameters := map[string]interface{}{ + "api-version": APIVersion, + } + + parameters.Etag = nil + preparer := autorest.CreatePreparer( + autorest.AsContentType("application/json; charset=utf-8"), + autorest.AsPut(), + autorest.WithBaseURL(client.BaseURI), + autorest.WithPathParameters("/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/{networkInterfaceName}", pathParameters), + withJsonWorkingAroundTheBrokenNetworkAPI(parameters), + autorest.WithQueryParameters(queryParameters)) + return preparer.Prepare((&http.Request{}).WithContext(ctx)) +} + +func withJsonWorkingAroundTheBrokenNetworkAPI(v network.Interface) autorest.PrepareDecorator { + return func(p autorest.Preparer) autorest.Preparer { + return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { + r, err := p.Prepare(r) + if err == nil { + b, err := json.Marshal(v) + if err == nil { + // there's a few fields which can be intentionally set to nil - as such here we need to check if they should be nil and force them to be nil + var out map[string]interface{} + if err := json.Unmarshal(b, &out); err != nil { + return r, err + } + + // apply the hack + out = patchNICUpdateAPIIssue(v, out) + + // then reserialize it as needed + b, err = json.Marshal(out) + if err == nil { + r.ContentLength = int64(len(b)) + r.Body = ioutil.NopCloser(bytes.NewReader(b)) + } + } + } + return r, err + }) + } +} + +func patchNICUpdateAPIIssue(nic network.Interface, input map[string]interface{}) map[string]interface{} { + if nic.InterfacePropertiesFormat == nil { + return input + } + + output := input + + if v, ok := output["properties"]; ok { + props := v.(map[string]interface{}) + + if nic.InterfacePropertiesFormat.NetworkSecurityGroup == nil { + var hack *string // a nil-pointered string + props["networkSecurityGroup"] = hack + } + + output["properties"] = props + } + + return output +} diff --git a/azurerm/internal/azuresdkhacks/notes.go b/azurerm/internal/azuresdkhacks/notes.go new file mode 100644 index 0000000000000..a1612ed8dad82 --- /dev/null +++ b/azurerm/internal/azuresdkhacks/notes.go @@ -0,0 +1,15 @@ +package azuresdkhacks + +// There's a functional difference that exists between the Azure SDK for Go and Azure Resource Manager API +// where when performing a delta update unchanged fields are omited from the response when they could +// also have a legitimate value of `null` (to remove/disable a sub-block). +// +// Ultimately the Azure SDK for Go has opted to serialise structs with `json:"name,omitempty"` which +// means that this value will be omited if nil to allow for delta updates - however this means there's +// no means of removing/resetting a value of a nested object once provided since a `nil` object will be +// reset +// +// As such this set of well intentioned hacks is intended to force this behaviour where necessary. +// +// It's worth noting that these hacks are a last resort and the Swagger/API/SDK should almost always be +// fixed instead. diff --git a/azurerm/internal/services/network/network_interface_network_security_group_association_resource.go b/azurerm/internal/services/network/network_interface_network_security_group_association_resource.go new file mode 100644 index 0000000000000..b71f335adb043 --- /dev/null +++ b/azurerm/internal/services/network/network_interface_network_security_group_association_resource.go @@ -0,0 +1,218 @@ +package network + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/hashicorp/terraform-plugin-sdk/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/internal/azuresdkhacks" + "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/locks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmNetworkInterfaceSecurityGroupAssociation() *schema.Resource { + return &schema.Resource{ + Create: resourceArmNetworkInterfaceSecurityGroupAssociationCreate, + Read: resourceArmNetworkInterfaceSecurityGroupAssociationRead, + Delete: resourceArmNetworkInterfaceSecurityGroupAssociationDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "network_interface_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + + "network_security_group_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateResourceID, + }, + }, + } +} + +func resourceArmNetworkInterfaceSecurityGroupAssociationCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.InterfacesClient + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for Network Interface <-> Network Security Group Association creation.") + + networkInterfaceId := d.Get("network_interface_id").(string) + networkSecurityGroupId := d.Get("network_security_group_id").(string) + + nicId, err := azure.ParseAzureResourceID(networkInterfaceId) + if err != nil { + return err + } + + networkInterfaceName := nicId.Path["networkInterfaces"] + resourceGroup := nicId.ResourceGroup + + locks.ByName(networkInterfaceName, networkInterfaceResourceName) + defer locks.UnlockByName(networkInterfaceName, networkInterfaceResourceName) + + nsgId, err := azure.ParseAzureResourceID(networkSecurityGroupId) + if err != nil { + return err + } + nsgName := nsgId.Path["networkSecurityGroups"] + + locks.ByName(nsgName, networkSecurityGroupResourceName) + defer locks.UnlockByName(nsgName, networkSecurityGroupResourceName) + + read, err := client.Get(ctx, resourceGroup, networkInterfaceName, "") + if err != nil { + if utils.ResponseWasNotFound(read.Response) { + return fmt.Errorf("Network Interface %q (Resource Group %q) was not found!", networkInterfaceName, resourceGroup) + } + + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", networkInterfaceName, resourceGroup, err) + } + + props := read.InterfacePropertiesFormat + if props == nil { + return fmt.Errorf("Error: `properties` was nil for Network Interface %q (Resource Group %q)", networkInterfaceName, resourceGroup) + } + + // first double-check it doesn't exist + resourceId := fmt.Sprintf("%s|%s", networkInterfaceId, networkSecurityGroupId) + if features.ShouldResourcesBeImported() { + if props.NetworkSecurityGroup != nil { + return tf.ImportAsExistsError("azurerm_network_interface_security_group_association", resourceGroup) + } + } + + props.NetworkSecurityGroup = &network.SecurityGroup{ + ID: utils.String(networkSecurityGroupId), + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, networkInterfaceName, read) + if err != nil { + return fmt.Errorf("Error updating Security Group Association for Network Interface %q (Resource Group %q): %+v", networkInterfaceName, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for completion of Security Group Association for NIC %q (Resource Group %q): %+v", networkInterfaceName, resourceGroup, err) + } + + d.SetId(resourceId) + + return resourceArmNetworkInterfaceSecurityGroupAssociationRead(d, meta) +} + +func resourceArmNetworkInterfaceSecurityGroupAssociationRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.InterfacesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + splitId := strings.Split(d.Id(), "|") + if len(splitId) != 2 { + return fmt.Errorf("Expected ID to be in the format {networkInterfaceId}|{networkSecurityGroupId} but got %q", d.Id()) + } + + nicID, err := azure.ParseAzureResourceID(splitId[0]) + if err != nil { + return err + } + + name := nicID.Path["networkInterfaces"] + resourceGroup := nicID.ResourceGroup + + read, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(read.Response) { + return fmt.Errorf("Network Interface %q (Resource Group %q) was not found!", name, resourceGroup) + } + + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + props := read.InterfacePropertiesFormat + if props == nil { + return fmt.Errorf("Error: `properties` was nil for Network Interface %q (Resource Group %q)", name, resourceGroup) + } + + if props.NetworkSecurityGroup == nil || props.NetworkSecurityGroup.ID == nil { + log.Printf("Network Interface %q (Resource Group %q) doesn't have a Security Group attached - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + + d.Set("network_interface_id", read.ID) + + // nil-checked above + d.Set("network_security_group_id", props.NetworkSecurityGroup.ID) + + return nil +} + +func resourceArmNetworkInterfaceSecurityGroupAssociationDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.InterfacesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + splitId := strings.Split(d.Id(), "|") + if len(splitId) != 2 { + return fmt.Errorf("Expected ID to be in the format {networkInterfaceId}/{networkSecurityGroup} but got %q", d.Id()) + } + + nicID, err := azure.ParseAzureResourceID(splitId[0]) + if err != nil { + return err + } + + name := nicID.Path["networkInterfaces"] + resourceGroup := nicID.ResourceGroup + + locks.ByName(name, networkInterfaceResourceName) + defer locks.UnlockByName(name, networkInterfaceResourceName) + + read, err := client.Get(ctx, resourceGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(read.Response) { + return fmt.Errorf("Network Interface %q (Resource Group %q) was not found!", name, resourceGroup) + } + + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + props := read.InterfacePropertiesFormat + if props == nil { + return fmt.Errorf("Error: `properties` was nil for Network Interface %q (Resource Group %q)", name, resourceGroup) + } + + props.NetworkSecurityGroup = nil + read.InterfacePropertiesFormat = props + + future, err := azuresdkhacks.UpdateNetworkInterfaceAllowingRemovalOfNSG(ctx, client, resourceGroup, name, read) + if err != nil { + return fmt.Errorf("Error updating Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for update of Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + return nil +} diff --git a/azurerm/internal/services/network/registration.go b/azurerm/internal/services/network/registration.go index fc30e925d99b7..3209c66a5d484 100644 --- a/azurerm/internal/services/network/registration.go +++ b/azurerm/internal/services/network/registration.go @@ -71,6 +71,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_network_interface_application_security_group_association": resourceArmNetworkInterfaceApplicationSecurityGroupAssociation(), "azurerm_network_interface_backend_address_pool_association": resourceArmNetworkInterfaceBackendAddressPoolAssociation(), "azurerm_network_interface_nat_rule_association": resourceArmNetworkInterfaceNatRuleAssociation(), + "azurerm_network_interface_security_group_association": resourceArmNetworkInterfaceSecurityGroupAssociation(), "azurerm_network_packet_capture": resourceArmNetworkPacketCapture(), "azurerm_network_profile": resourceArmNetworkProfile(), "azurerm_packet_capture": resourceArmPacketCapture(), diff --git a/azurerm/internal/services/network/tests/network_interface_network_security_group_association_resource_test.go b/azurerm/internal/services/network/tests/network_interface_network_security_group_association_resource_test.go new file mode 100644 index 0000000000000..1ad3e382435be --- /dev/null +++ b/azurerm/internal/services/network/tests/network_interface_network_security_group_association_resource_test.go @@ -0,0 +1,281 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/azuresdkhacks" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" +) + +func TestAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_security_group_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMNetworkInterfaceSecurityGroupAssociation_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + data := acceptance.BuildTestData(t, "azurerm_network_interface_security_group_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(data.ResourceName), + ), + }, + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_network_interface_security_group_association"), + }, + }, + }) +} + +func TestAccAzureRMNetworkInterfaceSecurityGroupAssociation_deleted(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_security_group_association", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(data.ResourceName), + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationDisappears(data.ResourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAzureRMNetworkInterfaceSecurityGroupAssociation_updateNIC(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface_security_group_association", "test") + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterfaceSecurityGroupAssociation_updateNIC(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testCheckAzureRMNetworkInterfaceSecurityGroupAssociationExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // 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) + } + + nicID, err := azure.ParseAzureResourceID(rs.Primary.Attributes["network_interface_id"]) + if err != nil { + return err + } + + nicName := nicID.Path["networkInterfaces"] + resourceGroup := nicID.ResourceGroup + networkSecurityGroupId := rs.Primary.Attributes["network_security_group_id"] + + read, err := client.Get(ctx, resourceGroup, nicName, "") + if err != nil { + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", nicName, resourceGroup, err) + } + + found := false + if read.InterfacePropertiesFormat != nil { + if read.InterfacePropertiesFormat.NetworkSecurityGroup != nil && read.InterfacePropertiesFormat.NetworkSecurityGroup.ID != nil { + found = *read.InterfacePropertiesFormat.NetworkSecurityGroup.ID == networkSecurityGroupId + } + } + if !found { + return fmt.Errorf("Association between NIC %q and Network Security Group %q was not found!", nicName, networkSecurityGroupId) + } + + return nil + } +} + +func testCheckAzureRMNetworkInterfaceSecurityGroupAssociationDisappears(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.InterfacesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // 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) + } + + nicID, err := azure.ParseAzureResourceID(rs.Primary.Attributes["network_interface_id"]) + if err != nil { + return err + } + + nicName := nicID.Path["networkInterfaces"] + resourceGroup := nicID.ResourceGroup + + read, err := client.Get(ctx, resourceGroup, nicName, "") + if err != nil { + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", nicName, resourceGroup, err) + } + + read.InterfacePropertiesFormat.NetworkSecurityGroup = nil + + future, err := azuresdkhacks.UpdateNetworkInterfaceAllowingRemovalOfNSG(ctx, client, resourceGroup, nicName, read) + if err != nil { + return fmt.Errorf("Error removing Network Security Group Association for Network Interface %q (Resource Group %q): %+v", nicName, resourceGroup, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for removal of Network Security Group Association for NIC %q (Resource Group %q): %+v", nicName, resourceGroup, err) + } + + return nil + } +} + +func testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceSecurityGroupAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_network_interface_security_group_association" "test" { + network_interface_id = azurerm_network_interface.test.id + network_security_group_id = azurerm_network_security_group.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceSecurityGroupAssociation_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceSecurityGroupAssociation_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface_security_group_association" "import" { + network_interface_id = azurerm_network_interface_security_group_association.test.network_interface_id + network_security_group_id = azurerm_network_interface_security_group_association.test.network_security_group_id +} +`, template) +} + +func testAccAzureRMNetworkInterfaceSecurityGroupAssociation_updateNIC(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterfaceSecurityGroupAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + primary = true + } + + ip_configuration { + name = "testconfiguration2" + private_ip_address_version = "IPv6" + private_ip_address_allocation = "dynamic" + } +} + +resource "azurerm_network_interface_security_group_association" "test" { + network_interface_id = azurerm_network_interface.test.id + network_security_group_id = azurerm_network_security_group.test.id +} +`, template, data.RandomInteger) +} + +func testAccAzureRMNetworkInterfaceSecurityGroupAssociation_template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvn-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.1.0/24" +} + +resource "azurerm_network_security_group" "test" { + name = "acctestnsg-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/website/docs/r/network_interface_security_group_association.html.markdown b/website/docs/r/network_interface_security_group_association.html.markdown new file mode 100644 index 0000000000000..3bc138982a77d --- /dev/null +++ b/website/docs/r/network_interface_security_group_association.html.markdown @@ -0,0 +1,91 @@ +--- +subcategory: "Network" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_network_interface_security_group_association" +description: |- + Manages the association between a Network Interface and a Network Security Group. + +--- + +# azurerm_network_interface_security_group_association + +Manages the association between a Network Interface and a Network Security Group. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_virtual_network" "example" { + name = "example-network" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_subnet" "example" { + name = "internal" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_network_security_group" "example" { + name = "example-nsg" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name +} + +resource "azurerm_network_interface" "example" { + name = "example-nic" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + ip_configuration { + name = "testconfiguration1" + subnet_id = azurerm_subnet.example.id + private_ip_address_allocation = "Dynamic" + } +} + +resource "azurerm_network_interface_security_group_association" "example" { + network_interface_id = azurerm_network_interface.example.id + network_security_group_id = azurerm_network_security_group.example.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `network_interface_id` - (Required) The ID of the Network Interface. Changing this forces a new resource to be created. + +* `network_security_group_id` - (Required) The ID of the Network Security Group which should be attached to the Network Interface. Changing this forces a new resource to be created. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The (Terraform specific) ID of the Association between the Network Interface and the Network Interface. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the association between the Network Interface and the Network Security Group. +* `update` - (Defaults to 30 minutes) Used when updating the association between the Network Interface and the Network Security Group. +* `read` - (Defaults to 5 minutes) Used when retrieving the association between the Network Interface and the Network Security Group. +* `delete` - (Defaults to 30 minutes) Used when deleting the association between the Network Interface and the Network Security Group. + +## Import + +Associations between Network Interfaces and Network Security Group can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_network_interface_security_group_association.association1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/microsoft.network/networkInterfaces/nic1/ipConfigurations/example|/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Network/networkSecurityGroups/group1 +``` + +-> **NOTE:** This ID is specific to Terraform - and is of the format `{networkInterfaceId}/|{networkSecurityGroupId}`. From 1a18b602c780be2853356b258a62176b46d85672 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 08:38:26 +0100 Subject: [PATCH 144/498] r/network_interface: applying properties managed in other resources to this resource --- .../network/resource_arm_network_interface.go | 203 +++++++++++++----- 1 file changed, 144 insertions(+), 59 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 0789e212bfea3..a6b1bd6d987c3 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -51,12 +51,6 @@ func resourceArmNetworkInterface() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - "network_security_group_id": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: azure.ValidateResourceIDOrEmpty, - }, - "ip_configuration": { Type: schema.TypeList, Required: true, @@ -218,23 +212,6 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) locks.ByName(name, networkInterfaceResourceName) defer locks.UnlockByName(name, networkInterfaceResourceName) - if v, ok := d.GetOk("network_security_group_id"); ok { - nsgId := v.(string) - properties.NetworkSecurityGroup = &network.SecurityGroup{ - ID: &nsgId, - } - - parsedNsgID, err := azure.ParseAzureResourceID(nsgId) - if err != nil { - return fmt.Errorf("Error parsing Network Security Group ID %q: %+v", nsgId, err) - } - - networkSecurityGroupName := parsedNsgID.Path["networkSecurityGroups"] - - locks.ByName(networkSecurityGroupName, networkSecurityGroupResourceName) - defer locks.UnlockByName(networkSecurityGroupName, networkSecurityGroupResourceName) - } - dns, hasDns := d.GetOk("dns_servers") nameLabel, hasNameLabel := d.GetOk("internal_dns_name_label") if hasDns || hasNameLabel { @@ -259,7 +236,7 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) if err != nil { return fmt.Errorf("Error expanding `ip_configuration`: %+v", err) } - lockingDetails, err := determineResourcesToLockFromIPConfiguration(&ipConfigs) + lockingDetails, err := determineResourcesToLockFromIPConfiguration(ipConfigs) if err != nil { return fmt.Errorf("Error determing locking details: %+v", err) } @@ -267,8 +244,8 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) lockingDetails.lock() defer lockingDetails.unlock() - if len(ipConfigs) > 0 { - properties.IPConfigurations = &ipConfigs + if len(*ipConfigs) > 0 { + properties.IPConfigurations = ipConfigs } iface := network.Interface{ @@ -320,6 +297,13 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) } + if existing.InterfacePropertiesFormat == nil { + return fmt.Errorf("Error retrieving Network Interface %q (Resource Group %q): `properties` was nil", name, resourceGroup) + } + + // then pull out things we need to lock on + info := parseFieldsFromNetworkInterface(*existing.InterfacePropertiesFormat) + location := azure.NormalizeLocation(d.Get("location").(string)) update := network.Interface{ Name: utils.String(name), @@ -360,7 +344,7 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) if err != nil { return fmt.Errorf("Error expanding `ip_configuration`: %+v", err) } - lockingDetails, err := determineResourcesToLockFromIPConfiguration(&ipConfigs) + lockingDetails, err := determineResourcesToLockFromIPConfiguration(ipConfigs) if err != nil { return fmt.Errorf("Error determing locking details: %+v", err) } @@ -368,20 +352,12 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) lockingDetails.lock() defer lockingDetails.unlock() - update.InterfacePropertiesFormat.IPConfigurations = &ipConfigs - } else { - update.InterfacePropertiesFormat.IPConfigurations = existing.InterfacePropertiesFormat.IPConfigurations - } + // then map the fields managed in other resources back + ipConfigs = mapFieldsToNetworkInterface(ipConfigs, info) - if d.HasChange("network_security_group_id") { - update.InterfacePropertiesFormat.NetworkSecurityGroup = &network.SecurityGroup{} - if networkSecurityGroupId := d.Get("network_security_group_id").(string); networkSecurityGroupId != "" { - update.InterfacePropertiesFormat.NetworkSecurityGroup.ID = utils.String(networkSecurityGroupId) - } else { - update.InterfacePropertiesFormat.NetworkSecurityGroup = nil - } + update.InterfacePropertiesFormat.IPConfigurations = ipConfigs } else { - update.InterfacePropertiesFormat.NetworkSecurityGroup = existing.InterfacePropertiesFormat.NetworkSecurityGroup + update.InterfacePropertiesFormat.IPConfigurations = existing.InterfacePropertiesFormat.IPConfigurations } if d.HasChange("tags") { @@ -389,6 +365,9 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) update.Tags = tags.Expand(tagsRaw) } + // this can be managed in another resource, so just port it over + update.InterfacePropertiesFormat.NetworkSecurityGroup = existing.InterfacePropertiesFormat.NetworkSecurityGroup + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, update) if err != nil { return fmt.Errorf("Error updating Network Interface %q (Resource Group %q): %+v", name, resourceGroup, err) @@ -459,10 +438,6 @@ func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) e } } - networkSecurityGroupId := "" - if props.NetworkSecurityGroup != nil && props.NetworkSecurityGroup.ID != nil { - networkSecurityGroupId = *props.NetworkSecurityGroup.ID - } virtualMachineId := "" if props.VirtualMachine != nil && props.VirtualMachine.ID != nil { virtualMachineId = *props.VirtualMachine.ID @@ -480,7 +455,6 @@ func resourceArmNetworkInterfaceRead(d *schema.ResourceData, meta interface{}) e d.Set("enable_accelerated_networking", resp.EnableAcceleratedNetworking) d.Set("internal_dns_name_label", internalDnsNameLabel) d.Set("mac_address", props.MacAddress) - d.Set("network_security_group_id", networkSecurityGroupId) d.Set("private_ip_address", primaryPrivateIPAddress) d.Set("virtual_machine_id", virtualMachineId) @@ -527,19 +501,6 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) } props := *existing.InterfacePropertiesFormat - if props.NetworkSecurityGroup != nil && props.NetworkSecurityGroup.ID != nil { - networkSecurityGroupId := *props.NetworkSecurityGroup.ID - parsedNsgID, err := azure.ParseAzureResourceID(networkSecurityGroupId) - if err != nil { - return fmt.Errorf("Error parsing Network Security Group ID %q: %+v", networkSecurityGroupId, err) - } - - networkSecurityGroupName := parsedNsgID.Path["networkSecurityGroups"] - - locks.ByName(networkSecurityGroupName, networkSecurityGroupResourceName) - defer locks.UnlockByName(networkSecurityGroupName, networkSecurityGroupResourceName) - } - lockingDetails, err := determineResourcesToLockFromIPConfiguration(props.IPConfigurations) if err != nil { return fmt.Errorf("Error determing locking details: %+v", err) @@ -560,7 +521,7 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) return nil } -func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.InterfaceIPConfiguration, error) { +func expandNetworkInterfaceIPConfigurations(input []interface{}) (*[]network.InterfaceIPConfiguration, error) { ipConfigs := make([]network.InterfaceIPConfiguration, 0) for _, configRaw := range input { @@ -622,7 +583,7 @@ func expandNetworkInterfaceIPConfigurations(input []interface{}) ([]network.Inte } } - return ipConfigs, nil + return &ipConfigs, nil } func flattenNetworkInterfaceIPConfigurations(input *[]network.InterfaceIPConfiguration) []interface{} { @@ -696,3 +657,127 @@ func flattenNetworkInterfaceDnsServers(input *[]string) []string { } return output } + +type networkInterfaceUpdateInformation struct { + applicationGatewayBackendAddressPoolIDs []string + applicationSecurityGroupIDs []string + loadBalancerBackendAddressPoolIDs []string + loadBalancerInboundNatRuleIDs []string + networkSecurityGroupID string +} + +func parseFieldsFromNetworkInterface(input network.InterfacePropertiesFormat) networkInterfaceUpdateInformation { + networkSecurityGroupId := "" + if input.NetworkSecurityGroup != nil && input.NetworkSecurityGroup.ID != nil { + networkSecurityGroupId = *input.NetworkSecurityGroup.ID + } + + var mapToSlice = func(input map[string]struct{}) []string { + output := make([]string, 0) + + for id, _ := range input { + output = append(output, id) + } + + return output + } + + applicationSecurityGroupIds := make(map[string]struct{}, 0) + applicationGatewayBackendAddressPoolIds := make(map[string]struct{}, 0) + loadBalancerBackendAddressPoolIds := make(map[string]struct{}, 0) + loadBalancerInboundNatRuleIds := make(map[string]struct{}, 0) + + if input.IPConfigurations != nil { + for _, v := range *input.IPConfigurations { + if v.InterfaceIPConfigurationPropertiesFormat == nil { + continue + } + + props := *v.InterfaceIPConfigurationPropertiesFormat + if props.ApplicationSecurityGroups != nil { + for _, asg := range *props.ApplicationSecurityGroups { + if asg.ID != nil { + applicationSecurityGroupIds[*asg.ID] = struct{}{} + } + } + } + + if props.ApplicationGatewayBackendAddressPools != nil { + for _, pool := range *props.ApplicationGatewayBackendAddressPools { + if pool.ID != nil { + applicationGatewayBackendAddressPoolIds[*pool.ID] = struct{}{} + } + } + } + + if props.LoadBalancerBackendAddressPools != nil { + for _, pool := range *props.LoadBalancerBackendAddressPools { + if pool.ID != nil { + loadBalancerBackendAddressPoolIds[*pool.ID] = struct{}{} + } + } + } + + if props.LoadBalancerInboundNatRules != nil { + for _, rule := range *props.LoadBalancerInboundNatRules { + if rule.ID != nil { + loadBalancerInboundNatRuleIds[*rule.ID] = struct{}{} + } + } + } + } + } + + return networkInterfaceUpdateInformation{ + applicationGatewayBackendAddressPoolIDs: mapToSlice(applicationGatewayBackendAddressPoolIds), + applicationSecurityGroupIDs: mapToSlice(applicationSecurityGroupIds), + loadBalancerBackendAddressPoolIDs: mapToSlice(loadBalancerBackendAddressPoolIds), + loadBalancerInboundNatRuleIDs: mapToSlice(loadBalancerInboundNatRuleIds), + networkSecurityGroupID: networkSecurityGroupId, + } +} + +func mapFieldsToNetworkInterface(input *[]network.InterfaceIPConfiguration, info networkInterfaceUpdateInformation) *[]network.InterfaceIPConfiguration { + output := input + + applicationSecurityGroups := make([]network.ApplicationSecurityGroup, 0) + for _, id := range info.applicationSecurityGroupIDs { + applicationSecurityGroups = append(applicationSecurityGroups, network.ApplicationSecurityGroup{ + ID: utils.String(id), + }) + } + + applicationGatewayBackendAddressPools := make([]network.ApplicationGatewayBackendAddressPool, 0) + for _, id := range info.applicationGatewayBackendAddressPoolIDs { + applicationGatewayBackendAddressPools = append(applicationGatewayBackendAddressPools, network.ApplicationGatewayBackendAddressPool{ + ID: utils.String(id), + }) + } + + loadBalancerBackendAddressPools := make([]network.BackendAddressPool, 0) + for _, id := range info.loadBalancerBackendAddressPoolIDs { + loadBalancerBackendAddressPools = append(loadBalancerBackendAddressPools, network.BackendAddressPool{ + ID: utils.String(id), + }) + } + + loadBalancerInboundNatRules := make([]network.InboundNatRule, 0) + for _, id := range info.loadBalancerInboundNatRuleIDs { + loadBalancerInboundNatRules = append(loadBalancerInboundNatRules, network.InboundNatRule{ + ID: utils.String(id), + }) + } + + for _, config := range *output { + if config.InterfaceIPConfigurationPropertiesFormat == nil { + continue + } + + config.ApplicationSecurityGroups = &applicationSecurityGroups + config.ApplicationGatewayBackendAddressPools = &applicationGatewayBackendAddressPools + config.LoadBalancerBackendAddressPools = &loadBalancerBackendAddressPools + config.LoadBalancerInboundNatRules = &loadBalancerInboundNatRules + } + + return output +} From a99d908e20a083d33262a217e65d20b77ec44f70 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 08:40:41 +0100 Subject: [PATCH 145/498] spelling --- azurerm/internal/azuresdkhacks/notes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/azuresdkhacks/notes.go b/azurerm/internal/azuresdkhacks/notes.go index a1612ed8dad82..f75c0ac1c827c 100644 --- a/azurerm/internal/azuresdkhacks/notes.go +++ b/azurerm/internal/azuresdkhacks/notes.go @@ -1,11 +1,11 @@ package azuresdkhacks // There's a functional difference that exists between the Azure SDK for Go and Azure Resource Manager API -// where when performing a delta update unchanged fields are omited from the response when they could +// where when performing a delta update unchanged fields are omitted from the response when they could // also have a legitimate value of `null` (to remove/disable a sub-block). // // Ultimately the Azure SDK for Go has opted to serialise structs with `json:"name,omitempty"` which -// means that this value will be omited if nil to allow for delta updates - however this means there's +// means that this value will be omitted if nil to allow for delta updates - however this means there's // no means of removing/resetting a value of a nested object once provided since a `nil` object will be // reset // From be435833dfc0df7d0467fabe88b96eedd2bf8616 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 09:32:30 +0100 Subject: [PATCH 146/498] updating to include #5710 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1804f23113323..ec7b41bad612d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,16 @@ BREAKING CHANGES: * `azurerm_relay_namespace` - removing the `sku` block in favour of the `sku_name` field [GH-5719] * `azurerm_scheduler_job` - This resource has been removed since it was deprecated [GH-5712] * `azurerm_scheduler_job_collection` - This resource has been removed since it was deprecated [GH-5712] +* `azurerm_storage_account` - removing the deprecated `account_type` field [GH-5710] +* `azurerm_storage_account` - removing the deprecated `enable_advanced_threat_protection` field [GH-5710] +* `azurerm_storage_blob` - making the `type` field case-sensitive [GH-5710] +* `azurerm_storage_blob` - removing the deprecated `attempts` field [GH-5710] +* `azurerm_storage_blob` - removing the deprecated `resource_group_name` field [GH-5710] +* `azurerm_storage_container` - removing the deprecated `resource_group_name` field [GH-5710] +* `azurerm_storage_container` - removing the deprecated `properties` block [GH-5710] +* `azurerm_storage_queue` - removing the deprecated `resource_group_name` field [GH-5710] +* `azurerm_storage_share` - removing the deprecated `resource_group_name` field [GH-5710] +* `azurerm_storage_table` - removing the deprecated `resource_group_name` field [GH-5710] IMPROVEMENTS: From cad4978e7f7bd6b670778660dff325a81d84e9b4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 11:15:27 +0100 Subject: [PATCH 147/498] r/network_interface: updating the tests / rewriting the docs --- .../network/resource_arm_network_interface.go | 10 +- .../resource_arm_network_interface_test.go | 839 +++++++----------- .../docs/r/network_interface.html.markdown | 83 +- 3 files changed, 361 insertions(+), 571 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index a6b1bd6d987c3..899d4bbfba607 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -112,14 +112,13 @@ func resourceArmNetworkInterface() *schema.Resource { }, "dns_servers": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: validation.StringIsNotEmpty, }, - Set: schema.HashString, }, "enable_accelerated_networking": { @@ -218,14 +217,13 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) dnsSettings := network.InterfaceDNSSettings{} if hasDns { - dnsRaw := dns.(*schema.Set).List() + dnsRaw := dns.([]interface{}) dns := expandNetworkInterfaceDnsServers(dnsRaw) dnsSettings.DNSServers = &dns } if hasNameLabel { - name_label := nameLabel.(string) - dnsSettings.InternalDNSNameLabel = &name_label + dnsSettings.InternalDNSNameLabel = utils.String(nameLabel.(string)) } properties.DNSSettings = &dnsSettings @@ -316,7 +314,7 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) update.InterfacePropertiesFormat.DNSSettings = &network.InterfaceDNSSettings{} } - dnsServersRaw := d.Get("dns_servers").(*schema.Set).List() + dnsServersRaw := d.Get("dns_servers").([]interface{}) dnsServers := expandNetworkInterfaceDnsServers(dnsServersRaw) update.InterfacePropertiesFormat.DNSSettings.DNSServers = &dnsServers diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go index 05170566f5b45..3ec528f8615a5 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go @@ -12,7 +12,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func TestAccAzureRMNetworkInterface_disappears(t *testing.T) { +func TestAccAzureRMNetworkInterface_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -23,20 +23,14 @@ func TestAccAzureRMNetworkInterface_disappears(t *testing.T) { Config: testAccAzureRMNetworkInterface_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - testCheckAzureRMNetworkInterfaceDisappears(data.ResourceName), ), - ExpectNonEmptyPlan: true, }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - +func TestAccAzureRMNetworkInterface_disappears(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -47,17 +41,15 @@ func TestAccAzureRMNetworkInterface_requiresImport(t *testing.T) { Config: testAccAzureRMNetworkInterface_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + testCheckAzureRMNetworkInterfaceDisappears(data.ResourceName), ), - }, - { - Config: testAccAzureRMNetworkInterface_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_network_interface"), + ExpectNonEmptyPlan: true, }, }, }) } -func TestAccAzureRMNetworkInterface_basic(t *testing.T) { +func TestAccAzureRMNetworkInterface_dnsServers(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -65,7 +57,14 @@ func TestAccAzureRMNetworkInterface_basic(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_basic(data), + Config: testAccAzureRMNetworkInterface_dnsServers(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterface_dnsServersUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), ), @@ -75,108 +74,122 @@ func TestAccAzureRMNetworkInterface_basic(t *testing.T) { }) } -func TestAccAzureRMNetworkInterface_setNetworkSecurityGroupId(t *testing.T) { +func TestAccAzureRMNetworkInterface_enableAcceleratedNetworking(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_basic(data), + // Enabled + Config: testAccAzureRMNetworkInterface_enableAcceleratedNetworking(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), ), }, + data.ImportStep(), + { + // Disabled + Config: testAccAzureRMNetworkInterface_enableAcceleratedNetworking(data, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), { - Config: testAccAzureRMNetworkInterface_basicWithNetworkSecurityGroup(data), + // Enabled + Config: testAccAzureRMNetworkInterface_enableAcceleratedNetworking(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "network_security_group_id"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_removeNetworkSecurityGroupId(t *testing.T) { +func TestAccAzureRMNetworkInterface_enableIPForwarding(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_basicWithNetworkSecurityGroup(data), + // Enabled + Config: testAccAzureRMNetworkInterface_enableIPForwarding(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), ), }, + data.ImportStep(), { - Config: testAccAzureRMNetworkInterface_basic(data), + // Disabled + Config: testAccAzureRMNetworkInterface_enableIPForwarding(data, false), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + // Enabled + Config: testAccAzureRMNetworkInterface_enableIPForwarding(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "network_security_group_id", ""), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_multipleSubnets(t *testing.T) { +func TestAccAzureRMNetworkInterface_internalDomainNameLabel(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_multipleSubnets(data), + Config: testAccAzureRMNetworkInterface_internalDomainNameLabel(data, "1"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterface_internalDomainNameLabel(data, "2"), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.#", "2"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_multipleSubnetsPrimary(t *testing.T) { +func TestAccAzureRMNetworkInterface_ipv6(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_multipleSubnets(data), + Config: testAccAzureRMNetworkInterface_ipv6(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.primary", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.name", "testconfiguration1"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.primary", "false"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.name", "testconfiguration2"), - ), - }, - { - Config: testAccAzureRMNetworkInterface_multipleSubnetsUpdatedPrimary(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.primary", "true"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.name", "testconfiguration2"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.primary", "false"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.name", "testconfiguration1"), + resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), + resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.private_ip_address_version", "IPv6"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_enableIPForwarding(t *testing.T) { +func TestAccAzureRMNetworkInterface_multipleIPConfigurations(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -184,17 +197,17 @@ func TestAccAzureRMNetworkInterface_enableIPForwarding(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_ipForwarding(data), + Config: testAccAzureRMNetworkInterface_multipleIPConfigurations(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_ip_forwarding", "true"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_enableAcceleratedNetworking(t *testing.T) { +func TestAccAzureRMNetworkInterface_multipleIPConfigurationsSecondaryAsPrimary(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -202,17 +215,17 @@ func TestAccAzureRMNetworkInterface_enableAcceleratedNetworking(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_acceleratedNetworking(data), + Config: testAccAzureRMNetworkInterface_multipleIPConfigurationsSecondaryAsPrimary(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "enable_accelerated_networking", "true"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_withTags(t *testing.T) { +func TestAccAzureRMNetworkInterface_publicIP(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -220,27 +233,36 @@ func TestAccAzureRMNetworkInterface_withTags(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_withTags(data), + Config: testAccAzureRMNetworkInterface_publicIP(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterface_publicIPRemoved(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "2"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "Production"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.cost_center", "MSFT"), ), }, + data.ImportStep(), { - Config: testAccAzureRMNetworkInterface_withTagsUpdate(data), + Config: testAccAzureRMNetworkInterface_publicIP(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "1"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.environment", "staging"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_IPAddressesBug1286(t *testing.T) { +func TestAccAzureRMNetworkInterface_requiresImport(t *testing.T) { + if !features.ShouldResourcesBeImported() { + t.Skip("Skipping since resources aren't required to be imported") + return + } + data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -248,75 +270,81 @@ func TestAccAzureRMNetworkInterface_IPAddressesBug1286(t *testing.T) { CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_withIPAddresses(data), + Config: testAccAzureRMNetworkInterface_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "ip_configuration.0.private_ip_address"), - resource.TestCheckResourceAttrSet(data.ResourceName, "ip_configuration.0.public_ip_address_id"), ), }, { - Config: testAccAzureRMNetworkInterface_withIPAddressesUpdate(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "ip_configuration.0.private_ip_address"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.public_ip_address_id", ""), - ), + Config: testAccAzureRMNetworkInterface_requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_network_interface"), }, }, }) } -func TestAccAzureRMNetworkInterface_IPAddressesFeature2543(t *testing.T) { +func TestAccAzureRMNetworkInterface_static(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_withIPv6Addresses(data), + Config: testAccAzureRMNetworkInterface_static(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMNetworkInterfaceExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.0.private_ip_address_version", "IPv4"), - resource.TestCheckResourceAttr(data.ResourceName, "ip_configuration.1.private_ip_address_version", "IPv6"), - resource.TestCheckResourceAttrSet(data.ResourceName, "private_ip_address"), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_bug7986(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_network_interface", "test1") - +func TestAccAzureRMNetworkInterface_tags(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_bug7986(data), + Config: testAccAzureRMNetworkInterface_tags(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterface_tagsUpdated(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMNetworkInterfaceExists("azurerm_network_interface.test1"), - testCheckAzureRMNetworkInterfaceExists("azurerm_network_interface.test2"), + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMNetworkInterface_importPublicIP(t *testing.T) { +func TestAccAzureRMNetworkInterface_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_network_interface", "test") - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMNetworkInterfaceDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMNetworkInterface_publicIP(data), + Config: testAccAzureRMNetworkInterface_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMNetworkInterface_multipleIPConfigurations(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkInterfaceExists(data.ResourceName), + ), }, data.ImportStep(), }, @@ -335,11 +363,7 @@ func testCheckAzureRMNetworkInterfaceExists(resourceName string) resource.TestCh } name := 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 availability set: %q", name) - } - + resourceGroup := rs.Primary.Attributes["resource_group_name"] resp, err := client.Get(ctx, resourceGroup, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { @@ -365,10 +389,7 @@ func testCheckAzureRMNetworkInterfaceDisappears(resourceName string) resource.Te } name := 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 availability set: %q", name) - } + resourceGroup := rs.Primary.Attributes["resource_group_name"] future, err := client.Delete(ctx, resourceGroup, name) if err != nil { @@ -411,580 +432,350 @@ func testCheckAzureRMNetworkInterfaceDestroy(s *terraform.State) error { } func testAccAzureRMNetworkInterface_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMNetworkInterface_basic(data) +func testAccAzureRMNetworkInterface_dnsServers(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` %s -resource "azurerm_network_interface" "import" { - name = "${azurerm_network_interface.test.name}" - location = "${azurerm_network_interface.test.location}" - resource_group_name = "${azurerm_network_interface.test.resource_group_name}" +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + dns_servers = [ + "10.0.0.5", + "10.0.0.6" + ] ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, template) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_basicWithNetworkSecurityGroup(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_dnsServersUpdated(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} - -resource "azurerm_network_security_group" "test" { - name = "acctestnsg-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_security_group_id = "${azurerm_network_security_group.test.id}" + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + dns_servers = [ + "10.0.0.6", + "10.0.0.5" + ] ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_multipleSubnets(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_enableAcceleratedNetworking(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - primary = true - } + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + enable_accelerated_networking = %t ip_configuration { - name = "testconfiguration2" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger, enabled) } -func testAccAzureRMNetworkInterface_multipleSubnetsUpdatedPrimary(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_enableIPForwarding(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration2" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - primary = true - } + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + enable_ip_forwarding = %t ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger, enabled) } -func testAccAzureRMNetworkInterface_ipForwarding(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_internalDomainNameLabel(data acceptance.TestData, suffix string) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - enable_ip_forwarding = true + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + internal_dns_name_label = "acctestni-%s-%s" ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger, suffix, data.RandomString) } -func testAccAzureRMNetworkInterface_acceleratedNetworking(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_ipv6(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - enable_ip_forwarding = false - enable_accelerated_networking = true + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" + primary = true } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} -func testAccAzureRMNetworkInterface_withTags(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" + ip_configuration { + name = "secondary" + private_ip_address_allocation = "Dynamic" + private_ip_address_version = "IPv6" + } } - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +`, template, data.RandomInteger) } -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +func testAccAzureRMNetworkInterface_multipleIPConfigurations(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) + return fmt.Sprintf(` +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" + primary = true } - tags = { - environment = "Production" - cost_center = "MSFT" + ip_configuration { + name = "secondary" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_withTagsUpdate(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_multipleIPConfigurationsSecondaryAsPrimary(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } - tags = { - environment = "staging" + ip_configuration { + name = "secondary" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + primary = true } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_withIPAddresses(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_publicIP(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_publicIPTemplate(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} - -resource "azurerm_public_ip" "test" { - name = "test-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Static" - domain_name_label = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Static" - private_ip_address = "10.0.2.9" - public_ip_address_id = "${azurerm_public_ip.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.test.id } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_withIPAddressesUpdate(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_publicIPRemoved(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_publicIPTemplate(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} - -resource "azurerm_public_ip" "test" { - name = "test-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Static" - domain_name_label = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_network_interface" "test" { name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_withIPv6Addresses(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_publicIPTemplate(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +%s resource "azurerm_public_ip" "test" { - name = "test-%d" + name = "acctestpublicip-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" allocation_method = "Static" - domain_name_label = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_network_interface" "test" { - name = "acctestni-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "dynamic" - primary = true - } - - ip_configuration { - name = "testconfiguration2" - private_ip_address_version = "IPv6" - private_ip_address_allocation = "dynamic" - } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_bug7986(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_basic(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest-%d" - location = "%s" -} +%s -resource "azurerm_network_security_group" "test" { - name = "acctest-%d-nsg" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +resource "azurerm_network_interface" "import" { + name = azurerm_network_interface.test.name + location = azurerm_network_interface.test.location + resource_group_name = azurerm_network_interface.test.resource_group_name - tags = { - environment = "Production" + ip_configuration { + name = "primary" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Dynamic" } } - -resource "azurerm_network_security_rule" "test1" { - name = "test1" - priority = 101 - direction = "Outbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "*" - destination_address_prefix = "*" - resource_group_name = "${azurerm_resource_group.test.name}" - network_security_group_name = "${azurerm_network_security_group.test.name}" +`, template) } -resource "azurerm_network_security_rule" "test2" { - name = "test2" - priority = 102 - direction = "Outbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "*" - destination_address_prefix = "*" - resource_group_name = "${azurerm_resource_group.test.name}" - network_security_group_name = "${azurerm_network_security_group.test.name}" -} +func testAccAzureRMNetworkInterface_static(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) + return fmt.Sprintf(` +%s -resource "azurerm_public_ip" "test" { - name = "acctest-%d-pip" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Dynamic" +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name - tags = { - environment = "Production" + ip_configuration { + name = "primary" + subnet_id = azurerm_subnet.test.id + private_ip_address_allocation = "Static" + private_ip_address = "10.0.2.15" } } - -resource "azurerm_virtual_network" "test" { - name = "acctest-%d-vn" - address_space = ["10.0.0.0/16"] - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" +`, template, data.RandomInteger) } -resource "azurerm_subnet" "test" { - name = "first" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" -} +func testAccAzureRMNetworkInterface_tags(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) + return fmt.Sprintf(` +%s -resource "azurerm_network_interface" "test1" { - name = "acctest-%d-nic1" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } tags = { - environment = "staging" + Hello = "World" } } +`, template, data.RandomInteger) +} -resource "azurerm_network_interface" "test2" { - name = "acctest-%d-nic2" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +func testAccAzureRMNetworkInterface_tagsUpdated(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_network_interface" "test" { + name = "acctestni-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" + name = "primary" + subnet_id = azurerm_subnet.test.id private_ip_address_allocation = "Dynamic" } tags = { - environment = "staging" + Hello = "World" + Elephants = "Five" } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, data.RandomInteger) } -func testAccAzureRMNetworkInterface_publicIP(data acceptance.TestData) string { +func testAccAzureRMNetworkInterface_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -993,36 +784,16 @@ resource "azurerm_resource_group" "test" { resource "azurerm_virtual_network" "test" { name = "acctestvn-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" } resource "azurerm_subnet" "test" { - name = "testsubnet" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" } - -resource "azurerm_public_ip" "testext" { - name = "acctestip-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Static" -} - -resource "azurerm_network_interface" "test" { - name = "acctestnic-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.testext.id}" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index d2045d5c50d6b..97e05d62d827f 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -3,50 +3,46 @@ subcategory: "Network" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_network_interface" description: |- - Manages a Network Interface located in a Virtual Network, usually attached to a Virtual Machine. + Manages a Network Interface. --- # azurerm_network_interface -Manages a Network Interface located in a Virtual Network, usually attached to a Virtual Machine. +Manages a Network Interface. ## Example Usage ```hcl resource "azurerm_resource_group" "example" { - name = "acceptanceTestResourceGroup1" - location = "West US" + name = "example-resources" + location = "West Europe" } resource "azurerm_virtual_network" "example" { - name = "acceptanceTestVirtualNetwork1" + name = "example-network" address_space = ["10.0.0.0/16"] location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name } resource "azurerm_subnet" "example" { - name = "testsubnet" + name = "internal" resource_group_name = azurerm_resource_group.example.name virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.0.2.0/24" } resource "azurerm_network_interface" "example" { - name = "acceptanceTestNetworkInterface1" + name = "example-nic" location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name ip_configuration { - name = "testconfiguration1" + name = "internal" subnet_id = azurerm_subnet.example.id private_ip_address_allocation = "Dynamic" } - - tags = { - environment = "staging" - } } ``` @@ -54,54 +50,79 @@ resource "azurerm_network_interface" "example" { The following arguments are supported: -* `name` - (Required) The name of the network interface. Changing this forces a new resource to be created. +* `ip_configuration` - (Required) One or more `ip_configuration` blocks as defined below. + +* `location` - (Required) The location where the Network Interface should exist. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to create the network interface. Changing this forces a new resource to be created. +* `name` - (Required) The name of the Network Interface. Changing this forces a new resource to be created. -* `location` - (Required) The location/region where the network interface is created. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the Resource Group in which to create the Network Interface. Changing this forces a new resource to be created. + +--- -* `network_security_group_id` - (Optional) The ID of the Network Security Group to associate with the network interface. +* `dns_servers` - (Optional) A list of IP Addresses defining the DNS Servers which should be used for this Network Interface. -* `internal_dns_name_label` - (Optional) Relative DNS name for this NIC used for internal communications between VMs in the same VNet +-> **Note:** Configuring DNS Servers on the Network Interface will override the DNS Servers defined on the Virtual Network. -* `enable_ip_forwarding` - (Optional) Enables IP Forwarding on the NIC. Defaults to `false`. +* `enable_ip_forwarding` - (Optional) Should IP Forwarding be enabled? Defaults to `false`. -* `enable_accelerated_networking` - (Optional) Enables Azure Accelerated Networking using SR-IOV. Only certain VM instance sizes are supported. Refer to [Create a Virtual Machine with Accelerated Networking](https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli). Defaults to `false`. +* `enable_accelerated_networking` - (Optional) Should Accelerated Networking be enabled? Defaults to `false`. -~> **NOTE:** when using Accelerated Networking in an Availability Set - the Availability Set must be deployed on an Accelerated Networking enabled cluster. +-> **Note:** Only certain Virtual Machine sizes are supported for Accelerated Networking - [more information can be found in this document](https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli). -* `dns_servers` - (Optional) List of DNS servers IP addresses to use for this NIC, overrides the VNet-level server list +-> **Note:** To use Accelerated Networking in an Availability Set, the Availability Set must be deployed onto an Accelerated Networking enabled cluster. -* `ip_configuration` - (Required) One or more `ip_configuration` associated with this NIC as documented below. +* `internal_dns_name_label` - (Optional) The (relative) DNS Name used for internal communications between Virtual Machines in the same Virtual Network. * `tags` - (Optional) A mapping of tags to assign to the resource. -The `ip_configuration` block supports: +--- -* `name` - (Required) User-defined name of the IP. +The `ip_configuration` block supports the following: -* `subnet_id` - (Optional) Reference to a subnet in which this NIC has been created. Required when `private_ip_address_version` is IPv4. +* `name` - (Required) A name used for this IP Configuration. -* `private_ip_address` - (Optional) Static IP Address. +* `subnet_id` - (Optional) The ID of the Subnet where this Network Interface should be located in. -* `private_ip_address_allocation` - (Required) Defines how a private IP address is assigned. Options are Static or Dynamic. +-> **Note:** This is required when `private_ip_address_version` is set to `IPv4`. * `private_ip_address_version` - (Optional) The IP Version to use. Possible values are `IPv4` or `IPv6`. Defaults to `IPv4`. +* `private_ip_address_allocation` - (Required) The allocation method used for the Private IP Address. Possible values are `Dynamic` and `Static`. + +~> **Note:** Azure does not assign a Dynamic IP Address until the Network Interface is attached to a running Virtual Machine (or other resource) + * `public_ip_address_id` - (Optional) Reference to a Public IP Address to associate with this NIC -* `primary` - (Optional) Is this the Primary Network Interface? If set to `true` this should be the first `ip_configuration` in the array. +* `primary` - (Optional) Is this the Primary IP Configuration? Must be `true` for the first `ip_configuration` when multiple are specified. Defaults to `false`. + +When `private_ip_address_allocation` is set to `Static` the following fields can be configured: + +* `private_ip_address` - (Optional) The Static IP Address which should be used. + +When `private_ip_address_version` is set to `IPv4` the following fields can be configured: + +* `subnet_id` - (Required) The ID of the Subnet where this Network Interface should be located in. ## Attributes Reference The following attributes are exported: +* `applied_dns_servers` - If the Virtual Machine using this Network Interface is part of an Availability Set, then this list will have the union of all DNS servers from all Network Interfaces that are part of the Availability Set. + * `id` - The ID of the Network Interface. -* `mac_address` - The media access control (MAC) address of the network interface. + +* `mac_address` - The Media Access Control (MAC) Address of the Network Interface. + * `private_ip_address` - The first private IP address of the network interface. + +~> **Note:** If a `Dynamic` allocation method is used Azure will not allocate an IP Address until the Network Interface is attached to a running resource (such as a Virtual Machine). + * `private_ip_addresses` - The private IP addresses of the network interface. -* `virtual_machine_id` - Reference to a VM with which this NIC has been associated. -* `applied_dns_servers` - If the VM that uses this NIC is part of an Availability Set, then this list will have the union of all DNS servers from all NICs that are part of the Availability Set + +~> **Note:** If a `Dynamic` allocation method is used Azure will not allocate an IP Address until the Network Interface is attached to a running resource (such as a Virtual Machine). + +* `virtual_machine_id` - The ID of the Virtual Machine which this Network Interface is connected to. ## Timeouts From 3ececb9672b0033770c6b19c7a7ea985bbab8839 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 11:18:02 +0100 Subject: [PATCH 148/498] r/network_interface: conditionally updating the nics only for ipv4 configurations --- .../services/network/network_interface.go | 134 ++++++++++++++++++ .../network/resource_arm_network_interface.go | 124 ---------------- 2 files changed, 134 insertions(+), 124 deletions(-) create mode 100644 azurerm/internal/services/network/network_interface.go diff --git a/azurerm/internal/services/network/network_interface.go b/azurerm/internal/services/network/network_interface.go new file mode 100644 index 0000000000000..dd29bb6aa188e --- /dev/null +++ b/azurerm/internal/services/network/network_interface.go @@ -0,0 +1,134 @@ +package network + +import ( + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-09-01/network" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +type networkInterfaceUpdateInformation struct { + applicationGatewayBackendAddressPoolIDs []string + applicationSecurityGroupIDs []string + loadBalancerBackendAddressPoolIDs []string + loadBalancerInboundNatRuleIDs []string + networkSecurityGroupID string +} + +func parseFieldsFromNetworkInterface(input network.InterfacePropertiesFormat) networkInterfaceUpdateInformation { + networkSecurityGroupId := "" + if input.NetworkSecurityGroup != nil && input.NetworkSecurityGroup.ID != nil { + networkSecurityGroupId = *input.NetworkSecurityGroup.ID + } + + var mapToSlice = func(input map[string]struct{}) []string { + output := make([]string, 0) + + for id, _ := range input { + output = append(output, id) + } + + return output + } + + applicationSecurityGroupIds := make(map[string]struct{}, 0) + applicationGatewayBackendAddressPoolIds := make(map[string]struct{}, 0) + loadBalancerBackendAddressPoolIds := make(map[string]struct{}, 0) + loadBalancerInboundNatRuleIds := make(map[string]struct{}, 0) + + if input.IPConfigurations != nil { + for _, v := range *input.IPConfigurations { + if v.InterfaceIPConfigurationPropertiesFormat == nil { + continue + } + + props := *v.InterfaceIPConfigurationPropertiesFormat + if props.ApplicationSecurityGroups != nil { + for _, asg := range *props.ApplicationSecurityGroups { + if asg.ID != nil { + applicationSecurityGroupIds[*asg.ID] = struct{}{} + } + } + } + + if props.ApplicationGatewayBackendAddressPools != nil { + for _, pool := range *props.ApplicationGatewayBackendAddressPools { + if pool.ID != nil { + applicationGatewayBackendAddressPoolIds[*pool.ID] = struct{}{} + } + } + } + + if props.LoadBalancerBackendAddressPools != nil { + for _, pool := range *props.LoadBalancerBackendAddressPools { + if pool.ID != nil { + loadBalancerBackendAddressPoolIds[*pool.ID] = struct{}{} + } + } + } + + if props.LoadBalancerInboundNatRules != nil { + for _, rule := range *props.LoadBalancerInboundNatRules { + if rule.ID != nil { + loadBalancerInboundNatRuleIds[*rule.ID] = struct{}{} + } + } + } + } + } + + return networkInterfaceUpdateInformation{ + applicationGatewayBackendAddressPoolIDs: mapToSlice(applicationGatewayBackendAddressPoolIds), + applicationSecurityGroupIDs: mapToSlice(applicationSecurityGroupIds), + loadBalancerBackendAddressPoolIDs: mapToSlice(loadBalancerBackendAddressPoolIds), + loadBalancerInboundNatRuleIDs: mapToSlice(loadBalancerInboundNatRuleIds), + networkSecurityGroupID: networkSecurityGroupId, + } +} + +func mapFieldsToNetworkInterface(input *[]network.InterfaceIPConfiguration, info networkInterfaceUpdateInformation) *[]network.InterfaceIPConfiguration { + output := input + + applicationSecurityGroups := make([]network.ApplicationSecurityGroup, 0) + for _, id := range info.applicationSecurityGroupIDs { + applicationSecurityGroups = append(applicationSecurityGroups, network.ApplicationSecurityGroup{ + ID: utils.String(id), + }) + } + + applicationGatewayBackendAddressPools := make([]network.ApplicationGatewayBackendAddressPool, 0) + for _, id := range info.applicationGatewayBackendAddressPoolIDs { + applicationGatewayBackendAddressPools = append(applicationGatewayBackendAddressPools, network.ApplicationGatewayBackendAddressPool{ + ID: utils.String(id), + }) + } + + loadBalancerBackendAddressPools := make([]network.BackendAddressPool, 0) + for _, id := range info.loadBalancerBackendAddressPoolIDs { + loadBalancerBackendAddressPools = append(loadBalancerBackendAddressPools, network.BackendAddressPool{ + ID: utils.String(id), + }) + } + + loadBalancerInboundNatRules := make([]network.InboundNatRule, 0) + for _, id := range info.loadBalancerInboundNatRuleIDs { + loadBalancerInboundNatRules = append(loadBalancerInboundNatRules, network.InboundNatRule{ + ID: utils.String(id), + }) + } + + for _, config := range *output { + if config.InterfaceIPConfigurationPropertiesFormat == nil { + continue + } + + if config.InterfaceIPConfigurationPropertiesFormat.PrivateIPAddressVersion != network.IPv4 { + continue + } + + config.ApplicationSecurityGroups = &applicationSecurityGroups + config.ApplicationGatewayBackendAddressPools = &applicationGatewayBackendAddressPools + config.LoadBalancerBackendAddressPools = &loadBalancerBackendAddressPools + config.LoadBalancerInboundNatRules = &loadBalancerInboundNatRules + } + + return output +} diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 899d4bbfba607..92f606503b841 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -655,127 +655,3 @@ func flattenNetworkInterfaceDnsServers(input *[]string) []string { } return output } - -type networkInterfaceUpdateInformation struct { - applicationGatewayBackendAddressPoolIDs []string - applicationSecurityGroupIDs []string - loadBalancerBackendAddressPoolIDs []string - loadBalancerInboundNatRuleIDs []string - networkSecurityGroupID string -} - -func parseFieldsFromNetworkInterface(input network.InterfacePropertiesFormat) networkInterfaceUpdateInformation { - networkSecurityGroupId := "" - if input.NetworkSecurityGroup != nil && input.NetworkSecurityGroup.ID != nil { - networkSecurityGroupId = *input.NetworkSecurityGroup.ID - } - - var mapToSlice = func(input map[string]struct{}) []string { - output := make([]string, 0) - - for id, _ := range input { - output = append(output, id) - } - - return output - } - - applicationSecurityGroupIds := make(map[string]struct{}, 0) - applicationGatewayBackendAddressPoolIds := make(map[string]struct{}, 0) - loadBalancerBackendAddressPoolIds := make(map[string]struct{}, 0) - loadBalancerInboundNatRuleIds := make(map[string]struct{}, 0) - - if input.IPConfigurations != nil { - for _, v := range *input.IPConfigurations { - if v.InterfaceIPConfigurationPropertiesFormat == nil { - continue - } - - props := *v.InterfaceIPConfigurationPropertiesFormat - if props.ApplicationSecurityGroups != nil { - for _, asg := range *props.ApplicationSecurityGroups { - if asg.ID != nil { - applicationSecurityGroupIds[*asg.ID] = struct{}{} - } - } - } - - if props.ApplicationGatewayBackendAddressPools != nil { - for _, pool := range *props.ApplicationGatewayBackendAddressPools { - if pool.ID != nil { - applicationGatewayBackendAddressPoolIds[*pool.ID] = struct{}{} - } - } - } - - if props.LoadBalancerBackendAddressPools != nil { - for _, pool := range *props.LoadBalancerBackendAddressPools { - if pool.ID != nil { - loadBalancerBackendAddressPoolIds[*pool.ID] = struct{}{} - } - } - } - - if props.LoadBalancerInboundNatRules != nil { - for _, rule := range *props.LoadBalancerInboundNatRules { - if rule.ID != nil { - loadBalancerInboundNatRuleIds[*rule.ID] = struct{}{} - } - } - } - } - } - - return networkInterfaceUpdateInformation{ - applicationGatewayBackendAddressPoolIDs: mapToSlice(applicationGatewayBackendAddressPoolIds), - applicationSecurityGroupIDs: mapToSlice(applicationSecurityGroupIds), - loadBalancerBackendAddressPoolIDs: mapToSlice(loadBalancerBackendAddressPoolIds), - loadBalancerInboundNatRuleIDs: mapToSlice(loadBalancerInboundNatRuleIds), - networkSecurityGroupID: networkSecurityGroupId, - } -} - -func mapFieldsToNetworkInterface(input *[]network.InterfaceIPConfiguration, info networkInterfaceUpdateInformation) *[]network.InterfaceIPConfiguration { - output := input - - applicationSecurityGroups := make([]network.ApplicationSecurityGroup, 0) - for _, id := range info.applicationSecurityGroupIDs { - applicationSecurityGroups = append(applicationSecurityGroups, network.ApplicationSecurityGroup{ - ID: utils.String(id), - }) - } - - applicationGatewayBackendAddressPools := make([]network.ApplicationGatewayBackendAddressPool, 0) - for _, id := range info.applicationGatewayBackendAddressPoolIDs { - applicationGatewayBackendAddressPools = append(applicationGatewayBackendAddressPools, network.ApplicationGatewayBackendAddressPool{ - ID: utils.String(id), - }) - } - - loadBalancerBackendAddressPools := make([]network.BackendAddressPool, 0) - for _, id := range info.loadBalancerBackendAddressPoolIDs { - loadBalancerBackendAddressPools = append(loadBalancerBackendAddressPools, network.BackendAddressPool{ - ID: utils.String(id), - }) - } - - loadBalancerInboundNatRules := make([]network.InboundNatRule, 0) - for _, id := range info.loadBalancerInboundNatRuleIDs { - loadBalancerInboundNatRules = append(loadBalancerInboundNatRules, network.InboundNatRule{ - ID: utils.String(id), - }) - } - - for _, config := range *output { - if config.InterfaceIPConfigurationPropertiesFormat == nil { - continue - } - - config.ApplicationSecurityGroups = &applicationSecurityGroups - config.ApplicationGatewayBackendAddressPools = &applicationGatewayBackendAddressPools - config.LoadBalancerBackendAddressPools = &loadBalancerBackendAddressPools - config.LoadBalancerInboundNatRules = &loadBalancerInboundNatRules - } - - return output -} From f22151a876a5de465164acf5b291d7104de7d866 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 11:22:02 +0100 Subject: [PATCH 149/498] r/network_interface_application_gateway_association: fixing the tests --- ..._network_interface_application_gateway_association_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go index f2dad35421cd7..2c02e84760305 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_application_gateway_association_test.go @@ -223,7 +223,7 @@ resource "azurerm_network_interface" "test" { ip_configuration { name = "testconfiguration1" - subnet_id = "${azurerm_subnet.frontend.id}" + subnet_id = "${azurerm_subnet.backend.id}" private_ip_address_allocation = "Dynamic" } } @@ -261,7 +261,7 @@ resource "azurerm_network_interface" "test" { ip_configuration { name = "testconfiguration1" - subnet_id = "${azurerm_subnet.frontend.id}" + subnet_id = "${azurerm_subnet.backend.id}" private_ip_address_allocation = "Dynamic" primary = true } From b751e18bf8920fa679ae19a8803c2d7cc867ceea Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 11:27:40 +0100 Subject: [PATCH 150/498] Update azurerm/internal/services/mariadb/resource_arm_mariadb_server.go --- .../internal/services/mariadb/resource_arm_mariadb_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go index 0b8fefbcd8847..e6329f8d340e5 100644 --- a/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go +++ b/azurerm/internal/services/mariadb/resource_arm_mariadb_server.go @@ -186,7 +186,7 @@ func resourceArmMariaDbServerCreateUpdate(d *schema.ResourceData, meta interface sku, err := expandServerSkuName(d.Get("sku_name").(string)) if err != nil { - return fmt.Errorf("error expanding sku_name for PostgreSQL Server %q (Resource Group %q): %v", name, resourceGroup, err) + return fmt.Errorf("error expanding sku_name for MariaDB Server %q (Resource Group %q): %v", name, resourceGroup, err) } skuName := sku.Name From 6e2924e5bb90a7d47555153b2ebe7d0d10fe5786 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 11:28:21 +0100 Subject: [PATCH 151/498] updating to include #5777 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec7b41bad612d..2f7708a81118e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ BREAKING CHANGES: * `azurerm_kubernetes_cluster` - updating the default value for `load_balancer_sku` to `Standard` from `Basic` [GH-5747] * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] +* `azurerm_mariadb_server` - removing the `sku` block since it's been deprecated in favour of the `sku_name` field [GH-5777] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] * `azurerm_notification_hub_namesapce` - removing the `sku` block in favour of the `sku_name` argument [GH-5722] * `azurerm_postgresql_server` - removing the `sku` block which has been deprecated in favour of the `sku_name` field [GH-5721] From 346e89d85771beae939f0b72ce228d6591bb0076 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 10:45:47 +0000 Subject: [PATCH 152/498] caught additional 2.0 todos --- .../resource_arm_automation_account.go | 67 ++----------------- .../resource_arm_automation_credential.go | 29 ++------ .../resource_arm_automation_runbook.go | 6 +- .../resource_arm_automation_schedule.go | 48 ++----------- 4 files changed, 17 insertions(+), 133 deletions(-) diff --git a/azurerm/internal/services/automation/resource_arm_automation_account.go b/azurerm/internal/services/automation/resource_arm_automation_account.go index bc04ffee144b9..ed612228403b2 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_account.go +++ b/azurerm/internal/services/automation/resource_arm_automation_account.go @@ -9,7 +9,6 @@ import ( "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/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" @@ -47,34 +46,9 @@ func resourceArmAutomationAccount() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - ConflictsWith: []string{"sku_name"}, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(automation.Basic), - string(automation.Free), - }, true), - }, - }, - }, - }, - "sku_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ string(automation.Basic), string(automation.Free), @@ -104,25 +78,8 @@ func resourceArmAutomationAccountCreateUpdate(d *schema.ResourceData, meta inter ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - // Remove in 2.0 - var sku automation.Sku - - if inputs := d.Get("sku").([]interface{}); len(inputs) != 0 { - input := inputs[0].(map[string]interface{}) - v := input["name"].(string) - - sku = automation.Sku{ - Name: automation.SkuNameEnum(v), - } - } else { - // Keep in 2.0 - sku = automation.Sku{ - Name: automation.SkuNameEnum(d.Get("sku_name").(string)), - } - } - - if sku.Name == "" { - return fmt.Errorf("either 'sku_name' or 'sku' must be defined in the configuration file") + sku := automation.Sku{ + Name: automation.SkuNameEnum(d.Get("sku_name").(string)), } log.Printf("[INFO] preparing arguments for Automation Account create/update.") @@ -214,11 +171,6 @@ func resourceArmAutomationAccountRead(d *schema.ResourceData, meta interface{}) } if sku := resp.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenAutomationAccountSku(sku)); err != nil { - return fmt.Errorf("Error setting 'sku': %+v", err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting 'sku_name': %+v", err) } @@ -263,14 +215,3 @@ func resourceArmAutomationAccountDelete(d *schema.ResourceData, meta interface{} return nil } - -// Remove in 2.0 -func flattenAutomationAccountSku(sku *automation.Sku) []interface{} { - if sku == nil { - return []interface{}{} - } - - result := map[string]interface{}{} - result["name"] = string(sku.Name) - return []interface{}{result} -} diff --git a/azurerm/internal/services/automation/resource_arm_automation_credential.go b/azurerm/internal/services/automation/resource_arm_automation_credential.go index 13d9a8040d09d..de4a7570f0646 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_credential.go +++ b/azurerm/internal/services/automation/resource_arm_automation_credential.go @@ -42,24 +42,11 @@ func resourceArmAutomationCredential() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - //this is AutomationAccountName in the SDK - "account_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - Deprecated: "account_name has been renamed to automation_account_name for clarity and to match the azure API", - ConflictsWith: []string{"automation_account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), - }, - "automation_account_name": { - Type: schema.TypeString, - Optional: true, //todo change to required once account_name has been removed - Computed: true, // todo remove once account_name has been removed - ForceNew: true, - ConflictsWith: []string{"account_name"}, // todo remove once account_name has been removed - ValidateFunc: azure.ValidateAutomationAccountName(), + Type: schema.TypeString, + Required: true, //todo change to required once account_name has been removed + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), }, "username": { @@ -91,12 +78,7 @@ func resourceArmAutomationCredentialCreateUpdate(d *schema.ResourceData, meta in name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) // todo remove this once `account_name` is removed - accountName := "" - if v, ok := d.GetOk("automation_account_name"); ok { - accountName = v.(string) - } else if v, ok := d.GetOk("account_name"); ok { - accountName = v.(string) - } + accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resGroup, accountName, name) @@ -168,7 +150,6 @@ func resourceArmAutomationCredentialRead(d *schema.ResourceData, meta interface{ d.Set("name", resp.Name) d.Set("resource_group_name", resGroup) d.Set("automation_account_name", accountName) - d.Set("account_name", accountName) if props := resp.CredentialProperties; props != nil { d.Set("username", props.UserName) } diff --git a/azurerm/internal/services/automation/resource_arm_automation_runbook.go b/azurerm/internal/services/automation/resource_arm_automation_runbook.go index 25c01f9f48d88..2edf3bb69747d 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_runbook.go +++ b/azurerm/internal/services/automation/resource_arm_automation_runbook.go @@ -46,7 +46,7 @@ func resourceArmAutomationRunbook() *schema.Resource { ValidateFunc: azure.ValidateAutomationRunbookName(), }, - "account_name": { + "automation_account_name": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -143,7 +143,7 @@ func resourceArmAutomationRunbookCreateUpdate(d *schema.ResourceData, meta inter log.Printf("[INFO] preparing arguments for AzureRM Automation Runbook creation.") name := d.Get("name").(string) - accName := d.Get("account_name").(string) + accName := d.Get("automation_account_name").(string) resGroup := d.Get("resource_group_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { @@ -243,7 +243,7 @@ func resourceArmAutomationRunbookRead(d *schema.ResourceData, meta interface{}) d.Set("location", azure.NormalizeLocation(*location)) } - d.Set("account_name", accName) + d.Set("automation_account_name", accName) if props := resp.RunbookProperties; props != nil { d.Set("log_verbose", props.LogVerbose) d.Set("log_progress", props.LogProgress) diff --git a/azurerm/internal/services/automation/resource_arm_automation_schedule.go b/azurerm/internal/services/automation/resource_arm_automation_schedule.go index dd889645a0b85..da4b12fc03a19 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_schedule.go +++ b/azurerm/internal/services/automation/resource_arm_automation_schedule.go @@ -49,23 +49,11 @@ func resourceArmAutomationSchedule() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - //this is AutomationAccountName in the SDK - "account_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "account_name has been renamed to automation_account_name for clarity and to match the azure API", - ConflictsWith: []string{"automation_account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), - }, - "automation_account_name": { - Type: schema.TypeString, - Optional: true, //todo change to required once account_name has been removed - Computed: true, - //ForceNew: true, //todo this needs to come back once account_name has been removed - ConflictsWith: []string{"account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), }, "frequency": { @@ -206,24 +194,6 @@ func resourceArmAutomationSchedule() *schema.Resource { return fmt.Errorf("`monthly_occurrence` can only be set when frequency is `Month`") } - _, hasAccount := diff.GetOk("automation_account_name") - _, hasAutomationAccountWeb := diff.GetOk("account_name") - if !hasAccount && !hasAutomationAccountWeb { - return fmt.Errorf("`automation_account_name` must be set") - } - - //if automation_account_name changed or account_name changed to or from nil force a new resource - //remove once we remove the deprecated property - oAan, nAan := diff.GetChange("automation_account_name") - if oAan != "" && nAan != "" { - diff.ForceNew("automation_account_name") - } - - oAn, nAn := diff.GetChange("account_name") - if oAn != "" && nAn != "" { - diff.ForceNew("account_name") - } - return nil }, } @@ -238,14 +208,7 @@ func resourceArmAutomationScheduleCreateUpdate(d *schema.ResourceData, meta inte name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) - //CustomizeDiff should ensure one of these two is set - // todo remove this once `account_name` is removed - accountName := "" - if v, ok := d.GetOk("automation_account_name"); ok { - accountName = v.(string) - } else if v, ok := d.GetOk("account_name"); ok { - accountName = v.(string) - } + accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resGroup, accountName, name) @@ -350,7 +313,6 @@ func resourceArmAutomationScheduleRead(d *schema.ResourceData, meta interface{}) d.Set("name", resp.Name) d.Set("resource_group_name", resGroup) d.Set("automation_account_name", accountName) - d.Set("account_name", accountName) // todo remove once `account_name` is removed d.Set("frequency", string(resp.Frequency)) if v := resp.StartTime; v != nil { From 7ca59a3acad25e8783cddbe0a2a85b95e2c8fd85 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 10:53:00 +0000 Subject: [PATCH 153/498] docs account_name to automation_account_name update --- .../r/automation_certificate.html.markdown | 8 ++--- .../docs/r/automation_runbook.html.markdown | 34 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/website/docs/r/automation_certificate.html.markdown b/website/docs/r/automation_certificate.html.markdown index e626a7a0e8086..81be197855532 100644 --- a/website/docs/r/automation_certificate.html.markdown +++ b/website/docs/r/automation_certificate.html.markdown @@ -27,9 +27,9 @@ resource "azurerm_automation_account" "example" { } resource "azurerm_automation_certificate" "example" { - name = "certificate1" - resource_group_name = "${azurerm_resource_group.example.name}" - account_name = "${azurerm_automation_account.example.name}" + name = "certificate1" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" description = "This is an example certificate" base64 = base64encode(file("certificate.pfx")) @@ -44,7 +44,7 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which the Certificate is created. Changing this forces a new resource to be created. -* `account_name` - (Required) The name of the automation account in which the Certificate is created. Changing this forces a new resource to be created. +* `automation_account_name` - (Required) The name of the automation account in which the Certificate is created. Changing this forces a new resource to be created. * `base64` - (Required) Base64 encoded value of the certificate. diff --git a/website/docs/r/automation_runbook.html.markdown b/website/docs/r/automation_runbook.html.markdown index 8fc49bbff75f6..d4e2325ccc556 100644 --- a/website/docs/r/automation_runbook.html.markdown +++ b/website/docs/r/automation_runbook.html.markdown @@ -29,14 +29,14 @@ resource "azurerm_automation_account" "example" { } resource "azurerm_automation_runbook" "example" { - name = "Get-AzureVMTutorial" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - account_name = azurerm_automation_account.example.name - log_verbose = "true" - log_progress = "true" - description = "This is an example runbook" - runbook_type = "PowerShellWorkflow" + name = "Get-AzureVMTutorial" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + log_verbose = "true" + log_progress = "true" + description = "This is an example runbook" + runbook_type = "PowerShellWorkflow" publish_content_link { uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/c4935ffb69246a6058eb24f54640f53f69d3ac9f/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" @@ -67,14 +67,14 @@ data "local_file" "example" { } resource "azurerm_automation_runbook" "example" { - name = "Get-AzureVMTutorial" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - account_name = azurerm_automation_account.example.name - log_verbose = "true" - log_progress = "true" - description = "This is an example runbook" - runbook_type = "PowerShell" + name = "Get-AzureVMTutorial" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + automation_account_name = azurerm_automation_account.example.name + log_verbose = "true" + log_progress = "true" + description = "This is an example runbook" + runbook_type = "PowerShell" publish_content_link { uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/c4935ffb69246a6058eb24f54640f53f69d3ac9f/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" @@ -94,7 +94,7 @@ The following arguments are supported: * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. -* `account_name` - (Required) The name of the automation account in which the Runbook is created. Changing this forces a new resource to be created. +* `automation_account_name` - (Required) The name of the automation account in which the Runbook is created. Changing this forces a new resource to be created. * `runbook_type` - (Required) The type of the runbook - can be either `Graph`, `GraphPowerShell`, `GraphPowerShellWorkflow`, `PowerShellWorkflow`, `PowerShell` or `Script`. From e36c347458b707e29afd98d7032f4a13e974d8cb Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 12:04:01 +0100 Subject: [PATCH 154/498] linting --- .../tests/resource_arm_key_vault_key_test.go | 24 +++++++++---------- .../resource_arm_key_vault_secret_test.go | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index b9cf42e1673b8..940cca033a0fa 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -640,10 +640,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - key_vault_id = "${azurerm_key_vault.test.id}" - key_type = "RSA" - key_size = 2048 + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "RSA" + key_size = 2048 key_opts = [ "encrypt", @@ -698,10 +698,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - key_vault_id = "${azurerm_key_vault.test.id}" - key_type = "EC" - curve = "P-521" + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "EC" + curve = "P-521" key_opts = [ "sign", @@ -753,10 +753,10 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_key" "test" { - name = "key-%s" - key_vault_id = "${azurerm_key_vault.test.id}" - key_type = "EC-HSM" - curve = "P-521" + name = "key-%s" + key_vault_id = "${azurerm_key_vault.test.id}" + key_type = "EC-HSM" + curve = "P-521" key_opts = [ "sign", diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go index 693c1a0cccb61..f34f1d82c0841 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go @@ -421,9 +421,9 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_secret" "test" { - name = "secret-%s" - value = "szechuan" - key_vault_id = "${azurerm_key_vault.test.id}" + name = "secret-%s" + value = "szechuan" + key_vault_id = "${azurerm_key_vault.test.id}" } `, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomString) } From 690ef6f1f3d8a5417b8251fdca592ff293efe5ab Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 12:05:14 +0100 Subject: [PATCH 155/498] r/key_vault_access_policy: removing the unused assignment --- .../internal/services/keyvault/data_source_key_vault.go | 9 --------- .../keyvault/resource_arm_key_vault_access_policy.go | 3 +-- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/azurerm/internal/services/keyvault/data_source_key_vault.go b/azurerm/internal/services/keyvault/data_source_key_vault.go index f99387eb327e7..42568e0d13c98 100644 --- a/azurerm/internal/services/keyvault/data_source_key_vault.go +++ b/azurerm/internal/services/keyvault/data_source_key_vault.go @@ -198,15 +198,6 @@ func dataSourceArmKeyVaultRead(d *schema.ResourceData, meta interface{}) error { return tags.FlattenAndSet(d, resp.Tags) } -// Remove in 2.0 -func flattenKeyVaultDataSourceSku(sku *keyvault.Sku) []interface{} { - result := map[string]interface{}{ - "name": string(sku.Name), - } - - return []interface{}{result} -} - func flattenKeyVaultDataSourceNetworkAcls(input *keyvault.NetworkRuleSet) []interface{} { if input == nil { return []interface{}{} diff --git a/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go b/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go index 61023c81a1ab9..cda95f3e30c2b 100644 --- a/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go +++ b/azurerm/internal/services/keyvault/resource_arm_key_vault_access_policy.go @@ -83,7 +83,6 @@ func resourceArmKeyVaultAccessPolicyCreateOrDelete(d *schema.ResourceData, meta log.Printf("[INFO] Preparing arguments for Key Vault Access Policy: %s.", action) vaultId := d.Get("key_vault_id").(string) - resourceGroup := d.Get("resource_group_name").(string) tenantIdRaw := d.Get("tenant_id").(string) tenantId, err := uuid.FromString(tenantIdRaw) @@ -99,7 +98,7 @@ func resourceArmKeyVaultAccessPolicyCreateOrDelete(d *schema.ResourceData, meta return err } - resourceGroup = id.ResourceGroup + resourceGroup := id.ResourceGroup vaultName, ok := id.Path["vaults"] if !ok { return fmt.Errorf("key_value_id does not contain `vaults`: %q", vaultId) From 44868cb05d0f323aaf79c3a817ea48c29f8e53ba Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 12:26:53 +0100 Subject: [PATCH 156/498] d/network_interface: updating the tests --- .../network/data_source_network_interface.go | 9 -- .../data_source_network_interface_test.go | 110 ++---------------- 2 files changed, 10 insertions(+), 109 deletions(-) diff --git a/azurerm/internal/services/network/data_source_network_interface.go b/azurerm/internal/services/network/data_source_network_interface.go index 7e934893da4ea..aac8054521939 100644 --- a/azurerm/internal/services/network/data_source_network_interface.go +++ b/azurerm/internal/services/network/data_source_network_interface.go @@ -73,7 +73,6 @@ func dataSourceArmNetworkInterface() *schema.Resource { Computed: true, }, - //TODO: should this be renamed to private_ip_address_allocation_method or private_ip_allocation_method ? "private_ip_address_allocation": { Type: schema.TypeString, Computed: true, @@ -145,14 +144,6 @@ func dataSourceArmNetworkInterface() *schema.Resource { Computed: true, }, - /** - * As of 2018-01-06: AN (aka. SR-IOV) on Azure is GA on Windows and Linux. - * - * Refer to: https://azure.microsoft.com/en-us/blog/maximize-your-vm-s-performance-with-accelerated-networking-now-generally-available-for-both-windows-and-linux/ - * - * Refer to: https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli - * For details, VM configuration and caveats. - */ "enable_accelerated_networking": { Type: schema.TypeBool, Computed: true, diff --git a/azurerm/internal/services/network/tests/data_source_network_interface_test.go b/azurerm/internal/services/network/tests/data_source_network_interface_test.go index e4c0bd02235ec..c40a91de9e186 100644 --- a/azurerm/internal/services/network/tests/data_source_network_interface_test.go +++ b/azurerm/internal/services/network/tests/data_source_network_interface_test.go @@ -8,124 +8,34 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceArmVirtualNetworkInterface_basic(t *testing.T) { +func TestAccDataSourceArmNetworkInterface_basic(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_network_interface", "test") - name := fmt.Sprintf("acctest-nic-%d", data.RandomInteger) - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceArmVirtualNetworkInterface_basic(data), + Config: testAccAzureRMNetworkInterface_static(data), }, { - Config: testAccDataSourceArmVirtualNetworkInterface_withDataSource(data), + Config: testAccDataSourceNetworkInterface_basic(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(data.ResourceName, "name", name), - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - resource.TestCheckResourceAttr(data.ResourceName, "private_ip_address", "10.0.1.4"), - resource.TestCheckResourceAttrSet(data.ResourceName, "network_security_group_id"), + resource.TestCheckResourceAttr(data.ResourceName, "private_ip_address", "10.0.2.15"), ), }, }, }) } -func testAccDataSourceArmVirtualNetworkInterface_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest-%d-rg" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctest-vn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_network_security_group" "test" { - name = "acctest-nsg-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "subnet1" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" -} - -resource "azurerm_network_interface" "test" { - name = "acctest-nic-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_security_group_id = "${azurerm_network_security_group.test.id}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - } - - tags = { - environment = "staging" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccDataSourceArmVirtualNetworkInterface_withDataSource(data acceptance.TestData) string { +func testAccDataSourceNetworkInterface_basic(data acceptance.TestData) string { + template := testAccAzureRMNetworkInterface_static(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest-%d-rg" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctest-vn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_network_security_group" "test" { - name = "acctest-nsg-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "subnet1" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" -} - -resource "azurerm_network_interface" "test" { - name = "acctest-nic-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - network_security_group_id = "${azurerm_network_security_group.test.id}" - - ip_configuration { - name = "testconfiguration1" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - } - - tags = { - environment = "staging" - } -} +%s data "azurerm_network_interface" "test" { - name = "acctest-nic-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + name = azurerm_network_interface.test.name + resource_group_name = azurerm_network_interface.test.resource_group_name } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } From 7f80483755caa5828ddf93af2cd2f895baeed0ee Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 13:22:47 +0100 Subject: [PATCH 157/498] updating to include #5624 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f7708a81118e..5de85a3955621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,8 +64,9 @@ IMPROVEMENTS: BUG FIXES: * `azurerm_linux_virtual_machine` - using the delete custom timeout during deletion [GH-5764] -* `azurerm_windows_virtual_machine` - using the delete custom timeout during deletion [GH-5764] +* `azurerm_role_assignment` - validating that the `name` is a UUID [GH-5624] * `azurerm_signalr_service` - ensuring the SignalR segment is parsed in the correct case [GH-5737] +* `azurerm_windows_virtual_machine` - using the delete custom timeout during deletion [GH-5764] --- From 94bbb6b92c160a6b079cba297ea3180c371df2b6 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 13:26:00 +0100 Subject: [PATCH 158/498] updating to include #5693 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5de85a3955621..b704a9cc23bff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ IMPROVEMENTS: BUG FIXES: * `azurerm_linux_virtual_machine` - using the delete custom timeout during deletion [GH-5764] +* `azurerm_public_ip_prefix` - fixing the validation for the `prefix_length` to match the Azure API [GH-5693] * `azurerm_role_assignment` - validating that the `name` is a UUID [GH-5624] * `azurerm_signalr_service` - ensuring the SignalR segment is parsed in the correct case [GH-5737] * `azurerm_windows_virtual_machine` - using the delete custom timeout during deletion [GH-5764] From 8e874af34c2025ba406dc0da9944c8e256a73caf Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 15:10:52 +0100 Subject: [PATCH 159/498] docs: adding the `azurerm_network_interface_security_group_association` to the sidebar --- website/azurerm.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/azurerm.erb b/website/azurerm.erb index 0ea9b471ad153..ac91bdd269443 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -1803,6 +1803,10 @@ azurerm_network_interface_nat_rule_association +
  • + azurerm_network_interface_security_group_association +
  • +
  • azurerm_network_packet_capture
  • From 04917d5ccb1c60e7a607bbfa876961c309d45f73 Mon Sep 17 00:00:00 2001 From: John Gleason Date: Mon, 17 Feb 2020 08:12:25 -0600 Subject: [PATCH 160/498] Very minor consistency edits --- website/docs/r/public_ip_prefix.html.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/docs/r/public_ip_prefix.html.markdown b/website/docs/r/public_ip_prefix.html.markdown index 0133bf8080591..16458054dbd8a 100644 --- a/website/docs/r/public_ip_prefix.html.markdown +++ b/website/docs/r/public_ip_prefix.html.markdown @@ -35,23 +35,23 @@ resource "azurerm_public_ip_prefix" "example" { The following arguments are supported: -* `name` - (Required) Specifies the name of the Public IP resource . Changing this forces a new resource to be created. +* `name` - (Required) Specifies the name of the Public IP Prefix resource . Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to create the public IP. +* `resource_group_name` - (Required) The name of the resource group in which to create the Public IP Prefix. * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. * `sku` - (Optional) The SKU of the Public IP Prefix. Accepted values are `Standard`. Defaults to `Standard`. Changing this forces a new resource to be created. --> **Note** Public IP Prefix can only be created with Standard SKUs at this time. +-> **Note**: Public IP Prefix can only be created with Standard SKUs at this time. * `prefix_length` - (Optional) Specifies the number of bits of the prefix. The value can be set between 28 (16 addresses) and 31 (2 addresses). Changing this forces a new resource to be created. --> **Please Note:**: There may be Public IP address limits on the subscription . [More information available here](https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits?toc=%2fazure%2fvirtual-network%2ftoc.json#publicip-address) +-> **Please Note**: There may be Public IP address limits on the subscription . [More information available here](https://docs.microsoft.com/en-us/azure/azure-subscription-service-limits?toc=%2fazure%2fvirtual-network%2ftoc.json#publicip-address) * `tags` - (Optional) A mapping of tags to assign to the resource. -* `zones` - (Optional) A collection containing the availability zone to allocate the Public IP in. +* `zones` - (Optional) A collection containing the availability zone to allocate the Public IP Prefix in. -> **Please Note**: Availability Zones are [only supported in several regions at this time](https://docs.microsoft.com/en-us/azure/availability-zones/az-overview). From 746e9bd2547907cc46f4a575f94ca65aa5a56e16 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 15:33:41 +0100 Subject: [PATCH 161/498] automation: fixing the tests to account for the field being removed --- .../resource_arm_automation_credential.go | 3 +- ...source_arm_automation_job_schedule_test.go | 19 ++++++----- .../resource_arm_automation_runbook_test.go | 32 +++++++++---------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/azurerm/internal/services/automation/resource_arm_automation_credential.go b/azurerm/internal/services/automation/resource_arm_automation_credential.go index de4a7570f0646..62e01a9cea3ff 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_credential.go +++ b/azurerm/internal/services/automation/resource_arm_automation_credential.go @@ -44,7 +44,7 @@ func resourceArmAutomationCredential() *schema.Resource { "automation_account_name": { Type: schema.TypeString, - Required: true, //todo change to required once account_name has been removed + Required: true, ForceNew: true, ValidateFunc: azure.ValidateAutomationAccountName(), }, @@ -77,7 +77,6 @@ func resourceArmAutomationCredentialCreateUpdate(d *schema.ResourceData, meta in name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) - // todo remove this once `account_name` is removed accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go index 799d4a25de725..48f4b35ecafc5 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go @@ -112,7 +112,7 @@ func testCheckAzureRMAutomationJobScheduleDestroy(s *terraform.State) error { } jobScheduleID := id.Path["jobSchedules"] jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) - accName := rs.Primary.Attributes["account_name"] + accName := rs.Primary.Attributes["automation_account_name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { @@ -190,15 +190,14 @@ resource "azurerm_automation_account" "test" { } resource "azurerm_automation_runbook" "test" { - name = "Output-HelloWorld" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - account_name = "${azurerm_automation_account.test.name}" - log_verbose = "true" - log_progress = "true" - description = "This is a test runbook for terraform acceptance test" - runbook_type = "PowerShell" + name = "Output-HelloWorld" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + log_verbose = "true" + log_progress = "true" + description = "This is a test runbook for terraform acceptance test" + runbook_type = "PowerShell" publish_content_link { uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/c4935ffb69246a6058eb24f54640f53f69d3ac9f/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go index c321e47ef7f9d..b3b5bc283530b 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go @@ -106,7 +106,7 @@ func testCheckAzureRMAutomationRunbookDestroy(s *terraform.State) error { } name := rs.Primary.Attributes["name"] - accName := rs.Primary.Attributes["account_name"] + accName := rs.Primary.Attributes["automation_account_name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { @@ -141,7 +141,7 @@ func testCheckAzureRMAutomationRunbookExists(resourceName string) resource.TestC } name := rs.Primary.Attributes["name"] - accName := rs.Primary.Attributes["account_name"] + accName := rs.Primary.Attributes["automation_account_name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { @@ -180,11 +180,11 @@ resource "azurerm_automation_account" "test" { } resource "azurerm_automation_runbook" "test" { - name = "Get-AzureVMTutorial" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "Get-AzureVMTutorial" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" - account_name = "${azurerm_automation_account.test.name}" log_verbose = "true" log_progress = "true" description = "This is a test runbook for terraform acceptance test" @@ -203,11 +203,11 @@ func testAccAzureRMAutomationRunbook_requiresImport(data acceptance.TestData) st %s resource "azurerm_automation_runbook" "import" { - name = "${azurerm_automation_runbook.test.name}" - location = "${azurerm_automation_runbook.test.location}" - resource_group_name = "${azurerm_automation_runbook.test.resource_group_name}" + name = "${azurerm_automation_runbook.test.name}" + location = "${azurerm_automation_runbook.test.location}" + resource_group_name = "${azurerm_automation_runbook.test.resource_group_name}" + automation_account_name = "${azurerm_automation_runbook.test.account_name}" - account_name = "${azurerm_automation_runbook.test.account_name}" log_verbose = "true" log_progress = "true" description = "This is a test runbook for terraform acceptance test" @@ -239,10 +239,10 @@ resource "azurerm_automation_account" "test" { resource "azurerm_automation_runbook" "test" { name = "Get-AzureVMTutorial" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" - account_name = "${azurerm_automation_account.test.name}" log_verbose = "true" log_progress = "true" description = "This is a test runbook for terraform acceptance test" @@ -280,10 +280,10 @@ resource "azurerm_automation_account" "test" { resource "azurerm_automation_runbook" "test" { name = "Get-AzureVMTutorial" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" - account_name = "${azurerm_automation_account.test.name}" log_verbose = "true" log_progress = "true" description = "This is a test runbook for terraform acceptance test" From da8015229b9054e0554e0c6367604c913d0f47dd Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 15:39:30 +0100 Subject: [PATCH 162/498] r/key_vault: removing the test expecting a complaint --- .../tests/resource_arm_key_vault_test.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 4fab60950554a..57fdaeecaef49 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -2,7 +2,6 @@ package tests import ( "fmt" - "regexp" "testing" "github.com/hashicorp/go-azure-helpers/response" @@ -92,23 +91,6 @@ func TestAccAzureRMKeyVault_basic(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMKeyVault_basicNotDefined(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_key_vault", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMKeyVaultDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMKeyVault_basicNotDefined(data), - ExpectError: regexp.MustCompile("either 'sku_name' or 'sku' must be defined in the configuration file"), - }, - }, - }) -} - func TestAccAzureRMKeyVault_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") From cb175c998dfc76e94aa32a6517946923845b7abf Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 16:06:27 +0100 Subject: [PATCH 163/498] r/key_vault_*: handling the parent key vault not being available once it's deleted --- .../keyvault/tests/resource_arm_key_vault_certificate_test.go | 3 ++- .../services/keyvault/tests/resource_arm_key_vault_key_test.go | 3 ++- .../keyvault/tests/resource_arm_key_vault_secret_test.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go index 59a2079005c5e..8748d336fbde2 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_certificate_test.go @@ -225,7 +225,8 @@ func testCheckAzureRMKeyVaultCertificateDestroy(s *terraform.State) error { keyVaultId := rs.Primary.Attributes["key_vault_id"] vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) if err != nil { - return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + // deleted, this is fine. + return nil } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index 940cca033a0fa..2f906cb728842 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -241,7 +241,8 @@ func testCheckAzureRMKeyVaultKeyDestroy(s *terraform.State) error { keyVaultId := rs.Primary.Attributes["key_vault_id"] vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) if err != nil { - return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + // key vault's been deleted + return nil } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go index f34f1d82c0841..2fb2f3e813c5c 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_secret_test.go @@ -166,7 +166,8 @@ func testCheckAzureRMKeyVaultSecretDestroy(s *terraform.State) error { keyVaultId := rs.Primary.Attributes["key_vault_id"] vaultBaseUrl, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) if err != nil { - return fmt.Errorf("Error looking up Secret %q vault url from id %q: %+v", name, keyVaultId, err) + // key vault's been deleted + return nil } ok, err := azure.KeyVaultExists(ctx, acceptance.AzureProvider.Meta().(*clients.Client).KeyVault.VaultsClient, keyVaultId) From 14578f7050b244f0929b65335b654a3d18958782 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 16:16:38 +0100 Subject: [PATCH 164/498] r/subnet: removing the `route_table_id` field from the examples/docs --- examples/kubernetes/advanced-networking-calico-policy/main.tf | 3 --- .../kubernetes/advanced-networking-multiple-agentpool/main.tf | 3 --- examples/kubernetes/advanced-networking/main.tf | 3 --- examples/virtual-networks/azure-firewall/main.tf | 1 - website/docs/r/subnet.html.markdown | 4 ---- website/docs/r/subnet_route_table_association.html.markdown | 3 --- 6 files changed, 17 deletions(-) diff --git a/examples/kubernetes/advanced-networking-calico-policy/main.tf b/examples/kubernetes/advanced-networking-calico-policy/main.tf index b14d95b0cc483..cf95062ee80ca 100644 --- a/examples/kubernetes/advanced-networking-calico-policy/main.tf +++ b/examples/kubernetes/advanced-networking-calico-policy/main.tf @@ -28,9 +28,6 @@ resource "azurerm_subnet" "test" { resource_group_name = "${azurerm_resource_group.test.name}" address_prefix = "10.1.0.0/24" virtual_network_name = "${azurerm_virtual_network.test.name}" - - # this field is deprecated and will be removed in 2.0 - but is required until then - route_table_id = "${azurerm_route_table.test.id}" } resource "azurerm_subnet_route_table_association" "test" { diff --git a/examples/kubernetes/advanced-networking-multiple-agentpool/main.tf b/examples/kubernetes/advanced-networking-multiple-agentpool/main.tf index a30e57432b882..bb3c463d167ed 100644 --- a/examples/kubernetes/advanced-networking-multiple-agentpool/main.tf +++ b/examples/kubernetes/advanced-networking-multiple-agentpool/main.tf @@ -28,9 +28,6 @@ resource "azurerm_subnet" "example" { resource_group_name = "${azurerm_resource_group.example.name}" address_prefix = "10.1.0.0/24" virtual_network_name = "${azurerm_virtual_network.example.name}" - - # this field is deprecated and will be removed in 2.0 - but is required until then - route_table_id = "${azurerm_route_table.example.id}" } resource "azurerm_subnet_route_table_association" "example" { diff --git a/examples/kubernetes/advanced-networking/main.tf b/examples/kubernetes/advanced-networking/main.tf index c778f7fb952a3..762b4db9718d8 100644 --- a/examples/kubernetes/advanced-networking/main.tf +++ b/examples/kubernetes/advanced-networking/main.tf @@ -28,9 +28,6 @@ resource "azurerm_subnet" "example" { resource_group_name = "${azurerm_resource_group.example.name}" address_prefix = "10.1.0.0/22" virtual_network_name = "${azurerm_virtual_network.example.name}" - - # this field is deprecated and will be removed in 2.0 - but is required until then - route_table_id = "${azurerm_route_table.example.id}" } resource "azurerm_subnet_route_table_association" "example" { diff --git a/examples/virtual-networks/azure-firewall/main.tf b/examples/virtual-networks/azure-firewall/main.tf index 90b4f70896778..1aaf9e8033a6d 100644 --- a/examples/virtual-networks/azure-firewall/main.tf +++ b/examples/virtual-networks/azure-firewall/main.tf @@ -89,7 +89,6 @@ resource "azurerm_subnet" "azusubnet" { resource_group_name = "${azurerm_resource_group.azurg.name}" virtual_network_name = "${azurerm_virtual_network.azuvnet.name}" address_prefix = "10.0.2.0/24" - route_table_id = "${azurerm_route_table.azurt.id}" } resource "azurerm_subnet_route_table_association" "azurtassoc" { diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index b23e95f7d5beb..6fc59355fd16e 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -63,10 +63,6 @@ The following arguments are supported: -> **NOTE:** At this time Subnet `<->` Network Security Group associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_subnet_network_security_group_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. -* `route_table_id` - (Optional / **Deprecated**) The ID of the Route Table to associate with the subnet. - --> **NOTE:** At this time Subnet `<->` Route Table associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_subnet_route_table_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - * `service_endpoints` - (Optional) The list of Service endpoints to associate with the subnet. Possible values include: `Microsoft.AzureActiveDirectory`, `Microsoft.AzureCosmosDB`, `Microsoft.ContainerRegistry`, `Microsoft.EventHub`, `Microsoft.KeyVault`, `Microsoft.ServiceBus`, `Microsoft.Sql`, `Microsoft.Storage` and `Microsoft.Web`. * `delegation` - (Optional) One or more `delegation` blocks as defined below. diff --git a/website/docs/r/subnet_route_table_association.html.markdown b/website/docs/r/subnet_route_table_association.html.markdown index c0076e37aab73..8a2f294f2c931 100644 --- a/website/docs/r/subnet_route_table_association.html.markdown +++ b/website/docs/r/subnet_route_table_association.html.markdown @@ -11,8 +11,6 @@ description: |- Associates a [Route Table](route_table.html) with a [Subnet](subnet.html) within a [Virtual Network](virtual_network.html). --> **NOTE:** Subnet `<->` Route Table associations currently need to be configured on both this resource and using the `route_table_id` field on the `azurerm_subnet` resource. The next major version of the AzureRM Provider (2.0) will remove the `route_table_id` field from the `azurerm_subnet` resource such that this resource is used to link resources in future. - ## Example Usage ```hcl @@ -33,7 +31,6 @@ resource "azurerm_subnet" "example" { resource_group_name = azurerm_resource_group.example.name virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.0.2.0/24" - route_table_id = azurerm_route_table.example.id } resource "azurerm_route_table" "example" { From 9ac1cfa12ce96653d18e189d57d249e8e3275c76 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 16:40:01 +0100 Subject: [PATCH 165/498] r/keyvault: updating the remaining tests --- .../keyvault/tests/resource_arm_key_vault_key_test.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go index 2f906cb728842..4e95d9a01fe07 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_key_test.go @@ -671,10 +671,7 @@ resource "azurerm_key_vault" "test" { location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku { - name = "premium" - } + sku_name = "premium" access_policy { tenant_id = "${data.azurerm_client_config.current.tenant_id}" @@ -726,10 +723,7 @@ resource "azurerm_key_vault" "test" { location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - sku { - name = "premium" - } + sku_name = "premium" access_policy { tenant_id = "${data.azurerm_client_config.current.tenant_id}" From 8ed01245730d2501ccd08e32c4b9dfbac4197a31 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 17:28:13 +0100 Subject: [PATCH 166/498] r/keyvault: removing dead code --- .../tests/resource_arm_key_vault_test.go | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 57fdaeecaef49..9fca6afecdf0e 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -411,37 +411,6 @@ resource "azurerm_key_vault" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMKeyVault_basicNotDefined(data acceptance.TestData) string { - return fmt.Sprintf(` -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_key_vault" "test" { - name = "vault%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - - access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" - object_id = "${data.azurerm_client_config.current.client_id}" - - key_permissions = [ - "create", - ] - - secret_permissions = [ - "set", - ] - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMKeyVault_requiresImport(data acceptance.TestData) string { template := testAccAzureRMKeyVault_basic(data) return fmt.Sprintf(` From 08b62095de650ac5617b61934e9bdacffefb6e1a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Mon, 17 Feb 2020 17:54:14 +0100 Subject: [PATCH 167/498] linting --- .../automation/tests/resource_arm_automation_runbook_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go index b3b5bc283530b..727072b6949c8 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go @@ -238,7 +238,7 @@ resource "azurerm_automation_account" "test" { } resource "azurerm_automation_runbook" "test" { - name = "Get-AzureVMTutorial" + name = "Get-AzureVMTutorial" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" automation_account_name = "${azurerm_automation_account.test.name}" @@ -279,7 +279,7 @@ resource "azurerm_automation_account" "test" { } resource "azurerm_automation_runbook" "test" { - name = "Get-AzureVMTutorial" + name = "Get-AzureVMTutorial" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" automation_account_name = "${azurerm_automation_account.test.name}" From 225783ab788404f0a10d475345a3911428576fa3 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Mon, 17 Feb 2020 18:07:55 +0100 Subject: [PATCH 168/498] updating to include #5774 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b704a9cc23bff..117366c22c229 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ BREAKING CHANGES: * Data Source: `azurerm_app_service_plan` - the deprecated `properties` block has been removed since these properties have been moved to the top level [GH-5717] * Data Source: `azurerm_azuread_application` - This data source has been removed since it was deprecated [GH-5748] * Data Source: `azurerm_azuread_service_principal` - This data source has been removed since it was deprecated [GH-5748] +* Data Source: `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] +* Data Source: `azurerm_key_vault_key` - removing the deprecated `vault_uri` field [GH-5774] +* Data Source: `azurerm_key_vault_secret` - removing the deprecated `vault_uri` field [GH-5774] * Data Source: `azurerm_role_definition` - removing the alias `VirtualMachineContributor` which has been deprecated in favour of the full name `Virtual Machine Contributor` [GH-5733] * Data Source: `azurerm_scheduler_job_collection` - This data source has been removed since it was deprecated [GH-5712] * `azurerm_app_service_plan` - the deprecated `properties` block has been removed since these properties have been moved to the top level [GH-5717] @@ -32,6 +35,12 @@ BREAKING CHANGES: * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] +* `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] +* `azurerm_key_vault_access_policy` - removing the deprecated field `vault_name` which has been superseded by the `key_vault_id` field [GH-5774] +* `azurerm_key_vault_access_policy` - removing the deprecated field `resource_group_name ` which has been superseded by the `key_vault_id` field [GH-5774] +* `azurerm_key_vault_certificate` - removing the deprecated `vault_uri` field [GH-5774] +* `azurerm_key_vault_key` - removing the deprecated `vault_uri` field [GH-5774] +* `azurerm_key_vault_secret` - removing the deprecated `vault_uri` field [GH-5774] * `azurerm_kubernetes_cluster` - updating the default value for `load_balancer_sku` to `Standard` from `Basic` [GH-5747] * `azurerm_log_analytics_workspace_linked_service` - This resource has been removed since it was deprecated [GH-5754] * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] From d2ec7bf661dcc28c242f97ff4ad2c55297bec970 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 17:34:57 +0000 Subject: [PATCH 169/498] fixup tests for sku_name --- .../tests/resource_arm_automation_account_test.go | 5 +---- .../resource_arm_automation_credential_test.go | 9 ++------- ...ource_arm_automation_dsc_configuration_test.go | 5 +---- ...e_arm_automation_dsc_nodeconfiguration_test.go | 5 +---- .../resource_arm_automation_job_schedule_test.go | 5 +---- .../tests/resource_arm_automation_module_test.go | 10 ++-------- .../tests/resource_arm_automation_runbook_test.go | 15 +++------------ .../resource_arm_automation_schedule_test.go | 5 +---- .../resource_arm_automation_variable_bool_test.go | 8 ++------ ...ource_arm_automation_variable_datetime_test.go | 10 ++-------- .../resource_arm_automation_variable_int_test.go | 10 ++-------- ...esource_arm_automation_variable_string_test.go | 10 ++-------- 12 files changed, 20 insertions(+), 77 deletions(-) diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go index a44de6d452e4f..82954de9d00a2 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go @@ -212,10 +212,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_credential_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_credential_test.go index e5220a6ce8f06..e2836e30d5fff 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_credential_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_credential_test.go @@ -153,10 +153,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_credential" "test" { @@ -195,10 +192,8 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" + sku_name = "Basic" - sku { - name = "Basic" - } } resource "azurerm_automation_credential" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_configuration_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_configuration_test.go index 42e9c066a2929..b90ae33efdd75 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_configuration_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_configuration_test.go @@ -135,10 +135,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_dsc_configuration" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_nodeconfiguration_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_nodeconfiguration_test.go index deded2a5d0c23..43ff42acc6d0e 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_nodeconfiguration_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_dsc_nodeconfiguration_test.go @@ -132,10 +132,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_dsc_configuration" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go index 48f4b35ecafc5..98bf5410a4942 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go @@ -183,10 +183,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAA-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_runbook" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_module_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_module_test.go index b932aa7c9ff06..f41479200cf46 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_module_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_module_test.go @@ -150,10 +150,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_module" "test" { @@ -179,10 +176,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_module" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go index 727072b6949c8..6b3e947a45145 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go @@ -173,10 +173,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_runbook" "test" { @@ -231,10 +228,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_runbook" "test" { @@ -272,10 +266,7 @@ resource "azurerm_automation_account" "test" { name = "acctest-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_runbook" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_schedule_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_schedule_test.go index f8c627f247975..50987ce112241 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_schedule_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_schedule_test.go @@ -293,10 +293,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAA-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_bool_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_bool_test.go index def9fe78d6f00..46a2eece17a7b 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_bool_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_bool_test.go @@ -103,10 +103,8 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" + sku_name = "Basic" - sku { - name = "Basic" - } } resource "azurerm_automation_variable_bool" "test" { @@ -129,10 +127,8 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" + sku_name = "Basic" - sku { - name = "Basic" - } } resource "azurerm_automation_variable_bool" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_datetime_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_datetime_test.go index efb0613a105c3..b3b5ea423d931 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_datetime_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_datetime_test.go @@ -103,10 +103,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_datetime" "test" { @@ -129,10 +126,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_datetime" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_int_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_int_test.go index ab4a6b89f3439..70e64939debab 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_int_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_int_test.go @@ -103,10 +103,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_int" "test" { @@ -129,10 +126,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_int" "test" { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_string_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_string_test.go index 6dbddc3747da9..eccf0d21bd5cf 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_variable_string_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_variable_string_test.go @@ -103,10 +103,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_string" "test" { @@ -129,10 +126,7 @@ resource "azurerm_automation_account" "test" { name = "acctestAutoAcct-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } + sku_name = "Basic" } resource "azurerm_automation_variable_string" "test" { From 97c13decb5e4b5e9100f505aed6179884accf5dd Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 17:42:30 +0000 Subject: [PATCH 170/498] fix two more tests for attribute reference --- .../tests/resource_arm_automation_certificate_test.go | 2 +- .../automation/tests/resource_arm_automation_runbook_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go index 57ed01c00ab6e..0e7aeec998267 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go @@ -202,7 +202,7 @@ func testAccAzureRMAutomationCertificate_requiresImport(data acceptance.TestData resource "azurerm_automation_certificate" "import" { name = azurerm_automation_certificate.test.name resource_group_name = azurerm_automation_certificate.test.resource_group_name - automation_account_name = azurerm_automation_certificate.test.account_name + automation_account_name = azurerm_automation_certificate.test.automation_account_name base64 = azurerm_automation_certificate.test.base64 thumbprint = azurerm_automation_certificate.test.thumbprint } diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go index 6b3e947a45145..d6db879dc44b7 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_runbook_test.go @@ -203,7 +203,7 @@ resource "azurerm_automation_runbook" "import" { name = "${azurerm_automation_runbook.test.name}" location = "${azurerm_automation_runbook.test.location}" resource_group_name = "${azurerm_automation_runbook.test.resource_group_name}" - automation_account_name = "${azurerm_automation_runbook.test.account_name}" + automation_account_name = "${azurerm_automation_runbook.test.automation_account_name}" log_verbose = "true" log_progress = "true" From 3aed7c858e081689951fad83b947ca1e1aa5035a Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 09:52:09 -0800 Subject: [PATCH 171/498] Remove deadcode --- .../tests/resource_arm_mysql_server_test.go | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go index b2070f11645dd..267d9ea4315da 100644 --- a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go +++ b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go @@ -408,34 +408,6 @@ resource "azurerm_mysql_server" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMMySQLServer_memoryOptimized(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_mysql_server" "test" { - name = "acctestmysqlsvr-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku_name = "MO_Gen5_16" - - storage_profile { - storage_mb = 4194304 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } - - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "5.7" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMMySQLServer_memoryOptimizedGeoRedundant(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From 32433ddb72c7d50d203e82826136fa921c94ca01 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Mon, 17 Feb 2020 17:55:58 +0000 Subject: [PATCH 172/498] Removed legacy tests no longer required --- .../resource_arm_automation_account_test.go | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go index 82954de9d00a2..f2d6252cce6fe 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go @@ -2,7 +2,6 @@ package tests import ( "fmt" - "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -36,47 +35,6 @@ func TestAccAzureRMAutomationAccount_basic(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMAutomationAccount_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_automation_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMAutomationAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMAutomationAccount_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMAutomationAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "Basic"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_server_endpoint"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_primary_access_key"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_secondary_access_key"), - ), - }, - data.ImportStep(), - }, - }) -} - -// Remove in 2.0 -func TestAccAzureRMAutomationAccount_basicNotDefined(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_automation_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMAutomationAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMAutomationAccount_basicNotDefined(data), - ExpectError: regexp.MustCompile("either 'sku_name' or 'sku' must be defined in the configuration file"), - }, - }, - }) -} - func TestAccAzureRMAutomationAccount_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -200,39 +158,6 @@ resource "azurerm_automation_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -// Remove in 2.0 -func testAccAzureRMAutomationAccount_basicClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_automation_account" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku_name = "Basic" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -// Remove in 2.0 -func testAccAzureRMAutomationAccount_basicNotDefined(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_automation_account" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMAutomationAccount_requiresImport(data acceptance.TestData) string { template := testAccAzureRMAutomationAccount_basic(data) return fmt.Sprintf(` From 206453694468df4ecb724ad200bd727454b5e71c Mon Sep 17 00:00:00 2001 From: John Wildes Date: Mon, 17 Feb 2020 12:52:18 -0600 Subject: [PATCH 173/498] Update ACR docs SKU and GeoRepl Note --- website/docs/r/container_registry.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/container_registry.html.markdown b/website/docs/r/container_registry.html.markdown index eed63df0fb58f..2f1a7435a45e8 100644 --- a/website/docs/r/container_registry.html.markdown +++ b/website/docs/r/container_registry.html.markdown @@ -46,7 +46,7 @@ The following arguments are supported: * `storage_account_id` - (Required for `Classic` Sku - Forbidden otherwise) The ID of a Storage Account which must be located in the same Azure Region as the Container Registry. -* `sku` - (Optional) The SKU name of the container registry. Possible values are `Classic` (which was previously `Basic`), `Basic`, `Standard` and `Premium`. +* `sku` - (Optional) The SKU name of the container registry. Possible values are `Basic`, `Standard` and `Premium`. `Classic` (which was previously `Basic`) is supported only for existing resources. ~> **NOTE:** The `Classic` SKU is Deprecated and will no longer be available for new resources from the end of March 2019. @@ -54,6 +54,8 @@ The following arguments are supported: * `georeplication_locations` - (Optional) A list of Azure locations where the container registry should be geo-replicated. +~> **NOTE:** The `georeplication_locations` is only supported on new resources with the `Premium` SKU. + * `network_rule_set` - (Optional) A `network_rule_set` block as documented below. `network_rule_set` supports the following: From 8e3a70fa2082e30950c0c895b84c81ae978a0349 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 11:39:12 -0800 Subject: [PATCH 174/498] eventhub -> 2.0 --- .../services/eventhub/resource_arm_eventhub.go | 3 --- .../resource_arm_eventhub_authorization_rule.go | 2 -- .../eventhub/resource_arm_eventhub_consumer_group.go | 2 -- .../eventhub/resource_arm_eventhub_namespace.go | 10 ---------- ...source_arm_eventhub_namespace_authorization_rule.go | 2 -- website/docs/r/eventhub_namespace.html.markdown | 4 ---- 6 files changed, 23 deletions(-) diff --git a/azurerm/internal/services/eventhub/resource_arm_eventhub.go b/azurerm/internal/services/eventhub/resource_arm_eventhub.go index a16f9b115fcde..9c123649a3fe1 100644 --- a/azurerm/internal/services/eventhub/resource_arm_eventhub.go +++ b/azurerm/internal/services/eventhub/resource_arm_eventhub.go @@ -52,9 +52,6 @@ func resourceArmEventHub() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // TODO: remove me in the next major version - "location": azure.SchemaLocationDeprecated(), - "partition_count": { Type: schema.TypeInt, Required: true, diff --git a/azurerm/internal/services/eventhub/resource_arm_eventhub_authorization_rule.go b/azurerm/internal/services/eventhub/resource_arm_eventhub_authorization_rule.go index 6c96f669d2a8b..8fcf45bc0cf5b 100644 --- a/azurerm/internal/services/eventhub/resource_arm_eventhub_authorization_rule.go +++ b/azurerm/internal/services/eventhub/resource_arm_eventhub_authorization_rule.go @@ -57,8 +57,6 @@ func resourceArmEventHubAuthorizationRule() *schema.Resource { }, "resource_group_name": azure.SchemaResourceGroupName(), - - "location": azure.SchemaLocationDeprecated(), }), CustomizeDiff: azure.EventHubAuthorizationRuleCustomizeDiff, diff --git a/azurerm/internal/services/eventhub/resource_arm_eventhub_consumer_group.go b/azurerm/internal/services/eventhub/resource_arm_eventhub_consumer_group.go index 6553378d42005..75d32d0fa6c81 100644 --- a/azurerm/internal/services/eventhub/resource_arm_eventhub_consumer_group.go +++ b/azurerm/internal/services/eventhub/resource_arm_eventhub_consumer_group.go @@ -57,8 +57,6 @@ func resourceArmEventHubConsumerGroup() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - "location": azure.SchemaLocationDeprecated(), - "user_metadata": { Type: schema.TypeString, Optional: true, diff --git a/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace.go b/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace.go index 75ae45576d158..b3d11deabdd0c 100644 --- a/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace.go +++ b/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace.go @@ -78,13 +78,6 @@ func resourceArmEventHubNamespace() *schema.Resource { Default: false, }, - "kafka_enabled": { - Type: schema.TypeBool, - Optional: true, - Computed: true, - Deprecated: "This field is now automatically set depending on the SKU used - as such it's no longer used and will be removed in 2.0 of the Azure Provider", - }, - "maximum_throughput_units": { Type: schema.TypeInt, Optional: true, @@ -314,9 +307,6 @@ func resourceArmEventHubNamespaceRead(d *schema.ResourceData, meta interface{}) if props := resp.EHNamespaceProperties; props != nil { d.Set("auto_inflate_enabled", props.IsAutoInflateEnabled) d.Set("maximum_throughput_units", int(*props.MaximumThroughputUnits)) - - // TODO: remove me in 2.0 - d.Set("kafka_enabled", props.KafkaEnabled) } ruleset, err := client.GetNetworkRuleSet(ctx, resGroup, name) diff --git a/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace_authorization_rule.go b/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace_authorization_rule.go index 662320cb9b97d..b1e96d35f049a 100644 --- a/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace_authorization_rule.go +++ b/azurerm/internal/services/eventhub/resource_arm_eventhub_namespace_authorization_rule.go @@ -50,8 +50,6 @@ func resourceArmEventHubNamespaceAuthorizationRule() *schema.Resource { }, "resource_group_name": azure.SchemaResourceGroupName(), - - "location": azure.SchemaLocationDeprecated(), }), CustomizeDiff: azure.EventHubAuthorizationRuleCustomizeDiff, diff --git a/website/docs/r/eventhub_namespace.html.markdown b/website/docs/r/eventhub_namespace.html.markdown index 11aabca1bb708..7ae14af1ec139 100644 --- a/website/docs/r/eventhub_namespace.html.markdown +++ b/website/docs/r/eventhub_namespace.html.markdown @@ -49,10 +49,6 @@ The following arguments are supported: * `maximum_throughput_units` - (Optional) Specifies the maximum number of throughput units when Auto Inflate is Enabled. Valid values range from `1` - `20`. -* `kafka_enabled` - (Optional / **Deprecated**) Is Kafka enabled for the EventHub Namespace? Defaults to `false`. - --> **NOTE:** `kafka_enabled` is now configured depending on the `sku` being provisioned, where this is Disabled for a `Basic` sku and Enabled for a Standard sku. - * `tags` - (Optional) A mapping of tags to assign to the resource. * `network_rulesets` - (Optional) A `network_rulesets` block as defined below. From b2777ab8645d21a7d80c97399d2b96adf4759f66 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 11:50:14 -0800 Subject: [PATCH 175/498] 2.0-dns --- .../services/dns/data_source_dns_zone.go | 7 - .../dns/resource_arm_dns_ns_record.go | 47 +--- .../services/dns/resource_arm_dns_zone.go | 15 - .../tests/resource_arm_dns_ns_record_test.go | 257 ------------------ .../dns/tests/resource_arm_dns_zone_test.go | 1 - website/docs/d/dns_zone.html.markdown | 3 - website/docs/r/dns_ns_record.html.markdown | 8 +- website/docs/r/dns_zone.html.markdown | 6 - 8 files changed, 5 insertions(+), 339 deletions(-) diff --git a/azurerm/internal/services/dns/data_source_dns_zone.go b/azurerm/internal/services/dns/data_source_dns_zone.go index 79f38a81fc4b3..4ee9f56b3eff2 100644 --- a/azurerm/internal/services/dns/data_source_dns_zone.go +++ b/azurerm/internal/services/dns/data_source_dns_zone.go @@ -51,12 +51,6 @@ func dataSourceArmDnsZone() *schema.Resource { Set: schema.HashString, }, - "zone_type": { - Type: schema.TypeString, - Computed: true, - Deprecated: "Private DNS Zones are now supported through a separate resource in Azure & Terraform", - }, - "registration_virtual_network_ids": { Type: schema.TypeList, Computed: true, @@ -114,7 +108,6 @@ func dataSourceArmDnsZoneRead(d *schema.ResourceData, meta interface{}) error { if props := resp.ZoneProperties; props != nil { d.Set("number_of_record_sets", props.NumberOfRecordSets) d.Set("max_number_of_record_sets", props.MaxNumberOfRecordSets) - d.Set("zone_type", props.ZoneType) registrationVNets := make([]string, 0) if rvns := props.RegistrationVirtualNetworks; rvns != nil { diff --git a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go index a1d5e37a85cb3..99a2eff1a6da5 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go +++ b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go @@ -48,28 +48,9 @@ func resourceArmDnsNsRecord() *schema.Resource { }, "records": { - Type: schema.TypeList, - //TODO: add `Required: true` once we remove the `record` attribute - Optional: true, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - ConflictsWith: []string{"record"}, - }, - - "record": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Deprecated: "This field has been replaced by `records`", - ConflictsWith: []string{"records"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "nsdname": { - Type: schema.TypeString, - Required: true, - }, - }, - }, + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, "ttl": { @@ -174,11 +155,6 @@ func resourceArmDnsNsRecordRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error settings `records`: %+v", err) } - //TODO: remove this once we remove the `record` attribute - if err := d.Set("record", flattenAzureRmDnsNsRecordsSet(resp.NsRecords)); err != nil { - return fmt.Errorf("Error settings `record`: %+v", err) - } - return tags.FlattenAndSet(d, resp.Metadata) } @@ -234,8 +210,7 @@ func flattenAzureRmDnsNsRecords(records *[]dns.NsRecord) []string { func expandAzureRmDnsNsRecords(d *schema.ResourceData) *[]dns.NsRecord { var records []dns.NsRecord - //TODO: remove this once we remove the `record` attribute - if d.HasChange("records") || !d.HasChange("record") { + if d.HasChange("records") { recordStrings := d.Get("records").([]interface{}) records = make([]dns.NsRecord, len(recordStrings)) for i, v := range recordStrings { @@ -247,20 +222,6 @@ func expandAzureRmDnsNsRecords(d *schema.ResourceData) *[]dns.NsRecord { records[i] = nsRecord } - } else { - recordList := d.Get("record").(*schema.Set).List() - if len(recordList) != 0 { - records = make([]dns.NsRecord, len(recordList)) - for i, v := range recordList { - record := v.(map[string]interface{}) - nsdname := record["nsdname"].(string) - nsRecord := dns.NsRecord{ - Nsdname: &nsdname, - } - - records[i] = nsRecord - } - } } return &records } diff --git a/azurerm/internal/services/dns/resource_arm_dns_zone.go b/azurerm/internal/services/dns/resource_arm_dns_zone.go index 8cbc72e5a3b8b..a073ae37bcf95 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_zone.go +++ b/azurerm/internal/services/dns/resource_arm_dns_zone.go @@ -7,7 +7,6 @@ import ( "github.com/Azure/azure-sdk-for-go/services/dns/mgmt/2018-05-01/dns" "github.com/hashicorp/go-azure-helpers/response" "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/internal/clients" @@ -60,17 +59,6 @@ func resourceArmDnsZone() *schema.Resource { Set: schema.HashString, }, - "zone_type": { - Type: schema.TypeString, - Default: string(dns.Public), - Optional: true, - Deprecated: "Use the `azurerm_private_dns_zone` resource instead.", - ValidateFunc: validation.StringInSlice([]string{ - string(dns.Private), - string(dns.Public), - }, false), - }, - "registration_virtual_network_ids": { Type: schema.TypeList, Optional: true, @@ -110,7 +98,6 @@ func resourceArmDnsZoneCreateUpdate(d *schema.ResourceData, meta interface{}) er } location := "global" - zoneType := d.Get("zone_type").(string) t := d.Get("tags").(map[string]interface{}) registrationVirtualNetworkIds := expandDnsZoneRegistrationVirtualNetworkIds(d) @@ -120,7 +107,6 @@ func resourceArmDnsZoneCreateUpdate(d *schema.ResourceData, meta interface{}) er Location: &location, Tags: tags.Expand(t), ZoneProperties: &dns.ZoneProperties{ - ZoneType: dns.ZoneType(zoneType), RegistrationVirtualNetworks: registrationVirtualNetworkIds, ResolutionVirtualNetworks: resolutionVirtualNetworkIds, }, @@ -173,7 +159,6 @@ func resourceArmDnsZoneRead(d *schema.ResourceData, meta interface{}) error { d.Set("resource_group_name", resGroup) d.Set("number_of_record_sets", resp.NumberOfRecordSets) d.Set("max_number_of_record_sets", resp.MaxNumberOfRecordSets) - d.Set("zone_type", resp.ZoneType) registrationVirtualNetworks := flattenDnsZoneRegistrationVirtualNetworkIDs(resp.RegistrationVirtualNetworks) if err := d.Set("registration_virtual_network_ids", registrationVirtualNetworks); err != nil { diff --git a/azurerm/internal/services/dns/tests/resource_arm_dns_ns_record_test.go b/azurerm/internal/services/dns/tests/resource_arm_dns_ns_record_test.go index f35992c2e2596..f4d159818a33d 100644 --- a/azurerm/internal/services/dns/tests/resource_arm_dns_ns_record_test.go +++ b/azurerm/internal/services/dns/tests/resource_arm_dns_ns_record_test.go @@ -13,25 +13,6 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" ) -//TODO: remove this once we remove the `record` attribute -func TestAccAzureRMDnsNsRecord_deprecatedBasic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDnsNsRecord_deprecatedBasic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - ), - }, - }, - }) -} - func TestAccAzureRMDnsNsRecord_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") @@ -79,33 +60,6 @@ func TestAccAzureRMDnsNsRecord_requiresImport(t *testing.T) { }) } -//TODO: remove this once we remove the `record` attribute -func TestAccAzureRMDnsNsRecord_deprecatedUpdateRecords(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDnsNsRecord_deprecatedBasic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "record.#", "2"), - ), - }, - { - Config: testAccAzureRMDnsNsRecord_deprecatedUpdateRecords(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "record.#", "3"), - ), - }, - }, - }) -} - func TestAccAzureRMDnsNsRecord_updateRecords(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") @@ -132,60 +86,6 @@ func TestAccAzureRMDnsNsRecord_updateRecords(t *testing.T) { }) } -//TODO: remove this once we remove the `record` attribute -func TestAccAzureRMDnsNsRecord_deprecatedChangeRecordToRecords(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDnsNsRecord_deprecatedBasic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "records.#", "2"), - ), - }, - { - Config: testAccAzureRMDnsNsRecord_deprecatedBasicNewRecords(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "records.#", "2"), - ), - }, - }, - }) -} - -//TODO: remove this once we remove the `record` attribute -func TestAccAzureRMDnsNsRecord_deprecatedWithTags(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDnsNsRecordDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDnsNsRecord_deprecatedWithTags(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "2"), - ), - }, - { - Config: testAccAzureRMDnsNsRecord_deprecatedWithTagsUpdate(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsNsRecordExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "1"), - ), - }, - }, - }) -} - func TestAccAzureRMDnsNsRecord_withTags(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_dns_ns_record", "test") @@ -310,60 +210,6 @@ resource "azurerm_dns_ns_record" "import" { `, template) } -//TODO: remove this once we remove the `record` attribute -func testAccAzureRMDnsNsRecord_deprecatedBasic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_dns_ns_record" "test" { - name = "mynsrecord%d" - resource_group_name = "${azurerm_resource_group.test.name}" - zone_name = "${azurerm_dns_zone.test.name}" - ttl = 300 - - record { - nsdname = "ns1.contoso.com" - } - - record { - nsdname = "ns2.contoso.com" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -//TODO: remove this once we remove the `record` attribute -func testAccAzureRMDnsNsRecord_deprecatedBasicNewRecords(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_dns_ns_record" "test" { - name = "mynsrecord%d" - resource_group_name = "${azurerm_resource_group.test.name}" - zone_name = "${azurerm_dns_zone.test.name}" - ttl = 300 - - records = ["ns2.contoso.com", "ns1.contoso.com"] -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - func testAccAzureRMDnsNsRecord_updateRecords(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -387,40 +233,6 @@ resource "azurerm_dns_ns_record" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } -//TODO: remove this once we remove the `record` attribute -func testAccAzureRMDnsNsRecord_deprecatedUpdateRecords(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_dns_ns_record" "test" { - name = "mynsrecord%d" - resource_group_name = "${azurerm_resource_group.test.name}" - zone_name = "${azurerm_dns_zone.test.name}" - ttl = 300 - - record { - nsdname = "ns1.contoso.com" - } - - record { - nsdname = "ns2.contoso.com" - } - - record { - nsdname = "ns3.contoso.com" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - func testAccAzureRMDnsNsRecord_withTags(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -449,41 +261,6 @@ resource "azurerm_dns_ns_record" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } -//TODO: remove this once we remove the `record` attribute -func testAccAzureRMDnsNsRecord_deprecatedWithTags(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_dns_ns_record" "test" { - name = "mynsrecord%d" - resource_group_name = "${azurerm_resource_group.test.name}" - zone_name = "${azurerm_dns_zone.test.name}" - ttl = 300 - - record { - nsdname = "ns1.contoso.com" - } - - record { - nsdname = "ns2.contoso.com" - } - - tags = { - environment = "Production" - cost_center = "MSFT" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - func testAccAzureRMDnsNsRecord_withTagsUpdate(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -510,37 +287,3 @@ resource "azurerm_dns_ns_record" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } - -//TODO: remove this once we remove the `record` attribute -func testAccAzureRMDnsNsRecord_deprecatedWithTagsUpdate(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_dns_ns_record" "test" { - name = "mynsrecord%d" - resource_group_name = "${azurerm_resource_group.test.name}" - zone_name = "${azurerm_dns_zone.test.name}" - ttl = 300 - - record { - nsdname = "ns1.contoso.com" - } - - record { - nsdname = "ns2.contoso.com" - } - - tags = { - environment = "staging" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} diff --git a/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go b/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go index 0d935db321d62..fc0302a2997c1 100644 --- a/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go +++ b/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go @@ -205,7 +205,6 @@ resource "azurerm_virtual_network" "test" { resource "azurerm_dns_zone" "test" { name = "acctestzone%d.com" resource_group_name = "${azurerm_resource_group.test.name}" - zone_type = "Private" registration_virtual_network_ids = ["${azurerm_virtual_network.test.id}"] } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Primary, data.RandomInteger) diff --git a/website/docs/d/dns_zone.html.markdown b/website/docs/d/dns_zone.html.markdown index 0ff4c48211cda..dbeac7e854005 100644 --- a/website/docs/d/dns_zone.html.markdown +++ b/website/docs/d/dns_zone.html.markdown @@ -41,9 +41,6 @@ in your subscription that matches `name` will be returned. * `registration_virtual_network_ids` - A list of Virtual Network ID's that register hostnames in this DNS zone. * `resolution_virtual_network_ids` - A list of Virtual Network ID's that resolve records in this DNS zone. * `tags` - A mapping of tags to assign to the EventHub Namespace. -* `zone_type` - (**Deprecated**) The type of this DNS zone, such as `Public` or `Private`. - -~> **Note:** This field is deprecated since Private DNS is now a separate resource and will be removed in 2.0 of the Azure Provider. ## Timeouts diff --git a/website/docs/r/dns_ns_record.html.markdown b/website/docs/r/dns_ns_record.html.markdown index 0774ff5adba72..97341fbf9a291 100644 --- a/website/docs/r/dns_ns_record.html.markdown +++ b/website/docs/r/dns_ns_record.html.markdown @@ -48,16 +48,10 @@ The following arguments are supported: * `ttl` - (Required) The Time To Live (TTL) of the DNS record in seconds. -* `records` - (Optional) A list of values that make up the NS record. *WARNING*: Either `records` or `record` is required. - -* `record` - (Optional) A list of values that make up the NS record. Each `record` block supports fields documented below. This field has been deprecated and will be removed in a future release. +* `records` - (Required) A list of values that make up the NS record. * `tags` - (Optional) A mapping of tags to assign to the resource. -The `record` block supports: - -* `nsdname` - (Required) The value of the record. - ## Attributes Reference The following attributes are exported: diff --git a/website/docs/r/dns_zone.html.markdown b/website/docs/r/dns_zone.html.markdown index 15ea41a3b08fe..230d4da6e0aa3 100644 --- a/website/docs/r/dns_zone.html.markdown +++ b/website/docs/r/dns_zone.html.markdown @@ -21,13 +21,11 @@ resource "azurerm_resource_group" "example" { resource "azurerm_dns_zone" "example-public" { name = "mydomain.com" resource_group_name = azurerm_resource_group.example.name - zone_type = "Public" } resource "azurerm_dns_zone" "example-private" { name = "mydomain.com" resource_group_name = azurerm_resource_group.example.name - zone_type = "Private" } ``` ## Argument Reference @@ -44,10 +42,6 @@ The following arguments are supported: * `tags` - (Optional) A mapping of tags to assign to the resource. -* `zone_type` - (Optional / **Deprecated**) Specifies the type of this DNS zone. Possible values are `Public` or `Private` (Defaults to `Public`). - -~> **NOTE:** This field was part of the initial Preview for Private DNS Zones - which has been [replaced by the separate resource `azurerm_private_dns_zone`](private_dns_zone.html) and will be removed in v2.0 of the Azure Provider. - ## Attributes Reference The following attributes are exported: From 3583ca4d8f2e70a4cb8c64d60d0ea8d572e46095 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 12:04:56 -0800 Subject: [PATCH 176/498] 2.0-devspace --- .../resource_arm_devspace_controller.go | 83 ++----------------- .../resource_arm_devspace_controller_test.go | 71 ---------------- 2 files changed, 5 insertions(+), 149 deletions(-) diff --git a/azurerm/internal/services/devspace/resource_arm_devspace_controller.go b/azurerm/internal/services/devspace/resource_arm_devspace_controller.go index 12b20d526e244..5bbfd9e51c0f6 100644 --- a/azurerm/internal/services/devspace/resource_arm_devspace_controller.go +++ b/azurerm/internal/services/devspace/resource_arm_devspace_controller.go @@ -53,43 +53,13 @@ func resourceArmDevSpaceController() *schema.Resource { "sku_name": { Type: schema.TypeString, - Optional: true, // required in 2.0 - Computed: true, // remove in 2.0 - //ForceNew: true, // uncomment in 2.0 - this should be fine as there is only 1 valid value - ConflictsWith: []string{"sku"}, + Required: true, + ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ "S1", }, false), }, - "sku": { - Type: schema.TypeList, - Optional: true, - //ForceNew: true, // uncomment in 2.0 - this should be fine as there is only 1 valid value - Computed: true, - ConflictsWith: []string{"sku_name"}, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "S1", - }, false), - }, - "tier": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(devspaces.Standard), - }, false), - }, - }, - }, - }, - "target_container_host_resource_id": { Type: schema.TypeString, Required: true, @@ -146,17 +116,9 @@ func resourceArmDevSpaceControllerCreate(d *schema.ResourceData, meta interface{ location := azure.NormalizeLocation(d.Get("location").(string)) t := d.Get("tags").(map[string]interface{}) - var sku *devspaces.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandControllerSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for DevSpace Controller %s (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandDevSpaceControllerSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for DevSpace Controller %q (Resource Group %q)", name, resourceGroup) + sku, err := expandControllerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding `sku_name` for DevSpace Controller %s (Resource Group %q): %v", name, resourceGroup, err) } controller := devspaces.Controller{ @@ -250,10 +212,6 @@ func resourceArmDevSpaceControllerRead(d *schema.ResourceData, meta interface{}) d.Set("sku_name", sku.Name) } - if err := d.Set("sku", flattenDevSpaceControllerSku(resp.Sku)); err != nil { - return fmt.Errorf("Error flattenning `sku`: %+v", err) - } - if props := resp.ControllerProperties; props != nil { d.Set("host_suffix", props.HostSuffix) d.Set("data_plane_fqdn", props.DataPlaneFqdn) @@ -299,34 +257,3 @@ func expandControllerSkuName(skuName string) (*devspaces.Sku, error) { Tier: tier, }, nil } - -func expandDevSpaceControllerSku(d *schema.ResourceData) *devspaces.Sku { - if _, ok := d.GetOk("sku"); !ok { - return nil - } - - skuConfigs := d.Get("sku").([]interface{}) - skuConfig := skuConfigs[0].(map[string]interface{}) - skuName := skuConfig["name"].(string) - skuTier := devspaces.SkuTier(skuConfig["tier"].(string)) - - return &devspaces.Sku{ - Name: &skuName, - Tier: skuTier, - } -} - -func flattenDevSpaceControllerSku(skuObj *devspaces.Sku) []interface{} { - if skuObj == nil { - return []interface{}{} - } - - skuConfig := make(map[string]interface{}) - if skuObj.Name != nil { - skuConfig["name"] = *skuObj.Name - } - - skuConfig["tier"] = skuObj.Tier - - return []interface{}{skuConfig} -} diff --git a/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go b/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go index e0f0b48df240c..ff7972fb838e3 100644 --- a/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go +++ b/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go @@ -29,29 +29,6 @@ func TestAccAzureRMDevSpaceController_basic(t *testing.T) { Config: testAccAzureRMDevSpaceController_basic(data, clientId, clientSecret), Check: resource.ComposeTestCheckFunc( testCheckAzureRMDevSpaceControllerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.#", "1"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), - ), - }, - }, - }) -} - -func TestAccAzureRMDevSpaceController_basicOldSku(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_devspace_controller", "test") - clientId := os.Getenv("ARM_CLIENT_ID") - clientSecret := os.Getenv("ARM_CLIENT_SECRET") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDevSpaceControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDevSpaceController_basicOldSku(data, clientId, clientSecret), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDevSpaceControllerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.#", "1"), resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), ), }, @@ -193,54 +170,6 @@ resource "azurerm_devspace_controller" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, clientId, clientSecret, data.RandomInteger) } -func testAccAzureRMDevSpaceController_basicOldSku(data acceptance.TestData, clientId string, clientSecret string) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_kubernetes_cluster" "test" { - name = "acctestaks%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - dns_prefix = "acctestaks1" - - linux_profile { - admin_username = "acctestuser1" - - ssh_key { - key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld" - } - } - - agent_pool_profile { - name = "default" - count = "1" - vm_size = "Standard_DS2_v2" - } - - service_principal { - client_id = "%s" - client_secret = "%s" - } -} - -resource "azurerm_devspace_controller" "test" { - name = "acctestdsc%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - target_container_host_resource_id = "${azurerm_kubernetes_cluster.test.id}" - target_container_host_credentials_base64 = "${base64encode(azurerm_kubernetes_cluster.test.kube_config_raw)}" - - sku { - name = "S1" - tier = "Standard" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, clientId, clientSecret, data.RandomInteger) -} - func testAccAzureRMDevSpaceController_requiresImport(data acceptance.TestData, clientId string, clientSecret string) string { template := testAccAzureRMDevSpaceController_basic(data, clientId, clientSecret) return fmt.Sprintf(` From fbceb8373435f2f6e22a37f712f121789d638fc4 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 12:31:06 -0800 Subject: [PATCH 177/498] 2.0-cosmos --- .../cosmos/resource_arm_cosmosdb_account.go | 167 ++---------------- 1 file changed, 11 insertions(+), 156 deletions(-) diff --git a/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go b/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go index 0bec359d958a8..b8fe4bfb06884 100644 --- a/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go +++ b/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go @@ -131,43 +131,9 @@ func resourceArmCosmosDbAccount() *schema.Resource { }, }, - // this actually maps to the Location field in the API/SDK on create/update so has been renamed - // failover_policy is just the name of the field we get back from the API on a read - "failover_policy": { - Type: schema.TypeSet, - Optional: true, - Deprecated: "This field has been renamed to 'geo_location' to match Azure's usage", - ConflictsWith: []string{"geo_location"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Optional: true, - Computed: true, - }, - - "location": { - Type: schema.TypeString, - Required: true, - StateFunc: azure.NormalizeLocation, - DiffSuppressFunc: azure.SuppressLocationDiff, - }, - - "priority": { - Type: schema.TypeInt, - Required: true, - }, - }, - }, - Set: resourceAzureRMCosmosDBAccountFailoverPolicyHash, - }, - "geo_location": { Type: schema.TypeSet, - //Required: true, //todo needs to be required when failover_policy is removed - Optional: true, - Computed: true, - ConflictsWith: []string{"failover_policy"}, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -349,21 +315,10 @@ func resourceArmCosmosDbAccountCreate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("CosmosDB Account %s already exists, please import the resource via terraform import", name) } - //hacky, todo fix up once deprecated field 'failover_policy' is removed - var geoLocations []documentdb.Location - if _, ok := d.GetOk("geo_location"); ok { - geoLocations, err = expandAzureRmCosmosDBAccountGeoLocations(name, d) - if err != nil { - return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) geo locations: %+v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("failover_policy"); ok { - geoLocations, err = expandAzureRmCosmosDBAccountFailoverPolicy(name, d) - if err != nil { - return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) failover_policy: %+v", name, resourceGroup, err) - } - } else { - //could be a CustomizeDiff?, but this is temporary - return fmt.Errorf("Neither `geo_location` or `failover_policy` is set for CosmosDB Account %s", name) + + geoLocations, err := expandAzureRmCosmosDBAccountGeoLocations(name, d) + if err != nil { + return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) geo locations: %+v", name, resourceGroup, err) } account := documentdb.DatabaseAccountCreateUpdateParameters{ @@ -429,22 +384,9 @@ func resourceArmCosmosDbAccountUpdate(d *schema.ResourceData, meta interface{}) enableAutomaticFailover := d.Get("enable_automatic_failover").(bool) enableMultipleWriteLocations := d.Get("enable_multiple_write_locations").(bool) - //hacky, todo fix up once deprecated field 'failover_policy' is removed - var newLocations []documentdb.Location - var err error - if _, ok := d.GetOk("geo_location"); ok { - newLocations, err = expandAzureRmCosmosDBAccountGeoLocations(name, d) - if err != nil { - return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) geo locations: %+v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("failover_policy"); ok { - newLocations, err = expandAzureRmCosmosDBAccountFailoverPolicy(name, d) - if err != nil { - return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) failover_policy: %+v", name, resourceGroup, err) - } - } else { - //could be a CustomizeDiff?, but this is temporary - return fmt.Errorf("Neither `geo_location` or `failover_policy` is set for CosmosDB Account '%s'", name) + newLocations, err := expandAzureRmCosmosDBAccountGeoLocations(name, d) + if err != nil { + return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) geo locations: %+v", name, resourceGroup, err) } //get existing locations (if exists) @@ -592,15 +534,9 @@ func resourceArmCosmosDbAccountRead(d *schema.ResourceData, meta interface{}) er if err = d.Set("consistency_policy", flattenAzureRmCosmosDBAccountConsistencyPolicy(resp.ConsistencyPolicy)); err != nil { return fmt.Errorf("Error setting CosmosDB Account %q `consistency_policy` (Resource Group %q): %+v", name, resourceGroup, err) } - if _, ok := d.GetOk("failover_policy"); ok { - if err = d.Set("failover_policy", flattenAzureRmCosmosDBAccountFailoverPolicy(resp.FailoverPolicies)); err != nil { - return fmt.Errorf("Error setting `failover_policy`: %+v", err) - } - } else { - //if failover policy isn't default to using geo_location - if err = d.Set("geo_location", flattenAzureRmCosmosDBAccountGeoLocations(d, resp)); err != nil { - return fmt.Errorf("Error setting `geo_location`: %+v", err) - } + + if err = d.Set("geo_location", flattenAzureRmCosmosDBAccountGeoLocations(d, resp)); err != nil { + return fmt.Errorf("Error setting `geo_location`: %+v", err) } if err = d.Set("capabilities", flattenAzureRmCosmosDBAccountCapabilities(resp.Capabilities)); err != nil { @@ -859,54 +795,6 @@ func expandAzureRmCosmosDBAccountGeoLocations(databaseName string, d *schema.Res return locations, nil } -// todo remove when deprecated field `failover_policy` is -func expandAzureRmCosmosDBAccountFailoverPolicy(databaseName string, d *schema.ResourceData) ([]documentdb.Location, error) { - input := d.Get("failover_policy").(*schema.Set).List() - locations := make([]documentdb.Location, 0, len(input)) - - for _, configRaw := range input { - data := configRaw.(map[string]interface{}) - - locationName := azure.NormalizeLocation(data["location"].(string)) - id := fmt.Sprintf("%s-%s", databaseName, locationName) - failoverPriority := int32(data["priority"].(int)) - - location := documentdb.Location{ - ID: &id, - LocationName: &locationName, - FailoverPriority: &failoverPriority, - } - - locations = append(locations, location) - } - - containsWriteLocation := false - writeFailoverPriority := int32(0) - for _, location := range locations { - if *location.FailoverPriority == writeFailoverPriority { - containsWriteLocation = true - break - } - } - - // all priorities must be unique - locationIds := make(map[int]struct{}, len(locations)) - for _, location := range locations { - priority := int(*location.FailoverPriority) - if _, ok := locationIds[priority]; ok { - return nil, fmt.Errorf("Each Failover Policy needs to be unique") - } - - locationIds[priority] = struct{}{} - } - - if !containsWriteLocation { - return nil, fmt.Errorf("Failover Policy should contain a Write Location (Location '0')") - } - - return locations, nil -} - func expandAzureRmCosmosDBAccountCapabilities(d *schema.ResourceData) *[]documentdb.Capability { capabilities := d.Get("capabilities").(*schema.Set).List() s := make([]documentdb.Capability, 0) @@ -943,25 +831,6 @@ func flattenAzureRmCosmosDBAccountConsistencyPolicy(policy *documentdb.Consisten return []interface{}{result} } -// todo remove when failover_policy field is removed -func flattenAzureRmCosmosDBAccountFailoverPolicy(list *[]documentdb.FailoverPolicy) *schema.Set { - results := schema.Set{ - F: resourceAzureRMCosmosDBAccountFailoverPolicyHash, - } - - for _, i := range *list { - result := map[string]interface{}{ - "id": *i.ID, - "location": azure.NormalizeLocation(*i.LocationName), - "priority": int(*i.FailoverPriority), - } - - results.Add(result) - } - - return &results -} - func flattenAzureRmCosmosDBAccountGeoLocations(d *schema.ResourceData, account documentdb.DatabaseAccount) *schema.Set { locationSet := schema.Set{ F: resourceAzureRMCosmosDBAccountGeoLocationHash, @@ -1029,20 +898,6 @@ func flattenAzureRmCosmosDBAccountVirtualNetworkRules(rules *[]documentdb.Virtua return &results } -// todo remove once deprecated field `failover_policy` is removed -func resourceAzureRMCosmosDBAccountFailoverPolicyHash(v interface{}) int { - var buf bytes.Buffer - - if m, ok := v.(map[string]interface{}); ok { - location := azure.NormalizeLocation(m["location"].(string)) - priority := int32(m["priority"].(int)) - - buf.WriteString(fmt.Sprintf("%s-%d", location, priority)) - } - - return hashcode.String(buf.String()) -} - func resourceAzureRMCosmosDBAccountGeoLocationHash(v interface{}) int { var buf bytes.Buffer From 956284bce4fe744089d6a47bf45d4733cec7b948 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 13:05:59 -0800 Subject: [PATCH 178/498] 2.0-cosmos --- .../services/cosmos/resource_arm_cosmosdb_account.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go b/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go index b8fe4bfb06884..cf632b22bdc6a 100644 --- a/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go +++ b/azurerm/internal/services/cosmos/resource_arm_cosmosdb_account.go @@ -132,8 +132,8 @@ func resourceArmCosmosDbAccount() *schema.Resource { }, "geo_location": { - Type: schema.TypeSet, - Required: true, + Type: schema.TypeSet, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -315,7 +315,6 @@ func resourceArmCosmosDbAccountCreate(d *schema.ResourceData, meta interface{}) return fmt.Errorf("CosmosDB Account %s already exists, please import the resource via terraform import", name) } - geoLocations, err := expandAzureRmCosmosDBAccountGeoLocations(name, d) if err != nil { return fmt.Errorf("Error expanding CosmosDB Account %q (Resource Group %q) geo locations: %+v", name, resourceGroup, err) From 4497bb45ad6e030ba73438c916413f719c844047 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 13:27:50 -0800 Subject: [PATCH 179/498] 2.0-cognitive --- .../resource_arm_cognitive_account.go | 94 ++----------------- .../resource_arm_cognitive_account_test.go | 44 --------- 2 files changed, 8 insertions(+), 130 deletions(-) diff --git a/azurerm/internal/services/cognitive/resource_arm_cognitive_account.go b/azurerm/internal/services/cognitive/resource_arm_cognitive_account.go index d59372452d1ab..7882aea3fbaef 100644 --- a/azurerm/internal/services/cognitive/resource_arm_cognitive_account.go +++ b/azurerm/internal/services/cognitive/resource_arm_cognitive_account.go @@ -91,45 +91,13 @@ func resourceArmCognitiveAccount() *schema.Resource { }, "sku_name": { - Type: schema.TypeString, - Optional: true, // required in 2.0 - Computed: true, // remove in 2.0 - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ "F0", "F1", "S0", "S1", "S2", "S3", "S4", "S5", "S6", "P0", "P1", "P2", }, false), }, - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku_name"}, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "F0", "F1", "S0", "S1", "S2", "S3", "S4", "S5", "S6", "P0", "P1", "P2", - }, false), - }, - - "tier": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - string(cognitiveservices.Free), - string(cognitiveservices.Standard), - string(cognitiveservices.Premium), - }, false), - }, - }, - }, - }, - "tags": tags.Schema(), "endpoint": { @@ -173,17 +141,9 @@ func resourceArmCognitiveAccountCreate(d *schema.ResourceData, meta interface{}) } } - var sku *cognitiveservices.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandAccountSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for Cognitive Account %s (Resource Group %q): %v", name, resourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandCognitiveAccountSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for Cognitive Account %q (Resource Group %q)", name, resourceGroup) + sku, err := expandAccountSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding sku_name for Cognitive Account %s (Resource Group %q): %v", name, resourceGroup, err) } properties := cognitiveservices.Account{ @@ -218,17 +178,9 @@ func resourceArmCognitiveAccountUpdate(d *schema.ResourceData, meta interface{}) return err } - var sku *cognitiveservices.Sku - if b, ok := d.GetOk("sku_name"); ok { - var err error - sku, err = expandAccountSkuName(b.(string)) - if err != nil { - return fmt.Errorf("error expanding sku_name for Cognitive Account %s (Resource Group %q): %v", id.Name, id.ResourceGroup, err) - } - } else if _, ok := d.GetOk("sku"); ok { - sku = expandCognitiveAccountSku(d) - } else { - return fmt.Errorf("One of `sku` or `sku_name` must be set for Cognitive Account %q (Resource Group %q)", id.Name, id.ResourceGroup) + sku, err := expandAccountSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("error expanding sku_name for Cognitive Account %s (Resource Group %q): %v", id.Name, id.ResourceGroup, err) } properties := cognitiveservices.Account{ @@ -276,10 +228,6 @@ func resourceArmCognitiveAccountRead(d *schema.ResourceData, meta interface{}) e d.Set("sku_name", sku.Name) } - if err = d.Set("sku", flattenCognitiveAccountSku(resp.Sku)); err != nil { - return fmt.Errorf("Error setting `sku`: %+v", err) - } - if props := resp.Properties; props != nil { d.Set("endpoint", props.Endpoint) } @@ -339,29 +287,3 @@ func expandAccountSkuName(skuName string) (*cognitiveservices.Sku, error) { Tier: tier, }, nil } - -func expandCognitiveAccountSku(d *schema.ResourceData) *cognitiveservices.Sku { - skus := d.Get("sku").([]interface{}) - sku := skus[0].(map[string]interface{}) - - return &cognitiveservices.Sku{ - Name: utils.String(sku["name"].(string)), - Tier: cognitiveservices.SkuTier(sku["tier"].(string)), - } -} - -func flattenCognitiveAccountSku(input *cognitiveservices.Sku) []interface{} { - if input == nil { - return []interface{}{} - } - - m := map[string]interface{}{ - "tier": string(input.Tier), - } - - if v := input.Name; v != nil { - m["name"] = *v - } - - return []interface{}{m} -} diff --git a/azurerm/internal/services/cognitive/tests/resource_arm_cognitive_account_test.go b/azurerm/internal/services/cognitive/tests/resource_arm_cognitive_account_test.go index 4ad47191f12d1..f09e0e1011dc3 100644 --- a/azurerm/internal/services/cognitive/tests/resource_arm_cognitive_account_test.go +++ b/azurerm/internal/services/cognitive/tests/resource_arm_cognitive_account_test.go @@ -37,29 +37,6 @@ func TestAccAzureRMCognitiveAccount_basic(t *testing.T) { }) } -func TestAccAzureRMCognitiveAccount_basicOldSku(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMAppCognitiveAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMCognitiveAccount_basicOldSku(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMCognitiveAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "kind", "Face"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), - resource.TestCheckResourceAttrSet(data.ResourceName, "primary_access_key"), - resource.TestCheckResourceAttrSet(data.ResourceName, "secondary_access_key"), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMCognitiveAccount_speechServices(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_cognitive_account", "test") @@ -241,27 +218,6 @@ resource "azurerm_cognitive_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -func testAccAzureRMCognitiveAccount_basicOldSku(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_cognitive_account" "test" { - name = "acctestcogacc-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - kind = "Face" - - sku { - name = "S0" - tier = "Standard" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMCognitiveAccount_speechServices(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From 38dd127eaf9ee2d5cfc0a30bf82b33dfb07834ca Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 22:14:30 -0800 Subject: [PATCH 180/498] 2.0-automation --- .../resource_arm_automation_account.go | 67 +--------------- .../resource_arm_automation_credential.go | 30 ++----- .../resource_arm_automation_schedule.go | 49 ++---------- .../resource_arm_automation_account_test.go | 78 ------------------- .../guides/2.0-upgrade-guide.html.markdown | 4 + 5 files changed, 19 insertions(+), 209 deletions(-) diff --git a/azurerm/internal/services/automation/resource_arm_automation_account.go b/azurerm/internal/services/automation/resource_arm_automation_account.go index bc04ffee144b9..ed612228403b2 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_account.go +++ b/azurerm/internal/services/automation/resource_arm_automation_account.go @@ -9,7 +9,6 @@ import ( "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/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" @@ -47,34 +46,9 @@ func resourceArmAutomationAccount() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - // Remove in 2.0 - "sku": { - Type: schema.TypeList, - Optional: true, - Computed: true, - Deprecated: "This property has been deprecated in favour of the 'sku_name' property and will be removed in version 2.0 of the provider", - ConflictsWith: []string{"sku_name"}, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(automation.Basic), - string(automation.Free), - }, true), - }, - }, - }, - }, - "sku_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ConflictsWith: []string{"sku"}, + Type: schema.TypeString, + Required: true, ValidateFunc: validation.StringInSlice([]string{ string(automation.Basic), string(automation.Free), @@ -104,25 +78,8 @@ func resourceArmAutomationAccountCreateUpdate(d *schema.ResourceData, meta inter ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - // Remove in 2.0 - var sku automation.Sku - - if inputs := d.Get("sku").([]interface{}); len(inputs) != 0 { - input := inputs[0].(map[string]interface{}) - v := input["name"].(string) - - sku = automation.Sku{ - Name: automation.SkuNameEnum(v), - } - } else { - // Keep in 2.0 - sku = automation.Sku{ - Name: automation.SkuNameEnum(d.Get("sku_name").(string)), - } - } - - if sku.Name == "" { - return fmt.Errorf("either 'sku_name' or 'sku' must be defined in the configuration file") + sku := automation.Sku{ + Name: automation.SkuNameEnum(d.Get("sku_name").(string)), } log.Printf("[INFO] preparing arguments for Automation Account create/update.") @@ -214,11 +171,6 @@ func resourceArmAutomationAccountRead(d *schema.ResourceData, meta interface{}) } if sku := resp.Sku; sku != nil { - // Remove in 2.0 - if err := d.Set("sku", flattenAutomationAccountSku(sku)); err != nil { - return fmt.Errorf("Error setting 'sku': %+v", err) - } - if err := d.Set("sku_name", string(sku.Name)); err != nil { return fmt.Errorf("Error setting 'sku_name': %+v", err) } @@ -263,14 +215,3 @@ func resourceArmAutomationAccountDelete(d *schema.ResourceData, meta interface{} return nil } - -// Remove in 2.0 -func flattenAutomationAccountSku(sku *automation.Sku) []interface{} { - if sku == nil { - return []interface{}{} - } - - result := map[string]interface{}{} - result["name"] = string(sku.Name) - return []interface{}{result} -} diff --git a/azurerm/internal/services/automation/resource_arm_automation_credential.go b/azurerm/internal/services/automation/resource_arm_automation_credential.go index 13d9a8040d09d..62e01a9cea3ff 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_credential.go +++ b/azurerm/internal/services/automation/resource_arm_automation_credential.go @@ -42,24 +42,11 @@ func resourceArmAutomationCredential() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - //this is AutomationAccountName in the SDK - "account_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - Deprecated: "account_name has been renamed to automation_account_name for clarity and to match the azure API", - ConflictsWith: []string{"automation_account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), - }, - "automation_account_name": { - Type: schema.TypeString, - Optional: true, //todo change to required once account_name has been removed - Computed: true, // todo remove once account_name has been removed - ForceNew: true, - ConflictsWith: []string{"account_name"}, // todo remove once account_name has been removed - ValidateFunc: azure.ValidateAutomationAccountName(), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), }, "username": { @@ -90,13 +77,7 @@ func resourceArmAutomationCredentialCreateUpdate(d *schema.ResourceData, meta in name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) - // todo remove this once `account_name` is removed - accountName := "" - if v, ok := d.GetOk("automation_account_name"); ok { - accountName = v.(string) - } else if v, ok := d.GetOk("account_name"); ok { - accountName = v.(string) - } + accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resGroup, accountName, name) @@ -168,7 +149,6 @@ func resourceArmAutomationCredentialRead(d *schema.ResourceData, meta interface{ d.Set("name", resp.Name) d.Set("resource_group_name", resGroup) d.Set("automation_account_name", accountName) - d.Set("account_name", accountName) if props := resp.CredentialProperties; props != nil { d.Set("username", props.UserName) } diff --git a/azurerm/internal/services/automation/resource_arm_automation_schedule.go b/azurerm/internal/services/automation/resource_arm_automation_schedule.go index dd889645a0b85..e89b2d8a7178a 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_schedule.go +++ b/azurerm/internal/services/automation/resource_arm_automation_schedule.go @@ -49,23 +49,12 @@ func resourceArmAutomationSchedule() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), - //this is AutomationAccountName in the SDK - "account_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "account_name has been renamed to automation_account_name for clarity and to match the azure API", - ConflictsWith: []string{"automation_account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), - }, - "automation_account_name": { - Type: schema.TypeString, - Optional: true, //todo change to required once account_name has been removed - Computed: true, - //ForceNew: true, //todo this needs to come back once account_name has been removed - ConflictsWith: []string{"account_name"}, - ValidateFunc: azure.ValidateAutomationAccountName(), + Type: schema.TypeString, + Required: true, + Computed: true, + ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), }, "frequency": { @@ -206,24 +195,6 @@ func resourceArmAutomationSchedule() *schema.Resource { return fmt.Errorf("`monthly_occurrence` can only be set when frequency is `Month`") } - _, hasAccount := diff.GetOk("automation_account_name") - _, hasAutomationAccountWeb := diff.GetOk("account_name") - if !hasAccount && !hasAutomationAccountWeb { - return fmt.Errorf("`automation_account_name` must be set") - } - - //if automation_account_name changed or account_name changed to or from nil force a new resource - //remove once we remove the deprecated property - oAan, nAan := diff.GetChange("automation_account_name") - if oAan != "" && nAan != "" { - diff.ForceNew("automation_account_name") - } - - oAn, nAn := diff.GetChange("account_name") - if oAn != "" && nAn != "" { - diff.ForceNew("account_name") - } - return nil }, } @@ -238,14 +209,7 @@ func resourceArmAutomationScheduleCreateUpdate(d *schema.ResourceData, meta inte name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) - //CustomizeDiff should ensure one of these two is set - // todo remove this once `account_name` is removed - accountName := "" - if v, ok := d.GetOk("automation_account_name"); ok { - accountName = v.(string) - } else if v, ok := d.GetOk("account_name"); ok { - accountName = v.(string) - } + accountName := d.Get("automation_account_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resGroup, accountName, name) @@ -350,7 +314,6 @@ func resourceArmAutomationScheduleRead(d *schema.ResourceData, meta interface{}) d.Set("name", resp.Name) d.Set("resource_group_name", resGroup) d.Set("automation_account_name", accountName) - d.Set("account_name", accountName) // todo remove once `account_name` is removed d.Set("frequency", string(resp.Frequency)) if v := resp.StartTime; v != nil { diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go index a44de6d452e4f..f2d6252cce6fe 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_account_test.go @@ -2,7 +2,6 @@ package tests import ( "fmt" - "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -36,47 +35,6 @@ func TestAccAzureRMAutomationAccount_basic(t *testing.T) { }) } -// Remove in 2.0 -func TestAccAzureRMAutomationAccount_basicClassic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_automation_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMAutomationAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMAutomationAccount_basicClassic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMAutomationAccountExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "Basic"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_server_endpoint"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_primary_access_key"), - resource.TestCheckResourceAttrSet(data.ResourceName, "dsc_secondary_access_key"), - ), - }, - data.ImportStep(), - }, - }) -} - -// Remove in 2.0 -func TestAccAzureRMAutomationAccount_basicNotDefined(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_automation_account", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMAutomationAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMAutomationAccount_basicNotDefined(data), - ExpectError: regexp.MustCompile("either 'sku_name' or 'sku' must be defined in the configuration file"), - }, - }, - }) -} - func TestAccAzureRMAutomationAccount_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -200,42 +158,6 @@ resource "azurerm_automation_account" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } -// Remove in 2.0 -func testAccAzureRMAutomationAccount_basicClassic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_automation_account" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - sku { - name = "Basic" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -// Remove in 2.0 -func testAccAzureRMAutomationAccount_basicNotDefined(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_automation_account" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMAutomationAccount_requiresImport(data acceptance.TestData) string { template := testAccAzureRMAutomationAccount_basic(data) return fmt.Sprintf(` diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index da2deff1552e6..e7aaca896b1ec 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -225,6 +225,10 @@ The deprecated `ip_address_list` field in the `backend_address_pool` block will The default value for the `body` field within the `match` block will change from `*` to an empty string. +### Resource: `azurerm_automation_account` + +The deprecated `sku` block has been replaced by the `sku_name` field and will be removed. + ### Resource: `azurerm_automation_credential` The deprecated `account_name` field will be removed. This has been deprecated in favour of the `automation_account_name` field. From ef5a2b76e416aa587637c9dc0ed99fdfe2a46d8e Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Mon, 17 Feb 2020 22:17:27 -0800 Subject: [PATCH 181/498] Remove deadcode --- .../services/dns/resource_arm_dns_ns_record.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go index 99a2eff1a6da5..77ff7a4c4846a 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go +++ b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go @@ -180,21 +180,6 @@ func resourceArmDnsNsRecordDelete(d *schema.ResourceData, meta interface{}) erro return nil } -//TODO: remove this once we remove the `record` attribute -func flattenAzureRmDnsNsRecordsSet(records *[]dns.NsRecord) []map[string]interface{} { - results := make([]map[string]interface{}, 0, len(*records)) - - if records != nil { - for _, record := range *records { - nsRecord := make(map[string]interface{}) - nsRecord["nsdname"] = *record.Nsdname - results = append(results, nsRecord) - } - } - - return results -} - func flattenAzureRmDnsNsRecords(records *[]dns.NsRecord) []string { results := make([]string, 0, len(*records)) From 5851764e2b813ee970603fa66f38c61bc27a69ac Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 07:31:25 +0100 Subject: [PATCH 182/498] updating to include #5797 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 117366c22c229..84c2c7339a68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ BREAKING CHANGES: * `azurerm_azuread_application` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_azuread_service_principal_password` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_azuread_service_principal` - This resource has been removed since it was deprecated [GH-5748] +* `azurerm_cognitive_account` - removing the deprecated `sku_name` block [GH-5797] * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] From 15eb7351bc763ffbf26788926e17e035cd6f9e9b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 11:55:57 +0100 Subject: [PATCH 183/498] r/subnet: removing the inline `route_table_id` and `network_security_group_id` fields --- ...rce_arm_kubernetes_cluster_network_test.go | 17 - ...e_arm_kubernetes_cluster_node_pool_test.go | 5 - .../resource_arm_databricks_workspace_test.go | 8 - .../services/network/data_source_subnet.go | 39 +- .../services/network/resource_arm_subnet.go | 314 ++++----- .../network/tests/data_source_subnet_test.go | 189 +++-- ...arm_subnet_nat_gateway_association_test.go | 107 ++- ...network_security_group_association_test.go | 102 ++- ...arm_subnet_route_table_association_test.go | 118 +++- .../network/tests/resource_arm_subnet_test.go | 659 ++++-------------- .../resource_arm_virtual_network_test.go | 84 --- website/docs/d/subnet.html.markdown | 1 - website/docs/r/subnet.html.markdown | 11 +- ...k_security_group_association.html.markdown | 1 - 14 files changed, 628 insertions(+), 1027 deletions(-) diff --git a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go index 1e40fe777f51c..e42a2ed19ecff 100644 --- a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go +++ b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_network_test.go @@ -595,11 +595,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.1.0.0/24" - - # TODO: remove in 2.0 - lifecycle { - ignore_changes = ["route_table_id"] - } } resource "azurerm_kubernetes_cluster" "test" { @@ -667,11 +662,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.1.0.0/24" - - # TODO: remove in 2.0 - lifecycle { - ignore_changes = ["route_table_id"] - } } resource "azurerm_subnet_route_table_association" "test" { @@ -802,7 +792,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.1.0.0/24" - route_table_id = azurerm_route_table.test.id } resource "azurerm_subnet_route_table_association" "test" { @@ -894,11 +883,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "172.0.2.0/24" - - # TODO: remove in 2.0 - lifecycle { - ignore_changes = ["route_table_id"] - } } resource "azurerm_kubernetes_cluster" "test" { @@ -1062,7 +1046,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.1.0.0/24" - route_table_id = azurerm_route_table.test.id } resource "azurerm_subnet_route_table_association" "test" { diff --git a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_node_pool_test.go b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_node_pool_test.go index 800c1bbbe403b..3bc04511a7733 100644 --- a/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_node_pool_test.go +++ b/azurerm/internal/services/containers/tests/resource_arm_kubernetes_cluster_node_pool_test.go @@ -1079,11 +1079,6 @@ resource "azurerm_subnet" "test" { resource_group_name = azurerm_resource_group.test.name virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.1.0.0/24" - - # TODO: remove in 2.0 - lifecycle { - ignore_changes = ["route_table_id"] - } } resource "azurerm_subnet_route_table_association" "test" { diff --git a/azurerm/internal/services/databricks/tests/resource_arm_databricks_workspace_test.go b/azurerm/internal/services/databricks/tests/resource_arm_databricks_workspace_test.go index 65bd9fbb5ce8e..79c28089bfb24 100644 --- a/azurerm/internal/services/databricks/tests/resource_arm_databricks_workspace_test.go +++ b/azurerm/internal/services/databricks/tests/resource_arm_databricks_workspace_test.go @@ -308,10 +308,6 @@ resource "azurerm_subnet" "public" { ] } } - - lifecycle { - ignore_changes = ["network_security_group_id"] - } } resource "azurerm_subnet" "private" { @@ -333,10 +329,6 @@ resource "azurerm_subnet" "private" { ] } } - - lifecycle { - ignore_changes = ["network_security_group_id"] - } } resource "azurerm_network_security_group" "nsg" { diff --git a/azurerm/internal/services/network/data_source_subnet.go b/azurerm/internal/services/network/data_source_subnet.go index befd916815880..752579d715852 100644 --- a/azurerm/internal/services/network/data_source_subnet.go +++ b/azurerm/internal/services/network/data_source_subnet.go @@ -2,7 +2,6 @@ package network import ( "fmt" - "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -51,13 +50,6 @@ func dataSourceArmSubnet() *schema.Resource { Computed: true, }, - "ip_configurations": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "service_endpoints": { Type: schema.TypeList, Computed: true, @@ -104,32 +96,23 @@ func dataSourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - if pe := props.PrivateEndpointNetworkPolicies; pe != nil { - d.Set("enforce_private_link_endpoint_network_policies", strings.EqualFold("Disabled", *pe)) - } - - if ps := props.PrivateLinkServiceNetworkPolicies; ps != nil { - d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *ps)) - } - - if props.NetworkSecurityGroup != nil { - d.Set("network_security_group_id", props.NetworkSecurityGroup.ID) - } else { - d.Set("network_security_group_id", "") - } + d.Set("enforce_private_link_endpoint_network_policies", flattenSubnetPrivateLinkNetworkPolicy(props.PrivateEndpointNetworkPolicies)) + d.Set("enforce_private_link_service_network_policies", flattenSubnetPrivateLinkNetworkPolicy(props.PrivateLinkServiceNetworkPolicies)) - if props.RouteTable != nil { - d.Set("route_table_id", props.RouteTable.ID) - } else { - d.Set("route_table_id", "") + networkSecurityGroupId := "" + if props.NetworkSecurityGroup != nil && props.NetworkSecurityGroup.ID != nil { + networkSecurityGroupId = *props.NetworkSecurityGroup.ID } + d.Set("network_security_group_id", networkSecurityGroupId) - if err := d.Set("ip_configurations", flattenSubnetIPConfigurations(props.IPConfigurations)); err != nil { - return err + routeTableId := "" + if props.RouteTable != nil && props.RouteTable.ID != nil { + routeTableId = *props.RouteTable.ID } + d.Set("route_table_id", routeTableId) if err := d.Set("service_endpoints", flattenSubnetServiceEndpoints(props.ServiceEndpoints)); err != nil { - return err + return fmt.Errorf("Error setting `service_endpoints`: %+v", err) } } diff --git a/azurerm/internal/services/network/resource_arm_subnet.go b/azurerm/internal/services/network/resource_arm_subnet.go index 725b51482d26a..d7d38b7e309b9 100644 --- a/azurerm/internal/services/network/resource_arm_subnet.go +++ b/azurerm/internal/services/network/resource_arm_subnet.go @@ -22,9 +22,9 @@ var SubnetResourceName = "azurerm_subnet" func resourceArmSubnet() *schema.Resource { return &schema.Resource{ - Create: resourceArmSubnetCreateUpdate, + Create: resourceArmSubnetCreate, Read: resourceArmSubnetRead, - Update: resourceArmSubnetCreateUpdate, + Update: resourceArmSubnetUpdate, Delete: resourceArmSubnetDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, @@ -57,26 +57,6 @@ func resourceArmSubnet() *schema.Resource { Required: true, }, - "network_security_group_id": { - Type: schema.TypeString, - Optional: true, - Deprecated: "Use the `azurerm_subnet_network_security_group_association` resource instead.", - }, - - "route_table_id": { - Type: schema.TypeString, - Optional: true, - Deprecated: "Use the `azurerm_subnet_route_table_association` resource instead.", - }, - - "ip_configurations": { - Type: schema.TypeSet, - Optional: true, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "service_endpoints": { Type: schema.TypeList, Optional: true, @@ -119,10 +99,10 @@ func resourceArmSubnet() *schema.Resource { "Microsoft.Web/serverFarms", }, false), }, + "actions": { Type: schema.TypeList, Optional: true, - Computed: true, ConfigMode: schema.SchemaConfigModeAttr, Elem: &schema.Schema{ Type: schema.TypeString, @@ -157,7 +137,8 @@ func resourceArmSubnet() *schema.Resource { } } -func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) error { +// TODO: refactor the create/flatten functions +func resourceArmSubnetCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Network.SubnetsClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -168,7 +149,7 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err vnetName := d.Get("virtual_network_name").(string) resGroup := d.Get("resource_group_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.Get(ctx, resGroup, vnetName, name, "") if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -186,71 +167,22 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err locks.ByName(vnetName, VirtualNetworkResourceName) defer locks.UnlockByName(vnetName, VirtualNetworkResourceName) - properties := network.SubnetPropertiesFormat{ - AddressPrefix: &addressPrefix, - } - - if v, ok := d.GetOk("enforce_private_link_service_network_policies"); ok { - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not - // supported by private endpoints. - if v.(bool) { - properties.PrivateLinkServiceNetworkPolicies = utils.String("Disabled") - } - } + privateEndpointNetworkPolicies := d.Get("enforce_private_link_endpoint_network_policies").(bool) + privateLinkServiceNetworkPolicies := d.Get("enforce_private_link_service_network_policies").(bool) - if v, ok := d.GetOk("network_security_group_id"); ok { - nsgId := v.(string) - properties.NetworkSecurityGroup = &network.SecurityGroup{ - ID: &nsgId, - } - - parsedNsgId, err := ParseNetworkSecurityGroupID(nsgId) - if err != nil { - return err - } - - locks.ByName(parsedNsgId.Name, networkSecurityGroupResourceName) - defer locks.UnlockByName(parsedNsgId.Name, networkSecurityGroupResourceName) - } else { - properties.NetworkSecurityGroup = nil - } - - if v, ok := d.GetOk("route_table_id"); ok { - rtId := v.(string) - properties.RouteTable = &network.RouteTable{ - ID: &rtId, - } - - parsedRouteTableId, err := ParseRouteTableID(rtId) - if err != nil { - return err - } + serviceEndpointsRaw := d.Get("service_endpoints").([]interface{}) + properties := network.SubnetPropertiesFormat{ + AddressPrefix: &addressPrefix, + ServiceEndpoints: expandSubnetServiceEndpoints(serviceEndpointsRaw), - locks.ByName(parsedRouteTableId.Name, routeTableResourceName) - defer locks.UnlockByName(parsedRouteTableId.Name, routeTableResourceName) - } else { - properties.RouteTable = nil - } - - if v, ok := d.GetOk("enforce_private_link_endpoint_network_policies"); ok { - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not - // supported by private endpoints. - if v.(bool) { - properties.PrivateEndpointNetworkPolicies = utils.String("Disabled") - } + // To enable private endpoints you must disable the network policies for the subnet because + // Network policies like network security groups are not supported by private endpoints. + PrivateEndpointNetworkPolicies: expandSubnetPrivateLinkNetworkPolicy(privateEndpointNetworkPolicies), + PrivateLinkServiceNetworkPolicies: expandSubnetPrivateLinkNetworkPolicy(privateLinkServiceNetworkPolicies), } - serviceEndpoints := expandSubnetServiceEndpoints(d) - properties.ServiceEndpoints = &serviceEndpoints - - delegations := expandSubnetDelegation(d) - properties.Delegations = &delegations + delegationsRaw := d.Get("delegation").([]interface{}) + properties.Delegations = expandSubnetDelegation(delegationsRaw) subnet := network.Subnet{ Name: &name, @@ -279,6 +211,73 @@ func resourceArmSubnetCreateUpdate(d *schema.ResourceData, meta interface{}) err return resourceArmSubnetRead(d, meta) } +func resourceArmSubnetUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.SubnetsClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + networkName := id.Path["virtualNetworks"] + name := id.Path["subnets"] + + existing, err := client.Get(ctx, resourceGroup, networkName, name, "") + if err != nil { + return fmt.Errorf("Error retrieving existing Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) + } + + if existing.SubnetPropertiesFormat == nil { + return fmt.Errorf("Error retrieving existing Subnet %q (Virtual Network %q / Resource Group %q): `properties` was nil", name, networkName, resourceGroup) + } + + // TODO: locking on the NSG/Route Table if applicable + + props := *existing.SubnetPropertiesFormat + + if d.HasChange("address_prefix") { + props.AddressPrefix = utils.String(d.Get("address_prefix").(string)) + } + + if d.HasChange("delegation") { + delegationsRaw := d.Get("delegation").([]interface{}) + props.Delegations = expandSubnetDelegation(delegationsRaw) + } + + if d.HasChange("enforce_private_link_endpoint_network_policies") { + v := d.Get("enforce_private_link_endpoint_network_policies").(bool) + props.PrivateEndpointNetworkPolicies = expandSubnetPrivateLinkNetworkPolicy(v) + } + + if d.HasChange("enforce_private_link_service_network_policies") { + v := d.Get("enforce_private_link_service_network_policies").(bool) + props.PrivateLinkServiceNetworkPolicies = expandSubnetPrivateLinkNetworkPolicy(v) + } + + if d.HasChange("service_endpoints") { + serviceEndpointsRaw := d.Get("service_endpoints").([]interface{}) + props.ServiceEndpoints = expandSubnetServiceEndpoints(serviceEndpointsRaw) + } + + subnet := network.Subnet{ + Name: utils.String(name), + SubnetPropertiesFormat: &props, + } + + future, err := client.CreateOrUpdate(ctx, resourceGroup, networkName, name, subnet) + if err != nil { + return fmt.Errorf("Error updating Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) + } + + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Error waiting for update of Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) + } + + return resourceArmSubnetRead(d, meta) +} + func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Network.SubnetsClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) @@ -288,71 +287,38 @@ func resourceArmSubnetRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - resGroup := id.ResourceGroup - vnetName := id.Path["virtualNetworks"] + resourceGroup := id.ResourceGroup + networkName := id.Path["virtualNetworks"] name := id.Path["subnets"] - resp, err := client.Get(ctx, resGroup, vnetName, name, "") + resp, err := client.Get(ctx, resourceGroup, networkName, name, "") if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Azure Subnet %q: %+v", name, err) + return fmt.Errorf("Error retrieving Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) } d.Set("name", name) - d.Set("resource_group_name", resGroup) - d.Set("virtual_network_name", vnetName) + d.Set("resource_group_name", resourceGroup) + d.Set("virtual_network_name", networkName) if props := resp.SubnetPropertiesFormat; props != nil { d.Set("address_prefix", props.AddressPrefix) - if p := props.PrivateLinkServiceNetworkPolicies; p != nil { - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not - // supported by private endpoints. - - d.Set("enforce_private_link_service_network_policies", strings.EqualFold("Disabled", *p)) - } - - var securityGroupId *string - if props.NetworkSecurityGroup != nil { - securityGroupId = props.NetworkSecurityGroup.ID - } - d.Set("network_security_group_id", securityGroupId) - - var routeTableId string - if props.RouteTable != nil && props.RouteTable.ID != nil { - routeTableId = *props.RouteTable.ID + delegation := flattenSubnetDelegation(props.Delegations) + if err := d.Set("delegation", delegation); err != nil { + return fmt.Errorf("Error flattening `delegation`: %+v", err) } - d.Set("route_table_id", routeTableId) - ips := flattenSubnetIPConfigurations(props.IPConfigurations) - if err := d.Set("ip_configurations", ips); err != nil { - return err - } + d.Set("enforce_private_link_endpoint_network_policies", flattenSubnetPrivateLinkNetworkPolicy(props.PrivateEndpointNetworkPolicies)) + d.Set("enforce_private_link_service_network_policies", flattenSubnetPrivateLinkNetworkPolicy(props.PrivateLinkServiceNetworkPolicies)) serviceEndpoints := flattenSubnetServiceEndpoints(props.ServiceEndpoints) if err := d.Set("service_endpoints", serviceEndpoints); err != nil { - return err - } - - // This is strange logic, but to get the schema to make sense for the end user - // I exposed it with the same name that the Azure CLI does to be consistent - // between the tool sets, which means true == Disabled. - // - // To enable private endpoints you must disable the network policies for the - // subnet because Network policies like network security groups are not - // supported by private endpoints. - if privateEndpointNetworkPolicies := props.PrivateEndpointNetworkPolicies; privateEndpointNetworkPolicies != nil { - d.Set("enforce_private_link_endpoint_network_policies", *privateEndpointNetworkPolicies == "Disabled") - } - - delegation := flattenSubnetDelegation(props.Delegations) - if err := d.Set("delegation", delegation); err != nil { - return fmt.Errorf("Error flattening `delegation`: %+v", err) + return fmt.Errorf("Error setting `service_endpoints`: %+v", err) } } @@ -368,55 +334,32 @@ func resourceArmSubnetDelete(d *schema.ResourceData, meta interface{}) error { if err != nil { return err } - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup name := id.Path["subnets"] - vnetName := id.Path["virtualNetworks"] + networkName := id.Path["virtualNetworks"] - if v, ok := d.GetOk("network_security_group_id"); ok { - networkSecurityGroupId := v.(string) - parsedNetworkSecurityGroupId, err2 := ParseNetworkSecurityGroupID(networkSecurityGroupId) - if err2 != nil { - return err2 - } - - locks.ByName(parsedNetworkSecurityGroupId.Name, networkSecurityGroupResourceName) - defer locks.UnlockByName(parsedNetworkSecurityGroupId.Name, networkSecurityGroupResourceName) - } - - if v, ok := d.GetOk("route_table_id"); ok { - rtId := v.(string) - parsedRouteTableId, err2 := ParseRouteTableID(rtId) - if err2 != nil { - return err2 - } - - locks.ByName(parsedRouteTableId.Name, routeTableResourceName) - defer locks.UnlockByName(parsedRouteTableId.Name, routeTableResourceName) - } - - locks.ByName(vnetName, VirtualNetworkResourceName) - defer locks.UnlockByName(vnetName, VirtualNetworkResourceName) + locks.ByName(networkName, VirtualNetworkResourceName) + defer locks.UnlockByName(networkName, VirtualNetworkResourceName) locks.ByName(name, SubnetResourceName) defer locks.UnlockByName(name, SubnetResourceName) - future, err := client.Delete(ctx, resGroup, vnetName, name) + future, err := client.Delete(ctx, resourceGroup, networkName, name) if err != nil { - return fmt.Errorf("Error deleting Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, vnetName, resGroup, err) + return fmt.Errorf("Error deleting Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for completion for Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, vnetName, resGroup, err) + return fmt.Errorf("Error waiting for deletion of Subnet %q (Virtual Network %q / Resource Group %q): %+v", name, networkName, resourceGroup, err) } return nil } -func expandSubnetServiceEndpoints(d *schema.ResourceData) []network.ServiceEndpointPropertiesFormat { - serviceEndpoints := d.Get("service_endpoints").([]interface{}) +func expandSubnetServiceEndpoints(input []interface{}) *[]network.ServiceEndpointPropertiesFormat { endpoints := make([]network.ServiceEndpointPropertiesFormat, 0) - for _, svcEndpointRaw := range serviceEndpoints { + for _, svcEndpointRaw := range input { if svc, ok := svcEndpointRaw.(string); ok { endpoint := network.ServiceEndpointPropertiesFormat{ Service: &svc, @@ -425,7 +368,7 @@ func expandSubnetServiceEndpoints(d *schema.ResourceData) []network.ServiceEndpo } } - return endpoints + return &endpoints } func flattenSubnetServiceEndpoints(serviceEndpoints *[]network.ServiceEndpointPropertiesFormat) []string { @@ -444,23 +387,10 @@ func flattenSubnetServiceEndpoints(serviceEndpoints *[]network.ServiceEndpointPr return endpoints } -func flattenSubnetIPConfigurations(ipConfigurations *[]network.IPConfiguration) []string { - ips := make([]string, 0) - - if ipConfigurations != nil { - for _, ip := range *ipConfigurations { - ips = append(ips, *ip.ID) - } - } - - return ips -} - -func expandSubnetDelegation(d *schema.ResourceData) []network.Delegation { - delegations := d.Get("delegation").([]interface{}) +func expandSubnetDelegation(input []interface{}) *[]network.Delegation { retDelegations := make([]network.Delegation, 0) - for _, deleValue := range delegations { + for _, deleValue := range input { deleData := deleValue.(map[string]interface{}) deleName := deleData["name"].(string) srvDelegations := deleData["service_delegation"].([]interface{}) @@ -485,7 +415,7 @@ func expandSubnetDelegation(d *schema.ResourceData) []network.Delegation { retDelegations = append(retDelegations, retDelegation) } - return retDelegations + return &retDelegations } func flattenSubnetDelegation(delegations *[]network.Delegation) []interface{} { @@ -522,3 +452,27 @@ func flattenSubnetDelegation(delegations *[]network.Delegation) []interface{} { return retDeles } + +// TODO: confirm this logic below + +func expandSubnetPrivateLinkNetworkPolicy(enabled bool) *string { + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + if enabled { + return utils.String("Disabled") + } + + return utils.String("Enabled") +} + +func flattenSubnetPrivateLinkNetworkPolicy(input *string) bool { + // This is strange logic, but to get the schema to make sense for the end user + // I exposed it with the same name that the Azure CLI does to be consistent + // between the tool sets, which means true == Disabled. + if input == nil { + return false + } + + return strings.EqualFold(*input, "Disabled") +} diff --git a/azurerm/internal/services/network/tests/data_source_subnet_test.go b/azurerm/internal/services/network/tests/data_source_subnet_test.go index 89440f431cfa2..c6f4fa89a1127 100644 --- a/azurerm/internal/services/network/tests/data_source_subnet_test.go +++ b/azurerm/internal/services/network/tests/data_source_subnet_test.go @@ -8,7 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMSubnet_basic(t *testing.T) { +func TestAccDataSourceSubnet_basic(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -16,7 +16,7 @@ func TestAccDataSourceAzureRMSubnet_basic(t *testing.T) { Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMSubnet_basic(data), + Config: testAccDataSourceSubnet_basic(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "name"), resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), @@ -30,7 +30,7 @@ func TestAccDataSourceAzureRMSubnet_basic(t *testing.T) { }) } -func TestAccDataSourceAzureRMSubnet_networkSecurityGroup(t *testing.T) { +func TestAccDataSourceSubnet_networkSecurityGroup(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -38,7 +38,11 @@ func TestAccDataSourceAzureRMSubnet_networkSecurityGroup(t *testing.T) { Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMSubnet_networkSecurityGroup(data), + // since the network security group association is a separate resource this forces it + Config: testAccDataSourceSubnet_networkSecurityGroupDependencies(data), + }, + { + Config: testAccDataSourceSubnet_networkSecurityGroup(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "name"), resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), @@ -52,7 +56,7 @@ func TestAccDataSourceAzureRMSubnet_networkSecurityGroup(t *testing.T) { }) } -func TestAccDataSourceAzureRMSubnet_routeTable(t *testing.T) { +func TestAccDataSourceSubnet_routeTable(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -60,21 +64,25 @@ func TestAccDataSourceAzureRMSubnet_routeTable(t *testing.T) { Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMSubnet_routeTable(data), + // since the route table association is a separate resource this forces it + Config: testAccDataSourceSubnet_routeTableDependencies(data), + }, + { + Config: testAccDataSourceSubnet_routeTable(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "name"), resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "virtual_network_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "address_prefix"), - resource.TestCheckResourceAttr(data.ResourceName, "network_security_group_id", ""), resource.TestCheckResourceAttrSet(data.ResourceName, "route_table_id"), + resource.TestCheckResourceAttr(data.ResourceName, "network_security_group_id", ""), ), }, }, }) } -func TestAccDataSourceAzureRMSubnet_serviceEndpoints(t *testing.T) { +func TestAccDataSourceSubnet_serviceEndpoints(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -82,7 +90,7 @@ func TestAccDataSourceAzureRMSubnet_serviceEndpoints(t *testing.T) { Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMSubnet_serviceEndpoints(data), + Config: testAccDataSourceSubnet_serviceEndpoint(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "name"), resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), @@ -99,46 +107,35 @@ func TestAccDataSourceAzureRMSubnet_serviceEndpoints(t *testing.T) { }) } -func testAccDataSourceAzureRMSubnet_basic(data acceptance.TestData) string { +func testAccDataSourceSubnet_basic(data acceptance.TestData) string { + template := testAccDataSourceSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest%d-rg" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctest%d-vn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "acctest%d-private" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.0.0/24" -} +%s data "azurerm_subnet" "test" { - name = "${azurerm_subnet.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = azurerm_subnet.test.name + virtual_network_name = azurerm_subnet.test.virtual_network_name + resource_group_name = azurerm_subnet.test.resource_group_name } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccDataSourceAzureRMSubnet_networkSecurityGroup(data acceptance.TestData) string { +func testAccDataSourceSubnet_networkSecurityGroupDependencies(data acceptance.TestData) string { + template := testAccDataSourceSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest%d-rg" - location = "%s" +%s + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.0.0/24" } resource "azurerm_network_security_group" "test" { name = "acctestnsg%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name security_rule { name = "test123" @@ -153,98 +150,96 @@ resource "azurerm_network_security_group" "test" { } } -resource "azurerm_virtual_network" "test" { - name = "acctest%d-vn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +resource "azurerm_subnet_network_security_group_association" "test" { + subnet_id = azurerm_subnet.test.id + network_security_group_id = azurerm_network_security_group.test.id } - -resource "azurerm_subnet" "test" { - name = "acctest%d-private" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.0.0/24" - network_security_group_id = "${azurerm_network_security_group.test.id}" +`, template, data.RandomInteger) } +func testAccDataSourceSubnet_networkSecurityGroup(data acceptance.TestData) string { + template := testAccDataSourceSubnet_networkSecurityGroupDependencies(data) + return fmt.Sprintf(` +%s + data "azurerm_subnet" "test" { - name = "${azurerm_subnet.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = azurerm_subnet.test.name + virtual_network_name = azurerm_subnet.test.virtual_network_name + resource_group_name = azurerm_subnet.test.resource_group_name } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccDataSourceAzureRMSubnet_routeTable(data acceptance.TestData) string { +func testAccDataSourceSubnet_routeTableDependencies(data acceptance.TestData) string { + template := testAccDataSourceSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" +%s + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.0.0/24" } resource "azurerm_route_table" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "acctestrt-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name route { - name = "acctest-%d" + name = "first" address_prefix = "10.100.0.0/14" next_hop_type = "VirtualAppliance" next_hop_in_ip_address = "10.10.1.1" } } -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" +resource "azurerm_subnet_route_table_association" "test" { + subnet_id = azurerm_subnet.test.id + route_table_id = azurerm_route_table.test.id +} +`, template, data.RandomInteger) } -resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - route_table_id = "${azurerm_route_table.test.id}" +func testAccDataSourceSubnet_routeTable(data acceptance.TestData) string { + template := testAccDataSourceSubnet_routeTableDependencies(data) + return fmt.Sprintf(` +%s + +data "azurerm_subnet" "test" { + name = azurerm_subnet.test.name + virtual_network_name = azurerm_subnet.test.virtual_network_name + resource_group_name = azurerm_subnet.test.resource_group_name +} +`, template) } +func testAccDataSourceSubnet_serviceEndpoint(data acceptance.TestData) string { + template := testAccAzureRMSubnet_serviceEndpointsUpdated(data) + return fmt.Sprintf(` +%s + data "azurerm_subnet" "test" { - name = "${azurerm_subnet.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = azurerm_subnet.test.name + virtual_network_name = azurerm_subnet.test.virtual_network_name + resource_group_name = azurerm_subnet.test.resource_group_name } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccDataSourceAzureRMSubnet_serviceEndpoints(data acceptance.TestData) string { +func testAccDataSourceSubnet_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctest%d-rg" location = "%s" } resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" + name = "acctest%d-vn" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"] -} - -data "azurerm_subnet" "test" { - name = "${azurerm_subnet.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_nat_gateway_association_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_nat_gateway_association_test.go index 86ff7f597aca1..2a2f2c12fdc7f 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_nat_gateway_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_nat_gateway_association_test.go @@ -55,7 +55,7 @@ func TestAccAzureRMSubnetNatGatewayAssociation_requiresImport(t *testing.T) { }, { Config: testAccAzureRMSubnetNatGatewayAssociation_requiresImport(data), - ExpectError: acceptance.RequiresImportError(""), + ExpectError: acceptance.RequiresImportError(data.ResourceType), }, }, }) @@ -83,6 +83,33 @@ func TestAccAzureRMSubnetNatGatewayAssociation_deleted(t *testing.T) { }) } +func TestAccAzureRMSubnetNatGatewayAssociation_updateSubnet(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_subnet_nat_gateway_association", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional since this is a virtual resource + CheckDestroy: testCheckAzureRMSubnetDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSubnetNatGatewayAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetNatGatewayAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSubnetNatGatewayAssociation_updateSubnet(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetNatGatewayAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMSubnetNatGatewayAssociationExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.SubnetsClient @@ -207,37 +234,22 @@ func testCheckAzureRMSubnetHasNoNatGateways(resourceName string) resource.TestCh } func testAccAzureRMSubnetNatGatewayAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMSubnetNatGatewayAssociation_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-network-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" } -resource "azurerm_nat_gateway" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - resource "azurerm_subnet_nat_gateway_association" "test" { - subnet_id = "${azurerm_subnet.test.id}" - nat_gateway_id = "${azurerm_nat_gateway.test.id}" + subnet_id = azurerm_subnet.test.id + nat_gateway_id = azurerm_nat_gateway.test.id } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } func testAccAzureRMSubnetNatGatewayAssociation_requiresImport(data acceptance.TestData) string { @@ -246,8 +258,51 @@ func testAccAzureRMSubnetNatGatewayAssociation_requiresImport(data acceptance.Te %s resource "azurerm_subnet_nat_gateway_association" "import" { - subnet_id = "${azurerm_subnet_nat_gateway_association.test.subnet_id}" - nat_gateway_id = "${azurerm_subnet_nat_gateway_association.test.nat_gateway_id}" + subnet_id = azurerm_subnet_nat_gateway_association.test.subnet_id + nat_gateway_id = azurerm_subnet_nat_gateway_association.test.nat_gateway_id +} +`, template) +} + +func testAccAzureRMSubnetNatGatewayAssociation_updateSubnet(data acceptance.TestData) string { + template := testAccAzureRMSubnetNatGatewayAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_subnet_nat_gateway_association" "test" { + subnet_id = azurerm_subnet.test.id + nat_gateway_id = azurerm_nat_gateway.test.id } `, template) } + +func testAccAzureRMSubnetNatGatewayAssociation_template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-network-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvn-%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_nat_gateway" "test" { + name = "acctest-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_network_security_group_association_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_network_security_group_association_test.go index 016a9e30c9610..960cc88e7c944 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_network_security_group_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_network_security_group_association_test.go @@ -61,6 +61,33 @@ func TestAccAzureRMSubnetNetworkSecurityGroupAssociation_requiresImport(t *testi }) } +func TestAccAzureRMSubnetNetworkSecurityGroupAssociation_updateSubnet(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_subnet_network_security_group_association", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional as this is a Virtual Resource + CheckDestroy: testCheckAzureRMSubnetDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSubnetNetworkSecurityGroupAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetNetworkSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSubnetNetworkSecurityGroupAssociation_updateSubnet(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetNetworkSecurityGroupAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMSubnetNetworkSecurityGroupAssociation_deleted(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet_network_security_group_association", "test") @@ -212,6 +239,58 @@ func testCheckAzureRMSubnetHasNoNetworkSecurityGroup(resourceName string) resour } func testAccAzureRMSubnetNetworkSecurityGroupAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMSubnetNetworkSecurityGroupAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_subnet_network_security_group_association" "test" { + subnet_id = azurerm_subnet.test.id + network_security_group_id = azurerm_network_security_group.test.id +} +`, template) +} + +func testAccAzureRMSubnetNetworkSecurityGroupAssociation_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMSubnetNetworkSecurityGroupAssociation_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_subnet_network_security_group_association" "internal" { + subnet_id = azurerm_subnet_network_security_group_association.test.subnet_id + network_security_group_id = azurerm_subnet_network_security_group_association.test.network_security_group_id +} +`, template) +} + +func testAccAzureRMSubnetNetworkSecurityGroupAssociation_updateSubnet(data acceptance.TestData) string { + template := testAccAzureRMSubnetNetworkSecurityGroupAssociation_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_subnet_network_security_group_association" "test" { + subnet_id = azurerm_subnet.test.id + network_security_group_id = azurerm_network_security_group.test.id +} +`, template) +} + +func testAccAzureRMSubnetNetworkSecurityGroupAssociation_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -225,14 +304,6 @@ resource "azurerm_virtual_network" "test" { resource_group_name = "${azurerm_resource_group.test.name}" } -resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - network_security_group_id = "${azurerm_network_security_group.test.id}" -} - resource "azurerm_network_security_group" "test" { name = "acctestnsg%d" location = "${azurerm_resource_group.test.location}" @@ -250,18 +321,5 @@ resource "azurerm_network_security_group" "test" { destination_address_prefix = "*" } } - -resource "azurerm_subnet_network_security_group_association" "test" { - subnet_id = "${azurerm_subnet.test.id}" - network_security_group_id = "${azurerm_network_security_group.test.id}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMSubnetNetworkSecurityGroupAssociation_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMSubnetNetworkSecurityGroupAssociation_basic(data) - return fmt.Sprintf(` -%s - -`, template) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_route_table_association_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_route_table_association_test.go index b6602d29c7f6e..8e539fcc3080a 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_route_table_association_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_route_table_association_test.go @@ -32,6 +32,7 @@ func TestAccAzureRMSubnetRouteTableAssociation_basic(t *testing.T) { }, }) } + func TestAccAzureRMSubnetRouteTableAssociation_requiresImport(t *testing.T) { if !features.ShouldResourcesBeImported() { t.Skip("Skipping since resources aren't required to be imported") @@ -54,12 +55,39 @@ func TestAccAzureRMSubnetRouteTableAssociation_requiresImport(t *testing.T) { }, { Config: testAccAzureRMSubnetRouteTableAssociation_requiresImport(data), - ExpectError: acceptance.RequiresImportError(""), + ExpectError: acceptance.RequiresImportError("azurerm_subnet_route_table_association"), }, }, }) } +func TestAccAzureRMSubnetRouteTableAssociation_updateSubnet(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_subnet_route_table_association", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + // intentional since this is a Virtual Resource + CheckDestroy: testCheckAzureRMSubnetDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSubnetRouteTableAssociation_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetRouteTableAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSubnetRouteTableAssociation_updateSubnet(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetRouteTableAssociationExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMSubnetRouteTableAssociation_deleted(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet_route_table_association", "test") @@ -211,45 +239,22 @@ func testCheckAzureRMSubnetHasNoRouteTable(resourceName string) resource.TestChe } func testAccAzureRMSubnetRouteTableAssociation_basic(data acceptance.TestData) string { + template := testAccAzureRMSubnetRouteTableAssociation_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" + name = "internal" resource_group_name = "${azurerm_resource_group.test.name}" virtual_network_name = "${azurerm_virtual_network.test.name}" address_prefix = "10.0.2.0/24" - route_table_id = "${azurerm_route_table.test.id}" -} - -resource "azurerm_route_table" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "acctest-%d" - address_prefix = "10.100.0.0/14" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = "10.10.1.1" - } } resource "azurerm_subnet_route_table_association" "test" { - subnet_id = "${azurerm_subnet.test.id}" - route_table_id = "${azurerm_route_table.test.id}" + subnet_id = azurerm_subnet.test.id + route_table_id = azurerm_route_table.test.id } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } func testAccAzureRMSubnetRouteTableAssociation_requiresImport(data acceptance.TestData) string { @@ -258,8 +263,57 @@ func testAccAzureRMSubnetRouteTableAssociation_requiresImport(data acceptance.Te %s resource "azurerm_subnet_route_table_association" "import" { - subnet_id = "${azurerm_subnet_route_table_association.test.subnet_id}" - route_table_id = "${azurerm_subnet_route_table_association.test.route_table_id}" + subnet_id = azurerm_subnet_route_table_association.test.subnet_id + route_table_id = azurerm_subnet_route_table_association.test.route_table_id +} +`, template) +} + +func testAccAzureRMSubnetRouteTableAssociation_updateSubnet(data acceptance.TestData) string { + template := testAccAzureRMSubnetRouteTableAssociation_template(data) + return fmt.Sprintf(` +%s +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" + + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_subnet_route_table_association" "test" { + subnet_id = azurerm_subnet.test.id + route_table_id = azurerm_route_table.test.id } `, template) } + +func testAccAzureRMSubnetRouteTableAssociation_template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvirtnet%d" + address_space = ["10.0.0.0/16"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_route_table" "test" { + name = "acctest-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + route { + name = "first" + address_prefix = "10.100.0.0/14" + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = "10.10.1.1" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go index d2334f1eecb29..e7804d863aefe 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go @@ -3,7 +3,6 @@ package tests import ( "fmt" "log" - "strings" "testing" "github.com/hashicorp/go-azure-helpers/response" @@ -61,7 +60,7 @@ func TestAccAzureRMSubnet_requiresImport(t *testing.T) { }) } -func TestAccAzureRMSubnet_delegation(t *testing.T) { +func TestAccAzureRMSubnet_disappears(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -70,17 +69,18 @@ func TestAccAzureRMSubnet_delegation(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_delegation(data), + Config: testAccAzureRMSubnet_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "delegation.#", "1"), + testCheckAzureRMSubnetDisappears(data.ResourceName), ), + ExpectNonEmptyPlan: true, }, }, }) } -func TestAccAzureRMSubnet_delegationComputedActions(t *testing.T) { +func TestAccAzureRMSubnet_delegation(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -89,42 +89,38 @@ func TestAccAzureRMSubnet_delegationComputedActions(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_delegationComputedActions(data), + Config: testAccAzureRMSubnet_delegation(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "delegation.#", "1"), ), }, - }, - }) -} - -func TestAccAzureRMSubnet_routeTableUpdate(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_subnet", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMSubnetDestroy, - Steps: []resource.TestStep{ + data.ImportStep(), { - Config: testAccAzureRMSubnet_routeTable(data), + Config: testAccAzureRMSubnet_delegationUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), ), }, - + data.ImportStep(), + { + Config: testAccAzureRMSubnet_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetExists(data.ResourceName), + ), + }, + data.ImportStep(), { - Config: testAccAzureRMSubnet_updatedRouteTable(data), + Config: testAccAzureRMSubnet_delegation(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMSubnetRouteTableExists(data.ResourceName, fmt.Sprintf("acctest-%d", data.RandomInteger)), + testCheckAzureRMSubnetExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMSubnet_routeTableRemove(t *testing.T) { +func TestAccAzureRMSubnet_enforcePrivateLinkEndpointNetworkPolicies(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -133,17 +129,23 @@ func TestAccAzureRMSubnet_routeTableRemove(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_routeTable(data), + Config: testAccAzureRMSubnet_enforcePrivateLinkEndpointNetworkPolicies(data, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMSubnet_enforcePrivateLinkEndpointNetworkPolicies(data, false), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "route_table_id"), ), }, + data.ImportStep(), { - Config: testAccAzureRMSubnet_routeTableUnlinked(data), + Config: testAccAzureRMSubnet_enforcePrivateLinkEndpointNetworkPolicies(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "route_table_id", ""), ), }, data.ImportStep(), @@ -151,7 +153,7 @@ func TestAccAzureRMSubnet_routeTableRemove(t *testing.T) { }) } -func TestAccAzureRMSubnet_removeNetworkSecurityGroup(t *testing.T) { +func TestAccAzureRMSubnet_enforcePrivateLinkServiceNetworkPolicies(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -160,44 +162,31 @@ func TestAccAzureRMSubnet_removeNetworkSecurityGroup(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_networkSecurityGroup(data), + Config: testAccAzureRMSubnet_enforcePrivateLinkServiceNetworkPolicies(data, true), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "network_security_group_id"), ), }, + data.ImportStep(), { - Config: testAccAzureRMSubnet_networkSecurityGroupDetached(data), + Config: testAccAzureRMSubnet_enforcePrivateLinkServiceNetworkPolicies(data, false), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "network_security_group_id", ""), ), }, data.ImportStep(), - }, - }) -} - -func TestAccAzureRMSubnet_bug7986(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_subnet", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMSubnetDestroy, - Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_bug7986(data), + Config: testAccAzureRMSubnet_enforcePrivateLinkServiceNetworkPolicies(data, true), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMSubnetExists("azurerm_subnet.first"), - testCheckAzureRMSubnetExists("azurerm_subnet.second"), + testCheckAzureRMSubnetExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMSubnet_bug15204(t *testing.T) { +func TestAccAzureRMSubnet_serviceEndpoints(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -206,55 +195,39 @@ func TestAccAzureRMSubnet_bug15204(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_bug15204(data), + Config: testAccAzureRMSubnet_serviceEndpoints(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), ), }, - }, - }) -} - -func TestAccAzureRMSubnet_disappears(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_subnet", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMSubnetDestroy, - Steps: []resource.TestStep{ + data.ImportStep(), { + Config: testAccAzureRMSubnet_serviceEndpointsUpdated(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMSubnetExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + // remove them Config: testAccAzureRMSubnet_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - testCheckAzureRMSubnetDisappears(data.ResourceName), ), - ExpectNonEmptyPlan: true, }, - }, - }) -} - -func TestAccAzureRMSubnet_serviceEndpoints(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_subnet", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMSubnetDestroy, - Steps: []resource.TestStep{ + data.ImportStep(), { Config: testAccAzureRMSubnet_serviceEndpoints(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMSubnetExists("azurerm_subnet.test"), - resource.TestCheckResourceAttr(data.ResourceName, "service_endpoints.#", "2"), + testCheckAzureRMSubnetExists(data.ResourceName), ), }, + data.ImportStep(), }, }) } -func TestAccAzureRMSubnet_serviceEndpointsVNetUpdate(t *testing.T) { +func TestAccAzureRMSubnet_updateAddressPrefix(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_subnet", "test") resource.ParallelTest(t, resource.TestCase{ @@ -263,19 +236,19 @@ func TestAccAzureRMSubnet_serviceEndpointsVNetUpdate(t *testing.T) { CheckDestroy: testCheckAzureRMSubnetDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSubnet_serviceEndpoints(data), + Config: testAccAzureRMSubnet_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "service_endpoints.#", "2"), ), }, + data.ImportStep(), { - Config: testAccAzureRMSubnet_serviceEndpointsVNetUpdate(data), + Config: testAccAzureRMSubnet_updatedAddressPrefix(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMSubnetExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "service_endpoints.#", "2"), ), }, + data.ImportStep(), }, }) } @@ -313,57 +286,6 @@ func testCheckAzureRMSubnetExists(resourceName string) resource.TestCheckFunc { } } -func testCheckAzureRMSubnetRouteTableExists(resourceName string, routeTableId string) resource.TestCheckFunc { - return func(s *terraform.State) error { - networksClient := acceptance.AzureProvider.Meta().(*clients.Client).Network.VnetClient - subnetsClient := acceptance.AzureProvider.Meta().(*clients.Client).Network.SubnetsClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // 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) - } - - log.Printf("[INFO] Checking Subnet update.") - - subnetName := rs.Primary.Attributes["name"] - vnetName := rs.Primary.Attributes["virtual_network_name"] - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for subnet: %s", subnetName) - } - - vnetResp, vnetErr := networksClient.Get(ctx, resourceGroup, vnetName, "") - if vnetErr != nil { - return fmt.Errorf("Bad: Get on vnetClient: %+v", vnetErr) - } - - if vnetResp.Subnets == nil { - return fmt.Errorf("Bad: Vnet %q (resource group: %q) does not have subnets after update", vnetName, resourceGroup) - } - - resp, err := subnetsClient.Get(ctx, resourceGroup, vnetName, subnetName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Bad: Subnet %q (resource group: %q) does not exist", subnetName, resourceGroup) - } - - return fmt.Errorf("Bad: Get on subnetClient: %+v", err) - } - - if resp.RouteTable == nil { - return fmt.Errorf("Bad: Subnet %q (resource group: %q) does not contain route tables after update", subnetName, resourceGroup) - } - - if !strings.Contains(*resp.RouteTable.ID, routeTableId) { - return fmt.Errorf("Bad: Subnet %q (resource group: %q) does not have route table %q", subnetName, resourceGroup, routeTableId) - } - - return nil - } -} - func testCheckAzureRMSubnetDisappears(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.SubnetsClient @@ -423,451 +345,162 @@ func testCheckAzureRMSubnetDestroy(s *terraform.State) error { } func testAccAzureRMSubnet_basic(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMSubnet_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMSubnet_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_subnet" "import" { - name = "${azurerm_subnet.test.name}" - resource_group_name = "${azurerm_subnet.test.resource_group_name}" - virtual_network_name = "${azurerm_subnet.test.virtual_network_name}" - address_prefix = "${azurerm_subnet.test.address_prefix}" -} `, template) } func testAccAzureRMSubnet_delegation(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" delegation { - name = "acctestdelegation" + name = "first" service_delegation { name = "Microsoft.ContainerInstance/containerGroups" - actions = ["Microsoft.Network/virtualNetworks/subnets/action"] + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + ] } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_delegationComputedActions(data acceptance.TestData) string { +func testAccAzureRMSubnet_delegationUpdated(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" delegation { - name = "acctestdelegation" + name = "first" service_delegation { - name = "Microsoft.Sql/managedInstances" + name = "Microsoft.Databricks/workspaces" + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", + "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action", + ] } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMSubnet_routeTable(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - route_table_id = "${azurerm_route_table.test.id}" -} - -resource "azurerm_route_table" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "acctest-%d" - address_prefix = "10.100.0.0/14" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = "10.10.1.1" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_routeTableUnlinked(data acceptance.TestData) string { +func testAccAzureRMSubnet_enforcePrivateLinkEndpointNetworkPolicies(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" - route_table_id = "" -} - -resource "azurerm_route_table" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - route { - name = "acctest-%d" - address_prefix = "10.100.0.0/14" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = "10.10.1.1" - } + enforce_private_link_endpoint_network_policies = %t } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, enabled) } -func testAccAzureRMSubnet_updatedRouteTable(data acceptance.TestData) string { +func testAccAzureRMSubnet_enforcePrivateLinkServiceNetworkPolicies(data acceptance.TestData, enabled bool) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" - - tags = { - environment = "Testing" - } -} - -resource "azurerm_network_security_group" "test_secgroup" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - security_rule { - name = "acctest-%d" - priority = 100 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "*" - destination_address_prefix = "*" - } - - tags = { - environment = "Testing" - } -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - tags = { - environment = "Testing" - } -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name address_prefix = "10.0.2.0/24" - route_table_id = "${azurerm_route_table.test.id}" -} - -resource "azurerm_route_table" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - route { - name = "acctest-%d" - address_prefix = "10.100.0.0/14" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = "10.10.1.1" - } - - tags = { - environment = "Testing" - } + enforce_private_link_service_network_policies = %t } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template, enabled) } -func testAccAzureRMSubnet_networkSecurityGroup(data acceptance.TestData) string { +func testAccAzureRMSubnet_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMSubnet_basic(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest%d-rg" - location = "%s" -} - -resource "azurerm_network_security_group" "test" { - name = "acctestnsg%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - security_rule { - name = "test123" - priority = 100 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "*" - destination_address_prefix = "*" - } -} - -resource "azurerm_virtual_network" "test" { - name = "acctest%d-vn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s -resource "azurerm_subnet" "test" { - name = "acctest%d-private" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.0.0/24" - network_security_group_id = "${azurerm_network_security_group.test.id}" +resource "azurerm_subnet" "import" { + name = azurerm_subnet.test.name + resource_group_name = azurerm_subnet.test.resource_group_name + virtual_network_name = azurerm_subnet.test.virtual_network_name + address_prefix = azurerm_subnet.test.address_prefix } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_networkSecurityGroupDetached(data acceptance.TestData) string { +func testAccAzureRMSubnet_serviceEndpoints(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest%d-rg" - location = "%s" -} - -resource "azurerm_network_security_group" "test" { - name = "acctestnsg%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - security_rule { - name = "test123" - priority = 100 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "*" - destination_address_prefix = "*" - } -} - -resource "azurerm_virtual_network" "test" { - name = "acctest%d-vn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctest%d-private" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.0.0/24" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMSubnet_bug7986(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest%d-rg" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctest%d-vn" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_route_table" "first" { - name = "acctest%d-private-1" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "acctest%d-private-1" - address_prefix = "0.0.0.0/0" - next_hop_type = "None" - } -} - -resource "azurerm_subnet" "first" { - name = "acctest%d-private-1" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.0.0/24" - route_table_id = "${azurerm_route_table.first.id}" -} - -resource "azurerm_route_table" "second" { - name = "acctest%d-private-2" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "acctest%d-private-2" - address_prefix = "0.0.0.0/0" - next_hop_type = "None" - } -} - -resource "azurerm_subnet" "second" { - name = "acctest%d-private-2" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" - route_table_id = "${azurerm_route_table.second.id}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.Sql"] } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_bug15204(data acceptance.TestData) string { +func testAccAzureRMSubnet_serviceEndpointsUpdated(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctest-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvn-%d" - address_space = ["10.85.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_network_security_group" "test" { - name = "acctestnsg-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_route_table" "test" { - name = "acctestrt-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.85.9.0/24" - route_table_id = "${azurerm_route_table.test.id}" - network_security_group_id = "${azurerm_network_security_group.test.id}" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.2.0/24" + service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"] } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_serviceEndpoints(data acceptance.TestData) string { +func testAccAzureRMSubnet_updatedAddressPrefix(data acceptance.TestData) string { + template := testAccAzureRMSubnet_template(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" -} +%s resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"] + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.3.0/24" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, template) } -func testAccAzureRMSubnet_serviceEndpointsVNetUpdate(data acceptance.TestData) string { +func testAccAzureRMSubnet_template(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -877,20 +510,8 @@ resource "azurerm_resource_group" "test" { resource "azurerm_virtual_network" "test" { name = "acctestvirtnet%d" address_space = ["10.0.0.0/16"] - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - tags = { - Environment = "Staging" - } -} - -resource "azurerm_subnet" "test" { - name = "acctestsubnet%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - service_endpoints = ["Microsoft.Sql", "Microsoft.Storage"] + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/network/tests/resource_arm_virtual_network_test.go b/azurerm/internal/services/network/tests/resource_arm_virtual_network_test.go index 353cda16a364c..f146d94925120 100644 --- a/azurerm/internal/services/network/tests/resource_arm_virtual_network_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_virtual_network_test.go @@ -163,24 +163,6 @@ func TestAccAzureRMVirtualNetwork_withTags(t *testing.T) { }) } -func TestAccAzureRMVirtualNetwork_bug373(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_virtual_network", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMVirtualNetworkDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMVirtualNetwork_bug373(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMVirtualNetworkExists(data.ResourceName), - ), - }, - }, - }) -} - func testCheckAzureRMVirtualNetworkExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Network.VnetClient @@ -416,69 +398,3 @@ resource "azurerm_virtual_network" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } - -func testAccAzureRMVirtualNetwork_bug373(data acceptance.TestData) string { - return fmt.Sprintf(` -variable "environment" { - default = "TestVirtualNetworkBug373" -} - -variable "network_cidr" { - default = "10.0.0.0/16" -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "${azurerm_resource_group.test.name}-vnet" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["${var.network_cidr}"] - location = "${azurerm_resource_group.test.location}" - - tags = { - environment = "${var.environment}" - } -} - -resource "azurerm_subnet" "public" { - name = "${azurerm_resource_group.test.name}-subnet-public" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" - network_security_group_id = "${azurerm_network_security_group.test.id}" -} - -resource "azurerm_subnet" "private" { - name = "${azurerm_resource_group.test.name}-subnet-private" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.2.0/24" - network_security_group_id = "${azurerm_network_security_group.test.id}" -} - -resource "azurerm_network_security_group" "test" { - name = "default-network-sg" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - security_rule { - name = "default-allow-all" - priority = 100 - direction = "Inbound" - access = "Allow" - protocol = "*" - source_port_range = "*" - destination_port_range = "*" - source_address_prefix = "${var.network_cidr}" - destination_address_prefix = "*" - } - - tags = { - environment = "${var.environment}" - } -} -`, data.RandomInteger, data.Locations.Primary) -} diff --git a/website/docs/d/subnet.html.markdown b/website/docs/d/subnet.html.markdown index 60d911819d0ca..73ea02db1300d 100644 --- a/website/docs/d/subnet.html.markdown +++ b/website/docs/d/subnet.html.markdown @@ -37,7 +37,6 @@ output "subnet_id" { * `enforce_private_link_service_network_policies` - Enable or Disable network policies on private link service in the subnet. * `network_security_group_id` - The ID of the Network Security Group associated with the subnet. * `route_table_id` - The ID of the Route Table associated with this subnet. -* `ip_configurations` - The collection of IP Configurations with IPs within this subnet. * `service_endpoints` - A list of Service Endpoints within this subnet. * `enforce_private_link_endpoint_network_policies` - Enable or Disable network policies for the private link endpoint on the subnet. * `enforce_private_link_service_network_policies` - Enable or Disable network policies for the private link service on the subnet. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 6fc59355fd16e..fe9a8c257c955 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -59,11 +59,7 @@ The following arguments are supported: * `address_prefix` - (Required) The address prefix to use for the subnet. -* `network_security_group_id` - (Optional / **Deprecated**) The ID of the Network Security Group to associate with the subnet. - --> **NOTE:** At this time Subnet `<->` Network Security Group associations need to be configured both using this field (which is now Deprecated) and using the `azurerm_subnet_network_security_group_association` resource. This field is deprecated and will be removed in favour of that resource in the next major version (2.0) of the AzureRM Provider. - -* `service_endpoints` - (Optional) The list of Service endpoints to associate with the subnet. Possible values include: `Microsoft.AzureActiveDirectory`, `Microsoft.AzureCosmosDB`, `Microsoft.ContainerRegistry`, `Microsoft.EventHub`, `Microsoft.KeyVault`, `Microsoft.ServiceBus`, `Microsoft.Sql`, `Microsoft.Storage` and `Microsoft.Web`. +--- * `delegation` - (Optional) One or more `delegation` blocks as defined below. @@ -71,10 +67,12 @@ The following arguments are supported: -> **NOTE:** Network policies, like network security groups (NSG), are not supported for Private Link Endpoints or Private Link Services. In order to deploy a Private Link Endpoint on a given subnet, you must set the `enforce_private_link_endpoint_network_policies` attribute to `true`. This setting is only applicable for the Private Link Endpoint, for all other resources in the subnet access is controlled based on the `network_security_group_id`. -* `enforce_private_link_service_network_policies` - (Optional) Enable or Disable network policies for the private link service on the subnet. Default valule is `false`. Conflicts with enforce_private_link_endpoint_network_policies. +* `enforce_private_link_service_network_policies` - (Optional) Enable or Disable network policies for the private link service on the subnet. Default valule is `false`. Conflicts with `enforce_private_link_endpoint_network_policies`. -> **NOTE:** In order to deploy a Private Link Service on a given subnet, you must set the `enforce_private_link_service_network_policies` attribute to `true`. This setting is only applicable for the Private Link Service, for all other resources in the subnet access is controlled based on the `network_security_group_id`. +* `service_endpoints` - (Optional) The list of Service endpoints to associate with the subnet. Possible values include: `Microsoft.AzureActiveDirectory`, `Microsoft.AzureCosmosDB`, `Microsoft.ContainerRegistry`, `Microsoft.EventHub`, `Microsoft.KeyVault`, `Microsoft.ServiceBus`, `Microsoft.Sql`, `Microsoft.Storage` and `Microsoft.Web`. + --- A `delegation` block supports the following: @@ -100,7 +98,6 @@ A `service_delegation` block supports the following: The following attributes are exported: * `id` - The subnet ID. -* `ip_configurations` - The collection of IP Configurations with IPs within this subnet. * `name` - The name of the subnet. * `resource_group_name` - The name of the resource group in which the subnet is created in. * `virtual_network_name` - The name of the virtual network in which the subnet is created in diff --git a/website/docs/r/subnet_network_security_group_association.html.markdown b/website/docs/r/subnet_network_security_group_association.html.markdown index 7872e2b1642ae..8ffd34c507768 100644 --- a/website/docs/r/subnet_network_security_group_association.html.markdown +++ b/website/docs/r/subnet_network_security_group_association.html.markdown @@ -33,7 +33,6 @@ resource "azurerm_subnet" "example" { resource_group_name = azurerm_resource_group.example.name virtual_network_name = azurerm_virtual_network.example.name address_prefix = "10.0.2.0/24" - network_security_group_id = azurerm_network_security_group.example.id } resource "azurerm_network_security_group" "example" { From 13796b7be541f01a8cb93d16cfcdbec485b0f83e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 12:03:52 +0100 Subject: [PATCH 184/498] r/route_table: removing an obsolete test This is now managed/tested in the association resource --- .../tests/resource_arm_route_table_test.go | 127 ------------------ 1 file changed, 127 deletions(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_route_table_test.go b/azurerm/internal/services/network/tests/resource_arm_route_table_test.go index e69d34553a312..b84133563c553 100644 --- a/azurerm/internal/services/network/tests/resource_arm_route_table_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_route_table_test.go @@ -265,34 +265,6 @@ func TestAccAzureRMRouteTable_multipleRoutes(t *testing.T) { }) } -func TestAccAzureRMRouteTable_withTagsSubnet(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_route_table", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRouteTableDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRouteTable_withTagsSubnet(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRouteTableExists("azurerm_route_table.test"), - testCheckAzureRMSubnetExists("azurerm_subnet.subnet1"), - resource.TestCheckResourceAttrSet("azurerm_subnet.subnet1", "route_table_id"), - ), - }, - { - Config: testAccAzureRMRouteTable_withAddTagsSubnet(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRouteTableExists("azurerm_route_table.test"), - testCheckAzureRMSubnetExists("azurerm_subnet.subnet1"), - resource.TestCheckResourceAttrSet("azurerm_subnet.subnet1", "route_table_id"), - ), - }, - }, - }) -} - func testCheckAzureRMRouteTableExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -582,102 +554,3 @@ resource "azurerm_route_table" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } - -func testAccAzureRMRouteTable_withTagsSubnet(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" - - tags = { - environment = "staging" - } -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["10.0.0.0/16"] - - tags = { - environment = "staging" - } -} - -resource "azurerm_subnet" "subnet1" { - name = "subnet1" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" - route_table_id = "${azurerm_route_table.test.id}" -} - -resource "azurerm_route_table" "test" { - name = "acctestrt%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "route1" - address_prefix = "10.1.0.0/16" - next_hop_type = "vnetlocal" - } - - tags = { - environment = "staging" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMRouteTable_withAddTagsSubnet(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" - - tags = { - environment = "staging" - cloud = "Azure" - } -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvirtnet%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["10.0.0.0/16"] - - tags = { - environment = "staging" - cloud = "Azure" - } -} - -resource "azurerm_subnet" "subnet1" { - name = "subnet1" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test.name}" - address_prefix = "10.0.1.0/24" - route_table_id = "${azurerm_route_table.test.id}" -} - -resource "azurerm_route_table" "test" { - name = "acctestrt%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - route { - name = "route1" - address_prefix = "10.1.0.0/16" - next_hop_type = "vnetlocal" - } - - tags = { - environment = "staging" - cloud = "Azure" - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} From c3863db2ad8557cd703be85ba01ac8e763e06b11 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 12:08:45 +0100 Subject: [PATCH 185/498] r/subnet: removing the old network_security_group_id field from the docs --- website/docs/r/subnet.html.markdown | 4 ++-- .../r/subnet_network_security_group_association.html.markdown | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index fe9a8c257c955..8b0f2b293da8d 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -65,11 +65,11 @@ The following arguments are supported: * `enforce_private_link_endpoint_network_policies` - (Optional) Enable or Disable network policies for the private link endpoint on the subnet. Default valule is `false`. Conflicts with enforce_private_link_service_network_policies. --> **NOTE:** Network policies, like network security groups (NSG), are not supported for Private Link Endpoints or Private Link Services. In order to deploy a Private Link Endpoint on a given subnet, you must set the `enforce_private_link_endpoint_network_policies` attribute to `true`. This setting is only applicable for the Private Link Endpoint, for all other resources in the subnet access is controlled based on the `network_security_group_id`. +-> **NOTE:** Network policies, like network security groups (NSG), are not supported for Private Link Endpoints or Private Link Services. In order to deploy a Private Link Endpoint on a given subnet, you must set the `enforce_private_link_endpoint_network_policies` attribute to `true`. This setting is only applicable for the Private Link Endpoint, for all other resources in the subnet access is controlled based via the Network Security Group which can be configured using the `azurerm_subnet_network_security_group_association` resource. * `enforce_private_link_service_network_policies` - (Optional) Enable or Disable network policies for the private link service on the subnet. Default valule is `false`. Conflicts with `enforce_private_link_endpoint_network_policies`. --> **NOTE:** In order to deploy a Private Link Service on a given subnet, you must set the `enforce_private_link_service_network_policies` attribute to `true`. This setting is only applicable for the Private Link Service, for all other resources in the subnet access is controlled based on the `network_security_group_id`. +-> **NOTE:** In order to deploy a Private Link Service on a given subnet, you must set the `enforce_private_link_service_network_policies` attribute to `true`. This setting is only applicable for the Private Link Service, for all other resources in the subnet access is controlled based on the Network Security Group which can be configured using the `azurerm_subnet_network_security_group_association` resource. * `service_endpoints` - (Optional) The list of Service endpoints to associate with the subnet. Possible values include: `Microsoft.AzureActiveDirectory`, `Microsoft.AzureCosmosDB`, `Microsoft.ContainerRegistry`, `Microsoft.EventHub`, `Microsoft.KeyVault`, `Microsoft.ServiceBus`, `Microsoft.Sql`, `Microsoft.Storage` and `Microsoft.Web`. diff --git a/website/docs/r/subnet_network_security_group_association.html.markdown b/website/docs/r/subnet_network_security_group_association.html.markdown index 8ffd34c507768..5259f4d0da244 100644 --- a/website/docs/r/subnet_network_security_group_association.html.markdown +++ b/website/docs/r/subnet_network_security_group_association.html.markdown @@ -11,8 +11,6 @@ description: |- Associates a [Network Security Group](network_security_group.html) with a [Subnet](subnet.html) within a [Virtual Network](virtual_network.html). --> **NOTE:** Subnet `<->` Network Security Group associations currently need to be configured on both this resource and using the `network_security_group_id` field on the `azurerm_subnet` resource. The next major version of the AzureRM Provider (2.0) will remove the `network_security_group_id` field from the `azurerm_subnet` resource such that this resource is used to link resources in future. - ## Example Usage ```hcl From 1310177ce5c98469fc3d7ece4d305acce21215b0 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 12:11:29 +0100 Subject: [PATCH 186/498] linting --- .../internal/services/network/network_interface.go | 8 ++++---- .../network/resource_arm_network_interface.go | 14 +++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/azurerm/internal/services/network/network_interface.go b/azurerm/internal/services/network/network_interface.go index dd29bb6aa188e..0f5c25a97bd4e 100644 --- a/azurerm/internal/services/network/network_interface.go +++ b/azurerm/internal/services/network/network_interface.go @@ -29,10 +29,10 @@ func parseFieldsFromNetworkInterface(input network.InterfacePropertiesFormat) ne return output } - applicationSecurityGroupIds := make(map[string]struct{}, 0) - applicationGatewayBackendAddressPoolIds := make(map[string]struct{}, 0) - loadBalancerBackendAddressPoolIds := make(map[string]struct{}, 0) - loadBalancerInboundNatRuleIds := make(map[string]struct{}, 0) + applicationSecurityGroupIds := make(map[string]struct{}) + applicationGatewayBackendAddressPoolIds := make(map[string]struct{}) + loadBalancerBackendAddressPoolIds := make(map[string]struct{}) + loadBalancerInboundNatRuleIds := make(map[string]struct{}) if input.IPConfigurations != nil { for _, v := range *input.IPConfigurations { diff --git a/azurerm/internal/services/network/resource_arm_network_interface.go b/azurerm/internal/services/network/resource_arm_network_interface.go index 92f606503b841..4b4c388d54994 100644 --- a/azurerm/internal/services/network/resource_arm_network_interface.go +++ b/azurerm/internal/services/network/resource_arm_network_interface.go @@ -236,7 +236,7 @@ func resourceArmNetworkInterfaceCreate(d *schema.ResourceData, meta interface{}) } lockingDetails, err := determineResourcesToLockFromIPConfiguration(ipConfigs) if err != nil { - return fmt.Errorf("Error determing locking details: %+v", err) + return fmt.Errorf("Error determining locking details: %+v", err) } lockingDetails.lock() @@ -344,7 +344,7 @@ func resourceArmNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) } lockingDetails, err := determineResourcesToLockFromIPConfiguration(ipConfigs) if err != nil { - return fmt.Errorf("Error determing locking details: %+v", err) + return fmt.Errorf("Error determining locking details: %+v", err) } lockingDetails.lock() @@ -501,7 +501,7 @@ func resourceArmNetworkInterfaceDelete(d *schema.ResourceData, meta interface{}) lockingDetails, err := determineResourcesToLockFromIPConfiguration(props.IPConfigurations) if err != nil { - return fmt.Errorf("Error determing locking details: %+v", err) + return fmt.Errorf("Error determining locking details: %+v", err) } lockingDetails.lock() @@ -645,13 +645,9 @@ func expandNetworkInterfaceDnsServers(input []interface{}) []string { } func flattenNetworkInterfaceDnsServers(input *[]string) []string { - output := make([]string, 0) if input == nil { - return output + return make([]string, 0) } - for _, v := range *input { - output = append(output, v) - } - return output + return *input } From d0de7627d90c491f199f65a5a3e6c64894d899c0 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 12:27:44 +0100 Subject: [PATCH 187/498] fixing the linting --- website/docs/r/private_endpoint.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/r/private_endpoint.html.markdown b/website/docs/r/private_endpoint.html.markdown index d590fd957bbc3..2a0c8428d9717 100644 --- a/website/docs/r/private_endpoint.html.markdown +++ b/website/docs/r/private_endpoint.html.markdown @@ -88,7 +88,7 @@ resource "azurerm_private_endpoint" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name subnet_id = azurerm_subnet.endpoint.id - + private_service_connection { name = "example-privateserviceconnection" private_connection_resource_id = azurerm_private_link_service.example.id From 86f3905b03c678d56374dac7c237d161324fd91e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 12:29:17 +0100 Subject: [PATCH 188/498] r/subnet: fixing the broken test --- .../internal/services/network/tests/resource_arm_subnet_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go index e7804d863aefe..e428fd039070a 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go @@ -400,7 +400,7 @@ resource "azurerm_subnet" "test" { service_delegation { name = "Microsoft.Databricks/workspaces" actions = [ - "Microsoft.Network/virtualNetworks/subnets/action", + "Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action", ] From 56e9065fd78c54e1861b1180581d3084d98bc079 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Tue, 18 Feb 2020 12:22:06 +0000 Subject: [PATCH 189/498] Fixup tests --- .../resource_arm_automation_job_schedule.go | 35 +++++++++++-------- ...esource_arm_automation_certificate_test.go | 1 - ...source_arm_automation_job_schedule_test.go | 1 + 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/azurerm/internal/services/automation/resource_arm_automation_job_schedule.go b/azurerm/internal/services/automation/resource_arm_automation_job_schedule.go index 469de5a3e3721..44bab456468d5 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_job_schedule.go +++ b/azurerm/internal/services/automation/resource_arm_automation_job_schedule.go @@ -6,6 +6,8 @@ import ( "strings" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" uuid "github.com/satori/go.uuid" @@ -86,9 +88,10 @@ func resourceArmAutomationJobSchedule() *schema.Resource { }, "job_schedule_id": { - Type: schema.TypeString, - Optional: true, - Computed: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validate.UUID, }, }, } @@ -102,17 +105,21 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa log.Printf("[INFO] preparing arguments for AzureRM Automation Job Schedule creation.") jobScheduleUUID := uuid.NewV4() - resGroup := d.Get("resource_group_name").(string) + if jobScheduleID, ok := d.GetOk("job_schedule_id"); ok { + jobScheduleUUID = uuid.FromStringOrNil(jobScheduleID.(string)) + } + + resourceGroup := d.Get("resource_group_name").(string) accountName := d.Get("automation_account_name").(string) runbookName := d.Get("runbook_name").(string) scheduleName := d.Get("schedule_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) + existing, err := client.Get(ctx, resourceGroup, accountName, jobScheduleUUID) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Automation Job Schedule %q (Account %q / Resource Group %q): %s", jobScheduleUUID, accountName, resGroup, err) + return fmt.Errorf("Error checking for presence of existing Automation Job Schedule %q (Account %q / Resource Group %q): %s", jobScheduleUUID, accountName, resourceGroup, err) } } @@ -148,17 +155,17 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa properties.RunOn = &value } - if _, err := client.Create(ctx, resGroup, accountName, jobScheduleUUID, parameters); err != nil { + if _, err := client.Create(ctx, resourceGroup, accountName, jobScheduleUUID, parameters); err != nil { return err } - read, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) + read, err := client.Get(ctx, resourceGroup, accountName, jobScheduleUUID) if err != nil { return err } if read.ID == nil { - return fmt.Errorf("Cannot read Automation Job Schedule '%s' (Account %q / Resource Group %s) ID", jobScheduleUUID, accountName, resGroup) + return fmt.Errorf("Cannot read Automation Job Schedule '%s' (Account %q / Resource Group %s) ID", jobScheduleUUID, accountName, resourceGroup) } d.SetId(*read.ID) @@ -178,10 +185,10 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface jobScheduleID := id.Path["jobSchedules"] jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] - resp, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) + resp, err := client.Get(ctx, resourceGroup, accountName, jobScheduleUUID) if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") @@ -192,7 +199,7 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface } d.Set("job_schedule_id", resp.JobScheduleID) - d.Set("resource_group_name", resGroup) + d.Set("resource_group_name", resourceGroup) d.Set("automation_account_name", accountName) d.Set("runbook_name", resp.JobScheduleProperties.Runbook.Name) d.Set("schedule_name", resp.JobScheduleProperties.Schedule.Name) @@ -224,10 +231,10 @@ func resourceArmAutomationJobScheduleDelete(d *schema.ResourceData, meta interfa jobScheduleID := id.Path["jobSchedules"] jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) - resGroup := id.ResourceGroup + resourceGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] - resp, err := client.Delete(ctx, resGroup, accountName, jobScheduleUUID) + resp, err := client.Delete(ctx, resourceGroup, accountName, jobScheduleUUID) if err != nil { if !utils.ResponseWasNotFound(resp) { return fmt.Errorf("Error issuing AzureRM delete request for Automation Job Schedule '%s': %+v", jobScheduleUUID, err) diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go index 0e7aeec998267..6d4e06d529cd2 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_certificate_test.go @@ -204,7 +204,6 @@ resource "azurerm_automation_certificate" "import" { resource_group_name = azurerm_automation_certificate.test.resource_group_name automation_account_name = azurerm_automation_certificate.test.automation_account_name base64 = azurerm_automation_certificate.test.base64 - thumbprint = azurerm_automation_certificate.test.thumbprint } `, template) } diff --git a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go index 98bf5410a4942..32fc5d00ab295 100644 --- a/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go +++ b/azurerm/internal/services/automation/tests/resource_arm_automation_job_schedule_test.go @@ -299,6 +299,7 @@ resource "azurerm_automation_job_schedule" "import" { automation_account_name = "${azurerm_automation_job_schedule.test.automation_account_name}" schedule_name = "${azurerm_automation_job_schedule.test.schedule_name}" runbook_name = "${azurerm_automation_job_schedule.test.runbook_name}" + job_schedule_id = "${azurerm_automation_job_schedule.test.job_schedule_id}" } `, template) } From 1d1008e3f7ace203eaef1478d778a0d26bd430e3 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 13:27:46 +0100 Subject: [PATCH 190/498] linting --- .../services/network/tests/resource_arm_subnet_test.go | 4 ++-- ...ubnet_network_security_group_association.html.markdown | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go index e428fd039070a..3e72723ecf97d 100644 --- a/azurerm/internal/services/network/tests/resource_arm_subnet_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_subnet_test.go @@ -373,7 +373,7 @@ resource "azurerm_subnet" "test" { name = "first" service_delegation { - name = "Microsoft.ContainerInstance/containerGroups" + name = "Microsoft.ContainerInstance/containerGroups" actions = [ "Microsoft.Network/virtualNetworks/subnets/action", ] @@ -398,7 +398,7 @@ resource "azurerm_subnet" "test" { name = "first" service_delegation { - name = "Microsoft.Databricks/workspaces" + name = "Microsoft.Databricks/workspaces" actions = [ "Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", diff --git a/website/docs/r/subnet_network_security_group_association.html.markdown b/website/docs/r/subnet_network_security_group_association.html.markdown index 5259f4d0da244..c172e34286136 100644 --- a/website/docs/r/subnet_network_security_group_association.html.markdown +++ b/website/docs/r/subnet_network_security_group_association.html.markdown @@ -27,10 +27,10 @@ resource "azurerm_virtual_network" "example" { } resource "azurerm_subnet" "example" { - name = "frontend" - resource_group_name = azurerm_resource_group.example.name - virtual_network_name = azurerm_virtual_network.example.name - address_prefix = "10.0.2.0/24" + name = "frontend" + resource_group_name = azurerm_resource_group.example.name + virtual_network_name = azurerm_virtual_network.example.name + address_prefix = "10.0.2.0/24" } resource "azurerm_network_security_group" "example" { From 065ef3172b00e0ca78d323464334948c6480dd0b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 13:29:10 +0100 Subject: [PATCH 191/498] linting --- azurerm/internal/services/network/network_interface.go | 2 +- .../network/tests/resource_arm_network_interface_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/network/network_interface.go b/azurerm/internal/services/network/network_interface.go index 0f5c25a97bd4e..798b38580bb45 100644 --- a/azurerm/internal/services/network/network_interface.go +++ b/azurerm/internal/services/network/network_interface.go @@ -22,7 +22,7 @@ func parseFieldsFromNetworkInterface(input network.InterfacePropertiesFormat) ne var mapToSlice = func(input map[string]struct{}) []string { output := make([]string, 0) - for id, _ := range input { + for id := range input { output = append(output, id) } diff --git a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go index 3ec528f8615a5..47ccf8ca5d295 100644 --- a/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_network_interface_test.go @@ -547,7 +547,7 @@ resource "azurerm_network_interface" "test" { name = "acctestni-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - internal_dns_name_label = "acctestni-%s-%s" + internal_dns_name_label = "acctestni-%s-%s" ip_configuration { name = "primary" From 1584c8f9a8d00d472fbc68b8b27b49ff67c8d262 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 13:36:39 +0100 Subject: [PATCH 192/498] r/api_management_api_(operation|schema): fixing the tests --- ...e_arm_api_management_api_operation_test.go | 1 - ...urce_arm_api_management_api_schema_test.go | 32 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go index bf2fd8babfee4..b6f49aaf5039d 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_operation_test.go @@ -239,7 +239,6 @@ resource "azurerm_api_management_api_operation" "test" { } func testAccAzureRMApiManagementApiOperation_requiresImport(data acceptance.TestData) string { - //template := testAccAzureRMApiManagementApiOperation_template(data) template := testAccAzureRMApiManagementApiOperation_basic(data) return fmt.Sprintf(` %s diff --git a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go index cead65cccb6ad..193082f8decb7 100644 --- a/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go +++ b/azurerm/internal/services/apimanagement/tests/resource_arm_api_management_api_schema_test.go @@ -118,30 +118,30 @@ func testAccAzureRMApiManagementApiSchema_basic(data acceptance.TestData) string %s resource "azurerm_api_management_api_schema" "test" { - api_name = "${azurerm_api_management_api.test.name}" - api_management_name = "${azurerm_api_management_api.test.api_management_name}" - resource_group_name = "${azurerm_api_management_api.test.resource_group_name}" + api_name = azurerm_api_management_api.test.name + api_management_name = azurerm_api_management_api.test.api_management_name + resource_group_name = azurerm_api_management_api.test.resource_group_name schema_id = "acctestSchema%d" content_type = "application/vnd.ms-azure-apim.xsd+xml" - value = "${file("testdata/api_management_api_schema.xml")}" + value = file("testdata/api_management_api_schema.xml") } `, template, data.RandomInteger) } func testAccAzureRMApiManagementApiSchema_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMApiManagementApiSchema_template(data) + template := testAccAzureRMApiManagementApiSchema_basic(data) return fmt.Sprintf(` %s resource "azurerm_api_management_api_schema" "import" { - api_name = "${azurerm_api_management_api.test.name}" - api_management_name = "${azurerm_api_management.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - schema_id = "acctestSchema%d" - content_type = "application/vnd.ms-azure-apim.xsd+xml" - value = "${file("testdata/api_management_api_schema.xml")}" + api_name = azurerm_api_management_api_schema.test.name + api_management_name = azurerm_api_management_api_schema.test.api_management_name + resource_group_name = azurerm_api_management_api_schema.test.resource_group_name + schema_id = azurerm_api_management_api_schema.test.schema_id + content_type = azurerm_api_management_api_schema.test.content_type + value = azurerm_api_management_api_schema.test.value } -`, template, data.RandomInteger) +`, template) } func testAccAzureRMApiManagementApiSchema_template(data acceptance.TestData) string { @@ -153,8 +153,8 @@ resource "azurerm_resource_group" "test" { resource "azurerm_api_management" "test" { name = "acctestAM-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name publisher_name = "pub1" publisher_email = "pub1@email.com" sku_name = "Developer_1" @@ -162,8 +162,8 @@ resource "azurerm_api_management" "test" { resource "azurerm_api_management_api" "test" { name = "acctestapi-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - api_management_name = "${azurerm_api_management.test.name}" + resource_group_name = azurerm_resource_group.test.name + api_management_name = azurerm_api_management.test.name display_name = "api1" path = "api1" protocols = ["https"] From 012e1a948007a31362edb09640507af9094dc48f Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 13:43:07 +0100 Subject: [PATCH 193/498] r/devspace: switching to use `default_node_pool` --- .../resource_arm_devspace_controller_test.go | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go b/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go index ff7972fb838e3..e968c6bcc18f6 100644 --- a/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go +++ b/azurerm/internal/services/devspace/tests/resource_arm_devspace_controller_test.go @@ -146,10 +146,10 @@ resource "azurerm_kubernetes_cluster" "test" { } } - agent_pool_profile { - name = "default" - count = "1" - vm_size = "Standard_DS2_v2" + default_node_pool { + name = "default" + node_count = 1 + vm_size = "Standard_DS2_v2" } service_principal { @@ -160,12 +160,11 @@ resource "azurerm_kubernetes_cluster" "test" { resource "azurerm_devspace_controller" "test" { name = "acctestdsc%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - target_container_host_resource_id = "${azurerm_kubernetes_cluster.test.id}" - target_container_host_credentials_base64 = "${base64encode(azurerm_kubernetes_cluster.test.kube_config_raw)}" - - sku_name = "S1" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + target_container_host_resource_id = azurerm_kubernetes_cluster.test.id + target_container_host_credentials_base64 = base64encode(azurerm_kubernetes_cluster.test.kube_config_raw) + sku_name = "S1" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, clientId, clientSecret, data.RandomInteger) } @@ -176,12 +175,12 @@ func testAccAzureRMDevSpaceController_requiresImport(data acceptance.TestData, c %s resource "azurerm_devspace_controller" "import" { - name = "${azurerm_devspace_controller.test.name}" - location = "${azurerm_devspace_controller.test.location}" - resource_group_name = "${azurerm_devspace_controller.test.resource_group_name}" - target_container_host_resource_id = "${azurerm_kubernetes_cluster.test.id}" - target_container_host_credentials_base64 = "${base64encode(azurerm_kubernetes_cluster.test.kube_config_raw)}" - sku_name = "${base64encode(azurerm_kubernetes_cluster.test.sku_name)}" + name = azurerm_devspace_controller.test.name + location = azurerm_devspace_controller.test.location + resource_group_name = azurerm_devspace_controller.test.resource_group_name + target_container_host_resource_id = azurerm_devspace_controller.test.target_container_host_resource_id + target_container_host_credentials_base64 = base64encode(azurerm_kubernetes_cluster.test.kube_config_raw) + sku_name = azurerm_devspace_controller.test.sku_name } `, template) } From f445802f81e66bd68629c95ed3d76bd0d6e88cc4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 14:37:51 +0100 Subject: [PATCH 194/498] r/dns_zone: removing tests covering the deprecated fields --- .../services/dns/data_source_dns_zone.go | 32 ------- .../services/dns/resource_arm_dns_zone.go | 84 +------------------ .../dns/tests/resource_arm_dns_zone_test.go | 42 ---------- website/docs/d/dns_zone.html.markdown | 2 - website/docs/r/dns_zone.html.markdown | 4 - 5 files changed, 1 insertion(+), 163 deletions(-) diff --git a/azurerm/internal/services/dns/data_source_dns_zone.go b/azurerm/internal/services/dns/data_source_dns_zone.go index 4ee9f56b3eff2..3c4586a34e8a4 100644 --- a/azurerm/internal/services/dns/data_source_dns_zone.go +++ b/azurerm/internal/services/dns/data_source_dns_zone.go @@ -51,18 +51,6 @@ func dataSourceArmDnsZone() *schema.Resource { Set: schema.HashString, }, - "registration_virtual_network_ids": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - - "resolution_virtual_network_ids": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "tags": tags.SchemaDataSource(), }, } @@ -109,26 +97,6 @@ func dataSourceArmDnsZoneRead(d *schema.ResourceData, meta interface{}) error { d.Set("number_of_record_sets", props.NumberOfRecordSets) d.Set("max_number_of_record_sets", props.MaxNumberOfRecordSets) - registrationVNets := make([]string, 0) - if rvns := props.RegistrationVirtualNetworks; rvns != nil { - for _, rvn := range *rvns { - registrationVNets = append(registrationVNets, *rvn.ID) - } - } - if err := d.Set("registration_virtual_network_ids", registrationVNets); err != nil { - return err - } - - resolutionVNets := make([]string, 0) - if rvns := props.ResolutionVirtualNetworks; rvns != nil { - for _, rvn := range *rvns { - resolutionVNets = append(resolutionVNets, *rvn.ID) - } - } - if err := d.Set("resolution_virtual_network_ids", resolutionVNets); err != nil { - return err - } - nameServers := make([]string, 0) if ns := props.NameServers; ns != nil { nameServers = *ns diff --git a/azurerm/internal/services/dns/resource_arm_dns_zone.go b/azurerm/internal/services/dns/resource_arm_dns_zone.go index a073ae37bcf95..53d04a030d38e 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_zone.go +++ b/azurerm/internal/services/dns/resource_arm_dns_zone.go @@ -59,18 +59,6 @@ func resourceArmDnsZone() *schema.Resource { Set: schema.HashString, }, - "registration_virtual_network_ids": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - - "resolution_virtual_network_ids": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - "tags": tags.Schema(), }, } @@ -100,22 +88,14 @@ func resourceArmDnsZoneCreateUpdate(d *schema.ResourceData, meta interface{}) er location := "global" t := d.Get("tags").(map[string]interface{}) - registrationVirtualNetworkIds := expandDnsZoneRegistrationVirtualNetworkIds(d) - resolutionVirtualNetworkIds := expandDnsZoneResolutionVirtualNetworkIds(d) - parameters := dns.Zone{ Location: &location, Tags: tags.Expand(t), - ZoneProperties: &dns.ZoneProperties{ - RegistrationVirtualNetworks: registrationVirtualNetworkIds, - ResolutionVirtualNetworks: resolutionVirtualNetworkIds, - }, } etag := "" ifNoneMatch := "" // set to empty to allow updates to records after creation - _, err := client.CreateOrUpdate(ctx, resGroup, name, parameters, etag, ifNoneMatch) - if err != nil { + if _, err := client.CreateOrUpdate(ctx, resGroup, name, parameters, etag, ifNoneMatch); err != nil { return fmt.Errorf("Error creating/updating DNS Zone %q (Resource Group %q): %s", name, resGroup, err) } @@ -160,16 +140,6 @@ func resourceArmDnsZoneRead(d *schema.ResourceData, meta interface{}) error { d.Set("number_of_record_sets", resp.NumberOfRecordSets) d.Set("max_number_of_record_sets", resp.MaxNumberOfRecordSets) - registrationVirtualNetworks := flattenDnsZoneRegistrationVirtualNetworkIDs(resp.RegistrationVirtualNetworks) - if err := d.Set("registration_virtual_network_ids", registrationVirtualNetworks); err != nil { - return err - } - - resolutionVirtualNetworks := flattenDnsZoneResolutionVirtualNetworkIDs(resp.ResolutionVirtualNetworks) - if err := d.Set("resolution_virtual_network_ids", resolutionVirtualNetworks); err != nil { - return err - } - nameServers := make([]string, 0) if s := resp.NameServers; s != nil { nameServers = *s @@ -212,55 +182,3 @@ func resourceArmDnsZoneDelete(d *schema.ResourceData, meta interface{}) error { return nil } - -func expandDnsZoneResolutionVirtualNetworkIds(d *schema.ResourceData) *[]dns.SubResource { - resolutionVirtualNetworks := d.Get("resolution_virtual_network_ids").([]interface{}) - - resolutionVNetSubResources := make([]dns.SubResource, 0, len(resolutionVirtualNetworks)) - for _, rvn := range resolutionVirtualNetworks { - id := rvn.(string) - resolutionVNetSubResources = append(resolutionVNetSubResources, dns.SubResource{ - ID: &id, - }) - } - - return &resolutionVNetSubResources -} - -func flattenDnsZoneRegistrationVirtualNetworkIDs(input *[]dns.SubResource) []string { - registrationVirtualNetworks := make([]string, 0) - - if input != nil { - for _, rvn := range *input { - registrationVirtualNetworks = append(registrationVirtualNetworks, *rvn.ID) - } - } - - return registrationVirtualNetworks -} - -func expandDnsZoneRegistrationVirtualNetworkIds(d *schema.ResourceData) *[]dns.SubResource { - registrationVirtualNetworks := d.Get("registration_virtual_network_ids").([]interface{}) - - registrationVNetSubResources := make([]dns.SubResource, 0) - for _, rvn := range registrationVirtualNetworks { - id := rvn.(string) - registrationVNetSubResources = append(registrationVNetSubResources, dns.SubResource{ - ID: &id, - }) - } - - return ®istrationVNetSubResources -} - -func flattenDnsZoneResolutionVirtualNetworkIDs(input *[]dns.SubResource) []string { - resolutionVirtualNetworks := make([]string, 0) - - if input != nil { - for _, rvn := range *input { - resolutionVirtualNetworks = append(resolutionVirtualNetworks, *rvn.ID) - } - } - - return resolutionVirtualNetworks -} diff --git a/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go b/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go index fc0302a2997c1..b886117ae7de1 100644 --- a/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go +++ b/azurerm/internal/services/dns/tests/resource_arm_dns_zone_test.go @@ -58,25 +58,6 @@ func TestAccAzureRMDnsZone_requiresImport(t *testing.T) { }) } -func TestAccAzureRMDnsZone_withVNets(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_dns_zone", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMDnsZoneDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMDnsZone_withVNets(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMDnsZoneExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - func TestAccAzureRMDnsZone_withTags(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_dns_zone", "test") @@ -187,29 +168,6 @@ resource "azurerm_dns_zone" "import" { `, template) } -func testAccAzureRMDnsZone_withVNets(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG_%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "acctestvnet%d" - location = "%s" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["10.0.0.0/16"] - dns_servers = ["168.63.129.16"] -} - -resource "azurerm_dns_zone" "test" { - name = "acctestzone%d.com" - resource_group_name = "${azurerm_resource_group.test.name}" - registration_virtual_network_ids = ["${azurerm_virtual_network.test.id}"] -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - func testAccAzureRMDnsZone_withTags(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { diff --git a/website/docs/d/dns_zone.html.markdown b/website/docs/d/dns_zone.html.markdown index dbeac7e854005..a44ce44651b75 100644 --- a/website/docs/d/dns_zone.html.markdown +++ b/website/docs/d/dns_zone.html.markdown @@ -38,8 +38,6 @@ in your subscription that matches `name` will be returned. * `max_number_of_record_sets` - Maximum number of Records in the zone. * `number_of_record_sets` - The number of records already in the zone. * `name_servers` - A list of values that make up the NS record for the zone. -* `registration_virtual_network_ids` - A list of Virtual Network ID's that register hostnames in this DNS zone. -* `resolution_virtual_network_ids` - A list of Virtual Network ID's that resolve records in this DNS zone. * `tags` - A mapping of tags to assign to the EventHub Namespace. ## Timeouts diff --git a/website/docs/r/dns_zone.html.markdown b/website/docs/r/dns_zone.html.markdown index 230d4da6e0aa3..21ef3b8166f9f 100644 --- a/website/docs/r/dns_zone.html.markdown +++ b/website/docs/r/dns_zone.html.markdown @@ -36,10 +36,6 @@ The following arguments are supported: * `resource_group_name` - (Required) Specifies the resource group where the resource exists. Changing this forces a new resource to be created. -* `registration_virtual_network_ids` - (Optional) A list of Virtual Network ID's that register hostnames in this DNS zone. This field can only be set when `zone_type` is set to `Private`. - -* `resolution_virtual_network_ids` - (Optional) A list of Virtual Network ID's that resolve records in this DNS zone. This field can only be set when `zone_type` is set to `Private`. - * `tags` - (Optional) A mapping of tags to assign to the resource. ## Attributes Reference From aeda0b669d58b972fd537fa03d5aab6af0ce2f10 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 14:38:04 +0100 Subject: [PATCH 195/498] r/dns_ns_record: fixing a bug during update ``` $ TF_ACC=1 go test -v ./azurerm/internal/services/dns/tests/ -timeout=60m -run=TestAccAzureRMDnsNsRecord_withTags === RUN TestAccAzureRMDnsNsRecord_withTags === PAUSE TestAccAzureRMDnsNsRecord_withTags === CONT TestAccAzureRMDnsNsRecord_withTags --- PASS: TestAccAzureRMDnsNsRecord_withTags (137.86s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/dns/tests 137.899s ``` --- .../dns/resource_arm_dns_ns_record.go | 112 +++++++++++++----- 1 file changed, 84 insertions(+), 28 deletions(-) diff --git a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go index 77ff7a4c4846a..efb3e9a2fb062 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go +++ b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go @@ -18,9 +18,9 @@ import ( func resourceArmDnsNsRecord() *schema.Resource { return &schema.Resource{ - Create: resourceArmDnsNsRecordCreateUpdate, + Create: resourceArmDnsNsRecordCreate, Read: resourceArmDnsNsRecordRead, - Update: resourceArmDnsNsRecordCreateUpdate, + Update: resourceArmDnsNsRecordUpdate, Delete: resourceArmDnsNsRecordDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, @@ -45,12 +45,15 @@ func resourceArmDnsNsRecord() *schema.Resource { "zone_name": { Type: schema.TypeString, Required: true, + ForceNew: true, }, "records": { Type: schema.TypeList, Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, "ttl": { @@ -68,16 +71,16 @@ func resourceArmDnsNsRecord() *schema.Resource { } } -func resourceArmDnsNsRecordCreateUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceArmDnsNsRecordCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Dns.RecordSetsClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) zoneName := d.Get("zone_name").(string) - if features.ShouldResourcesBeImported() && d.IsNewResource() { + if features.ShouldResourcesBeImported() { existing, err := client.Get(ctx, resGroup, zoneName, name, dns.NS) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { @@ -93,19 +96,22 @@ func resourceArmDnsNsRecordCreateUpdate(d *schema.ResourceData, meta interface{} ttl := int64(d.Get("ttl").(int)) t := d.Get("tags").(map[string]interface{}) + recordsRaw := d.Get("records").([]interface{}) + records := expandAzureRmDnsNsRecords(recordsRaw) + parameters := dns.RecordSet{ Name: &name, RecordSetProperties: &dns.RecordSetProperties{ Metadata: tags.Expand(t), TTL: &ttl, - NsRecords: expandAzureRmDnsNsRecords(d), + NsRecords: records, }, } eTag := "" ifNoneMatch := "" // set to empty to allow updates to records after creation if _, err := client.CreateOrUpdate(ctx, resGroup, zoneName, name, dns.NS, parameters, eTag, ifNoneMatch); err != nil { - return fmt.Errorf("Error creating/updating DNS NS Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) + return fmt.Errorf("Error creating DNS NS Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) } resp, err := client.Get(ctx, resGroup, zoneName, name, dns.NS) @@ -122,6 +128,53 @@ func resourceArmDnsNsRecordCreateUpdate(d *schema.ResourceData, meta interface{} return resourceArmDnsNsRecordRead(d, meta) } +func resourceArmDnsNsRecordUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Dns.RecordSetsClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + + resGroup := id.ResourceGroup + name := id.Path["NS"] + zoneName := id.Path["dnszones"] + + existing, err := client.Get(ctx, resGroup, zoneName, name, dns.NS) + if err != nil { + return fmt.Errorf("Error retrieving NS %q (DNS Zone %q / Resource Group %q): %+v", name, zoneName, resGroup, err) + } + + if existing.RecordSetProperties == nil { + return fmt.Errorf("Error retrieving NS %q (DNS Zone %q / Resource Group %q): `properties` was nil", name, zoneName, resGroup) + } + + if d.HasChange("records") { + recordsRaw := d.Get("records").([]interface{}) + records := expandAzureRmDnsNsRecords(recordsRaw) + existing.RecordSetProperties.NsRecords = records + } + + if d.HasChange("tags") { + t := d.Get("tags").(map[string]interface{}) + existing.RecordSetProperties.Metadata = tags.Expand(t) + } + + if d.HasChange("ttl") { + existing.RecordSetProperties.TTL = utils.Int64(int64(d.Get("ttl").(int))) + } + + eTag := "" + ifNoneMatch := "" // set to empty to allow updates to records after creation + if _, err := client.CreateOrUpdate(ctx, resGroup, zoneName, name, dns.NS, existing, eTag, ifNoneMatch); err != nil { + return fmt.Errorf("Error updating DNS NS Record %q (Zone %q / Resource Group %q): %s", name, zoneName, resGroup, err) + } + + return resourceArmDnsNsRecordRead(d, meta) +} + func resourceArmDnsNsRecordRead(d *schema.ResourceData, meta interface{}) error { dnsClient := meta.(*clients.Client).Dns.RecordSetsClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) @@ -151,8 +204,11 @@ func resourceArmDnsNsRecordRead(d *schema.ResourceData, meta interface{}) error d.Set("ttl", resp.TTL) d.Set("fqdn", resp.Fqdn) - if err := d.Set("records", flattenAzureRmDnsNsRecords(resp.NsRecords)); err != nil { - return fmt.Errorf("Error settings `records`: %+v", err) + if props := resp.RecordSetProperties; props != nil { + if err := d.Set("records", flattenAzureRmDnsNsRecords(props.NsRecords)); err != nil { + return fmt.Errorf("Error settings `records`: %+v", err) + } + } return tags.FlattenAndSet(d, resp.Metadata) @@ -180,33 +236,33 @@ func resourceArmDnsNsRecordDelete(d *schema.ResourceData, meta interface{}) erro return nil } -func flattenAzureRmDnsNsRecords(records *[]dns.NsRecord) []string { - results := make([]string, 0, len(*records)) +func flattenAzureRmDnsNsRecords(records *[]dns.NsRecord) []interface{} { + if records == nil { + return []interface{}{} + } - if records != nil { - for _, record := range *records { - results = append(results, *record.Nsdname) + results := make([]interface{}, 0) + for _, record := range *records { + if record.Nsdname == nil { + continue } + + results = append(results, *record.Nsdname) } return results } -func expandAzureRmDnsNsRecords(d *schema.ResourceData) *[]dns.NsRecord { - var records []dns.NsRecord +func expandAzureRmDnsNsRecords(input []interface{}) *[]dns.NsRecord { + records := make([]dns.NsRecord, len(input)) + for i, v := range input { + record := v.(string) - if d.HasChange("records") { - recordStrings := d.Get("records").([]interface{}) - records = make([]dns.NsRecord, len(recordStrings)) - for i, v := range recordStrings { - record := v.(string) - - nsRecord := dns.NsRecord{ - Nsdname: &record, - } - - records[i] = nsRecord + nsRecord := dns.NsRecord{ + Nsdname: &record, } + + records[i] = nsRecord } return &records } From b1b0e5dc49f6e71ecdffeb500214ff05d215b15a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 14:41:40 +0100 Subject: [PATCH 196/498] r/eventhub: updating the test config to account for the storage container no longer taking the rg name --- .../services/eventhub/tests/resource_arm_eventhub_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/eventhub/tests/resource_arm_eventhub_test.go b/azurerm/internal/services/eventhub/tests/resource_arm_eventhub_test.go index bdd3e5ec21dd2..c52913edad794 100644 --- a/azurerm/internal/services/eventhub/tests/resource_arm_eventhub_test.go +++ b/azurerm/internal/services/eventhub/tests/resource_arm_eventhub_test.go @@ -518,7 +518,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "acctest" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } From 869a1069c2f7a3e42f2736a6452ab7faa35645a2 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 14:50:28 +0100 Subject: [PATCH 197/498] updating to include #5784 --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84c2c7339a68f..5543e491ec30d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ FEATURES: * **Requires Import:** The Azure Provider now checks for the presence of an existing resource prior to creating it - which means that if you try and create a resource which already exists (without importing it) you'll be prompted to import this into the state. * **New Resource:** `azurerm_linux_virtual_machine` [GH-5705] * **New Resource:** `azurerm_linux_virtual_machine_scale_set` [GH-5705] +* **New Resource:** `azurerm_network_interface_security_group_association` [GH-5784] * **New Resource:** `azurerm_virtual_machine_scale_set_extension` [GH-5705] * **New Resource:** `azurerm_windows_virtual_machine` [GH-5705] * **New Resource:** `azurerm_windows_virtual_machine_scale_set` [GH-5705] @@ -47,6 +48,14 @@ BREAKING CHANGES: * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] * `azurerm_mariadb_server` - removing the `sku` block since it's been deprecated in favour of the `sku_name` field [GH-5777] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] +* `azurerm_network_interface` - the `dns_servers` field now respects ordering [GH-5784] +* `azurerm_network_interface` - removing the deprecated `application_gateway_backend_address_pools_ids` field from the `ip_configurations` block [GH-5784] +* `azurerm_network_interface` - removing the deprecated `application_security_group_ids ` field from the `ip_configurations` block [GH-5784] +* `azurerm_network_interface` - removing the deprecated `load_balancer_backend_address_pools_ids ` field from the `ip_configurations` block [GH-5784] +* `azurerm_network_interface` - removing the deprecated `load_balancer_inbound_nat_rules_ids ` field from the `ip_configurations` block [GH-5784] +* `azurerm_network_interface` - removing the deprecated `internal_fqdn` field [GH-5784] +* `azurerm_network_interface` - removing the `network_security_group_id` field in favour of a new split-out resource `azurerm_network_interface_security_group_association` [GH-5784] +* `azurerm_network_interface` - the `virtual_machine_id` field is now computed-only since it's not setable [GH-5784] * `azurerm_notification_hub_namesapce` - removing the `sku` block in favour of the `sku_name` argument [GH-5722] * `azurerm_postgresql_server` - removing the `sku` block which has been deprecated in favour of the `sku_name` field [GH-5721] * `azurerm_relay_namespace` - removing the `sku` block in favour of the `sku_name` field [GH-5719] From 90f782400d66f74b04ca9ab6f3cba21b6fb9b5ef Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 14:52:26 +0100 Subject: [PATCH 198/498] moving the bug fix to the bug fixes section --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5543e491ec30d..c6ddfa91a9049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,6 @@ BREAKING CHANGES: * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] * `azurerm_mariadb_server` - removing the `sku` block since it's been deprecated in favour of the `sku_name` field [GH-5777] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] -* `azurerm_network_interface` - the `dns_servers` field now respects ordering [GH-5784] * `azurerm_network_interface` - removing the deprecated `application_gateway_backend_address_pools_ids` field from the `ip_configurations` block [GH-5784] * `azurerm_network_interface` - removing the deprecated `application_security_group_ids ` field from the `ip_configurations` block [GH-5784] * `azurerm_network_interface` - removing the deprecated `load_balancer_backend_address_pools_ids ` field from the `ip_configurations` block [GH-5784] @@ -83,6 +82,7 @@ IMPROVEMENTS: BUG FIXES: * `azurerm_linux_virtual_machine` - using the delete custom timeout during deletion [GH-5764] +* `azurerm_network_interface` - the `dns_servers` field now respects ordering [GH-5784] * `azurerm_public_ip_prefix` - fixing the validation for the `prefix_length` to match the Azure API [GH-5693] * `azurerm_role_assignment` - validating that the `name` is a UUID [GH-5624] * `azurerm_signalr_service` - ensuring the SignalR segment is parsed in the correct case [GH-5737] From 33aa01f315b636e1d8f3f926d4e0cbe77c7f1819 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 14:58:15 +0100 Subject: [PATCH 199/498] dns: updating the tests to match the fields always being set --- .../services/dns/resource_arm_dns_cname_record.go | 8 +------- .../services/dns/tests/resource_arm_dns_a_record_test.go | 2 +- .../dns/tests/resource_arm_dns_cname_record_test.go | 4 ++-- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/azurerm/internal/services/dns/resource_arm_dns_cname_record.go b/azurerm/internal/services/dns/resource_arm_dns_cname_record.go index 715bdc968812e..9d62608bc817a 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_cname_record.go +++ b/azurerm/internal/services/dns/resource_arm_dns_cname_record.go @@ -47,12 +47,6 @@ func resourceArmDnsCNameRecord() *schema.Resource { Required: true, }, - "records": { - Type: schema.TypeString, - Optional: true, - Removed: "Use `record` instead. This attribute will be removed in a future version", - }, - "record": { Type: schema.TypeString, Optional: true, @@ -73,7 +67,7 @@ func resourceArmDnsCNameRecord() *schema.Resource { Type: schema.TypeString, Optional: true, ValidateFunc: azure.ValidateResourceID, - ConflictsWith: []string{"records"}, + ConflictsWith: []string{"record"}, }, "tags": tags.Schema(), diff --git a/azurerm/internal/services/dns/tests/resource_arm_dns_a_record_test.go b/azurerm/internal/services/dns/tests/resource_arm_dns_a_record_test.go index 81d1c015abb51..e3ed5c60671ab 100644 --- a/azurerm/internal/services/dns/tests/resource_arm_dns_a_record_test.go +++ b/azurerm/internal/services/dns/tests/resource_arm_dns_a_record_test.go @@ -163,7 +163,7 @@ func TestAccAzureRMDnsARecord_RecordsToAlias(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMDnsARecordExists(data.ResourceName), resource.TestCheckResourceAttrPair(data.ResourceName, "target_resource_id", targetResourceName, "id"), - resource.TestCheckNoResourceAttr(data.ResourceName, "records"), + resource.TestCheckResourceAttr(data.ResourceName, "records.#", "0"), ), }, data.ImportStep(), diff --git a/azurerm/internal/services/dns/tests/resource_arm_dns_cname_record_test.go b/azurerm/internal/services/dns/tests/resource_arm_dns_cname_record_test.go index 3e33c95bdcfe1..0e630f6e2fba9 100644 --- a/azurerm/internal/services/dns/tests/resource_arm_dns_cname_record_test.go +++ b/azurerm/internal/services/dns/tests/resource_arm_dns_cname_record_test.go @@ -180,7 +180,7 @@ func TestAccAzureRMDnsCNameRecord_RecordToAlias(t *testing.T) { Check: resource.ComposeTestCheckFunc( testCheckAzureRMDnsCNameRecordExists(data.ResourceName), resource.TestCheckResourceAttrPair(data.ResourceName, "target_resource_id", targetResourceName, "id"), - resource.TestCheckNoResourceAttr(data.ResourceName, "record"), + resource.TestCheckResourceAttr(data.ResourceName, "record", ""), ), }, data.ImportStep(), @@ -208,7 +208,7 @@ func TestAccAzureRMDnsCNameRecord_AliasToRecord(t *testing.T) { Config: testAccAzureRMDnsCNameRecord_AliasToRecordUpdate(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMDnsCNameRecordExists(data.ResourceName), - resource.TestCheckNoResourceAttr(data.ResourceName, "target_resource_id"), + resource.TestCheckResourceAttr(data.ResourceName, "target_resource_id", ""), ), }, data.ImportStep(), From 23bef270c237836838efee2a18fdd8c3a098c10d Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 15:14:16 +0100 Subject: [PATCH 200/498] updating to include #5795 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6ddfa91a9049..ab42ea3cf4c74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ BREAKING CHANGES: * `azurerm_azuread_service_principal` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_cognitive_account` - removing the deprecated `sku_name` block [GH-5797] * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] +* `azurerm_devspace_controller` - removing the deprecated `sku` block [GH-5795] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] From f5e686b3dcbb80cf3e66dbc81b08493b9f8c1098 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 16:30:03 +0100 Subject: [PATCH 201/498] r/mysql_server: fixing the tests --- .../mysql/tests/resource_arm_mysql_server_test.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go index 267d9ea4315da..942b7d50b67e2 100644 --- a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go +++ b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go @@ -131,7 +131,7 @@ func TestAccAzureRMMySQLServer_basicFiveSevenUpdated(t *testing.T) { Config: testAccAzureRMMySQLServer_basicFiveSeven(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_2"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_2"), resource.TestCheckResourceAttr(data.ResourceName, "version", "5.7"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "51200"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), @@ -141,7 +141,7 @@ func TestAccAzureRMMySQLServer_basicFiveSevenUpdated(t *testing.T) { Config: testAccAzureRMMySQLServer_basicFiveSevenUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_4"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_4"), resource.TestCheckResourceAttr(data.ResourceName, "version", "5.7"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), @@ -164,10 +164,7 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMMySQLServer_basicEightZero(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "GP_Gen5_32"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.capacity", "32"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.tier", "GeneralPurpose"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.family", "Gen5"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_32"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), @@ -176,10 +173,7 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMMySQLServer_basicFiveSevenUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "MO_Gen5_16"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.capacity", "16"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.tier", "MemoryOptimized"), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.family", "Gen5"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "MO_Gen5_16"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "4194304"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), From 35745e966495d67590daeb299d9284a1ff59c5d5 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 17:05:28 +0100 Subject: [PATCH 202/498] updating to include #5793 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab42ea3cf4c74..5023c78c482a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,11 @@ BREAKING CHANGES: * `azurerm_cognitive_account` - removing the deprecated `sku_name` block [GH-5797] * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_devspace_controller` - removing the deprecated `sku` block [GH-5795] +* `azurerm_eventhub` - removing the deprecated `location` field [GH-5793] +* `azurerm_eventhub_authorization_rule` - removing the deprecated `location` field [GH-5793] +* `azurerm_eventhub_consumer_group` - removing the deprecated `location` field [GH-5793] +* `azurerm_eventhub_namespace` - removing the deprecated `kafka_enabled` field since this is now managed by Azure [GH-5793] +* `azurerm_eventhub_namespace_authorization_rule` - removing the deprecated `location` field [GH-5793] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] From 9bf29c09a2d28c41cd65855333c5346ecebc5d5b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 16:58:06 +0100 Subject: [PATCH 203/498] r/mysqL_server: fixing assertions --- .../services/mysql/tests/resource_arm_mysql_server_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go index 942b7d50b67e2..a61082e0afd7e 100644 --- a/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go +++ b/azurerm/internal/services/mysql/tests/resource_arm_mysql_server_test.go @@ -164,8 +164,8 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMMySQLServer_basicEightZero(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_32"), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_2"), + resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "51200"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), }, @@ -173,7 +173,7 @@ func TestAccAzureRMMySQLServer_updateSKU(t *testing.T) { Config: testAccAzureRMMySQLServer_basicFiveSevenUpdated(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMySQLServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "MO_Gen5_16"), + resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_4"), resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "4194304"), resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), From 30be1a4814ac27439fed08660f94c9187f830257 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 17:14:39 +0100 Subject: [PATCH 204/498] linting --- azurerm/internal/services/dns/resource_arm_dns_ns_record.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go index efb3e9a2fb062..f1d6791083711 100644 --- a/azurerm/internal/services/dns/resource_arm_dns_ns_record.go +++ b/azurerm/internal/services/dns/resource_arm_dns_ns_record.go @@ -208,7 +208,6 @@ func resourceArmDnsNsRecordRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("records", flattenAzureRmDnsNsRecords(props.NsRecords)); err != nil { return fmt.Errorf("Error settings `records`: %+v", err) } - } return tags.FlattenAndSet(d, resp.Metadata) From 44842538a8c06b1a5e06d696c357750ff7b0ce32 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 17:20:45 +0100 Subject: [PATCH 205/498] updating to include #5523 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5023c78c482a2..f022bb8780874 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ FEATURES: * **Custom Timeouts:** - all resources within the Azure Provider now allow configuring custom timeouts - please [see Terraform's Timeout documentation](https://www.terraform.io/docs/configuration/resources.html#operation-timeouts) and the documentation in each data source resource for more information. * **Requires Import:** The Azure Provider now checks for the presence of an existing resource prior to creating it - which means that if you try and create a resource which already exists (without importing it) you'll be prompted to import this into the state. +* **New Resource:** `azurerm_express_route_gateway` [GH-5523] * **New Resource:** `azurerm_linux_virtual_machine` [GH-5705] * **New Resource:** `azurerm_linux_virtual_machine_scale_set` [GH-5705] * **New Resource:** `azurerm_network_interface_security_group_association` [GH-5784] From 22431e69ad6dd26fba2d5f25ca56c9bfcfd2e44a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 17:24:36 +0100 Subject: [PATCH 206/498] r/express_route_gateway: fixes from #5523 --- .../network/tests/resource_arm_express_route_gateway_test.go | 1 + website/docs/r/express_route_gateway.html.markdown | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go index ff468064d7fab..0551bd246dc9e 100644 --- a/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_express_route_gateway_test.go @@ -183,6 +183,7 @@ resource "azurerm_express_route_gateway" "import" { name = azurerm_express_route_gateway.test.name resource_group_name = azurerm_express_route_gateway.test.name location = azurerm_express_route_gateway.test.location + virtual_hub_id = azurerm_express_route_gateway.test.virtual_hub_id scale_units = azurerm_express_route_gateway.test.scale_units } `, template) diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown index 27900d800de6e..0630498168445 100644 --- a/website/docs/r/express_route_gateway.html.markdown +++ b/website/docs/r/express_route_gateway.html.markdown @@ -37,7 +37,7 @@ resource "azurerm_express_route_gateway" "example" { resource_group_name = azurerm_resource_group.example.name location = azurerm_resource_group.example.location virtual_hub_id = azurerm_virtual_hub.example.id - scale_unts = 1 + scale_units = 1 tags = { environment = "Production" From 513968cf8517c9c9f4f64ac6a7f2710be2942112 Mon Sep 17 00:00:00 2001 From: Jack Batzner Date: Tue, 18 Feb 2020 10:25:00 -0600 Subject: [PATCH 207/498] New data source: 'azurerm_eventhub_authorization_rule' === RUN TestAccDataSourceAzureRMEventHubAuthorizationRule === PAUSE TestAccDataSourceAzureRMEventHubAuthorizationRule === CONT TestAccDataSourceAzureRMEventHubAuthorizationRule --- PASS: TestAccDataSourceAzureRMEventHubAuthorizationRule (291.84s) PASS ok github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/eventhub/tests 292.144s --- ...data_source_eventhub_authorization_rule.go | 108 ++++++++++++++++++ .../services/eventhub/registration.go | 1 + ...source_eventhub_authorization_rule_test.go | 48 ++++++++ website/azurerm.erb | 4 + .../eventhub_authorization_rule.html.markdown | 52 +++++++++ 5 files changed, 213 insertions(+) create mode 100644 azurerm/internal/services/eventhub/data_source_eventhub_authorization_rule.go create mode 100644 azurerm/internal/services/eventhub/tests/data_source_eventhub_authorization_rule_test.go create mode 100644 website/docs/d/eventhub_authorization_rule.html.markdown diff --git a/azurerm/internal/services/eventhub/data_source_eventhub_authorization_rule.go b/azurerm/internal/services/eventhub/data_source_eventhub_authorization_rule.go new file mode 100644 index 0000000000000..79e64fe3b6f65 --- /dev/null +++ b/azurerm/internal/services/eventhub/data_source_eventhub_authorization_rule.go @@ -0,0 +1,108 @@ +package eventhub + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceEventHubAuthorizationRule() *schema.Resource { + return &schema.Resource{ + Read: dataSourceEventHubAuthorizationRuleRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: azure.EventHubAuthorizationRuleSchemaFrom(map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateEventHubAuthorizationRuleName(), + }, + + "namespace_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateEventHubNamespaceName(), + }, + + "eventhub_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateEventHubName(), + }, + + "primary_key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "secondary_key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "primary_connection_string": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "secondary_connection_string": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + }), + } +} + +func dataSourceEventHubAuthorizationRuleRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Eventhub.EventHubsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + eventHubName := d.Get("eventhub_name").(string) + namespaceName := d.Get("namespace_name").(string) + + resp, err := client.GetAuthorizationRule(ctx, resourceGroup, namespaceName, eventHubName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: EventHub Authorization Rule %q (Resource Group %q) was not found", name, resourceGroup) + } + return fmt.Errorf("Error: EventHub Authorization Rule %s: %+v", name, err) + } + + d.SetId(*resp.ID) + + d.Set("name", name) + d.Set("eventhub_name", eventHubName) + d.Set("namespace_name", namespaceName) + d.Set("resource_group_name", resourceGroup) + + keysResp, err := client.ListKeys(ctx, resourceGroup, namespaceName, eventHubName, name) + if err != nil { + return fmt.Errorf("Error making Read request on Azure EventHub Authorization Rule List Keys %s: %+v", name, err) + } + + d.Set("primary_key", keysResp.PrimaryKey) + d.Set("secondary_key", keysResp.SecondaryKey) + d.Set("primary_connection_string", keysResp.PrimaryConnectionString) + d.Set("secondary_connection_string", keysResp.SecondaryConnectionString) + + return nil +} diff --git a/azurerm/internal/services/eventhub/registration.go b/azurerm/internal/services/eventhub/registration.go index 330cd1b2f89de..b1e9dc3f4d783 100644 --- a/azurerm/internal/services/eventhub/registration.go +++ b/azurerm/internal/services/eventhub/registration.go @@ -14,6 +14,7 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ + "azurerm_eventhub_authorization_rule": dataSourceEventHubAuthorizationRule(), "azurerm_eventhub_consumer_group": dataSourceEventHubConsumerGroup(), "azurerm_eventhub_namespace": dataSourceEventHubNamespace(), "azurerm_eventhub_namespace_authorization_rule": dataSourceEventHubNamespaceAuthorizationRule(), diff --git a/azurerm/internal/services/eventhub/tests/data_source_eventhub_authorization_rule_test.go b/azurerm/internal/services/eventhub/tests/data_source_eventhub_authorization_rule_test.go new file mode 100644 index 0000000000000..64ed69fc41630 --- /dev/null +++ b/azurerm/internal/services/eventhub/tests/data_source_eventhub_authorization_rule_test.go @@ -0,0 +1,48 @@ +package tests + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccDataSourceAzureRMEventHubAuthorizationRule(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_eventhub_authorization_rule", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMEventHubAuthorizationRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMEventHubAuthorizationRule_base(data, true, true, true), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMEventHubAuthorizationRuleExists(data.ResourceName), + resource.TestCheckResourceAttrSet(data.ResourceName, "name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "namespace_name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "eventhub_name"), + resource.TestCheckResourceAttrSet(data.ResourceName, "primary_key"), + resource.TestCheckResourceAttrSet(data.ResourceName, "secondary_key"), + resource.TestCheckResourceAttrSet(data.ResourceName, "primary_connection_string"), + resource.TestCheckResourceAttrSet(data.ResourceName, "secondary_connection_string"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMEventHubAuthorizationRule_base(data acceptance.TestData, listen, send, manage bool) string { + template := testAccAzureRMEventHubAuthorizationRule_base(data, listen, send, manage) + return fmt.Sprintf(` +%s + +data "azurerm_eventhub_authorization_rule" "test" { + name = "${azurerm_eventhub_authorization_rule.test.name}" + namespace_name = "${azurerm_eventhub_namespace.test.name}" + eventhub_name = "${azurerm_eventhub.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, template) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 53e29d7672411..da54debf49181 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -186,6 +186,10 @@ azurerm_disk_encryption_set +
  • + azurerm_eventhub_authorization_rule +
  • +
  • azurerm_eventhub_consumer_group
  • diff --git a/website/docs/d/eventhub_authorization_rule.html.markdown b/website/docs/d/eventhub_authorization_rule.html.markdown new file mode 100644 index 0000000000000..01af5625ab12b --- /dev/null +++ b/website/docs/d/eventhub_authorization_rule.html.markdown @@ -0,0 +1,52 @@ +--- +subcategory: "Messaging" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_eventhub_authorization_rule" +description: |- + Gets information about an Event Hubs Authorization Rule within an Event Hub. +--- + +# azurerm_eventhub_authorization_rule + +Use this data source to access information about an existing Event Hubs Authorization Rule within an Event Hub. + +## Example Usage + +```hcl +data "azurerm_eventhub_authorization_rule" "test" { + name = "test" + namespace_name = "${azurerm_eventhub_namespace.test.name}" + eventhub_name = "${azurerm_eventhub.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +``` + +## Argument Reference + +* `name` - Specifies the name of the EventHub Authorization Rule resource. be created. + +* `namespace_name` - Specifies the name of the grandparent EventHub Namespace. + +* `eventhub_name` - Specifies the name of the EventHub. + +* `resource_group_name` - The name of the resource group in which the EventHub Authorization Rule's grandparent Namespace exists. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The EventHub ID. + +* `primary_key` - The Primary Key for the Event Hubs Authorization Rule. + +* `primary_connection_string` - The Primary Connection String for the Event Hubs Authorization Rule. + +* `secondary_key` - The Secondary Key for the Event Hubs Authorization Rule. + +* `secondary_connection_string` - The Secondary Connection String for the Event Hubs Authorization Rule. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the EventHub Authorization Rule. \ No newline at end of file From b7327f0a79b5030c4da9494a442d3218cf96cd9a Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 17:27:05 +0100 Subject: [PATCH 208/498] linting --- .../network/tests/data_source_subnet_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/azurerm/internal/services/network/tests/data_source_subnet_test.go b/azurerm/internal/services/network/tests/data_source_subnet_test.go index c6f4fa89a1127..c4aab9677713c 100644 --- a/azurerm/internal/services/network/tests/data_source_subnet_test.go +++ b/azurerm/internal/services/network/tests/data_source_subnet_test.go @@ -126,10 +126,10 @@ func testAccDataSourceSubnet_networkSecurityGroupDependencies(data acceptance.Te %s resource "azurerm_subnet" "test" { - name = "internal" - resource_group_name = azurerm_resource_group.test.name - virtual_network_name = azurerm_virtual_network.test.name - address_prefix = "10.0.0.0/24" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.0.0/24" } resource "azurerm_network_security_group" "test" { @@ -176,10 +176,10 @@ func testAccDataSourceSubnet_routeTableDependencies(data acceptance.TestData) st %s resource "azurerm_subnet" "test" { - name = "internal" - resource_group_name = azurerm_resource_group.test.name - virtual_network_name = azurerm_virtual_network.test.name - address_prefix = "10.0.0.0/24" + name = "internal" + resource_group_name = azurerm_resource_group.test.name + virtual_network_name = azurerm_virtual_network.test.name + address_prefix = "10.0.0.0/24" } resource "azurerm_route_table" "test" { From 2621110bee11054e479874277001f12f63125938 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 18 Feb 2020 09:00:57 -0800 Subject: [PATCH 209/498] Remove computed from required --- .../services/automation/resource_arm_automation_schedule.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/automation/resource_arm_automation_schedule.go b/azurerm/internal/services/automation/resource_arm_automation_schedule.go index e89b2d8a7178a..da4b12fc03a19 100644 --- a/azurerm/internal/services/automation/resource_arm_automation_schedule.go +++ b/azurerm/internal/services/automation/resource_arm_automation_schedule.go @@ -52,7 +52,6 @@ func resourceArmAutomationSchedule() *schema.Resource { "automation_account_name": { Type: schema.TypeString, Required: true, - Computed: true, ForceNew: true, ValidateFunc: azure.ValidateAutomationAccountName(), }, From 3063c5f97fdbc2f22a8006d66933b81baea046c0 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Tue, 18 Feb 2020 17:28:07 +0000 Subject: [PATCH 210/498] Test fixups --- ...urce_arm_cosmosdb_account_failover_test.go | 48 +++++++++---------- .../resource_arm_cosmosdb_account_test.go | 3 +- ...urce_arm_cosmosdb_gremlin_database_test.go | 6 +-- ...esource_arm_cosmosdb_gremlin_graph_test.go | 13 +++++ 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_failover_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_failover_test.go index 92cf8e8ad0643..ffd39ec016a8f 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_failover_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_failover_test.go @@ -153,9 +153,9 @@ resource "azurerm_cosmosdb_account" "test" { consistency_level = "BoundedStaleness" } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -180,9 +180,9 @@ resource "azurerm_cosmosdb_account" "test" { max_staleness_prefix = 200 } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -205,9 +205,9 @@ resource "azurerm_cosmosdb_account" "test" { consistency_level = "Eventual" } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -230,9 +230,9 @@ resource "azurerm_cosmosdb_account" "test" { consistency_level = "Session" } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -256,9 +256,9 @@ resource "azurerm_cosmosdb_account" "test" { consistency_level = "BoundedStaleness" } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -281,9 +281,9 @@ resource "azurerm_cosmosdb_account" "test" { consistency_level = "Strong" } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) @@ -308,14 +308,14 @@ resource "azurerm_cosmosdb_account" "test" { max_staleness_prefix = 101101 } - failover_policy { - location = "${azurerm_resource_group.test.location}" - priority = 0 + geo_location { + location = "${azurerm_resource_group.test.location}" + failover_priority = 0 } - failover_policy { - location = "%s" - priority = 1 + geo_location { + location = "%s" + failover_priority = 1 } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary) diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go index 1cf1b45825d57..bcc2ab06169b8 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go @@ -108,7 +108,7 @@ func TestAccAzureRMCosmosDBAccount_requiresImport(t *testing.T) { CheckDestroy: testCheckAzureRMCosmosDBAccountDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMCosmosDBAccount_basic(data, "", documentdb.Eventual), + Config: testAccAzureRMCosmosDBAccount_basic(data, "GlobalDocumentDB", documentdb.Eventual), Check: resource.ComposeAggregateTestCheckFunc( checkAccAzureRMCosmosDBAccount_basic(data, documentdb.Eventual, 1), ), @@ -524,6 +524,7 @@ resource "azurerm_cosmosdb_account" "test" { consistency_policy { consistency_level = "%[4]s" + max_interval_seconds = 300 max_staleness_prefix = 170000 } diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_database_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_database_test.go index 6034bda6d8d67..b4a3f56f13ed8 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_database_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_database_test.go @@ -161,9 +161,9 @@ func testAccAzureRMCosmosDatabase_requiresImport(data acceptance.TestData) strin %s resource "azurerm_cosmosdb_gremlin_database" "import" { - name = "${azurerm_cosmosdb_database.test.name}" - resource_group_name = "${azurerm_cosmosdb_database.test.resource_group_name}" - account_name = "${azurerm_cosmosdb_database.test.account_name}" + name = "${azurerm_cosmosdb_gremlin_database.test.name}" + resource_group_name = "${azurerm_cosmosdb_gremlin_database.test.resource_group_name}" + account_name = "${azurerm_cosmosdb_gremlin_database.test.account_name}" } `, testAccAzureRMCosmosGremlinDatabase_basic(data)) } diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_graph_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_graph_test.go index d8256add53ce2..b95dbdc18dd24 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_graph_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_gremlin_graph_test.go @@ -219,6 +219,19 @@ resource "azurerm_cosmosdb_gremlin_graph" "import" { resource_group_name = "${azurerm_cosmosdb_account.test.resource_group_name}" account_name = "${azurerm_cosmosdb_account.test.name}" database_name = "${azurerm_cosmosdb_gremlin_database.test.name}" + + index_policy { + automatic = true + indexing_mode = "Consistent" + included_paths = ["/*"] + excluded_paths = ["/\"_etag\"/?"] + } + + conflict_resolution_policy { + mode = "LastWriterWins" + conflict_resolution_path = "/_ts" + } + } `, testAccAzureRMCosmosDbGremlinGraph_basic(data)) } From 30941feb995a125eb46a96b93ecc538c0c1438d4 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Tue, 18 Feb 2020 17:38:30 +0000 Subject: [PATCH 211/498] config typo fix --- .../services/cosmos/tests/resource_arm_cosmosdb_account_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go index bcc2ab06169b8..dd99f1f65b3a6 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go @@ -524,7 +524,7 @@ resource "azurerm_cosmosdb_account" "test" { consistency_policy { consistency_level = "%[4]s" - max_interval_seconds = 300 + max_interval_in_seconds = 300 max_staleness_prefix = 170000 } From a229843e646377c8d188eb233deb86b739973b0b Mon Sep 17 00:00:00 2001 From: jackofallops Date: Tue, 18 Feb 2020 17:45:51 +0000 Subject: [PATCH 212/498] Linting --- .../cosmos/tests/resource_arm_cosmosdb_account_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go index dd99f1f65b3a6..15f4bfea25dac 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go @@ -523,9 +523,9 @@ resource "azurerm_cosmosdb_account" "test" { kind = "%[3]s" consistency_policy { - consistency_level = "%[4]s" + consistency_level = "%[4]s" max_interval_in_seconds = 300 - max_staleness_prefix = 170000 + max_staleness_prefix = 170000 } is_virtual_network_filter_enabled = true From 7304cafedc92791813ea0a1adb0e8a33a2b443fb Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 18:54:12 +0100 Subject: [PATCH 213/498] website: removing link to a dead link --- website/docs/r/express_route_gateway.html.markdown | 2 -- 1 file changed, 2 deletions(-) diff --git a/website/docs/r/express_route_gateway.html.markdown b/website/docs/r/express_route_gateway.html.markdown index 27900d800de6e..5e05e958a7fda 100644 --- a/website/docs/r/express_route_gateway.html.markdown +++ b/website/docs/r/express_route_gateway.html.markdown @@ -69,8 +69,6 @@ The following attributes are exported: ### Timeouts -~> **Note:** Custom Timeouts are available [as an opt-in Beta in version 1.43 of the Azure Provider](/docs/providers/azurerm/guides/2.0-beta.html) and will be enabled by default in version 2.0 of the Azure Provider. - The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: * `create` - (Defaults to 60 minutes) Used when creating the ExpressRoute Gateway. From 4ceb471f62d2f3583913ee40ef65f6b88bbc294a Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 19:08:14 +0100 Subject: [PATCH 214/498] updating to include #5794 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f022bb8780874..9576baade728c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ BREAKING CHANGES: * Data Source: `azurerm_app_service_plan` - the deprecated `properties` block has been removed since these properties have been moved to the top level [GH-5717] * Data Source: `azurerm_azuread_application` - This data source has been removed since it was deprecated [GH-5748] * Data Source: `azurerm_azuread_service_principal` - This data source has been removed since it was deprecated [GH-5748] +* Data Source: `azurerm_dns_zone` - removing the deprecated `zone_type` field [GH-5794] +* Data Source: `azurerm_dns_zone` - removing the deprecated `registration_virtual_network_ids` field [GH-5794] +* Data Source: `azurerm_dns_zone` - removing the deprecated `resolution_virtual_network_ids` field [GH-5794] * Data Source: `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] * Data Source: `azurerm_key_vault_key` - removing the deprecated `vault_uri` field [GH-5774] * Data Source: `azurerm_key_vault_secret` - removing the deprecated `vault_uri` field [GH-5774] @@ -37,6 +40,11 @@ BREAKING CHANGES: * `azurerm_cognitive_account` - removing the deprecated `sku_name` block [GH-5797] * `azurerm_container_service` - This resource has been removed since it was deprecated [GH-5709] * `azurerm_devspace_controller` - removing the deprecated `sku` block [GH-5795] +* `azurerm_dns_cname_record` - removing the deprecated `records` field [GH-5794] +* `azurerm_dns_ns_record` - removing the deprecated `records` field [GH-5794] +* `azurerm_dns_zone` - removing the deprecated `zone_type` field [GH-5794] +* `azurerm_dns_zone` - removing the deprecated `registration_virtual_network_ids` field [GH-5794] +* `azurerm_dns_zone` - removing the deprecated `resolution_virtual_network_ids` field [GH-5794] * `azurerm_eventhub` - removing the deprecated `location` field [GH-5793] * `azurerm_eventhub_authorization_rule` - removing the deprecated `location` field [GH-5793] * `azurerm_eventhub_consumer_group` - removing the deprecated `location` field [GH-5793] From 6a91c4546583c243f1afc3237a7a979325638158 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 19:13:23 +0100 Subject: [PATCH 215/498] updating to include #5743 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9576baade728c..f390dc0b740c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ BREAKING CHANGES: * `azurerm_maps_account` - the `sku_name` field is now case-sensitive [GH-5776] * `azurerm_mariadb_server` - removing the `sku` block since it's been deprecated in favour of the `sku_name` field [GH-5777] * `azurerm_mssql_elasticpool` - removing the deprecated `elastic_pool_properties` block [GH-5744] +* `azurerm_mysql_server` - removing the deprecated `sku` block [GH-5743] * `azurerm_network_interface` - removing the deprecated `application_gateway_backend_address_pools_ids` field from the `ip_configurations` block [GH-5784] * `azurerm_network_interface` - removing the deprecated `application_security_group_ids ` field from the `ip_configurations` block [GH-5784] * `azurerm_network_interface` - removing the deprecated `load_balancer_backend_address_pools_ids ` field from the `ip_configurations` block [GH-5784] From 044cbbc01da69ca7ec580f1ffa3cb6c7099f1a2e Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 19:16:34 +0100 Subject: [PATCH 216/498] updating to include #5805 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f390dc0b740c7..b66a3bda6291f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ FEATURES: * **Custom Timeouts:** - all resources within the Azure Provider now allow configuring custom timeouts - please [see Terraform's Timeout documentation](https://www.terraform.io/docs/configuration/resources.html#operation-timeouts) and the documentation in each data source resource for more information. * **Requires Import:** The Azure Provider now checks for the presence of an existing resource prior to creating it - which means that if you try and create a resource which already exists (without importing it) you'll be prompted to import this into the state. +* **New Data Source:** `azurerm_eventhub_authorization_rule` [GH-5805] * **New Resource:** `azurerm_express_route_gateway` [GH-5523] * **New Resource:** `azurerm_linux_virtual_machine` [GH-5705] * **New Resource:** `azurerm_linux_virtual_machine_scale_set` [GH-5705] From 339a7272a83abc79f59618dd2d826ae63fe63794 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 19:18:02 +0100 Subject: [PATCH 217/498] r/express_route_gateway: tweaking the timeouts --- .../services/network/resource_arm_express_route_gateway.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_express_route_gateway.go b/azurerm/internal/services/network/resource_arm_express_route_gateway.go index 731594d7fd24f..43c00367718e1 100644 --- a/azurerm/internal/services/network/resource_arm_express_route_gateway.go +++ b/azurerm/internal/services/network/resource_arm_express_route_gateway.go @@ -30,10 +30,10 @@ func resourceArmExpressRouteGateway() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(60 * time.Minute), + Create: schema.DefaultTimeout(90 * time.Minute), Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(60 * time.Minute), - Delete: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(90 * time.Minute), + Delete: schema.DefaultTimeout(90 * time.Minute), }, Schema: map[string]*schema.Schema{ From 847d34bb81fd30cd13e0d92f75658e96ffb336e7 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 19:51:12 +0100 Subject: [PATCH 218/498] updating to include #5801 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b66a3bda6291f..62474e85b2fbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ BREAKING CHANGES: * Data Source: `azurerm_key_vault_secret` - removing the deprecated `vault_uri` field [GH-5774] * Data Source: `azurerm_role_definition` - removing the alias `VirtualMachineContributor` which has been deprecated in favour of the full name `Virtual Machine Contributor` [GH-5733] * Data Source: `azurerm_scheduler_job_collection` - This data source has been removed since it was deprecated [GH-5712] +* Data Source: `azurerm_subnet` - removing the deprecated `ip_configuration` field [GH-5801] * `azurerm_app_service_plan` - the deprecated `properties` block has been removed since these properties have been moved to the top level [GH-5717] * `azurerm_application_gateway` - updating the default value for the `body` field within the `match` block from `*` to an empty string [GH-5752] * `azurerm_availability_set` - updating the default value for `managed` from `false` to `true` [GH-5724] @@ -87,6 +88,10 @@ BREAKING CHANGES: * `azurerm_storage_queue` - removing the deprecated `resource_group_name` field [GH-5710] * `azurerm_storage_share` - removing the deprecated `resource_group_name` field [GH-5710] * `azurerm_storage_table` - removing the deprecated `resource_group_name` field [GH-5710] +* `azurerm_subnet` - removing the deprecated `ip_configuration` field [GH-5801] +* `azurerm_subnet` - removing the deprecated `network_security_group_id` field [GH-5801] +* `azurerm_subnet` - removing the deprecated `route_table_id` field [GH-5801] +* `azurerm_subnet` - making the `actions` list within the `service_delegation` block within the `service_endpoints` block non-computed [GH-5801] IMPROVEMENTS: @@ -94,6 +99,7 @@ IMPROVEMENTS: * `azurerm_dedicated_host` - support for setting `sku_name` to `DSv3-Type2` and `ESv3-Type2` [GH-5768] * `azurerm_storage_account` - support for configuring the `static_website` block [GH-5649] * `azurerm_storage_account` - support for configuring `cors_rules` within the `blob_properties` block [GH-5425] +* `azurerm_subnet` - support for delta updates [GH-5801] * `azurerm_windows_virtual_machine` - fixing a bug when provisioning from a Shared Gallery image [GH-5661] BUG FIXES: @@ -103,6 +109,8 @@ BUG FIXES: * `azurerm_public_ip_prefix` - fixing the validation for the `prefix_length` to match the Azure API [GH-5693] * `azurerm_role_assignment` - validating that the `name` is a UUID [GH-5624] * `azurerm_signalr_service` - ensuring the SignalR segment is parsed in the correct case [GH-5737] +* `azurerm_subnet` - supporting updating of the `enforce_private_link_endpoint_network_policies` field [GH-5801] +* `azurerm_subnet` - supporting updating of the `enforce_private_link_service_network_policies` field [GH-5801] * `azurerm_windows_virtual_machine` - using the delete custom timeout during deletion [GH-5764] --- From 4808d93321e3f83d5748641f599fb6e05d8f862c Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 20:00:33 +0100 Subject: [PATCH 219/498] r/api_management_api_operation: support for Requires Import --- .../resource_arm_api_management_api_operation.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/azurerm/internal/services/apimanagement/resource_arm_api_management_api_operation.go b/azurerm/internal/services/apimanagement/resource_arm_api_management_api_operation.go index e4fd0bfb28081..8bb615228573c 100644 --- a/azurerm/internal/services/apimanagement/resource_arm_api_management_api_operation.go +++ b/azurerm/internal/services/apimanagement/resource_arm_api_management_api_operation.go @@ -8,7 +8,9 @@ import ( "github.com/Azure/azure-sdk-for-go/services/apimanagement/mgmt/2018-01-01/apimanagement" "github.com/hashicorp/terraform-plugin-sdk/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/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" ) @@ -117,6 +119,19 @@ func resourceArmApiManagementApiOperationCreateUpdate(d *schema.ResourceData, me apiId := d.Get("api_name").(string) operationId := d.Get("operation_id").(string) + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, serviceName, apiId, operationId) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Operation %q (API %q / API Management Service %q / Resource Group %q): %s", operationId, apiId, serviceName, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_api_management_api_operation", *existing.ID) + } + } + description := d.Get("description").(string) displayName := d.Get("display_name").(string) method := d.Get("method").(string) From 96e55dfe290c501fd528324e2dd93de8e0f90678 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 20:07:29 +0100 Subject: [PATCH 220/498] r/storage_account: updating the default for `enable_https_traffic_only` to `true` Fixes #5010 --- .../internal/services/storage/resource_arm_storage_account.go | 1 + website/docs/r/storage_account.html.markdown | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/storage/resource_arm_storage_account.go b/azurerm/internal/services/storage/resource_arm_storage_account.go index 6c915fb7d4809..e7faa93212012 100644 --- a/azurerm/internal/services/storage/resource_arm_storage_account.go +++ b/azurerm/internal/services/storage/resource_arm_storage_account.go @@ -158,6 +158,7 @@ func resourceArmStorageAccount() *schema.Resource { "enable_https_traffic_only": { Type: schema.TypeBool, Optional: true, + Default: true, }, "is_hns_enabled": { diff --git a/website/docs/r/storage_account.html.markdown b/website/docs/r/storage_account.html.markdown index ff6179cdf6bb8..50da869e31bd6 100644 --- a/website/docs/r/storage_account.html.markdown +++ b/website/docs/r/storage_account.html.markdown @@ -97,7 +97,7 @@ The following arguments are supported: * `enable_file_encryption` - (Optional) Boolean flag which controls if Encryption Services are enabled for File storage, see [here](https://azure.microsoft.com/en-us/documentation/articles/storage-service-encryption/) for more information. Defaults to `true`. * `enable_https_traffic_only` - (Optional) Boolean flag which forces HTTPS if enabled, see [here](https://docs.microsoft.com/en-us/azure/storage/storage-require-secure-transfer/) - for more information. + for more information. Defaults to `true`. * `is_hns_enabled` - (Optional) Is Hierarchical Namespace enabled? This can be used with Azure Data Lake Storage Gen 2 ([see here for more information](https://docs.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-quickstart-create-account/)). Changing this forces a new resource to be created. From ab37947c30057711d588c2ee9d187964faf1a5a4 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 18 Feb 2020 20:12:47 +0100 Subject: [PATCH 221/498] docs: adding to the upgrade guide --- website/docs/guides/2.0-upgrade-guide.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index da2deff1552e6..af509ce58c50f 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -498,6 +498,8 @@ The deprecated `account_type` field will be removed. This has been split into th The deprecated `enable_advanced_threat_protection` field will be removed. This functionality has been move in the more general `azurerm_advanced_threat_protection` resource. +The default value for the field `enable_https_traffic_only` has changed from `false` to `true`. + ### Resource: `azurerm_storage_blob` The deprecated `attempts` field will be removed, since Terraform now handles retries automatically. From 637fab5f01fb657c700b33f828ec3a4eacca3b72 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Tue, 18 Feb 2020 20:21:52 +0100 Subject: [PATCH 222/498] updating to include #5781 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62474e85b2fbe..68ede6be31f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,10 @@ BREAKING CHANGES: * Data Source: `azurerm_subnet` - removing the deprecated `ip_configuration` field [GH-5801] * `azurerm_app_service_plan` - the deprecated `properties` block has been removed since these properties have been moved to the top level [GH-5717] * `azurerm_application_gateway` - updating the default value for the `body` field within the `match` block from `*` to an empty string [GH-5752] +* `azurerm_automation_account` - removing the `sku` block which has been deprecated in favour of the `sku_name` field [GH-5781] +* `azurerm_automation_credential` - removing the deprecated `account_name` field [GH-5781] +* `azurerm_automation_runbook` - removing the deprecated `account_name` field [GH-5781] +* `azurerm_automation_schedule` - removing the deprecated `account_name` field [GH-5781] * `azurerm_availability_set` - updating the default value for `managed` from `false` to `true` [GH-5724] * `azurerm_azuread_application` - This resource has been removed since it was deprecated [GH-5748] * `azurerm_azuread_service_principal_password` - This resource has been removed since it was deprecated [GH-5748] From 7f48f3a1a9f698fb8627f4ab2b55096382a485e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 18 Feb 2020 14:11:13 -0800 Subject: [PATCH 223/498] Update test cases --- azurerm/internal/provider/features.go | 22 +++++++++---------- .../tests/data_source_key_vault_test.go | 2 +- .../tests/resource_arm_key_vault_test.go | 8 +++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/azurerm/internal/provider/features.go b/azurerm/internal/provider/features.go index 709bd29687404..8e26707224973 100644 --- a/azurerm/internal/provider/features.go +++ b/azurerm/internal/provider/features.go @@ -34,18 +34,18 @@ func schemaFeatures() *schema.Schema { Required: true, }, }, + }, + }, - "key_vault": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "purge_soft_delete_on_destroy": { - Type: schema.TypeBool, - Required: true, - }, - }, + "key_vault": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "purge_soft_delete_on_destroy": { + Type: schema.TypeBool, + Required: true, }, }, }, diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index cefa1addb401e..4ef5f6ba12fa5 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -108,7 +108,7 @@ func TestAccDataSourceAzureRMKeyVault_softDelete(t *testing.T) { resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), resource.TestCheckResourceAttr(data.ResourceName, "network_acls.#", "1"), resource.TestCheckResourceAttr(data.ResourceName, "network_acls.0.default_action", "Allow"), - resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0") + resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), ), }, { diff --git a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go index 0e5eb626b83d8..0699025aef01b 100644 --- a/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/resource_arm_key_vault_test.go @@ -847,7 +847,7 @@ func testAccAzureRMKeyVault_generateAccessPolicyConfigs(accountNum int) string { return fmt.Sprintf(` access_policy { - tenant_id = "${data.azurerm_client_config.current.tenant_id}" + tenant_id = data.azurerm_client_config.current.tenant_id object_id = "%s" key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] @@ -878,9 +878,9 @@ resource "azurerm_resource_group" "test" { resource "azurerm_key_vault" "test" { name = "vault%d" provider = azurerm.keyVault - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - tenant_id = "${data.azurerm_client_config.current.tenant_id}" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + tenant_id = data.azurerm_client_config.current.tenant_id soft_delete_enabled = true purge_protection_enabled = false From 0added90d846283d3aa2fbdc6a3cb6d06698d2bd Mon Sep 17 00:00:00 2001 From: aqche <39076898+aqche@users.noreply.github.com> Date: Tue, 18 Feb 2020 16:25:36 -0800 Subject: [PATCH 224/498] Update azurerm/internal/services/sql/resource_arm_sql_database.go Co-Authored-By: Tom Harvey --- azurerm/internal/services/sql/resource_arm_sql_database.go | 1 - 1 file changed, 1 deletion(-) diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 1f65c65fa817e..3a88fd06588d7 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -321,7 +321,6 @@ func resourceArmSqlDatabase() *schema.Resource { "zone_redundant": { Type: schema.TypeBool, Optional: true, - Computed: true, }, "tags": tags.Schema(), From 816bc1c2cefe28f49a080601d12a0d1537eebec8 Mon Sep 17 00:00:00 2001 From: aqche <39076898+aqche@users.noreply.github.com> Date: Tue, 18 Feb 2020 16:25:43 -0800 Subject: [PATCH 225/498] Update azurerm/internal/services/sql/resource_arm_sql_database.go Co-Authored-By: Tom Harvey --- azurerm/internal/services/sql/resource_arm_sql_database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 3a88fd06588d7..799fa5c373403 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -582,7 +582,7 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error if zoneRedundant := props.ZoneRedundant; zoneRedundant != nil { d.Set("zone_redundant", zoneRedundant) - } + d.Set("zone_redundant", props.ZoneRedundant) } return tags.FlattenAndSet(d, resp.Tags) From 94dfc85062c533800a1aa0dcbab799be71a480e5 Mon Sep 17 00:00:00 2001 From: Jeffrey Cline <20408400+WodansSon@users.noreply.github.com> Date: Tue, 18 Feb 2020 17:23:07 -0800 Subject: [PATCH 226/498] Fix test case --- .../services/keyvault/tests/data_source_key_vault_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go index 4ef5f6ba12fa5..c4efe633cb460 100644 --- a/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go +++ b/azurerm/internal/services/keyvault/tests/data_source_key_vault_test.go @@ -100,14 +100,7 @@ func TestAccDataSourceAzureRMKeyVault_softDelete(t *testing.T) { testCheckAzureRMKeyVaultExists(data.ResourceName), resource.TestCheckResourceAttr(data.ResourceName, "soft_delete_enabled", "true"), resource.TestCheckResourceAttr(data.ResourceName, "purge_protection_enabled", "false"), - resource.TestCheckResourceAttrSet(data.ResourceName, "tenant_id"), resource.TestCheckResourceAttrSet(data.ResourceName, "sku_name"), - resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.tenant_id"), - resource.TestCheckResourceAttrSet(data.ResourceName, "access_policy.0.object_id"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.key_permissions.0", "create"), - resource.TestCheckResourceAttr(data.ResourceName, "access_policy.0.secret_permissions.0", "set"), - resource.TestCheckResourceAttr(data.ResourceName, "network_acls.#", "1"), - resource.TestCheckResourceAttr(data.ResourceName, "network_acls.0.default_action", "Allow"), resource.TestCheckResourceAttr(data.ResourceName, "tags.%", "0"), ), }, From e5f358a7f0de105303d27781f955eef96953fe5c Mon Sep 17 00:00:00 2001 From: Austin Cheung Date: Tue, 18 Feb 2020 17:27:08 -0800 Subject: [PATCH 227/498] address review --- .../internal/services/sql/resource_arm_sql_database.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/azurerm/internal/services/sql/resource_arm_sql_database.go b/azurerm/internal/services/sql/resource_arm_sql_database.go index 799fa5c373403..930b0d0ca4216 100644 --- a/azurerm/internal/services/sql/resource_arm_sql_database.go +++ b/azurerm/internal/services/sql/resource_arm_sql_database.go @@ -356,6 +356,7 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} resourceGroup := d.Get("resource_group_name").(string) location := azure.NormalizeLocation(d.Get("location").(string)) createMode := d.Get("create_mode").(string) + zoneRedundant := d.Get("zone_redundant").(bool) t := d.Get("tags").(map[string]interface{}) if features.ShouldResourcesBeImported() && d.IsNewResource() { @@ -379,7 +380,8 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} properties := sql.Database{ Location: utils.String(location), DatabaseProperties: &sql.DatabaseProperties{ - CreateMode: sql.CreateMode(createMode), + CreateMode: sql.CreateMode(createMode), + ZoneRedundant: utils.Bool(zoneRedundant), }, Tags: tags.Expand(t), } @@ -454,10 +456,6 @@ func resourceArmSqlDatabaseCreateUpdate(d *schema.ResourceData, meta interface{} properties.DatabaseProperties.ReadScale = sql.ReadScaleDisabled } - if v, ok := d.GetOkExists("zone_redundant"); ok { - properties.DatabaseProperties.ZoneRedundant = utils.Bool(v.(bool)) - } - // The requested Service Objective Name does not match the requested Service Objective Id. if d.HasChange("requested_service_objective_name") && !d.HasChange("requested_service_objective_id") { properties.DatabaseProperties.RequestedServiceObjectiveID = nil @@ -580,8 +578,6 @@ func resourceArmSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error d.Set("read_scale", false) } - if zoneRedundant := props.ZoneRedundant; zoneRedundant != nil { - d.Set("zone_redundant", zoneRedundant) d.Set("zone_redundant", props.ZoneRedundant) } From b1d5967dfd78eaa4930fcb9190aae04ca43538a1 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 18 Feb 2020 20:33:36 -0800 Subject: [PATCH 228/498] Update iothub to 2.0 (#5790) --- .../services/iothub/resource_arm_iothub.go | 16 +----- .../resource_arm_iothub_consumer_group.go | 2 +- .../iothub/resource_arm_iothub_dps.go | 15 +----- .../resource_arm_iothub_fallback_route.go | 11 ++-- ...resource_arm_iothub_consumer_group_test.go | 1 - ...esource_arm_iothub_dps_certificate_test.go | 6 +-- ...rm_iothub_dps_shared_access_policy_test.go | 2 +- .../tests/resource_arm_iothub_dps_test.go | 4 +- ...ource_arm_iothub_endpoint_eventhub_test.go | 1 - ...m_iothub_endpoint_servicebus_queue_test.go | 1 - ...m_iothub_endpoint_servicebus_topic_test.go | 1 - ..._iothub_endpoint_storage_container_test.go | 2 - ...resource_arm_iothub_fallback_route_test.go | 50 ++----------------- .../tests/resource_arm_iothub_route_test.go | 2 - ...ce_arm_iothub_shared_access_policy_test.go | 2 - .../iothub/tests/resource_arm_iothub_test.go | 3 -- .../mysql/resource_arm_mysql_configuration.go | 3 ++ .../resource_arm_postgresql_configuration.go | 3 ++ .../guides/2.0-upgrade-guide.html.markdown | 4 ++ website/docs/r/iothub.html.markdown | 4 +- website/docs/r/iothub_dps.html.markdown | 2 - .../r/iothub_dps_certificate.html.markdown | 2 +- .../r/iothub_fallback_route.html.markdown | 6 ++- .../docs/r/mysql_configuration.html.markdown | 4 ++ .../r/postgresql_configuration.html.markdown | 4 ++ 25 files changed, 41 insertions(+), 110 deletions(-) diff --git a/azurerm/internal/services/iothub/resource_arm_iothub.go b/azurerm/internal/services/iothub/resource_arm_iothub.go index 82501ef838a71..270efa6c597c5 100644 --- a/azurerm/internal/services/iothub/resource_arm_iothub.go +++ b/azurerm/internal/services/iothub/resource_arm_iothub.go @@ -94,20 +94,7 @@ func resourceArmIotHub() *schema.Resource { string(devices.S1), string(devices.S2), string(devices.S3), - }, true), // todo 2.0 make this case sensitive (all constants?) - }, - - "tier": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property is no longer required and will be removed in version 2.0 of the provider", - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(devices.Basic), - string(devices.Free), - string(devices.Standard), - }, true), + }, false), }, "capacity": { @@ -880,7 +867,6 @@ func flattenIoTHubSku(input *devices.IotHubSkuInfo) []interface{} { output := make(map[string]interface{}) output["name"] = string(input.Name) - output["tier"] = string(input.Tier) if capacity := input.Capacity; capacity != nil { output["capacity"] = int(*capacity) } diff --git a/azurerm/internal/services/iothub/resource_arm_iothub_consumer_group.go b/azurerm/internal/services/iothub/resource_arm_iothub_consumer_group.go index 709c914bd1050..4c99cecd2ca17 100644 --- a/azurerm/internal/services/iothub/resource_arm_iothub_consumer_group.go +++ b/azurerm/internal/services/iothub/resource_arm_iothub_consumer_group.go @@ -69,7 +69,7 @@ func resourceArmIotHubConsumerGroupCreate(d *schema.ResourceData, meta interface resourceGroup := d.Get("resource_group_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) + existing, err := client.GetEventHubConsumerGroup(ctx, resourceGroup, iotHubName, endpointName, name) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { return fmt.Errorf("Error checking for presence of existing Consumer Group %q (Endpoint %q / IoTHub %q / Resource Group %q): %s", name, endpointName, iotHubName, resourceGroup, err) diff --git a/azurerm/internal/services/iothub/resource_arm_iothub_dps.go b/azurerm/internal/services/iothub/resource_arm_iothub_dps.go index 6313b3283c119..b475b62120a71 100644 --- a/azurerm/internal/services/iothub/resource_arm_iothub_dps.go +++ b/azurerm/internal/services/iothub/resource_arm_iothub_dps.go @@ -73,19 +73,7 @@ func resourceArmIotHubDPS() *schema.Resource { string(devices.S1), string(devices.S2), string(devices.S3), - }, true), // todo 2.0 make this case sensitive - }, - - "tier": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Deprecated: "This property is no longer required and will be removed in version 2.0 of the provider", - ValidateFunc: validation.StringInSlice([]string{ - string(devices.Basic), - string(devices.Free), - string(devices.Standard), - }, true), + }, false), }, "capacity": { @@ -354,7 +342,6 @@ func flattenIoTHubDPSSku(input *iothub.IotDpsSkuInfo) []interface{} { output := make(map[string]interface{}) output["name"] = string(input.Name) - output["tier"] = input.Tier if capacity := input.Capacity; capacity != nil { output["capacity"] = int(*capacity) } diff --git a/azurerm/internal/services/iothub/resource_arm_iothub_fallback_route.go b/azurerm/internal/services/iothub/resource_arm_iothub_fallback_route.go index 29d6958880488..d40021cdece11 100644 --- a/azurerm/internal/services/iothub/resource_arm_iothub_fallback_route.go +++ b/azurerm/internal/services/iothub/resource_arm_iothub_fallback_route.go @@ -7,10 +7,8 @@ import ( "github.com/Azure/azure-sdk-for-go/services/preview/iothub/mgmt/2018-12-01-preview/devices" "github.com/hashicorp/terraform-plugin-sdk/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/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -90,17 +88,15 @@ func resourceArmIotHubFallbackRouteCreateUpdate(d *schema.ResourceData, meta int return fmt.Errorf("Error loading IotHub %q (Resource Group %q): %+v", iothubName, resourceGroup, err) } + // NOTE: this resource intentionally doesn't support Requires Import + // since a fallback route is created by default + routing := iothub.Properties.Routing if routing == nil { routing = &devices.RoutingProperties{} } - resourceId := fmt.Sprintf("%s/FallbackRoute/defined", *iothub.ID) - if d.IsNewResource() && routing.FallbackRoute != nil && features.ShouldResourcesBeImported() { - return tf.ImportAsExistsError("azurerm_iothub_fallback_route", resourceId) - } - routing.FallbackRoute = &devices.FallbackRouteProperties{ Source: utils.String(string(devices.RoutingSourceDeviceMessages)), Condition: utils.String(d.Get("condition").(string)), @@ -117,6 +113,7 @@ func resourceArmIotHubFallbackRouteCreateUpdate(d *schema.ResourceData, meta int return fmt.Errorf("Error waiting for the completion of the creating/updating of IotHub %q (Resource Group %q): %+v", iothubName, resourceGroup, err) } + resourceId := fmt.Sprintf("%s/FallbackRoute/defined", *iothub.ID) d.SetId(resourceId) return resourceArmIotHubFallbackRouteRead(d, meta) diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_consumer_group_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_consumer_group_test.go index ac1bbf31e1b94..96aed6a0a3bad 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_consumer_group_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_consumer_group_test.go @@ -148,7 +148,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_certificate_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_certificate_test.go index e0d00abc3b9ca..db890d56597f7 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_certificate_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_certificate_test.go @@ -52,7 +52,7 @@ func TestAccAzureRMIotHubDPSCertificate_requiresImport(t *testing.T) { }, { Config: testAccAzureRMIotHubDPSCertificate_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_iothubdps"), + ExpectError: acceptance.RequiresImportError("azurerm_iothub_dps_certificate"), }, }, }) @@ -169,11 +169,11 @@ resource "azurerm_iothub_dps_certificate" "test" { } func testAccAzureRMIotHubDPSCertificate_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMIotHubDPS_basic(data) + template := testAccAzureRMIotHubDPSCertificate_basic(data) return fmt.Sprintf(` %s -resource "azurerm_iothub_dps_certificate" "test" { +resource "azurerm_iothub_dps_certificate" "import" { name = "${azurerm_iothub_dps_certificate.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" iot_dps_name = "${azurerm_iothub_dps.test.name}" diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_shared_access_policy_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_shared_access_policy_test.go index 6cb1cbf874502..320ab1e84076c 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_shared_access_policy_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_shared_access_policy_test.go @@ -240,7 +240,7 @@ func testCheckAzureRMIotHubDpsSharedAccessPolicyDestroy(s *terraform.State) erro for _, sharedAccessPolicy := range *resp.Properties.AuthorizationPolicies { if *sharedAccessPolicy.KeyName == keyName { - return fmt.Errorf("Bad: Shared Access Policy %s still exists on IoTHb DPS %s", keyName, iothubDpsName) + return fmt.Errorf("Bad: Shared Access Policy %s still exists on IoTHub DPS %s", keyName, iothubDpsName) } } } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go index d56e7fa952b27..c9ac2571f4e81 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_dps_test.go @@ -56,7 +56,7 @@ func TestAccAzureRMIotHubDPS_requiresImport(t *testing.T) { }, { Config: testAccAzureRMIotHubDPS_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_iothubdps"), + ExpectError: acceptance.RequiresImportError("azurerm_iothub_dps"), }, }, }) @@ -119,7 +119,7 @@ func testCheckAzureRMIotHubDPSDestroy(s *terraform.State) error { ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_iothubdps" { + if rs.Type != "azurerm_iothub_dps" { continue } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_eventhub_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_eventhub_test.go index 5292024f84136..a0358028964d3 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_eventhub_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_eventhub_test.go @@ -99,7 +99,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_queue_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_queue_test.go index fb9f0c74f1ea9..2248687779c1a 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_queue_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_queue_test.go @@ -100,7 +100,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_topic_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_topic_test.go index fa96e4dc1638f..50478bc5c65f1 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_topic_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_servicebus_topic_test.go @@ -98,7 +98,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_storage_container_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_storage_container_test.go index 90120fa25e590..1625fdb80dd20 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_storage_container_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_endpoint_storage_container_test.go @@ -80,7 +80,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "acctestcont" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -92,7 +91,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_fallback_route_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_fallback_route_test.go index 1e82148defed5..67f158625aee1 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_fallback_route_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_fallback_route_test.go @@ -9,10 +9,12 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "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/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +// NOTE: this resource intentionally doesn't support Requires Import +// since a fallback route is created by default + func TestAccAzureRMIotHubFallbackRoute_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_iothub_fallback_route", "test") @@ -32,33 +34,6 @@ func TestAccAzureRMIotHubFallbackRoute_basic(t *testing.T) { }) } -func TestAccAzureRMIotHubFallbackRoute_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - - data := acceptance.BuildTestData(t, "azurerm_iothub_fallback_route", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMIotHubDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMIotHubFallbackRoute_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMIotHubFallbackRouteExists(data.ResourceName), - ), - }, - { - Config: testAccAzureRMIotHubFallbackRoute_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_iothub_fallback_route"), - }, - }, - }) -} - func TestAccAzureRMIotHubFallbackRoute_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_iothub_fallback_route", "test") @@ -148,23 +123,6 @@ func testCheckAzureRMIotHubFallbackRouteExists(resourceName string) resource.Tes } } -func testAccAzureRMIotHubFallbackRoute_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMIotHub_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_iothub_fallback_route" "import" { - resource_group_name = "${azurerm_resource_group.test.name}" - iothub_name = "${azurerm_iothub.test.name}" - - source = "DeviceMessages" - condition = "true" - endpoint_names = ["${azurerm_iothub_endpoint_storage_container.test.name}"] - enabled = true -} -`, template) -} - func testAccAzureRMIotHubFallbackRoute_basic(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { @@ -182,7 +140,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test-%[1]d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -243,7 +200,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test-%[1]d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_route_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_route_test.go index eb1a49a39b94f..4dea04f7e3d5d 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_route_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_route_test.go @@ -205,7 +205,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test%[1]d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -269,7 +268,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test%[1]d" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_shared_access_policy_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_shared_access_policy_test.go index e25dff79f6aa9..85b681994d394 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_shared_access_policy_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_shared_access_policy_test.go @@ -96,7 +96,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } @@ -146,7 +145,6 @@ resource "azurerm_iothub" "test" { sku { name = "B1" - tier = "Basic" capacity = "1" } diff --git a/azurerm/internal/services/iothub/tests/resource_arm_iothub_test.go b/azurerm/internal/services/iothub/tests/resource_arm_iothub_test.go index e1fae76b447ea..e7da8ddbb1f67 100644 --- a/azurerm/internal/services/iothub/tests/resource_arm_iothub_test.go +++ b/azurerm/internal/services/iothub/tests/resource_arm_iothub_test.go @@ -251,7 +251,6 @@ resource "azurerm_iothub" "import" { sku { name = "B1" - tier = "Basic" capacity = "1" } @@ -333,7 +332,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } @@ -461,7 +459,6 @@ resource "azurerm_storage_account" "test" { resource "azurerm_storage_container" "test" { name = "test" - resource_group_name = "${azurerm_resource_group.test.name}" storage_account_name = "${azurerm_storage_account.test.name}" container_access_type = "private" } diff --git a/azurerm/internal/services/mysql/resource_arm_mysql_configuration.go b/azurerm/internal/services/mysql/resource_arm_mysql_configuration.go index 7b0744e7d22de..ea1cd6e80ad2c 100644 --- a/azurerm/internal/services/mysql/resource_arm_mysql_configuration.go +++ b/azurerm/internal/services/mysql/resource_arm_mysql_configuration.go @@ -73,6 +73,9 @@ func resourceArmMySQLConfigurationCreate(d *schema.ResourceData, meta interface{ }, } + // NOTE: this resource intentionally doesn't support Requires Import + // since a fallback route is created by default + future, err := client.CreateOrUpdate(ctx, resourceGroup, serverName, name, properties) if err != nil { return fmt.Errorf("Error issuing create/update request for MySQL Configuration %s (resource group %s, server name %s): %v", name, resourceGroup, serverName, err) diff --git a/azurerm/internal/services/postgres/resource_arm_postgresql_configuration.go b/azurerm/internal/services/postgres/resource_arm_postgresql_configuration.go index 3a3327b8d834d..f7720a3b116b1 100644 --- a/azurerm/internal/services/postgres/resource_arm_postgresql_configuration.go +++ b/azurerm/internal/services/postgres/resource_arm_postgresql_configuration.go @@ -73,6 +73,9 @@ func resourceArmPostgreSQLConfigurationCreateUpdate(d *schema.ResourceData, meta }, } + // NOTE: this resource intentionally doesn't support Requires Import + // since a fallback route is created by default + future, err := client.CreateOrUpdate(ctx, resGroup, serverName, name, properties) if err != nil { return err diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index da2deff1552e6..8162ad36e148c 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -327,10 +327,14 @@ The deprecated `internal_public_ip_address_id` field in the `ip_configuration` b The deprecated `sku.tier` property will be remove. +The `sku.name` property is now case sensitive. + ### Resource: `azurerm_iothub_dps` The deprecated `sku.tier` property will be remove. +The `sku.name` property is now case sensitive. + ### Resource: `azurerm_iot_dps` This resource has been renamed to `azurerm_iothub_dps` which is available from v1.37 of the AzureRM Provider - instructions on [how to migrate are available in this guide](https://terraform.io/docs/providers/azurerm/guides/migrating-between-renamed-resources.html). As such this resource will be removed. diff --git a/website/docs/r/iothub.html.markdown b/website/docs/r/iothub.html.markdown index 81a9d99c731be..79e6495f0b9cf 100644 --- a/website/docs/r/iothub.html.markdown +++ b/website/docs/r/iothub.html.markdown @@ -145,12 +145,10 @@ A `sku` block supports the following: * `name` - (Required) The name of the sku. Possible values are `B1`, `B2`, `B3`, `F1`, `S1`, `S2`, and `S3`. -* `tier` - (Required) The billing tier for the IoT Hub. Possible values are `Basic`, `Free` or `Standard`. +* `capacity` - (Required) The number of provisioned IoT Hub units. ~> **NOTE:** Only one IotHub can be on the `Free` tier per subscription. -* `capacity` - (Required) The number of provisioned IoT Hub units. - --- An `endpoint` block supports the following: diff --git a/website/docs/r/iothub_dps.html.markdown b/website/docs/r/iothub_dps.html.markdown index d071151ec821f..23c660e8e4734 100644 --- a/website/docs/r/iothub_dps.html.markdown +++ b/website/docs/r/iothub_dps.html.markdown @@ -52,8 +52,6 @@ A `sku` block supports the following: * `name` - (Required) The name of the sku. Possible values are `B1`, `B2`, `B3`, `F1`, `S1`, `S2`, and `S3`. -* `tier` - (Required) The billing tier for the IoT Device Provisioning Service. Possible values are `Basic`, `Free` or `Standard`. - * `capacity` - (Required) The number of provisioned IoT Device Provisioning Service units. --- diff --git a/website/docs/r/iothub_dps_certificate.html.markdown b/website/docs/r/iothub_dps_certificate.html.markdown index b6feabaee5df7..18654984dbb41 100644 --- a/website/docs/r/iothub_dps_certificate.html.markdown +++ b/website/docs/r/iothub_dps_certificate.html.markdown @@ -8,7 +8,7 @@ description: |- # azurerm_iothub_dps_certificate -Manages an IotHub Device Provisioning Service Certificate. +Manages an IotHub Device Provisioning Service Certificate. ## Example Usage diff --git a/website/docs/r/iothub_fallback_route.html.markdown b/website/docs/r/iothub_fallback_route.html.markdown index 1d8d47bd1af06..eba7e7676b64a 100644 --- a/website/docs/r/iothub_fallback_route.html.markdown +++ b/website/docs/r/iothub_fallback_route.html.markdown @@ -10,7 +10,11 @@ description: |- Manages an IotHub Fallback Route -~> **NOTE:** Fallback route can be defined either directly on the `azurerm_iothub` resource, or using the `azurerm_iothub_fallback_route` resource - but the two cannot be used together. If both are used against the same IoTHub, spurious changes will occur. +## Disclaimers + +~> **Note:** Fallback route can be defined either directly on the `azurerm_iothub` resource, or using the `azurerm_iothub_fallback_route` resource - but the two cannot be used together. If both are used against the same IoTHub, spurious changes will occur. + +~> **Note:** Since this resource is provisioned by default, the Azure Provider will not check for the presence of an existing resource prior to attempting to create it. ## Example Usage diff --git a/website/docs/r/mysql_configuration.html.markdown b/website/docs/r/mysql_configuration.html.markdown index 5d3ff29267817..7310442f5435f 100644 --- a/website/docs/r/mysql_configuration.html.markdown +++ b/website/docs/r/mysql_configuration.html.markdown @@ -10,6 +10,10 @@ description: |- Sets a MySQL Configuration value on a MySQL Server. +## Disclaimers + +~> **Note:** Since this resource is provisioned by default, the Azure Provider will not check for the presence of an existing resource prior to attempting to create it. + ## Example Usage ```hcl diff --git a/website/docs/r/postgresql_configuration.html.markdown b/website/docs/r/postgresql_configuration.html.markdown index 9f5b97ae9a842..c71033835c309 100644 --- a/website/docs/r/postgresql_configuration.html.markdown +++ b/website/docs/r/postgresql_configuration.html.markdown @@ -10,6 +10,10 @@ description: |- Sets a PostgreSQL Configuration value on a PostgreSQL Server. +## Disclaimers + +~> **Note:** Since this resource is provisioned by default, the Azure Provider will not check for the presence of an existing resource prior to attempting to create it. + ## Example Usage ```hcl From e5c0a46595e27210a9d587d614d26ed8d63f38c1 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 18 Feb 2020 20:45:20 -0800 Subject: [PATCH 229/498] Update Changelog for #5790 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68ede6be31f03..a65ad70b61d42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,8 @@ BREAKING CHANGES: * `azurerm_eventhub_namespace_authorization_rule` - removing the deprecated `location` field [GH-5793] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] +* `azurerm_iothub`- The deprecated `sku.tier` property will be removed. [GH-5790] +* `azurerm_iothub_dps` - The deprecated `sku.tier` property will be removed. [GH-5790] * `azurerm_key_vault` - removing the `sku` block since this has been deprecated in favour of the `sku_name` field [GH-5774] * `azurerm_key_vault_access_policy` - removing the deprecated field `vault_name` which has been superseded by the `key_vault_id` field [GH-5774] * `azurerm_key_vault_access_policy` - removing the deprecated field `resource_group_name ` which has been superseded by the `key_vault_id` field [GH-5774] From 91cb073670511b4084ce2ea037693ff9d9de4203 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 18 Feb 2020 20:48:12 -0800 Subject: [PATCH 230/498] Update the frontdoor package to 2.0 (#5792) --- azurerm/internal/services/frontdoor/resource_arm_frontdoor.go | 3 +-- website/docs/guides/2.0-upgrade-guide.html.markdown | 4 ++++ website/docs/r/frontdoor.html.markdown | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/frontdoor/resource_arm_frontdoor.go b/azurerm/internal/services/frontdoor/resource_arm_frontdoor.go index 2af4efdfb7df6..9110245f8b438 100644 --- a/azurerm/internal/services/frontdoor/resource_arm_frontdoor.go +++ b/azurerm/internal/services/frontdoor/resource_arm_frontdoor.go @@ -195,7 +195,6 @@ func resourceArmFrontDoor() *schema.Resource { Type: schema.TypeString, Optional: true, }, - // TODO: In 2.0 Switch default value from MatchRequest to HTTPSOnly #4627 "forwarding_protocol": { Type: schema.TypeString, Optional: true, @@ -204,7 +203,7 @@ func resourceArmFrontDoor() *schema.Resource { string(frontdoor.HTTPSOnly), string(frontdoor.MatchRequest), }, false), - Default: string(frontdoor.MatchRequest), + Default: string(frontdoor.HTTPSOnly), }, }, }, diff --git a/website/docs/guides/2.0-upgrade-guide.html.markdown b/website/docs/guides/2.0-upgrade-guide.html.markdown index 8162ad36e148c..89f9c5a2c5990 100644 --- a/website/docs/guides/2.0-upgrade-guide.html.markdown +++ b/website/docs/guides/2.0-upgrade-guide.html.markdown @@ -323,6 +323,10 @@ The deprecated `location` field will be removed, since this is no longer used. The deprecated `internal_public_ip_address_id` field in the `ip_configuration` block will be removed. This field has been replaced by the `public_ip_address_id` field in the `ip_configuration` block. +### Resource: `azurerm_frontdoor` + +The `forwarding_protocol` property now defaults to `HttpsOnly` + ### Resource: `azurerm_iothub` The deprecated `sku.tier` property will be remove. diff --git a/website/docs/r/frontdoor.html.markdown b/website/docs/r/frontdoor.html.markdown index b2aa75e52092f..5c364650603f8 100644 --- a/website/docs/r/frontdoor.html.markdown +++ b/website/docs/r/frontdoor.html.markdown @@ -205,7 +205,7 @@ The `forwarding_configuration` block supports the following: * `custom_forwarding_path` - (Optional) Path to use when constructing the request to forward to the backend. This functions as a URL Rewrite. Default behavior preserves the URL path. -* `forwarding_protocol` - (Optional) Protocol to use when redirecting. Valid options are `HttpOnly`, `HttpsOnly`, or `MatchRequest`. Defaults to `MatchRequest`. +* `forwarding_protocol` - (Optional) Protocol to use when redirecting. Valid options are `HttpOnly`, `HttpsOnly`, or `MatchRequest`. Defaults to `HttpsOnly`. --- From 93234e90515edcb603bab58024fab501964d8901 Mon Sep 17 00:00:00 2001 From: Matthew Frahry Date: Tue, 18 Feb 2020 20:49:51 -0800 Subject: [PATCH 231/498] Update changelog for #5792 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a65ad70b61d42..5bf933ada72d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ BREAKING CHANGES: * `azurerm_eventhub_consumer_group` - removing the deprecated `location` field [GH-5793] * `azurerm_eventhub_namespace` - removing the deprecated `kafka_enabled` field since this is now managed by Azure [GH-5793] * `azurerm_eventhub_namespace_authorization_rule` - removing the deprecated `location` field [GH-5793] +* `azurerm_frontdoor` - The `forwarding_protocol` property now defaults to `HttpsOnly` [GH-5792] * `azurerm_iot_dps` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iot_dps_certificate` - This resource has been removed since it was deprecated [GH-5753] * `azurerm_iothub`- The deprecated `sku.tier` property will be removed. [GH-5790] From f93ca4ca0d5bdbe443fd9da2b19500f0f739249a Mon Sep 17 00:00:00 2001 From: jackofallops Date: Wed, 19 Feb 2020 07:00:35 +0000 Subject: [PATCH 232/498] test fixes --- .../services/cosmos/tests/resource_arm_cosmosdb_account_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go index 15f4bfea25dac..57f10050fe6ad 100644 --- a/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go +++ b/azurerm/internal/services/cosmos/tests/resource_arm_cosmosdb_account_test.go @@ -445,7 +445,7 @@ resource "azurerm_cosmosdb_account" "import" { failover_priority = "${azurerm_cosmosdb_account.geo_location.0.location}" } } -`, testAccAzureRMCosmosDBAccount_basic(data, "", consistency)) +`, testAccAzureRMCosmosDBAccount_basic(data, "GlobalDocumentDB", consistency)) } func testAccAzureRMCosmosDBAccount_consistency(data acceptance.TestData, kind documentdb.DatabaseAccountKind, consistency documentdb.DefaultConsistencyLevel, interval, staleness int) string { From 720edf844df8bac07231829229bcf16fccf7f60b Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Wed, 19 Feb 2020 08:19:43 +0100 Subject: [PATCH 233/498] updating to include #5808 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bf933ada72d9..fbe25256c0288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,7 @@ BREAKING CHANGES: * `azurerm_scheduler_job_collection` - This resource has been removed since it was deprecated [GH-5712] * `azurerm_storage_account` - removing the deprecated `account_type` field [GH-5710] * `azurerm_storage_account` - removing the deprecated `enable_advanced_threat_protection` field [GH-5710] +* `azurerm_storage_account` - updating the default value for `enable_https_traffic_only` from `false` to `true` [GH-5808] * `azurerm_storage_blob` - making the `type` field case-sensitive [GH-5710] * `azurerm_storage_blob` - removing the deprecated `attempts` field [GH-5710] * `azurerm_storage_blob` - removing the deprecated `resource_group_name` field [GH-5710] From 8e8f3e4bf673bb722719bad423444d8e5275de1b Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Wed, 19 Feb 2020 08:13:01 +0100 Subject: [PATCH 234/498] auth: using the correct authorizer for the service principals client fixes a bug introduced in #5748 --- azurerm/internal/services/authorization/client/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azurerm/internal/services/authorization/client/client.go b/azurerm/internal/services/authorization/client/client.go index 756528480fa72..155708bebb0bb 100644 --- a/azurerm/internal/services/authorization/client/client.go +++ b/azurerm/internal/services/authorization/client/client.go @@ -19,8 +19,8 @@ func NewClient(o *common.ClientOptions) *Client { roleDefinitionsClient := authorization.NewRoleDefinitionsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&roleDefinitionsClient.Client, o.ResourceManagerAuthorizer) - servicePrincipalsClient := graphrbac.NewServicePrincipalsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&servicePrincipalsClient.Client, o.ResourceManagerAuthorizer) + servicePrincipalsClient := graphrbac.NewServicePrincipalsClientWithBaseURI(o.GraphEndpoint, o.TenantID) + o.ConfigureClient(&servicePrincipalsClient.Client, o.GraphAuthorizer) return &Client{ RoleAssignmentsClient: &roleAssignmentsClient, From 71b5494b32e854b553dc43b30cfa5ca9e80d855d Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Wed, 19 Feb 2020 09:57:52 +0100 Subject: [PATCH 235/498] updating to include #5772 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbe25256c0288..ec4a4c5779a77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,7 @@ IMPROVEMENTS: * Data Source: `azurerm_kubernetes_service_version` - support for filtering of preview releases [GH-5662] * `azurerm_dedicated_host` - support for setting `sku_name` to `DSv3-Type2` and `ESv3-Type2` [GH-5768] +* `azurerm_sql_database` - support for configuring `zone_redundant` [GH-5772] * `azurerm_storage_account` - support for configuring the `static_website` block [GH-5649] * `azurerm_storage_account` - support for configuring `cors_rules` within the `blob_properties` block [GH-5425] * `azurerm_subnet` - support for delta updates [GH-5801] From f518e1bad04b90f9284852d4c87baed1b5bb3bf3 Mon Sep 17 00:00:00 2001 From: jackofallops Date: Wed, 19 Feb 2020 10:44:03 +0000 Subject: [PATCH 236/498] removed deprecated recoveryservices resources. Updated datasource and docs --- ..._vm.go => data_source_backup_policy_vm.go} | 2 +- .../services/recoveryservices/registration.go | 36 +- .../resource_arm_recovery_services_fabric.go | 164 ---- ...e_arm_recovery_services_network_mapping.go | 216 ----- ...urce_arm_recovery_services_protected_vm.go | 283 ------- ..._recovery_services_protection_container.go | 162 ---- ...y_services_protection_container_mapping.go | 203 ----- ..._recovery_services_protection_policy_vm.go | 764 ------------------ ...rce_arm_recovery_services_replicated_vm.go | 353 -------- ...rm_recovery_services_replication_policy.go | 215 ----- ...very_services_protection_policy_vm_test.go | 16 +- ...ource_arm_recovery_services_fabric_test.go | 113 --- ..._recovery_services_network_mapping_test.go | 161 ---- ...arm_recovery_services_protected_vm_test.go | 642 --------------- ...vices_protection_container_mapping_test.go | 158 ---- ...very_services_protection_container_test.go | 121 --- ...very_services_protection_policy_vm_test.go | 555 ------------- ...rm_recovery_services_replicated_vm_test.go | 269 ------ ...covery_services_replication_policy_test.go | 113 --- website/azurerm.erb | 40 +- ..._vm.markdown => backup_policy_vm.markdown} | 4 +- .../guides/2.0-upgrade-guide.html.markdown | 32 + .../r/recovery_network_mapping.html.markdown | 114 --- .../r/recovery_services_fabric.html.markdown | 76 -- .../r/recovery_services_protected_vm.markdown | 87 -- ...ervices_protection_container.html.markdown | 83 -- ...protection_container_mapping.html.markdown | 121 --- ...ery_services_protection_policy_vm.markdown | 159 ---- ...overy_services_replicated_vm.html.markdown | 232 ------ ..._services_replication_policy.html.markdown | 74 -- 30 files changed, 61 insertions(+), 5507 deletions(-) rename azurerm/internal/services/recoveryservices/{data_source_recovery_services_protection_policy_vm.go => data_source_backup_policy_vm.go} (96%) delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_fabric.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_network_mapping.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protected_vm.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container_mapping.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_policy_vm.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replicated_vm.go delete mode 100644 azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replication_policy.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_fabric_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_network_mapping_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protected_vm_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_mapping_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_policy_vm_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replicated_vm_test.go delete mode 100644 azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replication_policy_test.go rename website/docs/d/{recovery_services_protection_policy_vm.markdown => backup_policy_vm.markdown} (89%) delete mode 100644 website/docs/r/recovery_network_mapping.html.markdown delete mode 100644 website/docs/r/recovery_services_fabric.html.markdown delete mode 100644 website/docs/r/recovery_services_protected_vm.markdown delete mode 100644 website/docs/r/recovery_services_protection_container.html.markdown delete mode 100644 website/docs/r/recovery_services_protection_container_mapping.html.markdown delete mode 100644 website/docs/r/recovery_services_protection_policy_vm.markdown delete mode 100644 website/docs/r/recovery_services_replicated_vm.html.markdown delete mode 100644 website/docs/r/recovery_services_replication_policy.html.markdown diff --git a/azurerm/internal/services/recoveryservices/data_source_recovery_services_protection_policy_vm.go b/azurerm/internal/services/recoveryservices/data_source_backup_policy_vm.go similarity index 96% rename from azurerm/internal/services/recoveryservices/data_source_recovery_services_protection_policy_vm.go rename to azurerm/internal/services/recoveryservices/data_source_backup_policy_vm.go index 401ff7fa38a9a..e427c0f329c4f 100644 --- a/azurerm/internal/services/recoveryservices/data_source_recovery_services_protection_policy_vm.go +++ b/azurerm/internal/services/recoveryservices/data_source_backup_policy_vm.go @@ -14,7 +14,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func dataSourceArmRecoveryServicesProtectionPolicyVm() *schema.Resource { +func dataSourceArmBackupPolicyVm() *schema.Resource { return &schema.Resource{ Read: dataSourceArmRecoveryServicesProtectionPolicyVmRead, diff --git a/azurerm/internal/services/recoveryservices/registration.go b/azurerm/internal/services/recoveryservices/registration.go index c2c497c382169..b9c2507e91223 100644 --- a/azurerm/internal/services/recoveryservices/registration.go +++ b/azurerm/internal/services/recoveryservices/registration.go @@ -14,33 +14,25 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), - "azurerm_recovery_services_protection_policy_vm": dataSourceArmRecoveryServicesProtectionPolicyVm(), + "azurerm_recovery_services_vault": dataSourceArmRecoveryServicesVault(), + "azurerm_backup_policy_vm": dataSourceArmBackupPolicyVm(), } } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_backup_container_storage_account": resourceArmBackupProtectionContainerStorageAccount(), - "azurerm_backup_policy_file_share": resourceArmBackupProtectionPolicyFileShare(), - "azurerm_backup_protected_file_share": resourceArmBackupProtectedFileShare(), - "azurerm_backup_protected_vm": resourceArmRecoveryServicesBackupProtectedVM(), - "azurerm_backup_policy_vm": resourceArmBackupProtectionPolicyVM(), - "azurerm_recovery_network_mapping": resourceArmRecoveryServicesNetworkMapping(), - "azurerm_recovery_replicated_vm": resourceArmRecoveryServicesReplicatedVm(), - "azurerm_recovery_services_fabric": resourceArmRecoveryServicesFabric(), - "azurerm_recovery_services_protected_vm": resourceArmRecoveryServicesProtectedVm(), - "azurerm_recovery_services_protection_container": resourceArmRecoveryServicesProtectionContainer(), - "azurerm_recovery_services_protection_container_mapping": resourceArmRecoveryServicesProtectionContainerMapping(), - "azurerm_recovery_services_protection_policy_vm": resourceArmRecoveryServicesProtectionPolicyVm(), - "azurerm_recovery_services_replication_policy": resourceArmRecoveryServicesReplicationPolicy(), - "azurerm_recovery_services_vault": resourceArmRecoveryServicesVault(), - "azurerm_site_recovery_fabric": resourceArmSiteRecoveryFabric(), - "azurerm_site_recovery_network_mapping": resourceArmSiteRecoveryNetworkMapping(), - "azurerm_site_recovery_protection_container": resourceArmSiteRecoveryProtectionContainer(), - "azurerm_site_recovery_protection_container_mapping": resourceArmSiteRecoveryProtectionContainerMapping(), - "azurerm_site_recovery_replicated_vm": resourceArmSiteRecoveryReplicatedVM(), - "azurerm_site_recovery_replication_policy": resourceArmSiteRecoveryReplicationPolicy(), + "azurerm_backup_container_storage_account": resourceArmBackupProtectionContainerStorageAccount(), + "azurerm_backup_policy_file_share": resourceArmBackupProtectionPolicyFileShare(), + "azurerm_backup_protected_file_share": resourceArmBackupProtectedFileShare(), + "azurerm_backup_protected_vm": resourceArmRecoveryServicesBackupProtectedVM(), + "azurerm_backup_policy_vm": resourceArmBackupProtectionPolicyVM(), + "azurerm_recovery_services_vault": resourceArmRecoveryServicesVault(), + "azurerm_site_recovery_fabric": resourceArmSiteRecoveryFabric(), + "azurerm_site_recovery_network_mapping": resourceArmSiteRecoveryNetworkMapping(), + "azurerm_site_recovery_protection_container": resourceArmSiteRecoveryProtectionContainer(), + "azurerm_site_recovery_protection_container_mapping": resourceArmSiteRecoveryProtectionContainerMapping(), + "azurerm_site_recovery_replicated_vm": resourceArmSiteRecoveryReplicatedVM(), + "azurerm_site_recovery_replication_policy": resourceArmSiteRecoveryReplicationPolicy(), } } diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_fabric.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_fabric.go deleted file mode 100644 index bb0d6e00b0b8f..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_fabric.go +++ /dev/null @@ -1,164 +0,0 @@ -package recoveryservices - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "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/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" -) - -func resourceArmRecoveryServicesFabric() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_fabric` resource is deprecated in favor of `azurerm_site_recovery_fabric` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesFabricCreate, - Read: resourceArmRecoveryServicesFabricRead, - Update: nil, - Delete: resourceArmRecoveryServicesFabricDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "location": azure.SchemaLocation(), - }, - } -} - -func resourceArmRecoveryServicesFabricCreate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - location := azure.NormalizeLocation(d.Get("location").(string)) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.FabricClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing rec overy services fabric %s (vault %s): %+v", name, vaultName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_resource_group", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - parameters := siterecovery.FabricCreationInput{ - Properties: &siterecovery.FabricCreationInputProperties{ - CustomDetails: siterecovery.AzureFabricCreationInput{ - InstanceType: "Azure", - Location: &location, - }, - }, - } - - future, err := client.Create(ctx, name, parameters) - if err != nil { - return fmt.Errorf("Error creating recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, name) - if err != nil { - return fmt.Errorf("Error retrieving recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryServicesFabricRead(d, meta) -} - -func resourceArmRecoveryServicesFabricRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - name := id.Path["replicationFabrics"] - - client := meta.(*clients.Client).RecoveryServices.FabricClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - - d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) - if props := resp.Properties; props != nil { - if azureDetails, isAzureDetails := props.CustomDetails.AsAzureFabricSpecificDetails(); isAzureDetails { - d.Set("location", azureDetails.Location) - } - } - d.Set("recovery_vault_name", vaultName) - return nil -} - -func resourceArmRecoveryServicesFabricDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - name := id.Path["replicationFabrics"] - - client := meta.(*clients.Client).RecoveryServices.FabricClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - future, err := client.Delete(ctx, name) - if err != nil { - return fmt.Errorf("Error deleting recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_network_mapping.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_network_mapping.go deleted file mode 100644 index fc6a4d24a3ba8..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_network_mapping.go +++ /dev/null @@ -1,216 +0,0 @@ -package recoveryservices - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "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/suppress" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "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" -) - -func resourceArmRecoveryServicesNetworkMapping() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_network_mapping` resource is deprecated in favor of `azurerm_site_recovery_network_mapping` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryNetworkMappingCreate, - Read: resourceArmRecoveryNetworkMappingRead, - Delete: resourceArmRecoveryNetworkMappingDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "source_recovery_fabric_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "target_recovery_fabric_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "source_network_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_network_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - }, - } -} - -func resourceArmRecoveryNetworkMappingCreate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - fabricName := d.Get("source_recovery_fabric_name").(string) - targetFabricName := d.Get("target_recovery_fabric_name").(string) - sourceNetworkId := d.Get("source_network_id").(string) - targetNetworkId := d.Get("target_network_id").(string) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.NetworkMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - //get network name from id - parsedSourceNetworkId, err := azure.ParseAzureResourceID(sourceNetworkId) - if err != nil { - return fmt.Errorf("[ERROR] Unable to parse source_network_id '%s' (network mapping %s): %+v", sourceNetworkId, name, err) - } - sourceNetworkName, hasName := parsedSourceNetworkId.Path["virtualNetworks"] - if !hasName { - sourceNetworkName, hasName = parsedSourceNetworkId.Path["virtualnetworks"] // Handle that different APIs return different ID casings - if !hasName { - return fmt.Errorf("[ERROR] parsed source_network_id '%s' doesn't contain 'virtualnetworks'", parsedSourceNetworkId) - } - } - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, fabricName, sourceNetworkName, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing recovery services fabric %s (vault %s): %+v", name, vaultName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_network_mapping", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - var parameters = siterecovery.CreateNetworkMappingInput{ - Properties: &siterecovery.CreateNetworkMappingInputProperties{ - RecoveryNetworkID: &targetNetworkId, - RecoveryFabricName: &targetFabricName, - FabricSpecificDetails: siterecovery.AzureToAzureCreateNetworkMappingInput{ - PrimaryNetworkID: &sourceNetworkId, - }, - }, - } - future, err := client.Create(ctx, fabricName, sourceNetworkName, name, parameters) - if err != nil { - return fmt.Errorf("Error creating recovery network mapping %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating recovery network mapping %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, fabricName, sourceNetworkName, name) - if err != nil { - return fmt.Errorf("Error retrieving recovery network mapping %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryNetworkMappingRead(d, meta) -} - -func resourceArmRecoveryNetworkMappingRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - networkName := id.Path["replicationNetworks"] - name := id.Path["replicationNetworkMappings"] - - client := meta.(*clients.Client).RecoveryServices.NetworkMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, fabricName, networkName, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - d.Set("resource_group_name", resGroup) - d.Set("recovery_vault_name", vaultName) - d.Set("source_recovery_fabric_name", fabricName) - d.Set("name", resp.Name) - if props := resp.Properties; props != nil { - d.Set("source_network_id", props.PrimaryNetworkID) - d.Set("target_network_id", props.RecoveryNetworkID) - - targetFabricId, err := azure.ParseAzureResourceID(azure.HandleAzureSdkForGoBug2824(*resp.Properties.RecoveryFabricArmID)) - if err != nil { - return err - } - d.Set("target_recovery_fabric_name", targetFabricId.Path["replicationFabrics"]) - } - - return nil -} - -func resourceArmRecoveryNetworkMappingDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - networkName := id.Path["replicationNetworks"] - name := id.Path["replicationNetworkMappings"] - - client := meta.(*clients.Client).RecoveryServices.NetworkMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - future, err := client.Delete(ctx, fabricName, networkName, name) - if err != nil { - return fmt.Errorf("Error deleting recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protected_vm.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protected_vm.go deleted file mode 100644 index 68181b97366c5..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protected_vm.go +++ /dev/null @@ -1,283 +0,0 @@ -package recoveryservices - -import ( - "context" - "fmt" - "log" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2019-05-13/backup" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/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/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmRecoveryServicesProtectedVm() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_protected_vm` resource is deprecated in favor of `azurerm_backup_protected_vm` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesProtectedVmCreateUpdate, - Read: resourceArmRecoveryServicesProtectedVmRead, - Update: resourceArmRecoveryServicesProtectedVmCreateUpdate, - Delete: resourceArmRecoveryServicesProtectedVmDelete, - - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(80 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(80 * time.Minute), - Delete: schema.DefaultTimeout(80 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - - "source_vm_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - }, - - "backup_policy_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - - "tags": tags.Schema(), - }, - } -} - -func resourceArmRecoveryServicesProtectedVmCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectedItemsClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - resourceGroup := d.Get("resource_group_name").(string) - t := d.Get("tags").(map[string]interface{}) - - vaultName := d.Get("recovery_vault_name").(string) - vmId := d.Get("source_vm_id").(string) - policyId := d.Get("backup_policy_id").(string) - - //get VM name from id - parsedVmId, err := azure.ParseAzureResourceID(vmId) - if err != nil { - return fmt.Errorf("[ERROR] Unable to parse source_vm_id '%s': %+v", vmId, err) - } - vmName, hasName := parsedVmId.Path["virtualMachines"] - if !hasName { - return fmt.Errorf("[ERROR] parsed source_vm_id '%s' doesn't contain 'virtualMachines'", vmId) - } - - protectedItemName := fmt.Sprintf("VM;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - containerName := fmt.Sprintf("iaasvmcontainer;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - - log.Printf("[DEBUG] Creating/updating Recovery Service Protected VM %s (resource group %q)", protectedItemName, resourceGroup) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err2 := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "") - if err2 != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Recovery Service Protected VM %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err2) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_services_protected_vm", *existing.ID) - } - } - - item := backup.ProtectedItemResource{ - Tags: tags.Expand(t), - Properties: &backup.AzureIaaSComputeVMProtectedItem{ - PolicyID: &policyId, - ProtectedItemType: backup.ProtectedItemTypeMicrosoftClassicComputevirtualMachines, - WorkloadType: backup.DataSourceTypeVM, - SourceResourceID: utils.String(vmId), - FriendlyName: utils.String(vmName), - VirtualMachineID: utils.String(vmId), - }, - } - - if _, err = client.CreateOrUpdate(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, item); err != nil { - return fmt.Errorf("Error creating/updating Recovery Service Protected VM %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err) - } - - resp, err := resourceArmRecoveryServicesProtectedVmWaitForStateCreateUpdate(ctx, client, vaultName, resourceGroup, containerName, protectedItemName, policyId, d) - if err != nil { - return err - } - - id := strings.Replace(*resp.ID, "Subscriptions", "subscriptions", 1) // This code is a workaround for this bug https://github.com/Azure/azure-sdk-for-go/issues/2824 - d.SetId(id) - - return resourceArmRecoveryServicesProtectedVmRead(d, meta) -} - -func resourceArmRecoveryServicesProtectedVmRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectedItemsClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - protectedItemName := id.Path["protectedItems"] - vaultName := id.Path["vaults"] - resourceGroup := id.ResourceGroup - containerName := id.Path["protectionContainers"] - - log.Printf("[DEBUG] Reading Recovery Service Protected VM %q (resource group %q)", protectedItemName, resourceGroup) - - resp, err := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - - return fmt.Errorf("Error making Read request on Recovery Service Protected VM %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err) - } - - d.Set("resource_group_name", resourceGroup) - d.Set("recovery_vault_name", vaultName) - - if properties := resp.Properties; properties != nil { - if vm, ok := properties.AsAzureIaaSComputeVMProtectedItem(); ok { - d.Set("source_vm_id", vm.SourceResourceID) - - if v := vm.PolicyID; v != nil { - d.Set("backup_policy_id", strings.Replace(*v, "Subscriptions", "subscriptions", 1)) - } - } - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmRecoveryServicesProtectedVmDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectedItemsClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - protectedItemName := id.Path["protectedItems"] - resourceGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - containerName := id.Path["protectionContainers"] - - log.Printf("[DEBUG] Deleting Recovery Service Protected Item %q (resource group %q)", protectedItemName, resourceGroup) - - resp, err := client.Delete(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName) - if err != nil { - if !utils.ResponseWasNotFound(resp) { - return fmt.Errorf("Error issuing delete request for Recovery Service Protected VM %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err) - } - } - - if _, err := resourceArmRecoveryServicesProtectedVmWaitForDeletion(ctx, client, vaultName, resourceGroup, containerName, protectedItemName, "", d); err != nil { - return err - } - - return nil -} - -func resourceArmRecoveryServicesProtectedVmWaitForStateCreateUpdate(ctx context.Context, client *backup.ProtectedItemsClient, vaultName, resourceGroup, containerName, protectedItemName string, policyId string, d *schema.ResourceData) (backup.ProtectedItemResource, error) { - state := &resource.StateChangeConf{ - MinTimeout: 30 * time.Second, - Delay: 10 * time.Second, - Pending: []string{"NotFound"}, - Target: []string{"Found"}, - Refresh: resourceArmRecoveryServicesProtectedVmRefreshFunc(ctx, client, vaultName, resourceGroup, containerName, protectedItemName, policyId, true), - } - - if d.IsNewResource() { - state.Timeout = d.Timeout(schema.TimeoutCreate) - } else { - state.Timeout = d.Timeout(schema.TimeoutUpdate) - } - - resp, err := state.WaitForState() - if err != nil { - i, _ := resp.(backup.ProtectedItemResource) - return i, fmt.Errorf("Error waiting for the Recovery Service Protected VM %q to be true (Resource Group %q) to provision: %+v", protectedItemName, resourceGroup, err) - } - - return resp.(backup.ProtectedItemResource), nil -} - -func resourceArmRecoveryServicesProtectedVmWaitForDeletion(ctx context.Context, client *backup.ProtectedItemsClient, vaultName, resourceGroup, containerName, protectedItemName string, policyId string, d *schema.ResourceData) (backup.ProtectedItemResource, error) { - state := &resource.StateChangeConf{ - MinTimeout: 30 * time.Second, - Delay: 10 * time.Second, - Pending: []string{"Found"}, - Target: []string{"NotFound"}, - Refresh: resourceArmRecoveryServicesProtectedVmRefreshFunc(ctx, client, vaultName, resourceGroup, containerName, protectedItemName, policyId, false), - Timeout: d.Timeout(schema.TimeoutDelete), - } - - resp, err := state.WaitForState() - if err != nil { - i, _ := resp.(backup.ProtectedItemResource) - return i, fmt.Errorf("Error waiting for the Recovery Service Protected VM %q to be false (Resource Group %q) to provision: %+v", protectedItemName, resourceGroup, err) - } - - return resp.(backup.ProtectedItemResource), nil -} - -func resourceArmRecoveryServicesProtectedVmRefreshFunc(ctx context.Context, client *backup.ProtectedItemsClient, vaultName, resourceGroup, containerName, protectedItemName string, policyId string, newResource bool) resource.StateRefreshFunc { - // TODO: split this into two functions - return func() (interface{}, string, error) { - resp, err := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return resp, "NotFound", nil - } - - return resp, "Error", fmt.Errorf("Error making Read request on Recovery Service Protected VM %q (Resource Group %q): %+v", protectedItemName, resourceGroup, err) - } else if !newResource && policyId != "" { - if properties := resp.Properties; properties != nil { - if vm, ok := properties.AsAzureIaaSComputeVMProtectedItem(); ok { - if v := vm.PolicyID; v != nil { - if strings.Replace(*v, "Subscriptions", "subscriptions", 1) != policyId { - return resp, "NotFound", nil - } - } else { - return resp, "Error", fmt.Errorf("Error reading policy ID attribute nil on Recovery Service Protected VM %q (Resource Group %q)", protectedItemName, resourceGroup) - } - } else { - return resp, "Error", fmt.Errorf("Error reading properties on Recovery Service Protected VM %q (Resource Group %q)", protectedItemName, resourceGroup) - } - } else { - return resp, "Error", fmt.Errorf("Error reading properties on empty Recovery Service Protected VM %q (Resource Group %q)", protectedItemName, resourceGroup) - } - } - return resp, "Found", nil - } -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container.go deleted file mode 100644 index f31bbd4c16266..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container.go +++ /dev/null @@ -1,162 +0,0 @@ -package recoveryservices - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "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/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" -) - -func resourceArmRecoveryServicesProtectionContainer() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_protection_container` resource is deprecated in favor of `azurerm_site_recovery_protection_container` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesProtectionContainerCreate, - Read: resourceArmRecoveryServicesProtectionContainerRead, - Update: nil, - Delete: resourceArmRecoveryServicesProtectionContainerDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "recovery_fabric_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - }, - } -} - -func resourceArmRecoveryServicesProtectionContainerCreate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - fabricName := d.Get("recovery_fabric_name").(string) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.ProtectionContainerClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, fabricName, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_services_protection_container", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - parameters := siterecovery.CreateProtectionContainerInput{ - Properties: &siterecovery.CreateProtectionContainerInputProperties{}, - } - - future, err := client.Create(ctx, fabricName, name, parameters) - if err != nil { - return fmt.Errorf("Error creating recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - - resp, err := client.Get(ctx, fabricName, name) - if err != nil { - return fmt.Errorf("Error retrieving site recovery protection container %s (fabric %s): %+v", name, fabricName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryServicesProtectionContainerRead(d, meta) -} - -func resourceArmRecoveryServicesProtectionContainerRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - name := id.Path["replicationProtectionContainers"] - - client := meta.(*clients.Client).RecoveryServices.ProtectionContainerClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, fabricName, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - - d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) - d.Set("recovery_vault_name", vaultName) - d.Set("recovery_fabric_name", fabricName) - return nil -} - -func resourceArmRecoveryServicesProtectionContainerDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - name := id.Path["replicationProtectionContainers"] - - client := meta.(*clients.Client).RecoveryServices.ProtectionContainerClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - future, err := client.Delete(ctx, fabricName, name) - if err != nil { - return fmt.Errorf("Error deleting recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services protection container %s (fabric %s): %+v", name, fabricName, err) - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container_mapping.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container_mapping.go deleted file mode 100644 index cbeea35521bf9..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_container_mapping.go +++ /dev/null @@ -1,203 +0,0 @@ -package recoveryservices - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "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/suppress" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "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" -) - -func resourceArmRecoveryServicesProtectionContainerMapping() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_protection_container_mapping` resource is deprecated in favor of `azurerm_site_recovery_protection_container_mapping` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesContainerMappingCreate, - Read: resourceArmRecoveryServicesContainerMappingRead, - Update: nil, - Delete: resourceArmRecoveryServicesContainerMappingDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "recovery_fabric_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "recovery_replication_policy_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "recovery_source_protection_container_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "recovery_target_protection_container_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - }, - } -} - -func resourceArmRecoveryServicesContainerMappingCreate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - fabricName := d.Get("recovery_fabric_name").(string) - policyId := d.Get("recovery_replication_policy_id").(string) - protectionContainerName := d.Get("recovery_source_protection_container_name").(string) - targetContainerId := d.Get("recovery_target_protection_container_id").(string) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.ContainerMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, fabricName, protectionContainerName, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing recovery services protection container mapping %s (fabric %s, container %s): %+v", name, fabricName, protectionContainerName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_services_protection_container_mapping", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - var parameters = siterecovery.CreateProtectionContainerMappingInput{ - Properties: &siterecovery.CreateProtectionContainerMappingInputProperties{ - TargetProtectionContainerID: &targetContainerId, - PolicyID: &policyId, - ProviderSpecificInput: siterecovery.ReplicationProviderSpecificContainerMappingInput{}, - }, - } - future, err := client.Create(ctx, fabricName, protectionContainerName, name, parameters) - if err != nil { - return fmt.Errorf("Error creating recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, fabricName, protectionContainerName, name) - if err != nil { - return fmt.Errorf("Error retrieving site recovery protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryServicesContainerMappingRead(d, meta) -} - -func resourceArmRecoveryServicesContainerMappingRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - protectionContainerName := id.Path["replicationProtectionContainers"] - name := id.Path["replicationProtectionContainerMappings"] - - client := meta.(*clients.Client).RecoveryServices.ContainerMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, fabricName, protectionContainerName, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - d.Set("resource_group_name", resGroup) - d.Set("recovery_vault_name", vaultName) - d.Set("recovery_fabric_name", fabricName) - d.Set("recovery_source_protection_container_name", resp.Properties.SourceProtectionContainerFriendlyName) - d.Set("name", resp.Name) - d.Set("recovery_replication_policy_id", resp.Properties.PolicyID) - d.Set("recovery_target_protection_container_id", resp.Properties.TargetProtectionContainerID) - return nil -} - -func resourceArmRecoveryServicesContainerMappingDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - protectionContainerName := id.Path["replicationProtectionContainers"] - name := id.Path["replicationProtectionContainerMappings"] - instanceType := string(siterecovery.InstanceTypeBasicReplicationProviderSpecificContainerMappingInputInstanceTypeA2A) - - client := meta.(*clients.Client).RecoveryServices.ContainerMappingClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - input := siterecovery.RemoveProtectionContainerMappingInput{ - Properties: &siterecovery.RemoveProtectionContainerMappingInputProperties{ - ProviderSpecificInput: &siterecovery.ReplicationProviderContainerUnmappingInput{ - InstanceType: &instanceType, - }, - }, - } - - future, err := client.Delete(ctx, fabricName, protectionContainerName, name, input) - if err != nil { - return fmt.Errorf("Error deleting recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services protection container mapping %s (vault %s): %+v", name, vaultName, err) - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_policy_vm.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_policy_vm.go deleted file mode 100644 index 9239c1d793493..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_protection_policy_vm.go +++ /dev/null @@ -1,764 +0,0 @@ -package recoveryservices - -import ( - "context" - "fmt" - "log" - "regexp" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2019-05-13/backup" - "github.com/Azure/go-autorest/autorest/date" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "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/set" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" - "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/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmRecoveryServicesProtectionPolicyVm() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_protection_policy_vm` resource is deprecated in favor of `azurerm_backup_policy_vm` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesProtectionPolicyVmCreateUpdate, - Read: resourceArmRecoveryServicesProtectionPolicyVmRead, - Update: resourceArmRecoveryServicesProtectionPolicyVmCreateUpdate, - Delete: resourceArmRecoveryServicesProtectionPolicyVmDelete, - - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile("^[a-zA-Z][-_!a-zA-Z0-9]{2,149}$"), - "Backup Policy name must be 3 - 150 characters long, start with a letter, contain only letters and numbers.", - ), - }, - - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - - "timezone": { - Type: schema.TypeString, - Optional: true, - Default: "UTC", - }, - - "backup": { - Type: schema.TypeList, - MaxItems: 1, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - - "frequency": { - Type: schema.TypeString, - Required: true, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(backup.ScheduleRunTypeDaily), - string(backup.ScheduleRunTypeWeekly), - }, true), - }, - - "time": { //applies to all backup schedules & retention times (they all must be the same) - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile("^([01][0-9]|[2][0-3]):([03][0])$"), //time must be on the hour or half past - "Time of day must match the format HH:mm where HH is 00-23 and mm is 00 or 30", - ), - }, - - "weekdays": { //only for weekly - Type: schema.TypeSet, - Optional: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.DayOfTheWeek(true), - }, - }, - }, - }, - }, - - "retention_daily": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "count": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 9999), - }, - }, - }, - }, - - "retention_weekly": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "count": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 9999), - }, - - "weekdays": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.DayOfTheWeek(true), - }, - }, - }, - }, - }, - - "retention_monthly": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "count": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 9999), - }, - - "weeks": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(backup.WeekOfMonthFirst), - string(backup.WeekOfMonthSecond), - string(backup.WeekOfMonthThird), - string(backup.WeekOfMonthFourth), - string(backup.WeekOfMonthLast), - }, true), - }, - }, - - "weekdays": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.DayOfTheWeek(true), - }, - }, - }, - }, - }, - - "retention_yearly": { - Type: schema.TypeList, - MaxItems: 1, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "count": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.IntBetween(1, 9999), - }, - - "months": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.Month(true), - }, - }, - - "weeks": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(backup.WeekOfMonthFirst), - string(backup.WeekOfMonthSecond), - string(backup.WeekOfMonthThird), - string(backup.WeekOfMonthFourth), - string(backup.WeekOfMonthLast), - }, true), - }, - }, - - "weekdays": { - Type: schema.TypeSet, - Required: true, - Set: set.HashStringIgnoreCase, - Elem: &schema.Schema{ - Type: schema.TypeString, - DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.DayOfTheWeek(true), - }, - }, - }, - }, - }, - - "tags": tags.Schema(), - }, - - //if daily, we need daily retention - //if weekly daily cannot be set, and we need weekly - CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { - _, hasDaily := diff.GetOk("retention_daily") - _, hasWeekly := diff.GetOk("retention_weekly") - - frequencyI, _ := diff.GetOk("backup.0.frequency") - frequency := strings.ToLower(frequencyI.(string)) - if frequency == "daily" { - if !hasDaily { - return fmt.Errorf("`retention_daily` must be set when backup.0.frequency is daily") - } - - if _, ok := diff.GetOk("backup.0.weekdays"); ok { - return fmt.Errorf("`backup.0.weekdays` should be not set when backup.0.frequency is daily") - } - } else if frequency == "weekly" { - if hasDaily { - return fmt.Errorf("`retention_daily` must be not set when backup.0.frequency is weekly") - } - if !hasWeekly { - return fmt.Errorf("`retention_weekly` must be set when backup.0.frequency is weekly") - } - } else { - return fmt.Errorf("Unrecognized value for backup.0.frequency") - } - - return nil - }, - } -} - -func resourceArmRecoveryServicesProtectionPolicyVmCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectionPoliciesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - policyName := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - t := d.Get("tags").(map[string]interface{}) - - log.Printf("[DEBUG] Creating/updating Recovery Service Protection Policy %s (resource group %q)", policyName, resourceGroup) - - //getting this ready now because its shared between *everything*, time is... complicated for this resource - timeOfDay := d.Get("backup.0.time").(string) - dateOfDay, err := time.Parse(time.RFC3339, fmt.Sprintf("2018-07-30T%s:00Z", timeOfDay)) - if err != nil { - return fmt.Errorf("Error generating time from %q for policy %q (Resource Group %q): %+v", timeOfDay, policyName, resourceGroup, err) - } - times := append(make([]date.Time, 0), date.Time{Time: dateOfDay}) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err2 := client.Get(ctx, vaultName, resourceGroup, policyName) - if err2 != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Recovery Service Protection Policy %q (Resource Group %q): %+v", policyName, resourceGroup, err2) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_services_protection_policy_vm", *existing.ID) - } - } - - policy := backup.ProtectionPolicyResource{ - Tags: tags.Expand(t), - Properties: &backup.AzureIaaSVMProtectionPolicy{ - TimeZone: utils.String(d.Get("timezone").(string)), - BackupManagementType: backup.BackupManagementTypeAzureIaasVM, - SchedulePolicy: expandArmRecoveryServicesProtectionPolicySchedule(d, times), - RetentionPolicy: &backup.LongTermRetentionPolicy{ //SimpleRetentionPolicy only has duration property ¯\_(ツ)_/¯ - RetentionPolicyType: backup.RetentionPolicyTypeLongTermRetentionPolicy, - DailySchedule: expandArmRecoveryServicesProtectionPolicyRetentionDaily(d, times), - WeeklySchedule: expandArmRecoveryServicesProtectionPolicyRetentionWeekly(d, times), - MonthlySchedule: expandArmRecoveryServicesProtectionPolicyRetentionMonthly(d, times), - YearlySchedule: expandArmRecoveryServicesProtectionPolicyRetentionYearly(d, times), - }, - }, - } - if _, err = client.CreateOrUpdate(ctx, vaultName, resourceGroup, policyName, policy); err != nil { - return fmt.Errorf("Error creating/updating Recovery Service Protection Policy %q (Resource Group %q): %+v", policyName, resourceGroup, err) - } - - resp, err := resourceArmRecoveryServicesProtectionPolicyWaitForUpdate(ctx, client, vaultName, resourceGroup, policyName, d) - if err != nil { - return err - } - - id := strings.Replace(*resp.ID, "Subscriptions", "subscriptions", 1) - d.SetId(id) - - return resourceArmRecoveryServicesProtectionPolicyVmRead(d, meta) -} - -func resourceArmRecoveryServicesProtectionPolicyVmRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectionPoliciesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - policyName := id.Path["backupPolicies"] - vaultName := id.Path["vaults"] - resourceGroup := id.ResourceGroup - - log.Printf("[DEBUG] Reading Recovery Service Protection Policy %q (resource group %q)", policyName, resourceGroup) - - resp, err := client.Get(ctx, vaultName, resourceGroup, policyName) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - - return fmt.Errorf("Error making Read request on Recovery Service Protection Policy %q (Resource Group %q): %+v", policyName, resourceGroup, err) - } - - d.Set("name", policyName) - d.Set("resource_group_name", resourceGroup) - d.Set("recovery_vault_name", vaultName) - - if properties, ok := resp.Properties.AsAzureIaaSVMProtectionPolicy(); ok && properties != nil { - d.Set("timezone", properties.TimeZone) - - if schedule, ok := properties.SchedulePolicy.AsSimpleSchedulePolicy(); ok && schedule != nil { - if err := d.Set("backup", flattenArmRecoveryServicesProtectionPolicySchedule(schedule)); err != nil { - return fmt.Errorf("Error setting `backup`: %+v", err) - } - } - - if retention, ok := properties.RetentionPolicy.AsLongTermRetentionPolicy(); ok && retention != nil { - if s := retention.DailySchedule; s != nil { - if err := d.Set("retention_daily", flattenArmRecoveryServicesProtectionPolicyRetentionDaily(s)); err != nil { - return fmt.Errorf("Error setting `retention_daily`: %+v", err) - } - } else { - d.Set("retention_daily", nil) - } - - if s := retention.WeeklySchedule; s != nil { - if err := d.Set("retention_weekly", flattenArmRecoveryServicesProtectionPolicyRetentionWeekly(s)); err != nil { - return fmt.Errorf("Error setting `retention_weekly`: %+v", err) - } - } else { - d.Set("retention_weekly", nil) - } - - if s := retention.MonthlySchedule; s != nil { - if err := d.Set("retention_monthly", flattenArmRecoveryServicesProtectionPolicyRetentionMonthly(s)); err != nil { - return fmt.Errorf("Error setting `retention_monthly`: %+v", err) - } - } else { - d.Set("retention_monthly", nil) - } - - if s := retention.YearlySchedule; s != nil { - if err := d.Set("retention_yearly", flattenArmRecoveryServicesProtectionPolicyRetentionYearly(s)); err != nil { - return fmt.Errorf("Error setting `retention_yearly`: %+v", err) - } - } else { - d.Set("retention_yearly", nil) - } - } - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmRecoveryServicesProtectionPolicyVmDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).RecoveryServices.ProtectionPoliciesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - policyName := id.Path["backupPolicies"] - resourceGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - - log.Printf("[DEBUG] Deleting Recovery Service Protected Item %q (resource group %q)", policyName, resourceGroup) - - resp, err := client.Delete(ctx, vaultName, resourceGroup, policyName) - if err != nil { - if !utils.ResponseWasNotFound(resp) { - return fmt.Errorf("Error issuing delete request for Recovery Service Protection Policy %q (Resource Group %q): %+v", policyName, resourceGroup, err) - } - } - - if _, err := resourceArmRecoveryServicesProtectionPolicyWaitForDeletion(ctx, client, vaultName, resourceGroup, policyName, d); err != nil { - return err - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicySchedule(d *schema.ResourceData, times []date.Time) *backup.SimpleSchedulePolicy { - if bb, ok := d.Get("backup").([]interface{}); ok && len(bb) > 0 { - block := bb[0].(map[string]interface{}) - - schedule := backup.SimpleSchedulePolicy{ //LongTermSchedulePolicy has no properties - SchedulePolicyType: backup.SchedulePolicyTypeSimpleSchedulePolicy, - ScheduleRunTimes: ×, - } - - if v, ok := block["frequency"].(string); ok { - schedule.ScheduleRunFrequency = backup.ScheduleRunType(v) - } - - if v, ok := block["weekdays"].(*schema.Set); ok { - days := make([]backup.DayOfWeek, 0) - for _, day := range v.List() { - days = append(days, backup.DayOfWeek(day.(string))) - } - schedule.ScheduleRunDays = &days - } - - return &schedule - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicyRetentionDaily(d *schema.ResourceData, times []date.Time) *backup.DailyRetentionSchedule { - if rb, ok := d.Get("retention_daily").([]interface{}); ok && len(rb) > 0 { - block := rb[0].(map[string]interface{}) - - return &backup.DailyRetentionSchedule{ - RetentionTimes: ×, - RetentionDuration: &backup.RetentionDuration{ - Count: utils.Int32(int32(block["count"].(int))), - DurationType: backup.RetentionDurationTypeDays, - }, - } - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicyRetentionWeekly(d *schema.ResourceData, times []date.Time) *backup.WeeklyRetentionSchedule { - if rb, ok := d.Get("retention_weekly").([]interface{}); ok && len(rb) > 0 { - block := rb[0].(map[string]interface{}) - - retention := backup.WeeklyRetentionSchedule{ - RetentionTimes: ×, - RetentionDuration: &backup.RetentionDuration{ - Count: utils.Int32(int32(block["count"].(int))), - DurationType: backup.RetentionDurationTypeWeeks, - }, - } - - if v, ok := block["weekdays"].(*schema.Set); ok { - days := make([]backup.DayOfWeek, 0) - for _, day := range v.List() { - days = append(days, backup.DayOfWeek(day.(string))) - } - retention.DaysOfTheWeek = &days - } - - return &retention - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicyRetentionMonthly(d *schema.ResourceData, times []date.Time) *backup.MonthlyRetentionSchedule { - if rb, ok := d.Get("retention_monthly").([]interface{}); ok && len(rb) > 0 { - block := rb[0].(map[string]interface{}) - - retention := backup.MonthlyRetentionSchedule{ - RetentionScheduleFormatType: backup.RetentionScheduleFormatWeekly, //this is always weekly ¯\_(ツ)_/¯ - RetentionScheduleDaily: nil, //and this is always nil.. - RetentionScheduleWeekly: expandArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(block), - RetentionTimes: ×, - RetentionDuration: &backup.RetentionDuration{ - Count: utils.Int32(int32(block["count"].(int))), - DurationType: backup.RetentionDurationTypeMonths, - }, - } - - return &retention - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicyRetentionYearly(d *schema.ResourceData, times []date.Time) *backup.YearlyRetentionSchedule { - if rb, ok := d.Get("retention_yearly").([]interface{}); ok && len(rb) > 0 { - block := rb[0].(map[string]interface{}) - - retention := backup.YearlyRetentionSchedule{ - RetentionScheduleFormatType: backup.RetentionScheduleFormatWeekly, //this is always weekly ¯\_(ツ)_/¯ - RetentionScheduleDaily: nil, //and this is always nil.. - RetentionScheduleWeekly: expandArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(block), - RetentionTimes: ×, - RetentionDuration: &backup.RetentionDuration{ - Count: utils.Int32(int32(block["count"].(int))), - DurationType: backup.RetentionDurationTypeYears, - }, - } - - if v, ok := block["months"].(*schema.Set); ok { - months := make([]backup.MonthOfYear, 0) - for _, month := range v.List() { - months = append(months, backup.MonthOfYear(month.(string))) - } - retention.MonthsOfYear = &months - } - - return &retention - } - - return nil -} - -func expandArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(block map[string]interface{}) *backup.WeeklyRetentionFormat { - weekly := backup.WeeklyRetentionFormat{} - - if v, ok := block["weekdays"].(*schema.Set); ok { - days := make([]backup.DayOfWeek, 0) - for _, day := range v.List() { - days = append(days, backup.DayOfWeek(day.(string))) - } - weekly.DaysOfTheWeek = &days - } - - if v, ok := block["weeks"].(*schema.Set); ok { - weeks := make([]backup.WeekOfMonth, 0) - for _, week := range v.List() { - weeks = append(weeks, backup.WeekOfMonth(week.(string))) - } - weekly.WeeksOfTheMonth = &weeks - } - - return &weekly -} - -func flattenArmRecoveryServicesProtectionPolicySchedule(schedule *backup.SimpleSchedulePolicy) []interface{} { - block := map[string]interface{}{} - - block["frequency"] = string(schedule.ScheduleRunFrequency) - - if times := schedule.ScheduleRunTimes; times != nil && len(*times) > 0 { - block["time"] = (*times)[0].Format("15:04") - } - - if days := schedule.ScheduleRunDays; days != nil { - weekdays := make([]interface{}, 0) - for _, d := range *days { - weekdays = append(weekdays, string(d)) - } - block["weekdays"] = schema.NewSet(schema.HashString, weekdays) - } - - return []interface{}{block} -} - -func flattenArmRecoveryServicesProtectionPolicyRetentionDaily(daily *backup.DailyRetentionSchedule) []interface{} { - block := map[string]interface{}{} - - if duration := daily.RetentionDuration; duration != nil { - if v := duration.Count; v != nil { - block["count"] = *v - } - } - - return []interface{}{block} -} - -func flattenArmRecoveryServicesProtectionPolicyRetentionWeekly(weekly *backup.WeeklyRetentionSchedule) []interface{} { - block := map[string]interface{}{} - - if duration := weekly.RetentionDuration; duration != nil { - if v := duration.Count; v != nil { - block["count"] = *v - } - } - - if days := weekly.DaysOfTheWeek; days != nil { - weekdays := make([]interface{}, 0) - for _, d := range *days { - weekdays = append(weekdays, string(d)) - } - block["weekdays"] = schema.NewSet(schema.HashString, weekdays) - } - - return []interface{}{block} -} - -func flattenArmRecoveryServicesProtectionPolicyRetentionMonthly(monthly *backup.MonthlyRetentionSchedule) []interface{} { - block := map[string]interface{}{} - - if duration := monthly.RetentionDuration; duration != nil { - if v := duration.Count; v != nil { - block["count"] = *v - } - } - - if weekly := monthly.RetentionScheduleWeekly; weekly != nil { - block["weekdays"], block["weeks"] = flattenArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(weekly) - } - - return []interface{}{block} -} - -func flattenArmRecoveryServicesProtectionPolicyRetentionYearly(yearly *backup.YearlyRetentionSchedule) []interface{} { - block := map[string]interface{}{} - - if duration := yearly.RetentionDuration; duration != nil { - if v := duration.Count; v != nil { - block["count"] = *v - } - } - - if weekly := yearly.RetentionScheduleWeekly; weekly != nil { - block["weekdays"], block["weeks"] = flattenArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(weekly) - } - - if months := yearly.MonthsOfYear; months != nil { - slice := make([]interface{}, 0) - for _, d := range *months { - slice = append(slice, string(d)) - } - block["months"] = schema.NewSet(schema.HashString, slice) - } - - return []interface{}{block} -} - -func flattenArmRecoveryServicesProtectionPolicyRetentionWeeklyFormat(retention *backup.WeeklyRetentionFormat) (weekdays, weeks *schema.Set) { - if days := retention.DaysOfTheWeek; days != nil { - slice := make([]interface{}, 0) - for _, d := range *days { - slice = append(slice, string(d)) - } - weekdays = schema.NewSet(schema.HashString, slice) - } - - if days := retention.WeeksOfTheMonth; days != nil { - slice := make([]interface{}, 0) - for _, d := range *days { - slice = append(slice, string(d)) - } - weeks = schema.NewSet(schema.HashString, slice) - } - - return weekdays, weeks -} - -func resourceArmRecoveryServicesProtectionPolicyWaitForUpdate(ctx context.Context, client *backup.ProtectionPoliciesClient, vaultName, resourceGroup, policyName string, d *schema.ResourceData) (backup.ProtectionPolicyResource, error) { - state := &resource.StateChangeConf{ - MinTimeout: 30 * time.Second, - Delay: 10 * time.Second, - Pending: []string{"NotFound"}, - Target: []string{"Found"}, - Refresh: resourceArmRecoveryServicesProtectionPolicyRefreshFunc(ctx, client, vaultName, resourceGroup, policyName), - } - - if d.IsNewResource() { - state.Timeout = d.Timeout(schema.TimeoutCreate) - } else { - state.Timeout = d.Timeout(schema.TimeoutUpdate) - } - - resp, err := state.WaitForState() - if err != nil { - return resp.(backup.ProtectionPolicyResource), fmt.Errorf("Error waiting for the Recovery Service Protection Policy %q to be true (Resource Group %q) to provision: %+v", policyName, resourceGroup, err) - } - - return resp.(backup.ProtectionPolicyResource), nil -} - -func resourceArmRecoveryServicesProtectionPolicyWaitForDeletion(ctx context.Context, client *backup.ProtectionPoliciesClient, vaultName, resourceGroup, policyName string, d *schema.ResourceData) (backup.ProtectionPolicyResource, error) { - state := &resource.StateChangeConf{ - MinTimeout: 30 * time.Second, - Delay: 10 * time.Second, - Pending: []string{"Found"}, - Target: []string{"NotFound"}, - Refresh: resourceArmRecoveryServicesProtectionPolicyRefreshFunc(ctx, client, vaultName, resourceGroup, policyName), - Timeout: d.Timeout(schema.TimeoutDelete), - } - - resp, err := state.WaitForState() - if err != nil { - return resp.(backup.ProtectionPolicyResource), fmt.Errorf("Error waiting for the Recovery Service Protection Policy %q to be false (Resource Group %q) to provision: %+v", policyName, resourceGroup, err) - } - - return resp.(backup.ProtectionPolicyResource), nil -} - -func resourceArmRecoveryServicesProtectionPolicyRefreshFunc(ctx context.Context, client *backup.ProtectionPoliciesClient, vaultName, resourceGroup, policyName string) resource.StateRefreshFunc { - return func() (interface{}, string, error) { - resp, err := client.Get(ctx, vaultName, resourceGroup, policyName) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return resp, "NotFound", nil - } - - return resp, "Error", fmt.Errorf("Error making Read request on Recovery Service Protection Policy %q (Resource Group %q): %+v", policyName, resourceGroup, err) - } - - return resp, "Found", nil - } -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replicated_vm.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replicated_vm.go deleted file mode 100644 index a93c4937d8d1c..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replicated_vm.go +++ /dev/null @@ -1,353 +0,0 @@ -package recoveryservices - -import ( - "bytes" - "fmt" - "strings" - "time" - - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute" - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" - "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/suppress" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "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" -) - -func resourceArmRecoveryServicesReplicatedVm() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_replicated_vm` resource is deprecated in favor of `azurerm_site_recovery_replicated_vm` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryReplicatedItemCreate, - Read: resourceArmRecoveryReplicatedItemRead, - Delete: resourceArmRecoveryReplicatedItemDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(80 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(80 * time.Minute), - Delete: schema.DefaultTimeout(80 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "source_recovery_fabric_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "source_vm_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_recovery_fabric_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "recovery_replication_policy_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "source_recovery_protection_container_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "target_recovery_protection_container_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_resource_group_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_availability_set_id": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "managed_disk": { - Type: schema.TypeSet, - ConfigMode: schema.SchemaConfigModeAttr, - Optional: true, - ForceNew: true, - Set: resourceArmRecoveryReplicatedVmDiskHash, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "disk_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - DiffSuppressFunc: suppress.CaseDifference, - }, - "staging_storage_account_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_resource_group_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateResourceID, - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_disk_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(compute.StandardLRS), - string(compute.PremiumLRS), - string(compute.StandardSSDLRS), - string(compute.UltraSSDLRS), - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - "target_replica_disk_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - string(compute.StandardLRS), - string(compute.PremiumLRS), - string(compute.StandardSSDLRS), - string(compute.UltraSSDLRS), - }, true), - DiffSuppressFunc: suppress.CaseDifference, - }, - }, - }, - }, - }, - } -} - -func resourceArmRecoveryReplicatedItemCreate(d *schema.ResourceData, meta interface{}) error { - name := d.Get("name").(string) - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - fabricName := d.Get("source_recovery_fabric_name").(string) - sourceVmId := d.Get("source_vm_id").(string) - policyId := d.Get("recovery_replication_policy_id").(string) - sourceProtectionContainerName := d.Get("source_recovery_protection_container_name").(string) - targetProtectionContainerId := d.Get("target_recovery_protection_container_id").(string) - targetResourceGroupId := d.Get("target_resource_group_id").(string) - - var targetAvailabilitySetID *string - if id, isSet := d.GetOk("target_availability_set_id"); isSet { - tmp := id.(string) - targetAvailabilitySetID = &tmp - } else { - targetAvailabilitySetID = nil - } - - client := meta.(*clients.Client).RecoveryServices.ReplicationMigrationItemsClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, fabricName, sourceProtectionContainerName, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing recovery services replicated vm %s (vault %s): %+v", name, vaultName, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_replicated_vm", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - managedDisks := []siterecovery.A2AVMManagedDiskInputDetails{} - - for _, raw := range d.Get("managed_disk").(*schema.Set).List() { - diskInput := raw.(map[string]interface{}) - diskId := diskInput["disk_id"].(string) - primaryStagingAzureStorageAccountID := diskInput["staging_storage_account_id"].(string) - recoveryResourceGroupId := diskInput["target_resource_group_id"].(string) - targetReplicaDiskType := diskInput["target_replica_disk_type"].(string) - targetDiskType := diskInput["target_disk_type"].(string) - - managedDisks = append(managedDisks, siterecovery.A2AVMManagedDiskInputDetails{ - DiskID: &diskId, - PrimaryStagingAzureStorageAccountID: &primaryStagingAzureStorageAccountID, - RecoveryResourceGroupID: &recoveryResourceGroupId, - RecoveryReplicaDiskAccountType: &targetReplicaDiskType, - RecoveryTargetDiskAccountType: &targetDiskType, - }) - } - - var parameters = siterecovery.EnableProtectionInput{ - Properties: &siterecovery.EnableProtectionInputProperties{ - PolicyID: &policyId, - ProviderSpecificDetails: siterecovery.A2AEnableProtectionInput{ - FabricObjectID: &sourceVmId, - RecoveryContainerID: &targetProtectionContainerId, - RecoveryResourceGroupID: &targetResourceGroupId, - RecoveryAvailabilitySetID: targetAvailabilitySetID, - VMManagedDisks: &managedDisks, - }, - }, - } - future, err := client.Create(ctx, fabricName, sourceProtectionContainerName, name, parameters) - if err != nil { - return fmt.Errorf("Error creating replicated vm %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating replicated vm %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, fabricName, sourceProtectionContainerName, name) - if err != nil { - return fmt.Errorf("Error retrieving replicated vm %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryReplicatedItemRead(d, meta) -} - -func resourceArmRecoveryReplicatedItemRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - protectionContainerName := id.Path["replicationProtectionContainers"] - name := id.Path["replicationProtectedItems"] - - client := meta.(*clients.Client).RecoveryServices.ReplicationMigrationItemsClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, fabricName, protectionContainerName, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services replicated vm %s (vault %s): %+v", name, vaultName, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resGroup) - d.Set("recovery_vault_name", vaultName) - d.Set("source_recovery_fabric_name", fabricName) - d.Set("target_recovery_fabric_id", resp.Properties.RecoveryFabricID) - d.Set("recovery_replication_policy_id", resp.Properties.PolicyID) - d.Set("source_recovery_protection_container_name", protectionContainerName) - d.Set("target_recovery_protection_container_id", resp.Properties.RecoveryContainerID) - - if a2aDetails, isA2a := resp.Properties.ProviderSpecificDetails.AsA2AReplicationDetails(); isA2a { - d.Set("source_vm_id", a2aDetails.FabricObjectID) - d.Set("target_resource_group_id", a2aDetails.RecoveryAzureResourceGroupID) - d.Set("target_availability_set_id", a2aDetails.RecoveryAvailabilitySet) - if a2aDetails.ProtectedManagedDisks != nil { - disksOutput := make([]interface{}, 0) - for _, disk := range *a2aDetails.ProtectedManagedDisks { - diskOutput := make(map[string]interface{}) - diskOutput["disk_id"] = *disk.DiskID - diskOutput["staging_storage_account_id"] = *disk.PrimaryStagingAzureStorageAccountID - diskOutput["target_resource_group_id"] = *disk.RecoveryResourceGroupID - diskOutput["target_replica_disk_type"] = *disk.RecoveryReplicaDiskAccountType - diskOutput["target_disk_type"] = *disk.RecoveryTargetDiskAccountType - - disksOutput = append(disksOutput, diskOutput) - } - d.Set("managed_disk", schema.NewSet(resourceArmRecoveryReplicatedVmDiskHash, disksOutput)) - } - } - - return nil -} - -func resourceArmRecoveryReplicatedItemDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - fabricName := id.Path["replicationFabrics"] - protectionContainerName := id.Path["replicationProtectionContainers"] - name := id.Path["replicationProtectedItems"] - - disableProtectionInput := siterecovery.DisableProtectionInput{ - Properties: &siterecovery.DisableProtectionInputProperties{ - DisableProtectionReason: siterecovery.NotSpecified, - ReplicationProviderInput: siterecovery.DisableProtectionProviderSpecificInput{}, - }, - } - - client := meta.(*clients.Client).RecoveryServices.ReplicationMigrationItemsClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - future, err := client.Delete(ctx, fabricName, protectionContainerName, name, disableProtectionInput) - if err != nil { - return fmt.Errorf("Error deleting recovery services replicated vm %s (vault %s): %+v", name, vaultName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services replicated vm %s (vault %s): %+v", name, vaultName, err) - } - return nil -} - -func resourceArmRecoveryReplicatedVmDiskHash(v interface{}) int { - var buf bytes.Buffer - - if m, ok := v.(map[string]interface{}); ok { - if v, ok := m["disk_id"]; ok { - buf.WriteString(strings.ToLower(v.(string))) - } - } - - return hashcode.String(buf.String()) -} diff --git a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replication_policy.go b/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replication_policy.go deleted file mode 100644 index 2288499b6ac5d..0000000000000 --- a/azurerm/internal/services/recoveryservices/resource_arm_recovery_services_replication_policy.go +++ /dev/null @@ -1,215 +0,0 @@ -package recoveryservices - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-01-10/siterecovery" - "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/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" -) - -func resourceArmRecoveryServicesReplicationPolicy() *schema.Resource { - return &schema.Resource{ - DeprecationMessage: "`azurerm_recovery_services_replication_policy` resource is deprecated in favor of `azurerm_site_recovery_replication_policy` and will be removed in v2.0 of the AzureRM Provider", - Create: resourceArmRecoveryServicesReplicationPolicyCreate, - Read: resourceArmRecoveryServicesReplicationPolicyRead, - Update: resourceArmRecoveryServicesReplicationPolicyUpdate, - Delete: resourceArmRecoveryServicesReplicationPolicyDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, - }, - "resource_group_name": azure.SchemaResourceGroupName(), - - "recovery_vault_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: azure.ValidateRecoveryServicesVaultName, - }, - "recovery_point_retention_in_minutes": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - ValidateFunc: validation.IntBetween(1, 365*24*60), - }, - "application_consistent_snapshot_frequency_in_minutes": { - Type: schema.TypeInt, - Required: true, - ForceNew: false, - ValidateFunc: validation.IntBetween(1, 365*24*60), - }, - }, - } -} - -func resourceArmRecoveryServicesReplicationPolicyCreate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resGroup, vaultName) - ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) - defer cancel() - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing recovery services replication policy %s: %+v", name, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_recovery_services_replication_policy", azure.HandleAzureSdkForGoBug2824(*existing.ID)) - } - } - - recoveryPoint := int32(d.Get("recovery_point_retention_in_minutes").(int)) - appConsitency := int32(d.Get("application_consistent_snapshot_frequency_in_minutes").(int)) - var parameters = siterecovery.CreatePolicyInput{ - Properties: &siterecovery.CreatePolicyInputProperties{ - ProviderSpecificInput: &siterecovery.A2APolicyCreationInput{ - RecoveryPointHistory: &recoveryPoint, - AppConsistentFrequencyInMinutes: &appConsitency, - MultiVMSyncStatus: siterecovery.Enable, - InstanceType: siterecovery.InstanceTypeBasicPolicyProviderSpecificInputInstanceTypeA2A, - }, - }, - } - future, err := client.Create(ctx, name, parameters) - if err != nil { - return fmt.Errorf("Error creating recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error creating recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, name) - if err != nil { - return fmt.Errorf("Error retrieving site recovery replication policy %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryServicesReplicationPolicyRead(d, meta) -} - -func resourceArmRecoveryServicesReplicationPolicyUpdate(d *schema.ResourceData, meta interface{}) error { - resGroup := d.Get("resource_group_name").(string) - vaultName := d.Get("recovery_vault_name").(string) - name := d.Get("name").(string) - - client := meta.(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resGroup, vaultName) - ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - recoveryPoint := int32(d.Get("recovery_point_retention_in_minutes").(int)) - appConsitency := int32(d.Get("application_consistent_snapshot_frequency_in_minutes").(int)) - var parameters = siterecovery.UpdatePolicyInput{ - Properties: &siterecovery.UpdatePolicyInputProperties{ - ReplicationProviderSettings: &siterecovery.A2APolicyCreationInput{ - RecoveryPointHistory: &recoveryPoint, - AppConsistentFrequencyInMinutes: &appConsitency, - MultiVMSyncStatus: siterecovery.Enable, - InstanceType: siterecovery.InstanceTypeBasicPolicyProviderSpecificInputInstanceTypeA2A, - }, - }, - } - future, err := client.Update(ctx, name, parameters) - if err != nil { - return fmt.Errorf("Error updating recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error updating recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - - resp, err := client.Get(ctx, name) - if err != nil { - return fmt.Errorf("Error retrieving site recovery replication policy %s (vault %s): %+v", name, vaultName, err) - } - - d.SetId(azure.HandleAzureSdkForGoBug2824(*resp.ID)) - - return resourceArmRecoveryServicesReplicationPolicyRead(d, meta) -} - -func resourceArmRecoveryServicesReplicationPolicyRead(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - name := id.Path["replicationPolicies"] - - client := meta.(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resGroup, vaultName) - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - resp, err := client.Get(ctx, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - d.SetId("") - return nil - } - return fmt.Errorf("Error making Read request on recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - - d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) - d.Set("recovery_vault_name", vaultName) - if a2APolicyDetails, isA2A := resp.Properties.ProviderSpecificDetails.AsA2APolicyDetails(); isA2A { - d.Set("recovery_point_retention_in_minutes", a2APolicyDetails.RecoveryPointHistory) - d.Set("application_consistent_snapshot_frequency_in_minutes", a2APolicyDetails.AppConsistentFrequencyInMinutes) - } - return nil -} - -func resourceArmRecoveryServicesReplicationPolicyDelete(d *schema.ResourceData, meta interface{}) error { - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - - resGroup := id.ResourceGroup - vaultName := id.Path["vaults"] - name := id.Path["replicationPolicies"] - - client := meta.(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resGroup, vaultName) - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - future, err := client.Delete(ctx, name) - if err != nil { - return fmt.Errorf("Error deleting recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for deletion of recovery services replication policy %s (vault %s): %+v", name, vaultName, err) - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/data_source_recovery_services_protection_policy_vm_test.go b/azurerm/internal/services/recoveryservices/tests/data_source_recovery_services_protection_policy_vm_test.go index 03af8b3759efe..53136f3780ce0 100644 --- a/azurerm/internal/services/recoveryservices/tests/data_source_recovery_services_protection_policy_vm_test.go +++ b/azurerm/internal/services/recoveryservices/tests/data_source_recovery_services_protection_policy_vm_test.go @@ -8,17 +8,17 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMRecoveryServicesProtectionPolicyVm_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_recovery_services_protection_policy_vm", "test") +func TestAccDataSourceAzureRMBackupPolicyVm_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_backup_policy_vm", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceRecoveryServicesProtectionPolicyVm_basic(data), + Config: testAccDataSourceBackupProtectionPolicyVm_basic(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(data.ResourceName), + testCheckAzureRMBackupProtectionPolicyVmExists(data.ResourceName), resource.TestCheckResourceAttrSet(data.ResourceName, "name"), resource.TestCheckResourceAttrSet(data.ResourceName, "recovery_vault_name"), resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), @@ -29,13 +29,13 @@ func TestAccDataSourceAzureRMRecoveryServicesProtectionPolicyVm_basic(t *testing }) } -func testAccDataSourceRecoveryServicesProtectionPolicyVm_basic(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data) +func testAccDataSourceBackupProtectionPolicyVm_basic(data acceptance.TestData) string { + template := testAccAzureRMBackupProtectionPolicyVM_basicDaily(data) return fmt.Sprintf(` %s -data "azurerm_recovery_services_protection_policy_vm" "test" { - name = "${azurerm_recovery_services_protection_policy_vm.test.name}" +data "azurerm_backup_policy_vm" "test" { + name = "${azurerm_backup_policy_vm.test.name}" recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_fabric_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_fabric_test.go deleted file mode 100644 index c832d65df33a7..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_fabric_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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" -) - -func TestAccAzureRMRecoveryFabric_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_fabric", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryFabricDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryFabric_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryFabricExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryFabric_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_fabric" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric-%d" - location = "${azurerm_resource_group.test.location}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryFabricExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // Ensure we have enough information in state to look up in API - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - fabricName := state.Primary.Attributes["name"] - - // Ensure fabric exists in API - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.FabricClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName) - if err != nil { - return fmt.Errorf("Bad: Get on fabricClient: %+v", err) - } - - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: fabric: %q does not exist", fabricName) - } - - return nil - } -} - -func testCheckAzureRMRecoveryFabricDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_fabric" { - continue - } - - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - resourceGroup := rs.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.FabricClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, resourceGroup) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Recovery Services Fabric still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_network_mapping_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_network_mapping_test.go deleted file mode 100644 index fb9148d2e0091..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_network_mapping_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" -) - -func TestAccAzureRMRecoveryNetworkMapping_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_network_mapping", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryNetworkMappingDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryNetworkMapping_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryNetworkMappingExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryNetworkMapping_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d-1" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_fabric" "test1" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric1-%d" - location = "${azurerm_resource_group.test.location}" -} - -resource "azurerm_recovery_services_fabric" "test2" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric2-%d" - location = "%s" - depends_on = ["azurerm_recovery_services_fabric.test1"] -} - -resource "azurerm_virtual_network" "test1" { - name = "network1-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["192.168.1.0/24"] - location = "${azurerm_recovery_services_fabric.test1.location}" -} - -resource "azurerm_virtual_network" "test2" { - name = "network2-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["192.168.2.0/24"] - location = "${azurerm_recovery_services_fabric.test2.location}" -} - -resource "azurerm_recovery_network_mapping" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "mapping-%d" - source_recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - target_recovery_fabric_name = "${azurerm_recovery_services_fabric.test2.name}" - source_network_id = "${azurerm_virtual_network.test1.id}" - target_network_id = "${azurerm_virtual_network.test2.id}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryNetworkMappingExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - // Ensure we have enough information in state to look up in API - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - fabricName := state.Primary.Attributes["source_recovery_fabric_name"] - networkId := state.Primary.Attributes["source_network_id"] - mappingName := state.Primary.Attributes["name"] - - id, err := azure.ParseAzureResourceID(networkId) - if err != nil { - return err - } - networkName := id.Path["virtualNetworks"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.NetworkMappingClient(resourceGroupName, vaultName) - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // TODO Fix Bad: networkMapping error - resp, err := client.Get(ctx, fabricName, networkName, mappingName) - if err != nil { - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: networkMapping: %q (network %q) does not exist", mappingName, networkName) - } - - return fmt.Errorf("Bad: Get on networkMappingClient: %+v", err) - } - - return nil - } -} - -func testCheckAzureRMRecoveryNetworkMappingDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_network_mapping" { - continue - } - - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - fabricName := rs.Primary.Attributes["source_recovery_fabric_name"] - networkId := rs.Primary.Attributes["source_network_id"] - mappingName := rs.Primary.Attributes["name"] - - id, err := azure.ParseAzureResourceID(networkId) - if err != nil { - return err - } - networkName := id.Path["virtualNetworks"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.NetworkMappingClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, networkName, mappingName) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Network Mapping still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protected_vm_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protected_vm_test.go deleted file mode 100644 index 6fcb6c1e6d365..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protected_vm_test.go +++ /dev/null @@ -1,642 +0,0 @@ -package tests - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "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/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func TestAccAzureRMRecoveryServicesProtectedVm_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protected_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectedVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectedVm_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectedVmExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), - ), - }, - data.ImportStep(), - { //vault cannot be deleted unless we unregister all backups - Config: testAccAzureRMRecoveryServicesProtectedVm_base(data), - Check: resource.ComposeTestCheckFunc(), - }, - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectedVm_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protected_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectedVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectedVm_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectedVmExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), - ), - }, - data.RequiresImportErrorStep(testAccAzureRMRecoveryServicesProtectedVm_requiresImport), - { //vault cannot be deleted unless we unregister all backups - Config: testAccAzureRMRecoveryServicesProtectedVm_base(data), - Check: resource.ComposeTestCheckFunc(), - }, - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectedVm_separateResourceGroups(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protected_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectedVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectedVm_separateResourceGroups(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectedVmExists(data.ResourceName), - resource.TestCheckResourceAttrSet(data.ResourceName, "resource_group_name"), - ), - }, - data.ImportStep(), - { //vault cannot be deleted unless we unregister all backups - Config: testAccAzureRMRecoveryServicesProtectedVm_additionalVault(data), - Check: resource.ComposeTestCheckFunc(), - }, - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectedVm_updateBackupPolicyId(t *testing.T) { - virtualMachine := "azurerm_virtual_machine.test" - fBackupPolicyResourceName := "azurerm_recovery_services_protection_policy_vm.test" - sBackupPolicyResourceName := "azurerm_recovery_services_protection_policy_vm.test_change_backup" - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protected_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectedVmDestroy, - Steps: []resource.TestStep{ - { // Create resources and link first backup policy id - ResourceName: fBackupPolicyResourceName, - Config: testAccAzureRMRecoveryServicesProtectedVm_linkFirstBackupPolicy(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair(data.ResourceName, "backup_policy_id", fBackupPolicyResourceName, "id"), - ), - }, - { // Modify backup policy id to the second one - // Set Destroy false to prevent error from cleaning up dangling resource - ResourceName: sBackupPolicyResourceName, - Config: testAccAzureRMRecoveryServicesProtectedVm_linkSecondBackupPolicy(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrPair(data.ResourceName, "backup_policy_id", sBackupPolicyResourceName, "id"), - ), - }, - { // Remove backup policy link - // Backup policy link will need to be removed first so the VM's backup policy subsequently reverts to Default - // Azure API is quite sensitive, adding the step to control resource cleanup order - ResourceName: fBackupPolicyResourceName, - Config: testAccAzureRMRecoveryServicesProtectedVm_withVM(data), - Check: resource.ComposeTestCheckFunc(), - }, - { // Then VM can be removed - ResourceName: virtualMachine, - Config: testAccAzureRMRecoveryServicesProtectedVm_withSecondPolicy(data), - Check: resource.ComposeTestCheckFunc(), - }, - { // Remove backup policies and vault - ResourceName: data.ResourceName, - Config: testAccAzureRMRecoveryServicesProtectedVm_basePolicyTest(data), - Check: resource.ComposeTestCheckFunc(), - }, - }, - }) -} - -func testCheckAzureRMRecoveryServicesProtectedVmDestroy(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectedItemsClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_protected_vm" { - continue - } - - resourceGroup := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - vmId := rs.Primary.Attributes["source_vm_id"] - - parsedVmId, err := azure.ParseAzureResourceID(vmId) - if err != nil { - return fmt.Errorf("[ERROR] Unable to parse source_vm_id '%s': %+v", vmId, err) - } - vmName, hasName := parsedVmId.Path["virtualMachines"] - if !hasName { - return fmt.Errorf("[ERROR] parsed source_vm_id '%s' doesn't contain 'virtualMachines'", vmId) - } - - protectedItemName := fmt.Sprintf("VM;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - containerName := fmt.Sprintf("iaasvmcontainer;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - - resp, err := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - - return err - } - - return fmt.Errorf("Recovery Services Protected VM still exists:\n%#v", resp) - } - - return nil -} - -func testCheckAzureRMRecoveryServicesProtectedVmExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectedItemsClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // 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: %q", resourceName) - } - - resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] - if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Recovery Services Protected VM: %q", resourceName) - } - - vaultName := rs.Primary.Attributes["recovery_vault_name"] - vmId := rs.Primary.Attributes["source_vm_id"] - - //get VM name from id - parsedVmId, err := azure.ParseAzureResourceID(vmId) - if err != nil { - return fmt.Errorf("[ERROR] Unable to parse source_vm_id '%s': %+v", vmId, err) - } - vmName, hasName := parsedVmId.Path["virtualMachines"] - if !hasName { - return fmt.Errorf("[ERROR] parsed source_vm_id '%s' doesn't contain 'virtualMachines'", vmId) - } - - protectedItemName := fmt.Sprintf("VM;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - containerName := fmt.Sprintf("iaasvmcontainer;iaasvmcontainerv2;%s;%s", parsedVmId.ResourceGroup, vmName) - - resp, err := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "") - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Recovery Services Protected VM %q (resource group: %q) was not found: %+v", protectedItemName, resourceGroup, err) - } - - return fmt.Errorf("Bad: Get on recoveryServicesVaultsClient: %+v", err) - } - - return nil - } -} - -func testAccAzureRMRecoveryServicesProtectedVm_base(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "vnet" - location = "${azurerm_resource_group.test.location}" - address_space = ["10.0.0.0/16"] - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "acctest_subnet" - virtual_network_name = "${azurerm_virtual_network.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - address_prefix = "10.0.10.0/24" -} - -resource "azurerm_network_interface" "test" { - name = "acctest_nic" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "acctestipconfig" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.test.id}" - } -} - -resource "azurerm_public_ip" "test" { - name = "acctest-ip" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Dynamic" - domain_name_label = "acctestip%d" -} - -resource "azurerm_storage_account" "test" { - name = "acctest%s" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_managed_disk" "test" { - name = "acctest-datadisk" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} - -resource "azurerm_virtual_machine" "test" { - name = "acctestvm" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - vm_size = "Standard_A0" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - storage_os_disk { - name = "acctest-osdisk" - managed_disk_type = "Standard_LRS" - caching = "ReadWrite" - create_option = "FromImage" - } - - storage_data_disk { - name = "acctest-datadisk" - managed_disk_id = "${azurerm_managed_disk.test.id}" - managed_disk_type = "Standard_LRS" - disk_size_gb = "${azurerm_managed_disk.test.disk_size_gb}" - create_option = "Attach" - lun = 0 - } - - os_profile { - computer_name = "acctest" - admin_username = "vmadmin" - admin_password = "Password123!@#" - } - - os_profile_linux_config { - disable_password_authentication = false - } - - boot_diagnostics { - enabled = true - storage_uri = "${azurerm_storage_account.test.primary_blob_endpoint}" - } -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMRecoveryServicesProtectedVm_basic(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protected_vm" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - source_vm_id = "${azurerm_virtual_machine.test.id}" - backup_policy_id = "${azurerm_recovery_services_protection_policy_vm.test.id}" -} -`, template) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_basePolicyTest(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d-1" - location = "%s" -} - -resource "azurerm_virtual_network" "test" { - name = "vnet" - location = "${azurerm_resource_group.test.location}" - address_space = ["10.0.0.0/16"] - resource_group_name = "${azurerm_resource_group.test.name}" -} - -resource "azurerm_subnet" "test" { - name = "acctest_subnet" - virtual_network_name = "${azurerm_virtual_network.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" - address_prefix = "10.0.10.0/24" -} - -resource "azurerm_network_interface" "test" { - name = "acctest_nic" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "acctestipconfig" - subnet_id = "${azurerm_subnet.test.id}" - private_ip_address_allocation = "Dynamic" - public_ip_address_id = "${azurerm_public_ip.test.id}" - } -} - -resource "azurerm_public_ip" "test" { - name = "acctest-ip" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - allocation_method = "Dynamic" - domain_name_label = "acctestip%d" -} - -resource "azurerm_storage_account" "test" { - name = "acctest%s" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_managed_disk" "test" { - name = "acctest-datadisk" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - storage_account_type = "Standard_LRS" - create_option = "Empty" - disk_size_gb = "1023" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomString) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_withVault(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_basePolicyTest(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} -`, template, data.RandomInteger) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_withFirstPolicy(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_withVault(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } -} -`, template, data.RandomInteger) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_withSecondPolicy(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_withFirstPolicy(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test_change_backup" { - name = "acctest2-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 15 - } -} -`, template, data.RandomInteger) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_withVM(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_withSecondPolicy(data) - return fmt.Sprintf(` -%s - -resource "azurerm_virtual_machine" "test" { - name = "acctestvm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - vm_size = "Standard_A0" - network_interface_ids = ["${azurerm_network_interface.test.id}"] - delete_os_disk_on_termination = true - - storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04-LTS" - version = "latest" - } - - storage_os_disk { - name = "acctest-osdisk" - managed_disk_type = "Standard_LRS" - caching = "ReadWrite" - create_option = "FromImage" - } - - storage_data_disk { - name = "acctest-datadisk" - managed_disk_id = "${azurerm_managed_disk.test.id}" - managed_disk_type = "Standard_LRS" - disk_size_gb = "${azurerm_managed_disk.test.disk_size_gb}" - create_option = "Attach" - lun = 0 - } - - os_profile { - computer_name = "acctest" - admin_username = "vmadmin" - admin_password = "Password123!@#" - } - - os_profile_linux_config { - disable_password_authentication = false - } - - boot_diagnostics { - enabled = true - storage_uri = "${azurerm_storage_account.test.primary_blob_endpoint}" - } -} -`, template, data.RandomInteger) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_linkFirstBackupPolicy(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_withVM(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protected_vm" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - source_vm_id = "${azurerm_virtual_machine.test.id}" - backup_policy_id = "${azurerm_recovery_services_protection_policy_vm.test.id}" -} -`, template) -} - -// For update backup policy id test -func testAccAzureRMRecoveryServicesProtectedVm_linkSecondBackupPolicy(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_withVM(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protected_vm" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - source_vm_id = "${azurerm_virtual_machine.test.id}" - backup_policy_id = "${azurerm_recovery_services_protection_policy_vm.test_change_backup.id}" -} -`, template) -} - -func testAccAzureRMRecoveryServicesProtectedVm_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protected_vm" "import" { - resource_group_name = "${azurerm_recovery_services_protected_vm.test.resource_group_name}" - recovery_vault_name = "${azurerm_recovery_services_protected_vm.test.recovery_vault_name}" - source_vm_id = "${azurerm_recovery_services_protected_vm.test.source_vm_id}" - backup_policy_id = "${azurerm_recovery_services_protected_vm.test.backup_policy_id}" -} -`, template) -} - -func testAccAzureRMRecoveryServicesProtectedVm_additionalVault(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_resource_group" "test2" { - name = "acctestRG-recovery-%d-2" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test2" { - name = "acctest2-%d" - location = "${azurerm_resource_group.test2.location}" - resource_group_name = "${azurerm_resource_group.test2.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_protection_policy_vm" "test2" { - name = "acctest2-%d" - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test2.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } -} -`, template, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testAccAzureRMRecoveryServicesProtectedVm_separateResourceGroups(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectedVm_additionalVault(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protected_vm" "test" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test2.name}" - backup_policy_id = "${azurerm_recovery_services_protection_policy_vm.test2.id}" - source_vm_id = "${azurerm_virtual_machine.test.id}" -} -`, template) -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_mapping_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_mapping_test.go deleted file mode 100644 index 9bd3f3eabebe8..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_mapping_test.go +++ /dev/null @@ -1,158 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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" -) - -func TestAccAzureRMRecoveryProtectionContainerMapping_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_container_mapping", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryProtectionContainerMappingDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryProtectionContainerMapping_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryProtectionContainerMappingExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryProtectionContainerMapping_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test1" { - name = "acctestRG-recovery-%d-1" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test1.location}" - resource_group_name = "${azurerm_resource_group.test1.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_fabric" "test1" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric1-%d" - location = "${azurerm_resource_group.test1.location}" -} - -resource "azurerm_recovery_services_fabric" "test2" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric2-%d" - location = "%s" - depends_on = ["azurerm_recovery_services_fabric.test1"] -} - -resource "azurerm_recovery_services_protection_container" "test1" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - name = "acctest-protection-cont1-%d" -} - -resource "azurerm_recovery_services_protection_container" "test2" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test2.name}" - name = "acctest-protection-cont2-%d" -} - -resource "azurerm_recovery_services_replication_policy" "test" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-policy-%d" - recovery_point_retention_in_minutes = "${24 * 60}" - application_consistent_snapshot_frequency_in_minutes = "${4 * 60}" -} - -resource "azurerm_recovery_services_protection_container_mapping" "test" { - resource_group_name = "${azurerm_resource_group.test1.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - recovery_source_protection_container_name = "${azurerm_recovery_services_protection_container.test1.name}" - recovery_target_protection_container_id = "${azurerm_recovery_services_protection_container.test2.id}" - recovery_replication_policy_id = "${azurerm_recovery_services_replication_policy.test.id}" - name = "mapping-%d" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryProtectionContainerMappingExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // Ensure we have enough information in state to look up in API - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - fabricName := state.Primary.Attributes["recovery_fabric_name"] - protectionContainerName := state.Primary.Attributes["recovery_source_protection_container_name"] - mappingName := state.Primary.Attributes["name"] - - // Ensure mapping exists in API - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ContainerMappingClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName, mappingName) - if err != nil { - return fmt.Errorf("Bad: Get on fabricClient: %+v", err) - } - - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: fabric: %q does not exist", fabricName) - } - - return nil - } -} - -func testCheckAzureRMRecoveryProtectionContainerMappingDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_protection_container_mapping" { - continue - } - - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - fabricName := rs.Primary.Attributes["recovery_fabric_name"] - protectionContainerName := rs.Primary.Attributes["recovery_source_protection_container_name"] - mappingName := rs.Primary.Attributes["name"] - - // Ensure mapping exists in API - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ContainerMappingClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName, mappingName) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Container Mapping still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_test.go deleted file mode 100644 index 28144fd3ae13d..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_container_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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" -) - -func TestAccAzureRMRecoveryProtectionContainer_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_container", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryProtectionContainerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryProtectionContainer_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryProtectionContainerExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryProtectionContainer_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_fabric" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric-%d" - location = "${azurerm_resource_group.test.location}" -} - -resource "azurerm_recovery_services_protection_container" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test.name}" - name = "acctest-protection-cont-%d" -} - -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryProtectionContainerExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - fabricName := state.Primary.Attributes["recovery_fabric_name"] - protectionContainerName := state.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectionContainerClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName) - if err != nil { - return fmt.Errorf("Bad: Get on RecoveryServices.ProtectionContainerClient: %+v", err) - } - - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Protection Container: %q does not exist", fabricName) - } - - return nil - } -} - -func testCheckAzureRMRecoveryProtectionContainerDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_protection_container" { - continue - } - - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - fabricName := rs.Primary.Attributes["recovery_fabric_name"] - protectionContainerName := rs.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectionContainerClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Protection Container Client still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_policy_vm_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_policy_vm_test.go deleted file mode 100644 index 06811f24f7233..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_protection_policy_vm_test.go +++ /dev/null @@ -1,555 +0,0 @@ -package tests - -import ( - "fmt" - "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/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_requiresImport(t *testing.T) { - if !features.ShouldResourcesBeImported() { - t.Skip("Skipping since resources aren't required to be imported") - return - } - - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data.ResourceName, data.RandomInteger), - }, - data.RequiresImportErrorStep(testAccAzureRMRecoveryServicesProtectionPolicyVm_requiresImport), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_updateDaily(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data.ResourceName, data.RandomInteger), - }, - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_updateWeekly(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data.ResourceName, data.RandomInteger), - }, - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_updateDailyToWeekly(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data.ResourceName, data.RandomInteger), - }, - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_updateWeeklyToDaily(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data.ResourceName, data.RandomInteger), - }, - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func TestAccAzureRMRecoveryServicesProtectionPolicyVm_updateWeeklyToPartial(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_protection_policy_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data.ResourceName, data.RandomInteger), - }, - { - Config: testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeeklyPartial(data), - Check: checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeeklyPartial(data.ResourceName, data.RandomInteger), - }, - data.ImportStep(), - }, - }) -} - -func testCheckAzureRMRecoveryServicesProtectionPolicyVmDestroy(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectionPoliciesClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_protection_policy_vm" { - continue - } - - resourceGroup := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - policyName := rs.Primary.Attributes["name"] - - resp, err := client.Get(ctx, vaultName, resourceGroup, policyName) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return nil - } - - return err - } - - return fmt.Errorf("Recovery Services Vault Policy still exists:\n%#v", resp) - } - - return nil -} - -func testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ProtectionPoliciesClient - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // 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: %q", resourceName) - } - - vaultName := rs.Primary.Attributes["recovery_vault_name"] - policyName := 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 Recovery Services Vault %q Policy: %q", vaultName, policyName) - } - - resp, err := client.Get(ctx, vaultName, resourceGroup, policyName) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Recovery Services Vault Policy %q (resource group: %q) was not found: %+v", policyName, resourceGroup, err) - } - - return fmt.Errorf("Bad: Get on recoveryServicesVaultsClient: %+v", err) - } - - return nil - } -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%[1]d" - location = "%[2]s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-%[1]d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} -`, data.RandomInteger, data.Locations.Primary) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } -} -`, template, data.RandomInteger) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "import" { - name = "${azurerm_recovery_services_protection_policy_vm.test.name}" - resource_group_name = "${azurerm_recovery_services_protection_policy_vm.test.resource_group_name}" - recovery_vault_name = "${azurerm_recovery_services_protection_policy_vm.test.recovery_vault_name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } -} -`, template) -} - -func checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicDaily(resourceName string, ri int) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "resource_group_name", fmt.Sprintf("acctestRG-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "recovery_vault_name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "backup.0.frequency", "Daily"), - resource.TestCheckResourceAttr(resourceName, "backup.0.time", "23:00"), - resource.TestCheckResourceAttr(resourceName, "retention_daily.0.count", "10"), - ) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Weekly" - time = "23:00" - weekdays = ["Sunday", "Wednesday"] - } - - retention_weekly { - count = 42 - weekdays = ["Sunday", "Wednesday"] - } -} -`, template, data.RandomInteger) -} - -func checkAccAzureRMRecoveryServicesProtectionPolicyVm_basicWeekly(resourceName string, ri int) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "resource_group_name", fmt.Sprintf("acctestRG-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "recovery_vault_name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "backup.0.frequency", "Weekly"), - resource.TestCheckResourceAttr(resourceName, "backup.0.time", "23:00"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.count", "42"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.weekdays.#", "2"), - ) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Daily" - time = "23:00" - } - - retention_daily { - count = 10 - } - - retention_weekly { - count = 42 - weekdays = ["Sunday", "Wednesday"] - } - - retention_monthly { - count = 7 - weekdays = ["Sunday", "Wednesday"] - weeks = ["First", "Last"] - } - - retention_yearly { - count = 77 - weekdays = ["Sunday", "Wednesday"] - weeks = ["First", "Last"] - months = ["January", "July"] - } -} -`, template, data.RandomInteger) -} - -func checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeDaily(resourceName string, ri int) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "resource_group_name", fmt.Sprintf("acctestRG-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "recovery_vault_name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "backup.0.frequency", "Daily"), - resource.TestCheckResourceAttr(resourceName, "backup.0.time", "23:00"), - resource.TestCheckResourceAttr(resourceName, "retention_daily.0.count", "10"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.count", "42"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.weekdays.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.count", "7"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weekdays.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weeks.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.count", "77"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weekdays.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weeks.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.months.#", "2"), - ) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Weekly" - time = "23:00" - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - } - - retention_weekly { - count = 42 - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - } - - retention_monthly { - count = 7 - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - weeks = ["First", "Last"] - } - - retention_yearly { - count = 77 - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - weeks = ["First", "Last"] - months = ["January", "July"] - } -} -`, template, data.RandomInteger) -} - -func checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeekly(resourceName string, ri int) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "resource_group_name", fmt.Sprintf("acctestRG-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "recovery_vault_name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "backup.0.frequency", "Weekly"), - resource.TestCheckResourceAttr(resourceName, "backup.0.time", "23:00"), - resource.TestCheckResourceAttr(resourceName, "backup.0.weekdays.#", "4"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.count", "42"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.weekdays.#", "4"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.count", "7"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weekdays.#", "4"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weeks.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.count", "77"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weekdays.#", "4"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weeks.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.months.#", "2"), - ) -} - -func testAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeeklyPartial(data acceptance.TestData) string { - template := testAccAzureRMRecoveryServicesProtectionPolicyVm_base(data) - return fmt.Sprintf(` -%s - -resource "azurerm_recovery_services_protection_policy_vm" "test" { - name = "acctest-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - - backup { - frequency = "Weekly" - time = "23:00" - weekdays = ["Sunday", "Wednesday", "Friday", "Saturday"] - } - - retention_weekly { - count = 42 - weekdays = ["Sunday", "Wednesday", "Friday"] - } - - retention_monthly { - count = 7 - weekdays = ["Sunday", "Wednesday"] - weeks = ["First", "Last"] - } - - retention_yearly { - count = 77 - weekdays = ["Sunday"] - weeks = ["Last"] - months = ["January"] - } -} -`, template, data.RandomInteger) -} - -func checkAccAzureRMRecoveryServicesProtectionPolicyVm_completeWeeklyPartial(resourceName string, ri int) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMRecoveryServicesProtectionPolicyVmExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "resource_group_name", fmt.Sprintf("acctestRG-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "recovery_vault_name", fmt.Sprintf("acctest-%d", ri)), - resource.TestCheckResourceAttr(resourceName, "backup.0.frequency", "Weekly"), - resource.TestCheckResourceAttr(resourceName, "backup.0.time", "23:00"), - resource.TestCheckResourceAttr(resourceName, "backup.0.weekdays.#", "4"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.count", "42"), - resource.TestCheckResourceAttr(resourceName, "retention_weekly.0.weekdays.#", "3"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.count", "7"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weekdays.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_monthly.0.weeks.#", "2"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.count", "77"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weekdays.#", "1"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.weeks.#", "1"), - resource.TestCheckResourceAttr(resourceName, "retention_yearly.0.months.#", "1"), - ) -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replicated_vm_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replicated_vm_test.go deleted file mode 100644 index ed035ebfd46ee..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replicated_vm_test.go +++ /dev/null @@ -1,269 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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" -) - -func TestAccAzureRMRecoveryReplicatedVm_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_replicated_vm", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryReplicatedVmDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryReplicatedVm_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryReplicatedVmExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryReplicatedVm_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d-1" - location = "%s" -} - -resource "azurerm_resource_group" "test2" { - name = "acctestRG-recovery-%d-2" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test2.location}" - resource_group_name = "${azurerm_resource_group.test2.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_fabric" "test1" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric1-%d" - location = "${azurerm_resource_group.test.location}" -} - -resource "azurerm_recovery_services_fabric" "test2" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-fabric2-%d" - location = "${azurerm_resource_group.test2.location}" - depends_on = ["azurerm_recovery_services_fabric.test1"] -} - -resource "azurerm_recovery_services_protection_container" "test1" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - name = "acctest-protection-cont1-%d" -} - -resource "azurerm_recovery_services_protection_container" "test2" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test2.name}" - name = "acctest-protection-cont2-%d" -} - -resource "azurerm_recovery_services_replication_policy" "test" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-policy-%d" - recovery_point_retention_in_minutes = "${24 * 60}" - application_consistent_snapshot_frequency_in_minutes = "${4 * 60}" -} - -resource "azurerm_recovery_services_protection_container_mapping" "test" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - recovery_source_protection_container_name = "${azurerm_recovery_services_protection_container.test1.name}" - recovery_target_protection_container_id = "${azurerm_recovery_services_protection_container.test2.id}" - recovery_replication_policy_id = "${azurerm_recovery_services_replication_policy.test.id}" - name = "mapping-%d" -} - -resource "azurerm_virtual_network" "test1" { - name = "net-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - address_space = ["192.168.1.0/24"] - location = "${azurerm_recovery_services_fabric.test1.location}" -} -resource "azurerm_subnet" "test1" { - name = "snet-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - virtual_network_name = "${azurerm_virtual_network.test1.name}" - address_prefix = "192.168.1.0/24" -} - - -resource "azurerm_virtual_network" "test2" { - name = "net-%d" - resource_group_name = "${azurerm_resource_group.test2.name}" - address_space = ["192.168.2.0/24"] - location = "${azurerm_recovery_services_fabric.test2.location}" -} - -resource "azurerm_recovery_network_mapping" "test" { - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "mapping-%d" - source_recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - target_recovery_fabric_name = "${azurerm_recovery_services_fabric.test2.name}" - source_network_id = "${azurerm_virtual_network.test1.id}" - target_network_id = "${azurerm_virtual_network.test2.id}" -} - -resource "azurerm_network_interface" "test" { - name = "vm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - ip_configuration { - name = "vm-%d" - subnet_id = "${azurerm_subnet.test1.id}" - private_ip_address_allocation = "Dynamic" - } -} - -resource "azurerm_virtual_machine" "test" { - name = "vm-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - - vm_size = "Standard_B1s" - - storage_image_reference { - publisher = "OpenLogic" - offer = "CentOS" - sku = "7.5" - version = "latest" - } - - storage_os_disk { - name = "disk-%d" - os_type = "Linux" - caching = "ReadWrite" - create_option = "FromImage" - managed_disk_type = "Premium_LRS" - } - - os_profile { - admin_username = "testadmin" - admin_password = "Password1234!" - computer_name = "vm-%d" - } - - os_profile_linux_config { - disable_password_authentication = false - - } - network_interface_ids = ["${azurerm_network_interface.test.id}"] -} - -resource "azurerm_storage_account" "test" { - name = "acct%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_recovery_replicated_vm" "test" { - name = "repl-%d" - resource_group_name = "${azurerm_resource_group.test2.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - source_vm_id = "${azurerm_virtual_machine.test.id}" - source_recovery_fabric_name = "${azurerm_recovery_services_fabric.test1.name}" - recovery_replication_policy_id = "${azurerm_recovery_services_replication_policy.test.id}" - source_recovery_protection_container_name = "${azurerm_recovery_services_protection_container.test1.name}" - - target_resource_group_id = "${azurerm_resource_group.test2.id}" - target_recovery_fabric_id = "${azurerm_recovery_services_fabric.test2.id}" - target_recovery_protection_container_id = "${azurerm_recovery_services_protection_container.test2.id}" - - managed_disk { - disk_id = "${azurerm_virtual_machine.test.storage_os_disk.0.managed_disk_id}" - staging_storage_account_id = "${azurerm_storage_account.test.id}" - target_resource_group_id = "${azurerm_resource_group.test2.id}" - target_disk_type = "Premium_LRS" - target_replica_disk_type = "Premium_LRS" - } - depends_on = ["azurerm_recovery_services_protection_container_mapping.test", "azurerm_recovery_network_mapping.test"] -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.Locations.Secondary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryReplicatedVmExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - fabricName := state.Primary.Attributes["source_recovery_fabric_name"] - protectionContainerName := state.Primary.Attributes["source_recovery_protection_container_name"] - replicationName := state.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ReplicationMigrationItemsClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName, replicationName) - if err != nil { - return fmt.Errorf("Bad: Get on RecoveryServices.ReplicationMigrationItemsClient: %+v", err) - } - - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Recovery Services Replicated VM: %q does not exist", fabricName) - } - - return nil - } -} - -func testCheckAzureRMRecoveryReplicatedVmDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_replicated_vm" { - continue - } - - resourceGroupName := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - fabricName := rs.Primary.Attributes["source_recovery_fabric_name"] - protectionContainerName := rs.Primary.Attributes["source_recovery_protection_container_name"] - replicationName := rs.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ReplicationMigrationItemsClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, fabricName, protectionContainerName, replicationName) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Recovery Services Replicated VM still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replication_policy_test.go b/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replication_policy_test.go deleted file mode 100644 index a414f13e7aa17..0000000000000 --- a/azurerm/internal/services/recoveryservices/tests/resource_arm_recovery_services_replication_policy_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package tests - -import ( - "fmt" - "net/http" - "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" -) - -func TestAccAzureRMRecoveryReplicationPolicy_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_recovery_services_replication_policy", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMRecoveryReplicationPolicyDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMRecoveryReplicationPolicy_basic(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMRecoveryReplicationPolicyExists(data.ResourceName), - ), - }, - data.ImportStep(), - }, - }) -} - -func testAccAzureRMRecoveryReplicationPolicy_basic(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-recovery-%d" - location = "%s" -} - -resource "azurerm_recovery_services_vault" "test" { - name = "acctest-vault-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "Standard" - - soft_delete_enabled = false -} - -resource "azurerm_recovery_services_replication_policy" "test" { - resource_group_name = "${azurerm_resource_group.test.name}" - recovery_vault_name = "${azurerm_recovery_services_vault.test.name}" - name = "acctest-policy-%d" - recovery_point_retention_in_minutes = "${24 * 60}" - application_consistent_snapshot_frequency_in_minutes = "${4 * 60}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) -} - -func testCheckAzureRMRecoveryReplicationPolicyExists(resourceName string) resource.TestCheckFunc { - return func(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - // Ensure we have enough information in state to look up in API - state, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - resourceGroupName := state.Primary.Attributes["resource_group_name"] - vaultName := state.Primary.Attributes["recovery_vault_name"] - policyName := state.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resourceGroupName, vaultName) - - resp, err := client.Get(ctx, policyName) - if err != nil { - return fmt.Errorf("Bad: Get on RecoveryServices.ReplicationPoliciesClient: %+v", err) - } - - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Replication Policies: %q does not exist", policyName) - } - - return nil - } -} - -func testCheckAzureRMRecoveryReplicationPolicyDestroy(s *terraform.State) error { - ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - - for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_recovery_services_replication_policy" { - continue - } - - resourceGroup := rs.Primary.Attributes["resource_group_name"] - vaultName := rs.Primary.Attributes["recovery_vault_name"] - policyName := rs.Primary.Attributes["name"] - - client := acceptance.AzureProvider.Meta().(*clients.Client).RecoveryServices.ReplicationPoliciesClient(resourceGroup, vaultName) - - resp, err := client.Get(ctx, policyName) - if err != nil { - return nil - } - - if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Replication Policy still exists:\n%#v", resp.Properties) - } - } - - return nil -} diff --git a/website/azurerm.erb b/website/azurerm.erb index 13e50d7b10782..450524c095bbd 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -122,6 +122,10 @@ azurerm_availability_set +
  • + azurerm_backup_policy_vm +
  • +
  • azurerm_batch_account
  • @@ -406,10 +410,6 @@ azurerm_recovery_services_vault -
  • - azurerm_recovery_services_protection_policy_vm -
  • -
  • azurerm_redis_cache
  • @@ -2014,38 +2014,6 @@
  • Recovery Services