diff --git a/azurerm/internal/services/cdn/cdn_endpoint_resource.go b/azurerm/internal/services/cdn/cdn_endpoint_resource.go index 78025a2c02b9..7fd678299c55 100644 --- a/azurerm/internal/services/cdn/cdn_endpoint_resource.go +++ b/azurerm/internal/services/cdn/cdn_endpoint_resource.go @@ -5,6 +5,8 @@ import ( "log" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/migration" + "github.com/Azure/azure-sdk-for-go/services/cdn/mgmt/2019-04-15/cdn" "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -201,10 +203,20 @@ func resourceArmCdnEndpoint() *schema.Resource { "tags": tags.Schema(), }, + + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: migration.CdnEndpointV0Schema().CoreConfigSchema().ImpliedType(), + Upgrade: migration.CdnEndpointV0ToV1, + Version: 0, + }, + }, } } func resourceArmCdnEndpointCreate(d *schema.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId endpointsClient := meta.(*clients.Client).Cdn.EndpointsClient profilesClient := meta.(*clients.Client).Cdn.ProfilesClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) @@ -303,7 +315,12 @@ func resourceArmCdnEndpointCreate(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error retrieving CDN Endpoint %q (Profile %q / Resource Group %q): %+v", name, profileName, resourceGroup, err) } - d.SetId(*read.ID) + id, err := parse.CdnEndpointID(*read.ID) + if err != nil { + return err + } + + d.SetId(id.ID(subscriptionId)) return resourceArmCdnEndpointRead(d, meta) } diff --git a/azurerm/internal/services/cdn/cdn_profile_data_source.go b/azurerm/internal/services/cdn/cdn_profile_data_source.go index 1607cf9ac854..cf239b1a730a 100644 --- a/azurerm/internal/services/cdn/cdn_profile_data_source.go +++ b/azurerm/internal/services/cdn/cdn_profile_data_source.go @@ -4,6 +4,8 @@ import ( "fmt" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/parse" + "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" @@ -41,6 +43,7 @@ func dataSourceArmCdnProfile() *schema.Resource { } func dataSourceArmCdnProfileRead(d *schema.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId client := meta.(*clients.Client).Cdn.ProfilesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -56,7 +59,12 @@ func dataSourceArmCdnProfileRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error making Read request on Azure CDN Profile %q (Resource Group %q): %+v", name, resourceGroup, err) } - d.SetId(*resp.ID) + id, err := parse.CdnProfileID(*resp.ID) + if err != nil { + return err + } + + d.SetId(id.ID(subscriptionId)) d.Set("name", name) d.Set("resource_group_name", resourceGroup) diff --git a/azurerm/internal/services/cdn/cdn_profile_resource.go b/azurerm/internal/services/cdn/cdn_profile_resource.go index 279608c4481b..703a26772202 100644 --- a/azurerm/internal/services/cdn/cdn_profile_resource.go +++ b/azurerm/internal/services/cdn/cdn_profile_resource.go @@ -5,6 +5,8 @@ import ( "log" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/migration" + "github.com/Azure/azure-sdk-for-go/services/cdn/mgmt/2019-04-15/cdn" "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -66,10 +68,20 @@ func resourceArmCdnProfile() *schema.Resource { "tags": tags.Schema(), }, + + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: migration.CdnProfileV0Schema().CoreConfigSchema().ImpliedType(), + Upgrade: migration.CdnProfileV0ToV1, + Version: 0, + }, + }, } } func resourceArmCdnProfileCreate(d *schema.ResourceData, meta interface{}) error { + subscriptionId := meta.(*clients.Client).Account.SubscriptionId client := meta.(*clients.Client).Cdn.ProfilesClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -121,7 +133,12 @@ func resourceArmCdnProfileCreate(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Cannot read CDN Profile %s (resource group %s) ID", name, resGroup) } - d.SetId(*read.ID) + id, err := parse.CdnProfileID(*read.ID) + if err != nil { + return err + } + + d.SetId(id.ID(subscriptionId)) return resourceArmCdnProfileRead(d, meta) } diff --git a/azurerm/internal/services/cdn/migration/cdn_endpoint.go b/azurerm/internal/services/cdn/migration/cdn_endpoint.go new file mode 100644 index 000000000000..f705ae78a9ba --- /dev/null +++ b/azurerm/internal/services/cdn/migration/cdn_endpoint.go @@ -0,0 +1,1019 @@ +package migration + +import ( + "log" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" + + "github.com/Azure/azure-sdk-for-go/services/cdn/mgmt/2019-04-15/cdn" + "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/suppress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/parse" +) + +func CdnEndpointV0Schema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: location.StateFunc, + DiffSuppressFunc: location.DiffSuppressFunc, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "profile_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "origin_host_header": { + Type: schema.TypeString, + Optional: true, + }, + + "is_http_allowed": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "is_https_allowed": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + + "origin": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "host_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "http_port": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 80, + }, + + "https_port": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Default: 443, + }, + }, + }, + }, + + "origin_path": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "querystring_caching_behaviour": { + Type: schema.TypeString, + Optional: true, + Default: string(cdn.IgnoreQueryString), + }, + + "content_types_to_compress": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + }, + + "is_compression_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "probe_path": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "geo_filter": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "relative_path": { + Type: schema.TypeString, + Required: true, + }, + "action": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: suppress.CaseDifference, + }, + "country_codes": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "optimization_type": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.CaseDifference, + }, + + "host_name": { + Type: schema.TypeString, + Computed: true, + }, + + "global_delivery_rule": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cache_expiration_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "behavior": { + Type: schema.TypeString, + Required: true, + }, + + "duration": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "cache_key_query_string_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "behavior": { + Type: schema.TypeString, + Required: true, + }, + + "parameters": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "modify_request_header_action": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "value": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "modify_response_header_action": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "value": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "url_redirect_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "redirect_type": { + Type: schema.TypeString, + Required: true, + }, + + "protocol": { + Type: schema.TypeString, + Optional: true, + Default: string(cdn.MatchRequest), + }, + + "hostname": { + Type: schema.TypeString, + Optional: true, + }, + + "path": { + Type: schema.TypeString, + Optional: true, + }, + + "query_string": { + Type: schema.TypeString, + Optional: true, + }, + + "fragment": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "url_rewrite_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "source_pattern": { + Type: schema.TypeString, + Required: true, + }, + + "destination": { + Type: schema.TypeString, + Required: true, + }, + + "preserve_unmatched_path": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + }, + }, + }, + }, + }, + }, + + "delivery_rule": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "order": { + Type: schema.TypeInt, + Required: true, + }, + + "cookies_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "selector": { + Type: schema.TypeString, + Required: true, + }, + + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "http_version_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Optional: true, + Default: "Equal", + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "device_condition": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Optional: true, + Default: "Equal", + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "post_arg_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "selector": { + Type: schema.TypeString, + Required: true, + }, + + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "query_string_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "remote_address_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "request_body_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "request_header_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "selector": { + Type: schema.TypeString, + Required: true, + }, + + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "request_method_condition": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Optional: true, + Default: "Equal", + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "request_scheme_condition": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Optional: true, + Default: "Equal", + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "request_uri_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "url_file_extension_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "url_file_name_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "url_path_condition": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "operator": { + Type: schema.TypeString, + Required: true, + }, + + "negate_condition": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "match_values": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "transforms": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "cache_expiration_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "behavior": { + Type: schema.TypeString, + Required: true, + }, + + "duration": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "cache_key_query_string_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "behavior": { + Type: schema.TypeString, + Required: true, + }, + + "parameters": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "modify_request_header_action": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "value": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "modify_response_header_action": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "value": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "url_redirect_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "redirect_type": { + Type: schema.TypeString, + Required: true, + }, + + "protocol": { + Type: schema.TypeString, + Optional: true, + Default: string(cdn.MatchRequest), + }, + + "hostname": { + Type: schema.TypeString, + Optional: true, + }, + + "path": { + Type: schema.TypeString, + Optional: true, + }, + + "query_string": { + Type: schema.TypeString, + Optional: true, + }, + + "fragment": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + + "url_rewrite_action": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "source_pattern": { + Type: schema.TypeString, + Required: true, + }, + + "destination": { + Type: schema.TypeString, + Required: true, + }, + + "preserve_unmatched_path": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + }, + }, + }, + }, + }, + }, + + "tags": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func CdnEndpointV0ToV1(rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) { + // old + // /subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName} + // new: + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName}/endpoints/{endpointName} + // summary: + // resourcegroups -> resourceGroups + oldId := rawState["id"].(string) + oldParsedId, err := azure.ParseAzureResourceID(oldId) + if err != nil { + return rawState, err + } + + resourceGroup := oldParsedId.ResourceGroup + profileName, err := oldParsedId.PopSegment("profiles") + if err != nil { + return rawState, err + } + name, err := oldParsedId.PopSegment("endpoints") + if err != nil { + return rawState, err + } + + newId := parse.NewCdnEndpointID(parse.NewCdnProfileID(resourceGroup, profileName), name) + newIdStr := newId.ID(oldParsedId.SubscriptionID) + + log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newIdStr) + + rawState["id"] = newIdStr + + return rawState, nil +} diff --git a/azurerm/internal/services/cdn/migration/cdn_endpoint_test.go b/azurerm/internal/services/cdn/migration/cdn_endpoint_test.go new file mode 100644 index 000000000000..7cc4128deaa0 --- /dev/null +++ b/azurerm/internal/services/cdn/migration/cdn_endpoint_test.go @@ -0,0 +1,55 @@ +package migration + +import ( + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestCdnEndpointV1ToV2(t *testing.T) { + testData := []struct { + name string + input map[string]interface{} + expected *string + }{ + { + name: "missing id", + input: map[string]interface{}{ + "id": "", + }, + expected: nil, + }, + { + name: "old id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourcegroups/group1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1"), + }, + { + name: "new id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1"), + }, + } + for _, test := range testData { + t.Logf("Testing %q..", test.name) + result, err := CdnEndpointV0ToV1(test.input, nil) + if err != nil && test.expected == nil { + continue + } else { + if err == nil && test.expected == nil { + t.Fatalf("Expected an error but didn't get one") + } else if err != nil && test.expected != nil { + t.Fatalf("Expected no error but got: %+v", err) + } + } + + actualId := result["id"].(string) + if *test.expected != actualId { + t.Fatalf("expected %q but got %q!", *test.expected, actualId) + } + } +} diff --git a/azurerm/internal/services/cdn/migration/cdn_profile.go b/azurerm/internal/services/cdn/migration/cdn_profile.go new file mode 100644 index 000000000000..58d208968551 --- /dev/null +++ b/azurerm/internal/services/cdn/migration/cdn_profile.go @@ -0,0 +1,82 @@ +package migration + +import ( + "log" + + "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/internal/location" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/cdn/parse" +) + +func CdnProfileV0Schema() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: location.StateFunc, + DiffSuppressFunc: location.DiffSuppressFunc, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "sku": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: suppress.CaseDifference, + }, + + "tags": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func CdnProfileV0ToV1(rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) { + // old + // /subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName} + // new: + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cdn/profiles/{profileName} + // summary: + // resourcegroups -> resourceGroups + oldId := rawState["id"].(string) + oldParsedId, err := azure.ParseAzureResourceID(oldId) + if err != nil { + return rawState, err + } + + resourceGroup := oldParsedId.ResourceGroup + name, err := oldParsedId.PopSegment("profiles") + if err != nil { + return rawState, err + } + + newId := parse.NewCdnProfileID(resourceGroup, name) + newIdStr := newId.ID(oldParsedId.SubscriptionID) + + log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newIdStr) + + rawState["id"] = newIdStr + + return rawState, nil +} diff --git a/azurerm/internal/services/cdn/migration/cdn_profile_test.go b/azurerm/internal/services/cdn/migration/cdn_profile_test.go new file mode 100644 index 000000000000..d58e25e9bac9 --- /dev/null +++ b/azurerm/internal/services/cdn/migration/cdn_profile_test.go @@ -0,0 +1,55 @@ +package migration + +import ( + "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestCdnProfileV1ToV2(t *testing.T) { + testData := []struct { + name string + input map[string]interface{} + expected *string + }{ + { + name: "missing id", + input: map[string]interface{}{ + "id": "", + }, + expected: nil, + }, + { + name: "old id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourcegroups/group1/providers/Microsoft.Cdn/profiles/profile1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1"), + }, + { + name: "new id", + input: map[string]interface{}{ + "id": "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1", + }, + expected: utils.String("/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1"), + }, + } + for _, test := range testData { + t.Logf("Testing %q..", test.name) + result, err := CdnProfileV0ToV1(test.input, nil) + if err != nil && test.expected == nil { + continue + } else { + if err == nil && test.expected == nil { + t.Fatalf("Expected an error but didn't get one") + } else if err != nil && test.expected != nil { + t.Fatalf("Expected no error but got: %+v", err) + } + } + + actualId := result["id"].(string) + if *test.expected != actualId { + t.Fatalf("expected %q but got %q!", *test.expected, actualId) + } + } +} diff --git a/azurerm/internal/services/cdn/parse/cdn_endpoint.go b/azurerm/internal/services/cdn/parse/cdn_endpoint.go index e1ab676e7280..225066302df9 100644 --- a/azurerm/internal/services/cdn/parse/cdn_endpoint.go +++ b/azurerm/internal/services/cdn/parse/cdn_endpoint.go @@ -12,6 +12,14 @@ type CdnEndpointId struct { Name string } +func NewCdnEndpointID(id CdnProfileId, name string) CdnEndpointId { + return CdnEndpointId{ + ResourceGroup: id.ResourceGroup, + ProfileName: id.Name, + Name: name, + } +} + func CdnEndpointID(input string) (*CdnEndpointId, error) { id, err := azure.ParseAzureResourceID(input) if err != nil { @@ -36,3 +44,8 @@ func CdnEndpointID(input string) (*CdnEndpointId, error) { return &endpoint, nil } + +func (id CdnEndpointId) ID(subscriptionId string) string { + base := NewCdnProfileID(id.ResourceGroup, id.ProfileName).ID(subscriptionId) + return fmt.Sprintf("%s/endpoints/%s", base, id.Name) +} diff --git a/azurerm/internal/services/cdn/parse/cdn_endpoint_test.go b/azurerm/internal/services/cdn/parse/cdn_endpoint_test.go index 914cbc5a59ba..8147bcfdb57b 100644 --- a/azurerm/internal/services/cdn/parse/cdn_endpoint_test.go +++ b/azurerm/internal/services/cdn/parse/cdn_endpoint_test.go @@ -2,8 +2,21 @@ package parse import ( "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid" ) +var _ resourceid.Formatter = CdnEndpointId{} + +func TestCdnEndpointIDFormatter(t *testing.T) { + subscriptionId := "12345678-1234-5678-1234-123456789012" + actual := NewCdnEndpointID(NewCdnProfileID("group1", "profile1"), "endpoint1").ID(subscriptionId) + expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1/endpoints/endpoint1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + func TestCdnEndpointId(t *testing.T) { testData := []struct { Name string diff --git a/azurerm/internal/services/cdn/parse/cdn_profile.go b/azurerm/internal/services/cdn/parse/cdn_profile.go index ea43900f94fe..479a57e1e9cf 100644 --- a/azurerm/internal/services/cdn/parse/cdn_profile.go +++ b/azurerm/internal/services/cdn/parse/cdn_profile.go @@ -9,7 +9,13 @@ import ( type CdnProfileId struct { ResourceGroup string Name string - ProfileName string +} + +func NewCdnProfileID(resourceGroup, name string) CdnProfileId { + return CdnProfileId{ + ResourceGroup: resourceGroup, + Name: name, + } } func CdnProfileID(input string) (*CdnProfileId, error) { @@ -32,3 +38,8 @@ func CdnProfileID(input string) (*CdnProfileId, error) { return &profile, nil } + +func (id CdnProfileId) ID(subscriptionId string) string { + return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Cdn/profiles/%s", + subscriptionId, id.ResourceGroup, id.Name) +} diff --git a/azurerm/internal/services/cdn/parse/cdn_profile_test.go b/azurerm/internal/services/cdn/parse/cdn_profile_test.go index cde57127dc8d..2112828f9456 100644 --- a/azurerm/internal/services/cdn/parse/cdn_profile_test.go +++ b/azurerm/internal/services/cdn/parse/cdn_profile_test.go @@ -2,8 +2,21 @@ package parse import ( "testing" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/resourceid" ) +var _ resourceid.Formatter = CdnProfileId{} + +func TestCdnProfileIDFormatter(t *testing.T) { + subscriptionId := "12345678-1234-5678-1234-123456789012" + actual := NewCdnProfileID("group1", "profile1").ID(subscriptionId) + expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Cdn/profiles/profile1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + func TestCdnProfileId(t *testing.T) { testData := []struct { Name string diff --git a/azurerm/internal/services/cdn/tests/cdn_endpoint_resource_test.go b/azurerm/internal/services/cdn/tests/cdn_endpoint_resource_test.go index c46c87ad5f96..cbc8dfe5e252 100644 --- a/azurerm/internal/services/cdn/tests/cdn_endpoint_resource_test.go +++ b/azurerm/internal/services/cdn/tests/cdn_endpoint_resource_test.go @@ -345,6 +345,25 @@ func TestAccAzureRMCdnEndpoint_deliveryRule(t *testing.T) { }) } +func TestAccAzureRMCdnEndpoint_dnsAlias(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_cdn_endpoint", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMCdnEndpointDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMCdnEndpoint_dnsAlias(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMCdnEndpointExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func testCheckAzureRMCdnEndpointExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { conn := acceptance.AzureProvider.Meta().(*clients.Client).Cdn.EndpointsClient @@ -1109,3 +1128,50 @@ resource "azurerm_cdn_endpoint" "test" { } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } + +func testAccAzureRMCdnEndpoint_dnsAlias(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_dns_zone" "test" { + name = "acctestcdnep%d.com" + resource_group_name = azurerm_resource_group.test.name +} + +resource "azurerm_cdn_profile" "test" { + name = "acctestcdnep%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Standard_Verizon" +} + +resource "azurerm_cdn_endpoint" "test" { + name = "acctestcdnep%d" + profile_name = azurerm_cdn_profile.test.name + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + + origin { + name = "acceptanceTestCdnOrigin1" + host_name = "www.contoso.com" + https_port = 443 + http_port = 80 + } +} + +resource "azurerm_dns_a_record" "test" { + name = "myarecord%d" + resource_group_name = azurerm_resource_group.test.name + zone_name = azurerm_dns_zone.test.name + ttl = 300 + target_resource_id = azurerm_cdn_endpoint.test.id +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) +}