From 77c334a4fbf67cb7ffb01f1e2fc94a60b7eebe7a Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:28:32 +0100
Subject: [PATCH 01/24] frontdoor: updating the ID parsers to enable generation

---
 azurerm/internal/services/frontdoor/parse/backend_pool.go   | 6 +++---
 .../internal/services/frontdoor/parse/backend_pool_test.go  | 3 +--
 .../internal/services/frontdoor/parse/frontend_endpoint.go  | 6 +++---
 .../services/frontdoor/parse/frontend_endpoint_test.go      | 3 +--
 azurerm/internal/services/frontdoor/parse/health_probe.go   | 6 +++---
 .../internal/services/frontdoor/parse/health_probe_test.go  | 3 +--
 azurerm/internal/services/frontdoor/parse/load_balancing.go | 6 +++---
 .../services/frontdoor/parse/load_balancing_test.go         | 3 +--
 azurerm/internal/services/frontdoor/parse/routing_rule.go   | 6 +++---
 .../internal/services/frontdoor/parse/routing_rule_test.go  | 3 +--
 10 files changed, 20 insertions(+), 25 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool.go b/azurerm/internal/services/frontdoor/parse/backend_pool.go
index 7d333ef569c7..969256124c8b 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool.go
@@ -8,10 +8,10 @@ type BackendPoolId struct {
 	Name          string
 }
 
-func NewBackendPoolID(id FrontDoorId, name string) BackendPoolId {
+func NewBackendPoolID(resourceGroup, frontDoorName, name string) BackendPoolId {
 	return BackendPoolId{
-		ResourceGroup: id.ResourceGroup,
-		FrontDoorName: id.Name,
+		ResourceGroup: resourceGroup,
+		FrontDoorName: frontDoorName,
 		Name:          name,
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
index 6e4ee710d2d9..a3884da5de66 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
@@ -10,8 +10,7 @@ var _ resourceid.Formatter = BackendPoolId{}
 
 func TestBackendPoolIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	frontDoorId := NewFrontDoorID("group1", "frontdoor1")
-	actual := NewBackendPoolID(frontDoorId, "pool1").ID(subscriptionId)
+	actual := NewBackendPoolID("group1", "frontdoor1", "pool1").ID(subscriptionId)
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
index 74c04f61b9c1..cf78af4db524 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
@@ -8,10 +8,10 @@ type FrontendEndpointId struct {
 	Name          string
 }
 
-func NewFrontendEndpointID(id FrontDoorId, name string) FrontendEndpointId {
+func NewFrontendEndpointID(resourceGroup, frontDoorName, name string) FrontendEndpointId {
 	return FrontendEndpointId{
-		ResourceGroup: id.ResourceGroup,
-		FrontDoorName: id.Name,
+		ResourceGroup: resourceGroup,
+		FrontDoorName: frontDoorName,
 		Name:          name,
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
index ea51d53f3233..3a34f89bcc87 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
@@ -10,8 +10,7 @@ var _ resourceid.Formatter = FrontendEndpointId{}
 
 func TestFrontendEndpointIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	frontDoorId := NewFrontDoorID("group1", "frontdoor1")
-	actual := NewFrontendEndpointID(frontDoorId, "endpoint1").ID(subscriptionId)
+	actual := NewFrontendEndpointID("group1", "frontdoor1", "endpoint1").ID(subscriptionId)
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe.go b/azurerm/internal/services/frontdoor/parse/health_probe.go
index 1cc56b6865cb..dd657ac7438c 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe.go
@@ -8,10 +8,10 @@ type HealthProbeId struct {
 	Name          string
 }
 
-func NewHealthProbeID(id FrontDoorId, name string) HealthProbeId {
+func NewHealthProbeID(resourceGroup, frontDoorName, name string) HealthProbeId {
 	return HealthProbeId{
-		ResourceGroup: id.ResourceGroup,
-		FrontDoorName: id.Name,
+		ResourceGroup: resourceGroup,
+		FrontDoorName: frontDoorName,
 		Name:          name,
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe_test.go b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
index 52951a31165a..70fb9d6296f5 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe_test.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
@@ -10,8 +10,7 @@ var _ resourceid.Formatter = HealthProbeId{}
 
 func TestHealthProbeIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	frontDoorId := NewFrontDoorID("group1", "frontdoor1")
-	actual := NewHealthProbeID(frontDoorId, "probe1").ID(subscriptionId)
+	actual := NewHealthProbeID("group1", "frontdoor1", "probe1").ID(subscriptionId)
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing.go b/azurerm/internal/services/frontdoor/parse/load_balancing.go
index 6e54be67e5ee..408aa7411092 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing.go
@@ -8,10 +8,10 @@ type LoadBalancingId struct {
 	Name          string
 }
 
-func NewLoadBalancingID(id FrontDoorId, name string) LoadBalancingId {
+func NewLoadBalancingID(resourceGroup, frontDoorName, name string) LoadBalancingId {
 	return LoadBalancingId{
-		ResourceGroup: id.ResourceGroup,
-		FrontDoorName: id.Name,
+		ResourceGroup: resourceGroup,
+		FrontDoorName: frontDoorName,
 		Name:          name,
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
index 375e5cc37c36..8ee9b53116d9 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
@@ -10,8 +10,7 @@ var _ resourceid.Formatter = LoadBalancingId{}
 
 func TestLoadBalancingIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	frontDoorId := NewFrontDoorID("group1", "frontdoor1")
-	actual := NewLoadBalancingID(frontDoorId, "setting1").ID(subscriptionId)
+	actual := NewLoadBalancingID("group1", "frontdoor1", "setting1").ID(subscriptionId)
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule.go b/azurerm/internal/services/frontdoor/parse/routing_rule.go
index 688606a496e8..e982b29dcab0 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule.go
@@ -8,10 +8,10 @@ type RoutingRuleId struct {
 	Name          string
 }
 
-func NewRoutingRuleID(id FrontDoorId, name string) RoutingRuleId {
+func NewRoutingRuleID(resourceGroup, frontDoorName, name string) RoutingRuleId {
 	return RoutingRuleId{
-		ResourceGroup: id.ResourceGroup,
-		FrontDoorName: id.Name,
+		ResourceGroup: resourceGroup,
+		FrontDoorName: frontDoorName,
 		Name:          name,
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
index 9a3e5abf95fd..eb456537e46b 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
@@ -10,8 +10,7 @@ var _ resourceid.Formatter = RoutingRuleId{}
 
 func TestRoutingRuleIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	frontDoorId := NewFrontDoorID("group1", "frontdoor1")
-	actual := NewRoutingRuleID(frontDoorId, "rule1").ID(subscriptionId)
+	actual := NewRoutingRuleID("group1", "frontdoor1", "rule1").ID(subscriptionId)
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)

From fa5a536f81843a4386b43363c7b3226734f81153 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:32:30 +0100
Subject: [PATCH 02/24] frontdoor: adding subscriptionId as an argument to
 match the upcoming generated code

---
 azurerm/internal/services/frontdoor/parse/backend_pool.go     | 4 ++--
 .../internal/services/frontdoor/parse/backend_pool_test.go    | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor.go        | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor_test.go   | 2 +-
 .../internal/services/frontdoor/parse/frontend_endpoint.go    | 4 ++--
 .../services/frontdoor/parse/frontend_endpoint_test.go        | 2 +-
 azurerm/internal/services/frontdoor/parse/health_probe.go     | 4 ++--
 .../internal/services/frontdoor/parse/health_probe_test.go    | 2 +-
 azurerm/internal/services/frontdoor/parse/load_balancing.go   | 4 ++--
 .../internal/services/frontdoor/parse/load_balancing_test.go  | 2 +-
 azurerm/internal/services/frontdoor/parse/routing_rule.go     | 4 ++--
 .../internal/services/frontdoor/parse/routing_rule_test.go    | 2 +-
 .../frontdoor/parse/web_application_firewall_policy.go        | 2 +-
 .../frontdoor/parse/web_application_firewall_policy_test.go   | 2 +-
 14 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool.go b/azurerm/internal/services/frontdoor/parse/backend_pool.go
index 969256124c8b..44eddddb5982 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool.go
@@ -8,7 +8,7 @@ type BackendPoolId struct {
 	Name          string
 }
 
-func NewBackendPoolID(resourceGroup, frontDoorName, name string) BackendPoolId {
+func NewBackendPoolID(subscriptionId, resourceGroup, frontDoorName, name string) BackendPoolId {
 	return BackendPoolId{
 		ResourceGroup: resourceGroup,
 		FrontDoorName: frontDoorName,
@@ -17,7 +17,7 @@ func NewBackendPoolID(resourceGroup, frontDoorName, name string) BackendPoolId {
 }
 
 func (id BackendPoolId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
+	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
 	return fmt.Sprintf("%s/backendPools/%s", base, id.Name)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
index a3884da5de66..a93af1722f2c 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = BackendPoolId{}
 
 func TestBackendPoolIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewBackendPoolID("group1", "frontdoor1", "pool1").ID(subscriptionId)
+	actual := NewBackendPoolID(subscriptionId, "group1", "frontdoor1", "pool1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor.go b/azurerm/internal/services/frontdoor/parse/frontdoor.go
index 9172078ff58c..5c40b90ee44f 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor.go
@@ -12,7 +12,7 @@ type FrontDoorId struct {
 	ResourceGroup string
 }
 
-func NewFrontDoorID(resourceGroup, name string) FrontDoorId {
+func NewFrontDoorID(subscriptionId, resourceGroup, name string) FrontDoorId {
 	return FrontDoorId{
 		Name:          name,
 		ResourceGroup: resourceGroup,
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
index 3cc2cadcbb4e..6dfc1ec69c2a 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = FrontDoorId{}
 
 func TestFrontDoorIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewFrontDoorID("group1", "frontDoor1").ID(subscriptionId)
+	actual := NewFrontDoorID(subscriptionId, "group1", "frontDoor1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
index cf78af4db524..781aa8a4133d 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
@@ -8,7 +8,7 @@ type FrontendEndpointId struct {
 	Name          string
 }
 
-func NewFrontendEndpointID(resourceGroup, frontDoorName, name string) FrontendEndpointId {
+func NewFrontendEndpointID(subscriptionId, resourceGroup, frontDoorName, name string) FrontendEndpointId {
 	return FrontendEndpointId{
 		ResourceGroup: resourceGroup,
 		FrontDoorName: frontDoorName,
@@ -17,7 +17,7 @@ func NewFrontendEndpointID(resourceGroup, frontDoorName, name string) FrontendEn
 }
 
 func (id FrontendEndpointId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
+	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
 	return fmt.Sprintf("%s/frontendEndpoints/%s", base, id.Name)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
index 3a34f89bcc87..e1e110718080 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = FrontendEndpointId{}
 
 func TestFrontendEndpointIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewFrontendEndpointID("group1", "frontdoor1", "endpoint1").ID(subscriptionId)
+	actual := NewFrontendEndpointID(subscriptionId, "group1", "frontdoor1", "endpoint1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe.go b/azurerm/internal/services/frontdoor/parse/health_probe.go
index dd657ac7438c..a09a5c5b4719 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe.go
@@ -8,7 +8,7 @@ type HealthProbeId struct {
 	Name          string
 }
 
-func NewHealthProbeID(resourceGroup, frontDoorName, name string) HealthProbeId {
+func NewHealthProbeID(subscriptionId, resourceGroup, frontDoorName, name string) HealthProbeId {
 	return HealthProbeId{
 		ResourceGroup: resourceGroup,
 		FrontDoorName: frontDoorName,
@@ -17,7 +17,7 @@ func NewHealthProbeID(resourceGroup, frontDoorName, name string) HealthProbeId {
 }
 
 func (id HealthProbeId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
+	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
 	return fmt.Sprintf("%s/healthProbeSettings/%s", base, id.Name)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe_test.go b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
index 70fb9d6296f5..625b81063129 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe_test.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = HealthProbeId{}
 
 func TestHealthProbeIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewHealthProbeID("group1", "frontdoor1", "probe1").ID(subscriptionId)
+	actual := NewHealthProbeID(subscriptionId, "group1", "frontdoor1", "probe1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing.go b/azurerm/internal/services/frontdoor/parse/load_balancing.go
index 408aa7411092..df90bdf524a6 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing.go
@@ -8,7 +8,7 @@ type LoadBalancingId struct {
 	Name          string
 }
 
-func NewLoadBalancingID(resourceGroup, frontDoorName, name string) LoadBalancingId {
+func NewLoadBalancingID(subscriptionId, resourceGroup, frontDoorName, name string) LoadBalancingId {
 	return LoadBalancingId{
 		ResourceGroup: resourceGroup,
 		FrontDoorName: frontDoorName,
@@ -17,7 +17,7 @@ func NewLoadBalancingID(resourceGroup, frontDoorName, name string) LoadBalancing
 }
 
 func (id LoadBalancingId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
+	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
 	return fmt.Sprintf("%s/loadBalancingSettings/%s", base, id.Name)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
index 8ee9b53116d9..2bdb913f74d1 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = LoadBalancingId{}
 
 func TestLoadBalancingIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewLoadBalancingID("group1", "frontdoor1", "setting1").ID(subscriptionId)
+	actual := NewLoadBalancingID(subscriptionId, "group1", "frontdoor1", "setting1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule.go b/azurerm/internal/services/frontdoor/parse/routing_rule.go
index e982b29dcab0..f484d8a3a620 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule.go
@@ -8,7 +8,7 @@ type RoutingRuleId struct {
 	Name          string
 }
 
-func NewRoutingRuleID(resourceGroup, frontDoorName, name string) RoutingRuleId {
+func NewRoutingRuleID(subscriptionId, resourceGroup, frontDoorName, name string) RoutingRuleId {
 	return RoutingRuleId{
 		ResourceGroup: resourceGroup,
 		FrontDoorName: frontDoorName,
@@ -17,7 +17,7 @@ func NewRoutingRuleID(resourceGroup, frontDoorName, name string) RoutingRuleId {
 }
 
 func (id RoutingRuleId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
+	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
 	return fmt.Sprintf("%s/routingRules/%s", base, id.Name)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
index eb456537e46b..5b800c317710 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = RoutingRuleId{}
 
 func TestRoutingRuleIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewRoutingRuleID("group1", "frontdoor1", "rule1").ID(subscriptionId)
+	actual := NewRoutingRuleID(subscriptionId, "group1", "frontdoor1", "rule1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
index 5a320251078e..26935c9294bb 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
@@ -11,7 +11,7 @@ type WebApplicationFirewallPolicyId struct {
 	Name          string
 }
 
-func NewWebApplicationFirewallPolicyID(resourceGroup, name string) WebApplicationFirewallPolicyId {
+func NewWebApplicationFirewallPolicyID(subscriptionId, resourceGroup, name string) WebApplicationFirewallPolicyId {
 	return WebApplicationFirewallPolicyId{
 		ResourceGroup: resourceGroup,
 		Name:          name,
diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
index ff7a93df1595..9e75f70aa586 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
@@ -10,7 +10,7 @@ var _ resourceid.Formatter = WebApplicationFirewallPolicyId{}
 
 func TestWebApplicationFirewallPolicyIDFormatter(t *testing.T) {
 	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewWebApplicationFirewallPolicyID("group1", "policy1").ID(subscriptionId)
+	actual := NewWebApplicationFirewallPolicyID(subscriptionId, "group1", "policy1").ID("")
 	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)

From 9133376eea9c201bb9397e5ca8c818f19068cf1e Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:43:41 +0100
Subject: [PATCH 03/24] frontdoor: updating to match the updated method
 signature

---
 .../frontdoor_firewall_policy_resource.go     |  2 +-
 .../services/frontdoor/frontdoor_resource.go  | 34 +++++++++----------
 .../migration/custom_https_configuration.go   |  4 +--
 .../services/frontdoor/migration/frontdoor.go |  4 +--
 .../web_application_firewall_policy.go        |  4 +--
 .../services/frontdoor/parse/frontdoor.go     |  5 +--
 6 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
index 3da97c0e32cf..5dd1253bab79 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
@@ -443,7 +443,7 @@ func resourceFrontDoorFirewallPolicyCreateUpdate(d *schema.ResourceData, meta in
 
 	name := d.Get("name").(string)
 	resourceGroup := d.Get("resource_group_name").(string)
-	id := parse.NewWebApplicationFirewallPolicyID(resourceGroup, name).ID(subscriptionId)
+	id := parse.NewWebApplicationFirewallPolicyID(subscriptionId, resourceGroup, name).ID("")
 
 	if d.IsNewResource() {
 		existing, err := client.Get(ctx, resourceGroup, name)
diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 6cef3d35e3d8..09e18af01fa7 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -483,7 +483,7 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 	name := d.Get("name").(string)
 	resourceGroup := d.Get("resource_group_name").(string)
 	subscriptionId := meta.(*clients.Client).Account.SubscriptionId
-	frontDoorId := parse.NewFrontDoorID(resourceGroup, name)
+	frontDoorId := parse.NewFrontDoorID(subscriptionId, resourceGroup, name)
 
 	if d.IsNewResource() {
 		resp, err := client.Get(ctx, resourceGroup, name)
@@ -493,7 +493,7 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 			}
 		}
 		if !utils.ResponseWasNotFound(resp.Response) {
-			return tf.ImportAsExistsError("azurerm_frontdoor", frontDoorId.ID(subscriptionId))
+			return tf.ImportAsExistsError("azurerm_frontdoor", frontDoorId.ID(""))
 		}
 	}
 
@@ -554,7 +554,7 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 		return fmt.Errorf("waiting for creation of Front Door %q (Resource Group %q): %+v", name, resourceGroup, err)
 	}
 
-	d.SetId(frontDoorId.ID(subscriptionId))
+	d.SetId(frontDoorId.ID(""))
 
 	// Now loop through the FrontendEndpoints and enable/disable Custom Domain HTTPS
 	// on each individual Frontend Endpoint if required
@@ -574,7 +574,7 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 		if properties := resp.FrontendEndpointProperties; properties != nil {
 			frontendClient := meta.(*clients.Client).Frontdoor.FrontDoorsFrontendClient
 			customHttpsConfigurationNew := frontendEndpoint["custom_https_configuration"].([]interface{})
-			frontendInputId := parse.NewFrontendEndpointID(frontDoorId, endpointName)
+			frontendInputId := parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, endpointName)
 			input := customHttpsConfigurationUpdateInput{
 				customHttpsConfigurationCurrent: properties.CustomHTTPSConfiguration,
 				customHttpsConfigurationNew:     customHttpsConfigurationNew,
@@ -713,9 +713,9 @@ func expandFrontDoorBackendPools(input []interface{}, frontDoorId parse.FrontDoo
 
 		backends := backendPool["backend"].([]interface{})
 
-		backendPoolId := parse.NewBackendPoolID(frontDoorId, backendPoolName).ID(subscriptionId)
-		healthProbeId := parse.NewHealthProbeID(frontDoorId, backendPoolHealthProbeName).ID(subscriptionId)
-		loadBalancingId := parse.NewLoadBalancingID(frontDoorId, backendPoolLoadBalancingName).ID(subscriptionId)
+		backendPoolId := parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolName).ID("")
+		healthProbeId := parse.NewHealthProbeID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolHealthProbeName).ID("")
+		loadBalancingId := parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolLoadBalancingName).ID("")
 
 		result := frontdoor.BackendPool{
 			ID:   utils.String(backendPoolId),
@@ -809,7 +809,7 @@ func expandFrontDoorFrontendEndpoint(input []interface{}, frontDoorId parse.Fron
 		sessionAffinityTtlSeconds := int32(frontendEndpoint["session_affinity_ttl_seconds"].(int))
 		waf := frontendEndpoint["web_application_firewall_policy_link_id"].(string)
 		name := frontendEndpoint["name"].(string)
-		id := parse.NewFrontendEndpointID(frontDoorId, name).ID(subscriptionId)
+		id := parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name).ID("")
 
 		sessionAffinityEnabled := frontdoor.SessionAffinityEnabledStateDisabled
 		if isSessionAffinityEnabled {
@@ -859,7 +859,7 @@ func expandFrontDoorHealthProbeSettingsModel(input []interface{}, frontDoorId pa
 			healthProbeEnabled = frontdoor.HealthProbeEnabledDisabled
 		}
 
-		healthProbeId := parse.NewHealthProbeID(frontDoorId, name).ID(subscriptionId)
+		healthProbeId := parse.NewHealthProbeID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name).ID("")
 
 		result := frontdoor.HealthProbeSettingsModel{
 			ID:   utils.String(healthProbeId),
@@ -893,7 +893,7 @@ func expandFrontDoorLoadBalancingSettingsModel(input []interface{}, frontDoorId
 		sampleSize := int32(loadBalanceSetting["sample_size"].(int))
 		successfulSamplesRequired := int32(loadBalanceSetting["successful_samples_required"].(int))
 		additionalLatencyMilliseconds := int32(loadBalanceSetting["additional_latency_milliseconds"].(int))
-		loadBalancingId := parse.NewLoadBalancingID(frontDoorId, name).ID(subscriptionId)
+		loadBalancingId := parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name).ID(subscriptionId)
 
 		result := frontdoor.LoadBalancingSettingsModel{
 			ID:   utils.String(loadBalancingId),
@@ -986,7 +986,7 @@ func expandFrontDoorFrontEndEndpoints(input []interface{}, frontDoorId parse.Fro
 
 	output := make([]frontdoor.SubResource, 0)
 	for _, name := range input {
-		frontendEndpointId := parse.NewFrontendEndpointID(frontDoorId, name.(string)).ID(subscriptionId)
+		frontendEndpointId := parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name.(string)).ID(subscriptionId)
 		result := frontdoor.SubResource{
 			ID: utils.String(frontendEndpointId),
 		}
@@ -1055,7 +1055,7 @@ func expandFrontDoorForwardingConfiguration(input []interface{}, frontDoorId par
 	cacheQueryParameterStripDirective := v["cache_query_parameter_strip_directive"].(string)
 	cacheEnabled := v["cache_enabled"].(bool)
 
-	backendPoolId := parse.NewBackendPoolID(frontDoorId, backendPoolName).ID(subscriptionId)
+	backendPoolId := parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolName).ID(subscriptionId)
 	backend := &frontdoor.SubResource{
 		ID: utils.String(backendPoolId),
 	}
@@ -1104,7 +1104,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewBackendPoolID(frontDoorId, *v.Name).ID(subscriptionId)
+			id = parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
 			name = *v.Name
 		}
 
@@ -1249,7 +1249,7 @@ func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId p
 		name := ""
 		if item.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewFrontendEndpointID(frontDoorId, *item.Name).ID(subscriptionId)
+			id = parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *item.Name).ID("")
 			name = *item.Name
 		}
 
@@ -1313,7 +1313,7 @@ func flattenFrontDoorHealthProbeSettingsModel(input *[]frontdoor.HealthProbeSett
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewHealthProbeID(frontDoorId, *v.Name).ID(subscriptionId)
+			id = parse.NewHealthProbeID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
 			name = *v.Name
 		}
 
@@ -1365,7 +1365,7 @@ func flattenFrontDoorLoadBalancingSettingsModel(input *[]frontdoor.LoadBalancing
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewLoadBalancingID(frontDoorId, *v.Name).ID(subscriptionId)
+			id = parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
 			name = *v.Name
 		}
 
@@ -1407,7 +1407,7 @@ func flattenFrontDoorRoutingRule(input *[]frontdoor.RoutingRule, oldBlocks inter
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewRoutingRuleID(frontDoorId, *v.Name).ID(subscriptionId)
+			id = parse.NewRoutingRuleID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
 			name = *v.Name
 		}
 
diff --git a/azurerm/internal/services/frontdoor/migration/custom_https_configuration.go b/azurerm/internal/services/frontdoor/migration/custom_https_configuration.go
index 615d45e6710b..aebc66c4d458 100644
--- a/azurerm/internal/services/frontdoor/migration/custom_https_configuration.go
+++ b/azurerm/internal/services/frontdoor/migration/custom_https_configuration.go
@@ -101,8 +101,8 @@ func CustomHttpsConfigurationV0ToV1(rawState map[string]interface{}, _ interface
 		return rawState, fmt.Errorf("couldn't find the `frontendEndpoints` segment in the old resource id %q", oldId)
 	}
 
-	newId := parse.NewFrontendEndpointID(parse.NewFrontDoorID(resourceGroup, frontdoorName), frontendEndpointName)
-	newIdStr := newId.ID(oldParsedId.SubscriptionID)
+	newId := parse.NewFrontendEndpointID(oldParsedId.SubscriptionID, resourceGroup, frontdoorName, frontendEndpointName)
+	newIdStr := newId.ID("")
 
 	log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newIdStr)
 
diff --git a/azurerm/internal/services/frontdoor/migration/frontdoor.go b/azurerm/internal/services/frontdoor/migration/frontdoor.go
index 03c3da93f5cc..1ce8bd47b574 100644
--- a/azurerm/internal/services/frontdoor/migration/frontdoor.go
+++ b/azurerm/internal/services/frontdoor/migration/frontdoor.go
@@ -411,8 +411,8 @@ func FrontDoorV1ToV2(rawState map[string]interface{}, _ interface{}) (map[string
 		return rawState, fmt.Errorf("couldn't find the `frontDoors` segment in the old resource id %q", oldId)
 	}
 
-	newId := parse.NewFrontDoorID(resourceGroup, frontDoorName)
-	newIdStr := newId.ID(oldParsedId.SubscriptionID)
+	newId := parse.NewFrontDoorID(oldParsedId.SubscriptionID, resourceGroup, frontDoorName)
+	newIdStr := newId.ID("")
 
 	log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newIdStr)
 
diff --git a/azurerm/internal/services/frontdoor/migration/web_application_firewall_policy.go b/azurerm/internal/services/frontdoor/migration/web_application_firewall_policy.go
index 8ce58425391c..3dc5436f622c 100644
--- a/azurerm/internal/services/frontdoor/migration/web_application_firewall_policy.go
+++ b/azurerm/internal/services/frontdoor/migration/web_application_firewall_policy.go
@@ -308,8 +308,8 @@ func WebApplicationFirewallPolicyV0ToV1(rawState map[string]interface{}, _ inter
 		return rawState, fmt.Errorf("couldn't find the `frontDoorWebApplicationFirewallPolicies` segment in the old resource id %q", oldId)
 	}
 
-	newId := parse.NewWebApplicationFirewallPolicyID(resourceGroup, policyName)
-	newIdStr := newId.ID(oldParsedId.SubscriptionID)
+	newId := parse.NewWebApplicationFirewallPolicyID(oldParsedId.SubscriptionID, resourceGroup, policyName)
+	newIdStr := newId.ID("")
 
 	log.Printf("[DEBUG] Updating ID from %q to %q", oldId, newIdStr)
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor.go b/azurerm/internal/services/frontdoor/parse/frontdoor.go
index 5c40b90ee44f..f3ac6380caf3 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor.go
@@ -8,8 +8,9 @@ import (
 )
 
 type FrontDoorId struct {
-	Name          string
-	ResourceGroup string
+	SubscriptionId string
+	Name           string
+	ResourceGroup  string
 }
 
 func NewFrontDoorID(subscriptionId, resourceGroup, name string) FrontDoorId {

From 0359fd5cd047975dbb9ee8e89cdbe663bb5e8852 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:48:35 +0100
Subject: [PATCH 04/24] frontdoor: removing the direct dependency on
 subscriptionId

This enables this to be threaded through directly from the FrontDoor ID
---
 .../services/frontdoor/frontdoor_resource.go  | 65 +++++++++----------
 1 file changed, 32 insertions(+), 33 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 09e18af01fa7..6ce2f2cea01b 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -535,12 +535,12 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 		Location: utils.String(location),
 		Properties: &frontdoor.Properties{
 			FriendlyName:          utils.String(friendlyName),
-			RoutingRules:          expandFrontDoorRoutingRule(routingRules, frontDoorId, subscriptionId),
-			BackendPools:          expandFrontDoorBackendPools(backendPools, frontDoorId, subscriptionId),
+			RoutingRules:          expandFrontDoorRoutingRule(routingRules, frontDoorId),
+			BackendPools:          expandFrontDoorBackendPools(backendPools, frontDoorId),
 			BackendPoolsSettings:  expandFrontDoorBackendPoolsSettings(backendPoolsSettings, backendPoolsSendReceiveTimeoutSeconds),
-			FrontendEndpoints:     expandFrontDoorFrontendEndpoint(frontendEndpoints, frontDoorId, subscriptionId),
-			HealthProbeSettings:   expandFrontDoorHealthProbeSettingsModel(healthProbeSettings, frontDoorId, subscriptionId),
-			LoadBalancingSettings: expandFrontDoorLoadBalancingSettingsModel(loadBalancingSettings, frontDoorId, subscriptionId),
+			FrontendEndpoints:     expandFrontDoorFrontendEndpoint(frontendEndpoints, frontDoorId),
+			HealthProbeSettings:   expandFrontDoorHealthProbeSettingsModel(healthProbeSettings, frontDoorId),
+			LoadBalancingSettings: expandFrontDoorLoadBalancingSettingsModel(loadBalancingSettings, frontDoorId),
 			EnabledState:          expandFrontDoorEnabledState(enabledState),
 		},
 		Tags: tags.Expand(t),
@@ -594,7 +594,6 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 
 func resourceFrontDoorRead(d *schema.ResourceData, meta interface{}) error {
 	client := meta.(*clients.Client).Frontdoor.FrontDoorsClient
-	subscriptionId := meta.(*clients.Client).Account.SubscriptionId
 	ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
@@ -618,7 +617,7 @@ func resourceFrontDoorRead(d *schema.ResourceData, meta interface{}) error {
 	d.Set("location", azure.NormalizeLocation(*resp.Location))
 
 	if props := resp.Properties; props != nil {
-		flattenedBackendPools, err := flattenFrontDoorBackendPools(props.BackendPools, *id, subscriptionId)
+		flattenedBackendPools, err := flattenFrontDoorBackendPools(props.BackendPools, *id)
 		if err != nil {
 			return fmt.Errorf("flattening `backend_pool`: %+v", err)
 		}
@@ -642,7 +641,7 @@ func resourceFrontDoorRead(d *schema.ResourceData, meta interface{}) error {
 		if err != nil {
 			return fmt.Errorf("retrieving FrontEnd Endpoint Custom HTTPS Information: %+v", err)
 		}
-		frontDoorFrontendEndpoints, err := flattenFrontEndEndpoints(frontEndEndpointInfo, *id, subscriptionId)
+		frontDoorFrontendEndpoints, err := flattenFrontEndEndpoints(frontEndEndpointInfo, *id)
 		if err != nil {
 			return fmt.Errorf("flattening `frontend_endpoint`: %+v", err)
 		}
@@ -650,15 +649,15 @@ func resourceFrontDoorRead(d *schema.ResourceData, meta interface{}) error {
 			return fmt.Errorf("setting `frontend_endpoint`: %+v", err)
 		}
 
-		if err := d.Set("backend_pool_health_probe", flattenFrontDoorHealthProbeSettingsModel(props.HealthProbeSettings, *id, subscriptionId)); err != nil {
+		if err := d.Set("backend_pool_health_probe", flattenFrontDoorHealthProbeSettingsModel(props.HealthProbeSettings, *id)); err != nil {
 			return fmt.Errorf("setting `backend_pool_health_probe`: %+v", err)
 		}
 
-		if err := d.Set("backend_pool_load_balancing", flattenFrontDoorLoadBalancingSettingsModel(props.LoadBalancingSettings, *id, subscriptionId)); err != nil {
+		if err := d.Set("backend_pool_load_balancing", flattenFrontDoorLoadBalancingSettingsModel(props.LoadBalancingSettings, *id)); err != nil {
 			return fmt.Errorf("setting `backend_pool_load_balancing`: %+v", err)
 		}
 
-		flattenedRoutingRules, err := flattenFrontDoorRoutingRule(props.RoutingRules, d.Get("routing_rule"), *id, subscriptionId)
+		flattenedRoutingRules, err := flattenFrontDoorRoutingRule(props.RoutingRules, d.Get("routing_rule"), *id)
 		if err != nil {
 			return fmt.Errorf("flattening `routing_rules`: %+v", err)
 		}
@@ -697,7 +696,7 @@ func resourceFrontDoorDelete(d *schema.ResourceData, meta interface{}) error {
 	return nil
 }
 
-func expandFrontDoorBackendPools(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.BackendPool {
+func expandFrontDoorBackendPools(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.BackendPool {
 	if len(input) == 0 {
 		return &[]frontdoor.BackendPool{}
 	}
@@ -794,7 +793,7 @@ func expandFrontDoorBackendPoolsSettings(enforceCertificateNameCheck bool, backe
 	return &result
 }
 
-func expandFrontDoorFrontendEndpoint(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.FrontendEndpoint {
+func expandFrontDoorFrontendEndpoint(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.FrontendEndpoint {
 	if len(input) == 0 {
 		return &[]frontdoor.FrontendEndpoint{}
 	}
@@ -838,7 +837,7 @@ func expandFrontDoorFrontendEndpoint(input []interface{}, frontDoorId parse.Fron
 	return &output
 }
 
-func expandFrontDoorHealthProbeSettingsModel(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.HealthProbeSettingsModel {
+func expandFrontDoorHealthProbeSettingsModel(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.HealthProbeSettingsModel {
 	if len(input) == 0 {
 		return &[]frontdoor.HealthProbeSettingsModel{}
 	}
@@ -879,7 +878,7 @@ func expandFrontDoorHealthProbeSettingsModel(input []interface{}, frontDoorId pa
 	return &output
 }
 
-func expandFrontDoorLoadBalancingSettingsModel(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.LoadBalancingSettingsModel {
+func expandFrontDoorLoadBalancingSettingsModel(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.LoadBalancingSettingsModel {
 	if len(input) == 0 {
 		return &[]frontdoor.LoadBalancingSettingsModel{}
 	}
@@ -893,7 +892,7 @@ func expandFrontDoorLoadBalancingSettingsModel(input []interface{}, frontDoorId
 		sampleSize := int32(loadBalanceSetting["sample_size"].(int))
 		successfulSamplesRequired := int32(loadBalanceSetting["successful_samples_required"].(int))
 		additionalLatencyMilliseconds := int32(loadBalanceSetting["additional_latency_milliseconds"].(int))
-		loadBalancingId := parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name).ID(subscriptionId)
+		loadBalancingId := parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name).ID("")
 
 		result := frontdoor.LoadBalancingSettingsModel{
 			ID:   utils.String(loadBalancingId),
@@ -911,7 +910,7 @@ func expandFrontDoorLoadBalancingSettingsModel(input []interface{}, frontDoorId
 	return &output
 }
 
-func expandFrontDoorRoutingRule(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.RoutingRule {
+func expandFrontDoorRoutingRule(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.RoutingRule {
 	if len(input) == 0 {
 		return nil
 	}
@@ -939,14 +938,14 @@ func expandFrontDoorRoutingRule(input []interface{}, frontDoorId parse.FrontDoor
 		if rc := routingRule["redirect_configuration"].([]interface{}); len(rc) != 0 {
 			routingConfiguration = expandFrontDoorRedirectConfiguration(rc)
 		} else if fc := routingRule["forwarding_configuration"].([]interface{}); len(fc) != 0 {
-			routingConfiguration = expandFrontDoorForwardingConfiguration(fc, frontDoorId, subscriptionId)
+			routingConfiguration = expandFrontDoorForwardingConfiguration(fc, frontDoorId)
 		}
 
 		currentRoutingRule := frontdoor.RoutingRule{
 			ID:   utils.String(id),
 			Name: utils.String(name),
 			RoutingRuleProperties: &frontdoor.RoutingRuleProperties{
-				FrontendEndpoints:  expandFrontDoorFrontEndEndpoints(frontendEndpoints, frontDoorId, subscriptionId),
+				FrontendEndpoints:  expandFrontDoorFrontEndEndpoints(frontendEndpoints, frontDoorId),
 				AcceptedProtocols:  expandFrontDoorAcceptedProtocols(acceptedProtocols),
 				PatternsToMatch:    &patternsToMatch,
 				EnabledState:       frontdoor.RoutingRuleEnabledState(expandFrontDoorEnabledState(enabled)),
@@ -979,14 +978,14 @@ func expandFrontDoorAcceptedProtocols(input []interface{}) *[]frontdoor.Protocol
 	return &output
 }
 
-func expandFrontDoorFrontEndEndpoints(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) *[]frontdoor.SubResource {
+func expandFrontDoorFrontEndEndpoints(input []interface{}, frontDoorId parse.FrontDoorId) *[]frontdoor.SubResource {
 	if len(input) == 0 {
 		return &[]frontdoor.SubResource{}
 	}
 
 	output := make([]frontdoor.SubResource, 0)
 	for _, name := range input {
-		frontendEndpointId := parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name.(string)).ID(subscriptionId)
+		frontendEndpointId := parse.NewFrontendEndpointID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, name.(string)).ID("")
 		result := frontdoor.SubResource{
 			ID: utils.String(frontendEndpointId),
 		}
@@ -1042,7 +1041,7 @@ func expandFrontDoorRedirectConfiguration(input []interface{}) frontdoor.Redirec
 	return redirectConfiguration
 }
 
-func expandFrontDoorForwardingConfiguration(input []interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) frontdoor.ForwardingConfiguration {
+func expandFrontDoorForwardingConfiguration(input []interface{}, frontDoorId parse.FrontDoorId) frontdoor.ForwardingConfiguration {
 	if len(input) == 0 {
 		return frontdoor.ForwardingConfiguration{}
 	}
@@ -1055,7 +1054,7 @@ func expandFrontDoorForwardingConfiguration(input []interface{}, frontDoorId par
 	cacheQueryParameterStripDirective := v["cache_query_parameter_strip_directive"].(string)
 	cacheEnabled := v["cache_enabled"].(bool)
 
-	backendPoolId := parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolName).ID(subscriptionId)
+	backendPoolId := parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, backendPoolName).ID("")
 	backend := &frontdoor.SubResource{
 		ID: utils.String(backendPoolId),
 	}
@@ -1093,7 +1092,7 @@ func expandFrontDoorForwardingConfiguration(input []interface{}, frontDoorId par
 	return forwardingConfiguration
 }
 
-func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId parse.FrontDoorId, subscriptionId string) (*[]interface{}, error) {
+func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId parse.FrontDoorId) (*[]interface{}, error) {
 	if input == nil {
 		return &[]interface{}{}, nil
 	}
@@ -1104,7 +1103,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
+			id = parse.NewBackendPoolID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID("")
 			name = *v.Name
 		}
 
@@ -1238,7 +1237,7 @@ func retrieveFrontEndEndpointInformation(ctx context.Context, client *frontdoor.
 	return &output, nil
 }
 
-func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId parse.FrontDoorId, subscriptionId string) (*[]interface{}, error) {
+func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId parse.FrontDoorId) (*[]interface{}, error) {
 	results := make([]interface{}, 0)
 	if input == nil {
 		return &results, nil
@@ -1279,7 +1278,7 @@ func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId p
 					return nil, err
 				}
 
-				webApplicationFirewallPolicyLinkId = parsed.ID(subscriptionId)
+				webApplicationFirewallPolicyLinkId = parsed.ID("")
 			}
 
 			flattenedHttpsConfig := flattenCustomHttpsConfiguration(props)
@@ -1302,7 +1301,7 @@ func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId p
 	return &results, nil
 }
 
-func flattenFrontDoorHealthProbeSettingsModel(input *[]frontdoor.HealthProbeSettingsModel, frontDoorId parse.FrontDoorId, subscriptionId string) []interface{} {
+func flattenFrontDoorHealthProbeSettingsModel(input *[]frontdoor.HealthProbeSettingsModel, frontDoorId parse.FrontDoorId) []interface{} {
 	results := make([]interface{}, 0)
 	if input == nil {
 		return results
@@ -1313,7 +1312,7 @@ func flattenFrontDoorHealthProbeSettingsModel(input *[]frontdoor.HealthProbeSett
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewHealthProbeID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
+			id = parse.NewHealthProbeID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID("")
 			name = *v.Name
 		}
 
@@ -1354,7 +1353,7 @@ func flattenFrontDoorHealthProbeSettingsModel(input *[]frontdoor.HealthProbeSett
 	return results
 }
 
-func flattenFrontDoorLoadBalancingSettingsModel(input *[]frontdoor.LoadBalancingSettingsModel, frontDoorId parse.FrontDoorId, subscriptionId string) []interface{} {
+func flattenFrontDoorLoadBalancingSettingsModel(input *[]frontdoor.LoadBalancingSettingsModel, frontDoorId parse.FrontDoorId) []interface{} {
 	results := make([]interface{}, 0)
 	if input == nil {
 		return results
@@ -1365,7 +1364,7 @@ func flattenFrontDoorLoadBalancingSettingsModel(input *[]frontdoor.LoadBalancing
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
+			id = parse.NewLoadBalancingID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID("")
 			name = *v.Name
 		}
 
@@ -1396,7 +1395,7 @@ func flattenFrontDoorLoadBalancingSettingsModel(input *[]frontdoor.LoadBalancing
 	return results
 }
 
-func flattenFrontDoorRoutingRule(input *[]frontdoor.RoutingRule, oldBlocks interface{}, frontDoorId parse.FrontDoorId, subscriptionId string) (*[]interface{}, error) {
+func flattenFrontDoorRoutingRule(input *[]frontdoor.RoutingRule, oldBlocks interface{}, frontDoorId parse.FrontDoorId) (*[]interface{}, error) {
 	if input == nil {
 		return &[]interface{}{}, nil
 	}
@@ -1407,7 +1406,7 @@ func flattenFrontDoorRoutingRule(input *[]frontdoor.RoutingRule, oldBlocks inter
 		name := ""
 		if v.Name != nil {
 			// rewrite the ID to ensure it's consistent
-			id = parse.NewRoutingRuleID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID(subscriptionId)
+			id = parse.NewRoutingRuleID(frontDoorId.SubscriptionId, frontDoorId.ResourceGroup, frontDoorId.Name, *v.Name).ID("")
 			name = *v.Name
 		}
 

From 246388ad2106cbe4ec754047c661f904cbe2a1eb Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:51:01 +0100
Subject: [PATCH 05/24] frontdoor: removing the direct dependency on
 subscriptionId

---
 .../frontdoor_custom_https_configuration_resource.go | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
index bbf6e09b5094..3898f413ad9c 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
@@ -79,7 +79,6 @@ func resourceFrontDoorCustomHttpsConfiguration() *schema.Resource {
 
 func resourceFrontDoorCustomHttpsConfigurationCreateUpdate(d *schema.ResourceData, meta interface{}) error {
 	client := meta.(*clients.Client).Frontdoor.FrontDoorsFrontendClient
-	subscriptionId := meta.(*clients.Client).Account.SubscriptionId
 	ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
@@ -106,14 +105,13 @@ func resourceFrontDoorCustomHttpsConfigurationCreateUpdate(d *schema.ResourceDat
 		customHttpsProvisioningEnabled:  d.Get("custom_https_provisioning_enabled").(bool),
 		frontendEndpointId:              *id,
 		provisioningState:               props.CustomHTTPSProvisioningState,
-		subscriptionId:                  subscriptionId,
 	}
 	if err := updateCustomHttpsConfiguration(ctx, client, input); err != nil {
 		return fmt.Errorf("updating Custom HTTPS configuration for Frontend Endpoint %q (Front Door %q / Resource Group %q): %+v", id.Name, id.FrontDoorName, id.ResourceGroup, err)
 	}
 
 	if d.IsNewResource() {
-		d.SetId(id.ID(subscriptionId))
+		d.SetId(id.ID(""))
 	}
 
 	return resourceFrontDoorCustomHttpsConfigurationRead(d, meta)
@@ -121,7 +119,6 @@ func resourceFrontDoorCustomHttpsConfigurationCreateUpdate(d *schema.ResourceDat
 
 func resourceFrontDoorCustomHttpsConfigurationRead(d *schema.ResourceData, meta interface{}) error {
 	client := meta.(*clients.Client).Frontdoor.FrontDoorsFrontendClient
-	subscriptionId := meta.(*clients.Client).Account.SubscriptionId
 	ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
@@ -141,7 +138,7 @@ func resourceFrontDoorCustomHttpsConfigurationRead(d *schema.ResourceData, meta
 		return fmt.Errorf("reading Front Door Endpoint %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
 	}
 
-	d.Set("frontend_endpoint_id", id.ID(subscriptionId))
+	d.Set("frontend_endpoint_id", id.ID(""))
 	d.Set("resource_group_name", id.ResourceGroup)
 
 	flattenedHttpsConfig := flattenCustomHttpsConfiguration(resp.FrontendEndpointProperties)
@@ -157,7 +154,6 @@ func resourceFrontDoorCustomHttpsConfigurationRead(d *schema.ResourceData, meta
 
 func resourceFrontDoorCustomHttpsConfigurationDelete(d *schema.ResourceData, meta interface{}) error {
 	client := meta.(*clients.Client).Frontdoor.FrontDoorsFrontendClient
-	subscriptionId := meta.(*clients.Client).Account.SubscriptionId
 	ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
@@ -185,7 +181,6 @@ func resourceFrontDoorCustomHttpsConfigurationDelete(d *schema.ResourceData, met
 		customHttpsProvisioningEnabled:  false,
 		frontendEndpointId:              *id,
 		provisioningState:               props.CustomHTTPSProvisioningState,
-		subscriptionId:                  subscriptionId,
 	}
 	if err := updateCustomHttpsConfiguration(ctx, client, input); err != nil {
 		return fmt.Errorf("disabling Custom HTTPS configuration for Frontend Endpoint %q (Front Door %q / Resource Group %q): %+v", id.Name, id.FrontDoorName, id.ResourceGroup, err)
@@ -200,12 +195,11 @@ type customHttpsConfigurationUpdateInput struct {
 	customHttpsProvisioningEnabled  bool
 	frontendEndpointId              parse.FrontendEndpointId
 	provisioningState               frontdoor.CustomHTTPSProvisioningState
-	subscriptionId                  string
 }
 
 func updateCustomHttpsConfiguration(ctx context.Context, client *frontdoor.FrontendEndpointsClient, input customHttpsConfigurationUpdateInput) error {
 	// Locking to prevent parallel changes causing issues
-	frontendEndpointResourceId := input.frontendEndpointId.ID(input.subscriptionId)
+	frontendEndpointResourceId := input.frontendEndpointId.ID("")
 	locks.ByID(frontendEndpointResourceId)
 	defer locks.UnlockByID(frontendEndpointResourceId)
 

From 3834494b0c2662fcc34fb82f189ee0201c53aa6c Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:52:10 +0100
Subject: [PATCH 06/24] frontdoor: refactoring/renaming the existing
 BackendPoolID method to match the upcoming generated name

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/backend_pool.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/backend_pool_test.go | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 6ce2f2cea01b..3f939f828792 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1461,7 +1461,7 @@ func flattenRoutingRuleForwardingConfiguration(config frontdoor.BasicRouteConfig
 
 	name := ""
 	if v.BackendPool != nil && v.BackendPool.ID != nil {
-		backendPoolId, err := parse.BackendPoolID(*v.BackendPool.ID)
+		backendPoolId, err := parse.BackendPoolIDInsensitively(*v.BackendPool.ID)
 		if err != nil {
 			return nil, err
 		}
diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool.go b/azurerm/internal/services/frontdoor/parse/backend_pool.go
index 44eddddb5982..77d0cd63aba1 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool.go
@@ -21,7 +21,7 @@ func (id BackendPoolId) ID(subscriptionId string) string {
 	return fmt.Sprintf("%s/backendPools/%s", base, id.Name)
 }
 
-func BackendPoolID(input string) (*BackendPoolId, error) {
+func BackendPoolIDInsensitively(input string) (*BackendPoolId, error) {
 	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing Backend Pool ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
index a93af1722f2c..04ab4dbac1be 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
@@ -57,7 +57,7 @@ func TestBackendPoolIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := BackendPoolID(test.input)
+		actual, err := BackendPoolIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From a27cb0d646407c70fe260cb2d431ce267a955752 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:54:22 +0100
Subject: [PATCH 07/24] frontdoor: updating to match the upcoming generated
 names

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go     | 4 ++--
 .../internal/services/frontdoor/frontdoor_resource_test.go    | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor.go        | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor_test.go   | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 3f939f828792..d2caf41d225a 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -597,7 +597,7 @@ func resourceFrontDoorRead(d *schema.ResourceData, meta interface{}) error {
 	ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.FrontDoorID(d.Id())
+	id, err := parse.FrontDoorIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
@@ -674,7 +674,7 @@ func resourceFrontDoorDelete(d *schema.ResourceData, meta interface{}) error {
 	ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.FrontDoorID(d.Id())
+	id, err := parse.FrontDoorIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource_test.go b/azurerm/internal/services/frontdoor/frontdoor_resource_test.go
index 477c10ddd28b..6e27cb7225ac 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource_test.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource_test.go
@@ -209,7 +209,7 @@ func TestAccFrontDoor_CustomHttps(t *testing.T) {
 }
 
 func (FrontDoorResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
-	id, err := parse.FrontDoorID(state.ID)
+	id, err := parse.FrontDoorIDInsensitively(state.ID)
 	if err != nil {
 		return nil, err
 	}
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor.go b/azurerm/internal/services/frontdoor/parse/frontdoor.go
index f3ac6380caf3..2d7829519504 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor.go
@@ -20,7 +20,7 @@ func NewFrontDoorID(subscriptionId, resourceGroup, name string) FrontDoorId {
 	}
 }
 
-func FrontDoorID(input string) (*FrontDoorId, error) {
+func FrontDoorIDInsensitively(input string) (*FrontDoorId, error) {
 	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing FrontDoor ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
index 6dfc1ec69c2a..4160e6e24501 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
@@ -57,7 +57,7 @@ func TestFrontDoorIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := FrontDoorID(test.input)
+		actual, err := FrontDoorIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From 43eaf2900f573d982201fc6375de4c9745116391 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:55:00 +0100
Subject: [PATCH 08/24] frontdoor: updating to match the generated name for the
 strict method

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go   | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/frontdoor_test.go | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index d2caf41d225a..5605fab6a95c 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -31,7 +31,7 @@ func resourceFrontDoor() *schema.Resource {
 		Delete: resourceFrontDoorDelete,
 
 		Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
-			_, err := parse.FrontDoorIDForImport(id)
+			_, err := parse.FrontDoorID(id)
 			return err
 		}),
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor.go b/azurerm/internal/services/frontdoor/parse/frontdoor.go
index 2d7829519504..c329d1eb2718 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor.go
@@ -33,7 +33,7 @@ func FrontDoorIDInsensitively(input string) (*FrontDoorId, error) {
 	return frontDoorId, nil
 }
 
-func FrontDoorIDForImport(input string) (*FrontDoorId, error) {
+func FrontDoorID(input string) (*FrontDoorId, error) {
 	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing FrontDoor ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
index 4160e6e24501..a99fe9965177 100644
--- a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontdoor_test.go
@@ -109,7 +109,7 @@ func TestFrontDoorIDForImportParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := FrontDoorIDForImport(test.input)
+		actual, err := FrontDoorID(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From d809c2c0841e8fdd06997ce03cce7f4f5089932f Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:56:29 +0100
Subject: [PATCH 09/24] frontdoor: updating to match the generated name

---
 .../frontdoor_custom_https_configuration_resource.go        | 6 +++---
 .../frontdoor_custom_https_configuration_resource_test.go   | 2 +-
 azurerm/internal/services/frontdoor/frontdoor_resource.go   | 2 +-
 .../internal/services/frontdoor/parse/frontend_endpoint.go  | 2 +-
 .../services/frontdoor/parse/frontend_endpoint_test.go      | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
index 3898f413ad9c..96307721d3d1 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
@@ -82,7 +82,7 @@ func resourceFrontDoorCustomHttpsConfigurationCreateUpdate(d *schema.ResourceDat
 	ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.FrontendEndpointID(d.Get("frontend_endpoint_id").(string))
+	id, err := parse.FrontendEndpointIDInsensitively(d.Get("frontend_endpoint_id").(string))
 	if err != nil {
 		return err
 	}
@@ -122,7 +122,7 @@ func resourceFrontDoorCustomHttpsConfigurationRead(d *schema.ResourceData, meta
 	ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.FrontendEndpointID(d.Id())
+	id, err := parse.FrontendEndpointIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
@@ -157,7 +157,7 @@ func resourceFrontDoorCustomHttpsConfigurationDelete(d *schema.ResourceData, met
 	ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.FrontendEndpointID(d.Id())
+	id, err := parse.FrontendEndpointIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go
index 22a03763c27e..dcfae37ca338 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go
@@ -40,7 +40,7 @@ func TestAccFrontDoorCustomHttpsConfiguration_CustomHttps(t *testing.T) {
 }
 
 func (FrontDoorCustomHttpsConfigurationResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
-	id, err := parse.FrontendEndpointID(state.ID)
+	id, err := parse.FrontendEndpointIDInsensitively(state.ID)
 	if err != nil {
 		return nil, err
 	}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 5605fab6a95c..8ec381a1b77b 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1583,7 +1583,7 @@ func flattenFrontDoorFrontendEndpointsSubResources(input *[]frontdoor.SubResourc
 			continue
 		}
 
-		id, err := parse.FrontendEndpointID(*v.ID)
+		id, err := parse.FrontendEndpointIDInsensitively(*v.ID)
 		if err != nil {
 			return nil, err
 		}
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
index 781aa8a4133d..469fc8f1baeb 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
@@ -21,7 +21,7 @@ func (id FrontendEndpointId) ID(subscriptionId string) string {
 	return fmt.Sprintf("%s/frontendEndpoints/%s", base, id.Name)
 }
 
-func FrontendEndpointID(input string) (*FrontendEndpointId, error) {
+func FrontendEndpointIDInsensitively(input string) (*FrontendEndpointId, error) {
 	return parseFrontendEndpointID(input, false)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
index e1e110718080..929390229f7d 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
@@ -53,7 +53,7 @@ func TestFrontendEndpointIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := FrontendEndpointID(test.input)
+		actual, err := FrontendEndpointIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From 0b8c7977bab8185cbe5f8fa1a0e24f419a3bdd70 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:57:13 +0100
Subject: [PATCH 10/24] frontdoor_frontend_endpoint: updating to use the
 generated method name for the strict method

---
 azurerm/internal/services/frontdoor/customizediff.go            | 2 +-
 .../frontdoor/frontdoor_custom_https_configuration_resource.go  | 2 +-
 azurerm/internal/services/frontdoor/parse/frontend_endpoint.go  | 2 +-
 .../internal/services/frontdoor/parse/frontend_endpoint_test.go | 2 +-
 .../services/frontdoor/validate/frontend_endpoint_id.go         | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/customizediff.go b/azurerm/internal/services/frontdoor/customizediff.go
index a78181b6d8d2..0ee628676596 100644
--- a/azurerm/internal/services/frontdoor/customizediff.go
+++ b/azurerm/internal/services/frontdoor/customizediff.go
@@ -11,7 +11,7 @@ import (
 
 func customizeHttpsConfigurationCustomizeDiff(d *schema.ResourceDiff, v interface{}) error {
 	if v, ok := d.GetOk("frontend_endpoint_id"); ok && v.(string) != "" {
-		id, err := parse.FrontendEndpointIDForImport(v.(string))
+		id, err := parse.FrontendEndpointID(v.(string))
 		if err != nil {
 			return err
 		}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
index 96307721d3d1..19573d9f3741 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go
@@ -27,7 +27,7 @@ func resourceFrontDoorCustomHttpsConfiguration() *schema.Resource {
 		Delete: resourceFrontDoorCustomHttpsConfigurationDelete,
 
 		Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
-			_, err := parse.FrontendEndpointIDForImport(id)
+			_, err := parse.FrontendEndpointID(id)
 			return err
 		}),
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
index 469fc8f1baeb..6b5553d0d0b7 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
@@ -25,7 +25,7 @@ func FrontendEndpointIDInsensitively(input string) (*FrontendEndpointId, error)
 	return parseFrontendEndpointID(input, false)
 }
 
-func FrontendEndpointIDForImport(input string) (*FrontendEndpointId, error) {
+func FrontendEndpointID(input string) (*FrontendEndpointId, error) {
 	return parseFrontendEndpointID(input, true)
 }
 
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
index 929390229f7d..d02054234e69 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
@@ -110,7 +110,7 @@ func TestFrontendEndpointIDForImportParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := FrontendEndpointIDForImport(test.input)
+		actual, err := FrontendEndpointID(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {
diff --git a/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
index 819c8929877b..d86b8d970902 100644
--- a/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
+++ b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
@@ -13,7 +13,7 @@ func FrontendEndpointID(i interface{}, k string) (warnings []string, errors []er
 		return
 	}
 
-	if _, err := parse.FrontendEndpointIDForImport(v); err != nil {
+	if _, err := parse.FrontendEndpointID(v); err != nil {
 		errors = append(errors, fmt.Errorf("Can not parse %q as a resource id: %v", k, err))
 		return
 	}

From 0abf5e4e6710941d3f0cf8fb312a9c311861f634 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:57:48 +0100
Subject: [PATCH 11/24] frontdoor/health_probe: updating to match the generated
 name

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/health_probe.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/health_probe_test.go | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 8ec381a1b77b..0b37242addee 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1115,7 +1115,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 			backend = flattenFrontDoorBackend(props.Backends)
 
 			if props.HealthProbeSettings != nil && props.HealthProbeSettings.ID != nil {
-				name, err := parse.HealthProbeID(*props.HealthProbeSettings.ID)
+				name, err := parse.HealthProbeIDInsensitively(*props.HealthProbeSettings.ID)
 				if err != nil {
 					return nil, err
 				}
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe.go b/azurerm/internal/services/frontdoor/parse/health_probe.go
index a09a5c5b4719..cf0f9bc6bd00 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe.go
@@ -21,7 +21,7 @@ func (id HealthProbeId) ID(subscriptionId string) string {
 	return fmt.Sprintf("%s/healthProbeSettings/%s", base, id.Name)
 }
 
-func HealthProbeID(input string) (*HealthProbeId, error) {
+func HealthProbeIDInsensitively(input string) (*HealthProbeId, error) {
 	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing FrontDoor Health Probe ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe_test.go b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
index 625b81063129..d776e60315f3 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe_test.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
@@ -53,7 +53,7 @@ func TestHealthProbeIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := HealthProbeID(test.input)
+		actual, err := HealthProbeIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From a85b5036d085fdc18f93ae8c11ae346a12b111e0 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:58:19 +0100
Subject: [PATCH 12/24] frontdoor/load_balancing: updating to match the
 generated name

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go       | 2 +-
 azurerm/internal/services/frontdoor/parse/load_balancing.go     | 2 +-
 .../internal/services/frontdoor/parse/load_balancing_test.go    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 0b37242addee..a68e6328590d 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1124,7 +1124,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 			}
 
 			if props.LoadBalancingSettings != nil && props.LoadBalancingSettings.ID != nil {
-				name, err := parse.LoadBalancingID(*props.LoadBalancingSettings.ID)
+				name, err := parse.LoadBalancingIDInsensitively(*props.LoadBalancingSettings.ID)
 				if err != nil {
 					return nil, err
 				}
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing.go b/azurerm/internal/services/frontdoor/parse/load_balancing.go
index df90bdf524a6..b927ad868269 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing.go
@@ -21,7 +21,7 @@ func (id LoadBalancingId) ID(subscriptionId string) string {
 	return fmt.Sprintf("%s/loadBalancingSettings/%s", base, id.Name)
 }
 
-func LoadBalancingID(input string) (*LoadBalancingId, error) {
+func LoadBalancingIDInsensitively(input string) (*LoadBalancingId, error) {
 	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing FrontDoor Load Balancing ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
index 2bdb913f74d1..2dfa29d4999a 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
@@ -53,7 +53,7 @@ func TestLoadBalancingIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := LoadBalancingID(test.input)
+		actual, err := LoadBalancingIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From 87d0310abdcffefda9e4e36b737015f39b23e4ab Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:58:47 +0100
Subject: [PATCH 13/24] frontdoor: renaming routing rule to match the generated
 name

---
 azurerm/internal/services/frontdoor/parse/routing_rule.go      | 2 +-
 azurerm/internal/services/frontdoor/parse/routing_rule_test.go | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule.go b/azurerm/internal/services/frontdoor/parse/routing_rule.go
index f484d8a3a620..100a029fb840 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule.go
@@ -21,7 +21,7 @@ func (id RoutingRuleId) ID(subscriptionId string) string {
 	return fmt.Sprintf("%s/routingRules/%s", base, id.Name)
 }
 
-func RoutingRuleID(input string) (*RoutingRuleId, error) {
+func RoutingRuleIDInsensitively(input string) (*RoutingRuleId, error) {
 	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing Routing Rule ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
index 5b800c317710..c128bfcb969c 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
@@ -53,7 +53,7 @@ func TestRoutingRuleIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := RoutingRuleID(test.input)
+		actual, err := RoutingRuleIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From f811f6fa7c8efd80533e7e0f5eccd9f411754b4b Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 19:59:38 +0100
Subject: [PATCH 14/24] r/frontdoor: fixing the build

---
 azurerm/internal/services/frontdoor/frontdoor_resource.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index a68e6328590d..3a32c47539a7 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -581,7 +581,6 @@ func resourceFrontDoorCreateUpdate(d *schema.ResourceData, meta interface{}) err
 				customHttpsProvisioningEnabled:  customHttpsProvisioningEnabled,
 				frontendEndpointId:              frontendInputId,
 				provisioningState:               properties.CustomHTTPSProvisioningState,
-				subscriptionId:                  subscriptionId,
 			}
 			if err := updateCustomHttpsConfiguration(ctx, frontendClient, input); err != nil {
 				return fmt.Errorf("updating Custom HTTPS configuration for Frontend Endpoint %q (Front Door %q / Resource Group %q): %+v", endpointName, name, resourceGroup, err)

From 2dcfd36b5381de9b998942aa7fc8f328078c8bab Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:00:09 +0100
Subject: [PATCH 15/24] frontdoor: renaming to match the generated name

---
 .../frontdoor/frontdoor_firewall_policy_resource.go         | 6 +++---
 .../frontdoor/frontdoor_firewall_policy_resource_test.go    | 2 +-
 azurerm/internal/services/frontdoor/frontdoor_resource.go   | 2 +-
 .../frontdoor/parse/web_application_firewall_policy.go      | 2 +-
 .../frontdoor/parse/web_application_firewall_policy_test.go | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
index 5dd1253bab79..74c50698f42a 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
@@ -30,7 +30,7 @@ func resourceFrontDoorFirewallPolicy() *schema.Resource {
 		Delete: resourceFrontDoorFirewallPolicyDelete,
 
 		Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error {
-			_, err := parse.WebApplicationFirewallPolicyID(id)
+			_, err := parse.WebApplicationFirewallPolicyIDInsensitively(id)
 			return err
 		}),
 
@@ -512,7 +512,7 @@ func resourceFrontDoorFirewallPolicyRead(d *schema.ResourceData, meta interface{
 	ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.WebApplicationFirewallPolicyID(d.Id())
+	id, err := parse.WebApplicationFirewallPolicyIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
@@ -564,7 +564,7 @@ func resourceFrontDoorFirewallPolicyDelete(d *schema.ResourceData, meta interfac
 	ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
 	defer cancel()
 
-	id, err := parse.WebApplicationFirewallPolicyID(d.Id())
+	id, err := parse.WebApplicationFirewallPolicyIDInsensitively(d.Id())
 	if err != nil {
 		return err
 	}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
index 84904eacc9bd..ce03f0a0b67e 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
@@ -109,7 +109,7 @@ func TestAccFrontDoorFirewallPolicy_complete(t *testing.T) {
 }
 
 func (FrontDoorFirewallPolicyResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) {
-	id, err := parse.WebApplicationFirewallPolicyID(state.ID)
+	id, err := parse.WebApplicationFirewallPolicyIDInsensitively(state.ID)
 	if err != nil {
 		return nil, err
 	}
diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 3a32c47539a7..536cad0d5eac 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1272,7 +1272,7 @@ func flattenFrontEndEndpoints(input *[]frontdoor.FrontendEndpoint, frontDoorId p
 
 			if waf := props.WebApplicationFirewallPolicyLink; waf != nil && waf.ID != nil {
 				// rewrite the ID to ensure it's consistent
-				parsed, err := parse.WebApplicationFirewallPolicyID(*waf.ID)
+				parsed, err := parse.WebApplicationFirewallPolicyIDInsensitively(*waf.ID)
 				if err != nil {
 					return nil, err
 				}
diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
index 26935c9294bb..3dd9147f9532 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
@@ -22,7 +22,7 @@ func (id WebApplicationFirewallPolicyId) ID(subscriptionId string) string {
 	return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/%s", subscriptionId, id.ResourceGroup, id.Name)
 }
 
-func WebApplicationFirewallPolicyID(input string) (*WebApplicationFirewallPolicyId, error) {
+func WebApplicationFirewallPolicyIDInsensitively(input string) (*WebApplicationFirewallPolicyId, error) {
 	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
 		return nil, fmt.Errorf("parsing Web Application Firewall Policy ID %q: %+v", input, err)
diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
index 9e75f70aa586..e346ab2c00bf 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
@@ -48,7 +48,7 @@ func TestWebApplicationFirewallPolicyIDParser(t *testing.T) {
 	}
 	for _, test := range testData {
 		t.Logf("Testing %q..", test.input)
-		actual, err := WebApplicationFirewallPolicyID(test.input)
+		actual, err := WebApplicationFirewallPolicyIDInsensitively(test.input)
 		if err != nil && test.expected == nil {
 			continue
 		} else {

From e49bede3499df8a07e3760b4fb81b4b4d44079ad Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:06:16 +0100
Subject: [PATCH 16/24] frontdoor: generating the Resource ID
 Formatter/Parser/Validator for BackendPool

---
 .../services/frontdoor/parse/backend_pool.go  | 126 ++++++--
 .../frontdoor/parse/backend_pool_test.go      | 271 +++++++++++++++---
 .../services/frontdoor/resourceids.go         |   3 +
 .../frontdoor/validate/backend_pool_id.go     |  23 ++
 .../validate/backend_pool_id_test.go          |  88 ++++++
 5 files changed, 443 insertions(+), 68 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/resourceids.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/backend_pool_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/backend_pool_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool.go b/azurerm/internal/services/frontdoor/parse/backend_pool.go
index 77d0cd63aba1..226178b798ea 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool.go
@@ -1,50 +1,130 @@
 package parse
 
-import "fmt"
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
+)
 
 type BackendPoolId struct {
-	ResourceGroup string
-	FrontDoorName string
-	Name          string
+	SubscriptionId string
+	ResourceGroup  string
+	FrontDoorName  string
+	Name           string
 }
 
 func NewBackendPoolID(subscriptionId, resourceGroup, frontDoorName, name string) BackendPoolId {
 	return BackendPoolId{
-		ResourceGroup: resourceGroup,
-		FrontDoorName: frontDoorName,
-		Name:          name,
+		SubscriptionId: subscriptionId,
+		ResourceGroup:  resourceGroup,
+		FrontDoorName:  frontDoorName,
+		Name:           name,
+	}
+}
+
+func (id BackendPoolId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Name %q", id.FrontDoorName),
+		fmt.Sprintf("Name %q", id.Name),
 	}
+	return strings.Join(segments, " / ")
 }
 
-func (id BackendPoolId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
-	return fmt.Sprintf("%s/backendPools/%s", base, id.Name)
+func (id BackendPoolId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s/backendPools/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorName, id.Name)
+}
+
+// BackendPoolID parses a BackendPool ID into an BackendPoolId struct
+func BackendPoolID(input string) (*BackendPoolId, error) {
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := BackendPoolId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorName, err = id.PopSegment("frontDoors"); err != nil {
+		return nil, err
+	}
+	if resourceId.Name, err = id.PopSegment("backendPools"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
+// BackendPoolIDInsensitively parses an BackendPool ID into an BackendPoolId struct, insensitively
+// This should only be used to parse an ID for rewriting, the BackendPoolID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
 func BackendPoolIDInsensitively(input string) (*BackendPoolId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
+	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing Backend Pool ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := BackendPoolId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	poolId := BackendPoolId{
-		ResourceGroup: frontDoorId.ResourceGroup,
-		FrontDoorName: frontDoorId.Name,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	// API is broken - https://github.com/Azure/azure-sdk-for-go/issues/6762
-	// note: the ordering is important since the defined case (we want to error with) is backendPools
-	if poolId.Name, err = id.PopSegment("backendpools"); err != nil {
-		if poolId.Name, err = id.PopSegment("BackendPools"); err != nil {
-			if poolId.Name, err = id.PopSegment("backendPools"); err != nil {
-				return nil, err
-			}
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
+			break
 		}
 	}
+	if resourceId.FrontDoorName, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	// find the correct casing for the 'backendPools' segment
+	backendPoolsKey := "backendPools"
+	for key := range id.Path {
+		if strings.EqualFold(key, backendPoolsKey) {
+			backendPoolsKey = key
+			break
+		}
+	}
+	if resourceId.Name, err = id.PopSegment(backendPoolsKey); err != nil {
+		return nil, err
+	}
 
 	if err := id.ValidateNoEmptySegments(input); err != nil {
 		return nil, err
 	}
 
-	return &poolId, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
index 04ab4dbac1be..fc934ef089a2 100644
--- a/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
+++ b/azurerm/internal/services/frontdoor/parse/backend_pool_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,75 +11,254 @@ import (
 var _ resourceid.Formatter = BackendPoolId{}
 
 func TestBackendPoolIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewBackendPoolID(subscriptionId, "group1", "frontdoor1", "pool1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1"
+	actual := NewBackendPoolID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1", "pool1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestBackendPoolIDParser(t *testing.T) {
+func TestBackendPoolID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *BackendPoolId
+		Input    string
+		Error    bool
+		Expected *BackendPoolId
 	}{
+
 		{
-			// lower case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/backendpools/pool1",
-			expected: &BackendPoolId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "pool1",
-			},
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/backendPools/pool1",
-			expected: &BackendPoolId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "pool1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
 		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/BackendPools/pool1",
-			expected: &BackendPoolId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "pool1",
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1",
+			Expected: &BackendPoolId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "pool1",
 			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Backendpools/pool1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/BACKENDPOOLS/POOL1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := BackendPoolIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := BackendPoolID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
+	}
+}
+
+func TestBackendPoolIDInsensitively(t *testing.T) {
+	testData := []struct {
+		Input    string
+		Error    bool
+		Expected *BackendPoolId
+	}{
+
+		{
+			// empty
+			Input: "",
+			Error: true,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
 
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1",
+			Expected: &BackendPoolId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "pool1",
+			},
+		},
+
+		{
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1/backendpools/pool1",
+			Expected: &BackendPoolId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "pool1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1/BACKENDPOOLS/pool1",
+			Expected: &BackendPoolId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "pool1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1/BaCkEnDpOoLs/pool1",
+			Expected: &BackendPoolId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "pool1",
+			},
+		},
+	}
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := BackendPoolIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
+			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
new file mode 100644
index 000000000000..d2d4cd31dede
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -0,0 +1,3 @@
+package frontdoor
+
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=BackendPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/backend_pool_id.go b/azurerm/internal/services/frontdoor/validate/backend_pool_id.go
new file mode 100644
index 000000000000..7b4163b60cd2
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/backend_pool_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func BackendPoolID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.BackendPoolID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/backend_pool_id_test.go b/azurerm/internal/services/frontdoor/validate/backend_pool_id_test.go
new file mode 100644
index 000000000000..16744e722f2c
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/backend_pool_id_test.go
@@ -0,0 +1,88 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestBackendPoolID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Valid: false,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/BACKENDPOOLS/POOL1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := BackendPoolID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From 6fc0e426c671de13a04ffd83091f3287be39b471 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:07:56 +0100
Subject: [PATCH 17/24] frontdoor: renaming to match the generated filenames

---
 .../services/frontdoor/parse/{frontdoor.go => front_door.go}      | 0
 .../frontdoor/parse/{frontdoor_test.go => front_door_test.go}     | 0
 .../frontdoor/validate/{frontdoor_name.go => front_door_name.go}  | 0
 .../validate/{frontdoor_waf_name.go => front_door_waf_name.go}    | 0
 .../{frontdoor_waf_name_test.go => front_door_waf_name_test.go}   | 0
 5 files changed, 0 insertions(+), 0 deletions(-)
 rename azurerm/internal/services/frontdoor/parse/{frontdoor.go => front_door.go} (100%)
 rename azurerm/internal/services/frontdoor/parse/{frontdoor_test.go => front_door_test.go} (100%)
 rename azurerm/internal/services/frontdoor/validate/{frontdoor_name.go => front_door_name.go} (100%)
 rename azurerm/internal/services/frontdoor/validate/{frontdoor_waf_name.go => front_door_waf_name.go} (100%)
 rename azurerm/internal/services/frontdoor/validate/{frontdoor_waf_name_test.go => front_door_waf_name_test.go} (100%)

diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor.go b/azurerm/internal/services/frontdoor/parse/front_door.go
similarity index 100%
rename from azurerm/internal/services/frontdoor/parse/frontdoor.go
rename to azurerm/internal/services/frontdoor/parse/front_door.go
diff --git a/azurerm/internal/services/frontdoor/parse/frontdoor_test.go b/azurerm/internal/services/frontdoor/parse/front_door_test.go
similarity index 100%
rename from azurerm/internal/services/frontdoor/parse/frontdoor_test.go
rename to azurerm/internal/services/frontdoor/parse/front_door_test.go
diff --git a/azurerm/internal/services/frontdoor/validate/frontdoor_name.go b/azurerm/internal/services/frontdoor/validate/front_door_name.go
similarity index 100%
rename from azurerm/internal/services/frontdoor/validate/frontdoor_name.go
rename to azurerm/internal/services/frontdoor/validate/front_door_name.go
diff --git a/azurerm/internal/services/frontdoor/validate/frontdoor_waf_name.go b/azurerm/internal/services/frontdoor/validate/front_door_waf_name.go
similarity index 100%
rename from azurerm/internal/services/frontdoor/validate/frontdoor_waf_name.go
rename to azurerm/internal/services/frontdoor/validate/front_door_waf_name.go
diff --git a/azurerm/internal/services/frontdoor/validate/frontdoor_waf_name_test.go b/azurerm/internal/services/frontdoor/validate/front_door_waf_name_test.go
similarity index 100%
rename from azurerm/internal/services/frontdoor/validate/frontdoor_waf_name_test.go
rename to azurerm/internal/services/frontdoor/validate/front_door_waf_name_test.go

From a8ef402415b6bee348ab9f53d323f3d9061d1aef Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:08:38 +0100
Subject: [PATCH 18/24] frontdoor: generating the Resource ID
 Formatter/Parser/Validator

---
 .../services/frontdoor/parse/front_door.go    |  96 ++++---
 .../frontdoor/parse/front_door_test.go        | 250 ++++++++++++------
 .../services/frontdoor/resourceids.go         |   1 +
 .../frontdoor/validate/front_door_id.go       |  23 ++
 .../frontdoor/validate/front_door_id_test.go  |  76 ++++++
 5 files changed, 336 insertions(+), 110 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/front_door_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/front_door_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/front_door.go b/azurerm/internal/services/frontdoor/parse/front_door.go
index c329d1eb2718..522142752e17 100644
--- a/azurerm/internal/services/frontdoor/parse/front_door.go
+++ b/azurerm/internal/services/frontdoor/parse/front_door.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"fmt"
 	"strings"
@@ -9,41 +11,52 @@ import (
 
 type FrontDoorId struct {
 	SubscriptionId string
-	Name           string
 	ResourceGroup  string
+	Name           string
 }
 
 func NewFrontDoorID(subscriptionId, resourceGroup, name string) FrontDoorId {
 	return FrontDoorId{
-		Name:          name,
-		ResourceGroup: resourceGroup,
+		SubscriptionId: subscriptionId,
+		ResourceGroup:  resourceGroup,
+		Name:           name,
 	}
 }
 
-func FrontDoorIDInsensitively(input string) (*FrontDoorId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
-	if err != nil {
-		return nil, fmt.Errorf("parsing FrontDoor ID %q: %+v", input, err)
-	}
-
-	if err := id.ValidateNoEmptySegments(input); err != nil {
-		return nil, err
+func (id FrontDoorId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Name %q", id.Name),
 	}
+	return strings.Join(segments, " / ")
+}
 
-	return frontDoorId, nil
+func (id FrontDoorId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.Name)
 }
 
+// FrontDoorID parses a FrontDoor ID into an FrontDoorId struct
 func FrontDoorID(input string) (*FrontDoorId, error) {
 	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing FrontDoor ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := FrontDoorId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	frontDoorId := FrontDoorId{
-		ResourceGroup: id.ResourceGroup,
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
 	}
 
-	if frontDoorId.Name, err = id.PopSegment("frontDoors"); err != nil {
+	if resourceId.Name, err = id.PopSegment("frontDoors"); err != nil {
 		return nil, err
 	}
 
@@ -51,34 +64,49 @@ func FrontDoorID(input string) (*FrontDoorId, error) {
 		return nil, err
 	}
 
-	return &frontDoorId, nil
+	return &resourceId, nil
 }
 
-func (id FrontDoorId) ID(subscriptionId string) string {
-	return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s", subscriptionId, id.ResourceGroup, id.Name)
-}
-
-func parseFrontDoorChildResourceId(input string) (*FrontDoorId, *azure.ResourceID, error) {
+// FrontDoorIDInsensitively parses an FrontDoor ID into an FrontDoorId struct, insensitively
+// This should only be used to parse an ID for rewriting, the FrontDoorID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
+func FrontDoorIDInsensitively(input string) (*FrontDoorId, error) {
 	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, nil, err
+		return nil, err
+	}
+
+	resourceId := FrontDoorId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	frontdoor := FrontDoorId{
-		ResourceGroup: id.ResourceGroup,
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
 	}
 
-	for key, value := range id.Path {
-		// In Azure API's should follow Postel's Law - where URI's should be insensitive for requests,
-		// but case-sensitive when referencing URI's in responses. Unfortunately the Networking API's
-		// treat both as case-insensitive - so until these API's follow the spec we need to identify
-		// the correct casing here.
-		if strings.EqualFold(key, "frontDoors") {
-			frontdoor.Name = value
-			delete(id.Path, key)
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
 			break
 		}
 	}
+	if resourceId.Name, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
 
-	return &frontdoor, id, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/front_door_test.go b/azurerm/internal/services/frontdoor/parse/front_door_test.go
index a99fe9965177..04f02b6ed3a5 100644
--- a/azurerm/internal/services/frontdoor/parse/front_door_test.go
+++ b/azurerm/internal/services/frontdoor/parse/front_door_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,123 +11,219 @@ import (
 var _ resourceid.Formatter = FrontDoorId{}
 
 func TestFrontDoorIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewFrontDoorID(subscriptionId, "group1", "frontDoor1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1"
+	actual := NewFrontDoorID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestFrontDoorIDParser(t *testing.T) {
+func TestFrontDoorID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *FrontDoorId
+		Input    string
+		Error    bool
+		Expected *FrontDoorId
 	}{
+
 		{
-			// lower case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1",
-			expected: &FrontDoorId{
-				ResourceGroup: "group1",
-				Name:          "frontDoor1",
-			},
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1",
-			expected: &FrontDoorId{
-				ResourceGroup: "group1",
-				Name:          "frontDoor1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
 		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1",
-			expected: &FrontDoorId{
-				ResourceGroup: "group1",
-				Name:          "frontDoor1",
-			},
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
 		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
 		{
-			// pascal case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1",
-			expected: &FrontDoorId{
-				ResourceGroup: "group1",
-				Name:          "frontDoor1",
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1",
+			Expected: &FrontDoorId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				Name:           "frontdoor1",
 			},
 		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1",
+			Error: true,
+		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := FrontDoorIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := FrontDoorID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
-		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
 
-func TestFrontDoorIDForImportParser(t *testing.T) {
+func TestFrontDoorIDInsensitively(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *FrontDoorId
+		Input    string
+		Error    bool
+		Expected *FrontDoorId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1",
-			expected: &FrontDoorId{
-				ResourceGroup: "group1",
-				Name:          "frontDoor1",
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1",
+			Expected: &FrontDoorId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				Name:           "frontdoor1",
 			},
 		},
+
 		{
-			// title case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1",
-			expected: nil,
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1",
+			Expected: &FrontDoorId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				Name:           "frontdoor1",
+			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1",
-			expected: nil,
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1",
+			Expected: &FrontDoorId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				Name:           "frontdoor1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1",
+			Expected: &FrontDoorId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				Name:           "frontdoor1",
+			},
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := FrontDoorID(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := FrontDoorIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
-		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index d2d4cd31dede..58c34b0460f1 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -1,3 +1,4 @@
 package frontdoor
 
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=BackendPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontDoor -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/front_door_id.go b/azurerm/internal/services/frontdoor/validate/front_door_id.go
new file mode 100644
index 000000000000..9be7c75fce5e
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/front_door_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func FrontDoorID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.FrontDoorID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/front_door_id_test.go b/azurerm/internal/services/frontdoor/validate/front_door_id_test.go
new file mode 100644
index 000000000000..8a82e0a139a6
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/front_door_id_test.go
@@ -0,0 +1,76 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestFrontDoorID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := FrontDoorID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From 6e83a5ed5788e55667d8b754c092e07cf1c2b501 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:09:17 +0100
Subject: [PATCH 19/24] frontdoor: generating the Resource ID
 Formatter/Parser/Validator for Frontend Endpoint

---
 .../frontdoor/parse/frontend_endpoint.go      | 133 +++++---
 .../frontdoor/parse/frontend_endpoint_test.go | 286 +++++++++++++-----
 .../services/frontdoor/resourceids.go         |   6 +
 .../validate/frontend_endpoint_id.go          |  13 +-
 .../validate/frontend_endpoint_id_test.go     |  88 ++++++
 5 files changed, 406 insertions(+), 120 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/frontend_endpoint_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
index 6b5553d0d0b7..c243c69d79cf 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint.go
@@ -1,67 +1,130 @@
 package parse
 
-import "fmt"
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
+)
 
 type FrontendEndpointId struct {
-	ResourceGroup string
-	FrontDoorName string
-	Name          string
+	SubscriptionId string
+	ResourceGroup  string
+	FrontDoorName  string
+	Name           string
 }
 
 func NewFrontendEndpointID(subscriptionId, resourceGroup, frontDoorName, name string) FrontendEndpointId {
 	return FrontendEndpointId{
-		ResourceGroup: resourceGroup,
-		FrontDoorName: frontDoorName,
-		Name:          name,
+		SubscriptionId: subscriptionId,
+		ResourceGroup:  resourceGroup,
+		FrontDoorName:  frontDoorName,
+		Name:           name,
 	}
 }
 
-func (id FrontendEndpointId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
-	return fmt.Sprintf("%s/frontendEndpoints/%s", base, id.Name)
+func (id FrontendEndpointId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Name %q", id.FrontDoorName),
+		fmt.Sprintf("Name %q", id.Name),
+	}
+	return strings.Join(segments, " / ")
 }
 
-func FrontendEndpointIDInsensitively(input string) (*FrontendEndpointId, error) {
-	return parseFrontendEndpointID(input, false)
+func (id FrontendEndpointId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s/frontendEndpoints/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorName, id.Name)
 }
 
+// FrontendEndpointID parses a FrontendEndpoint ID into an FrontendEndpointId struct
 func FrontendEndpointID(input string) (*FrontendEndpointId, error) {
-	return parseFrontendEndpointID(input, true)
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := FrontendEndpointId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorName, err = id.PopSegment("frontDoors"); err != nil {
+		return nil, err
+	}
+	if resourceId.Name, err = id.PopSegment("frontendEndpoints"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
-func parseFrontendEndpointID(input string, caseSensitive bool) (*FrontendEndpointId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
+// FrontendEndpointIDInsensitively parses an FrontendEndpoint ID into an FrontendEndpointId struct, insensitively
+// This should only be used to parse an ID for rewriting, the FrontendEndpointID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
+func FrontendEndpointIDInsensitively(input string) (*FrontendEndpointId, error) {
+	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing Frontend Endpoint ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := FrontendEndpointId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	endpointId := FrontendEndpointId{
-		ResourceGroup: frontDoorId.ResourceGroup,
-		FrontDoorName: frontDoorId.Name,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	// The Azure API (per the ARM Spec/chatting with the ARM Team) should be following Postel's Law;
-	// where ID's are insensitive for Requests but sensitive in responses - but it's not.
-	//
-	// For us this means ID's should be sensitive at import time - but we have to work around these
-	// API bugs for the moment.
-	if caseSensitive {
-		if endpointId.Name, err = id.PopSegment("frontendEndpoints"); err != nil {
-			return nil, err
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
+			break
 		}
-	} else {
-		// https://github.com/Azure/azure-sdk-for-go/issues/6762
-		// note: the ordering is important since the defined case (we want to error with) is frontendEndpoints
-		if endpointId.Name, err = id.PopSegment("FrontendEndpoints"); err != nil {
-			if endpointId.Name, err = id.PopSegment("frontendEndpoints"); err != nil {
-				return nil, err
-			}
+	}
+	if resourceId.FrontDoorName, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	// find the correct casing for the 'frontendEndpoints' segment
+	frontendEndpointsKey := "frontendEndpoints"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontendEndpointsKey) {
+			frontendEndpointsKey = key
+			break
 		}
 	}
+	if resourceId.Name, err = id.PopSegment(frontendEndpointsKey); err != nil {
+		return nil, err
+	}
 
 	if err := id.ValidateNoEmptySegments(input); err != nil {
 		return nil, err
 	}
 
-	return &endpointId, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
index d02054234e69..8a70f74c1625 100644
--- a/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
+++ b/azurerm/internal/services/frontdoor/parse/frontend_endpoint_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,128 +11,254 @@ import (
 var _ resourceid.Formatter = FrontendEndpointId{}
 
 func TestFrontendEndpointIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewFrontendEndpointID(subscriptionId, "group1", "frontdoor1", "endpoint1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1"
+	actual := NewFrontendEndpointID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1", "endpoint1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestFrontendEndpointIDParser(t *testing.T) {
+func TestFrontendEndpointID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *FrontendEndpointId
+		Input    string
+		Error    bool
+		Expected *FrontendEndpointId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/frontendendpoints/endpoint1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/frontendEndpoints/endpoint1",
-			expected: &FrontendEndpointId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "endpoint1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
 		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/FrontendEndpoints/endpoint1",
-			expected: &FrontendEndpointId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "endpoint1",
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1",
+			Expected: &FrontendEndpointId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "endpoint1",
 			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Frontendendpoints/endpoint1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/FRONTENDENDPOINTS/ENDPOINT1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := FrontendEndpointIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := FrontendEndpointID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
-		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+			t.Fatalf("Expect a value but got an error: %s", err)
 		}
-
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
 
-func TestFrontendEndpointIDForImportParser(t *testing.T) {
+func TestFrontendEndpointIDInsensitively(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *FrontendEndpointId
+		Input    string
+		Error    bool
+		Expected *FrontendEndpointId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/frontendendpoints/endpoint1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/frontendEndpoints/endpoint1",
-			expected: &FrontendEndpointId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "endpoint1",
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1",
+			Expected: &FrontendEndpointId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "endpoint1",
 			},
 		},
+
 		{
-			// title case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/FrontendEndpoints/endpoint1",
-			expected: nil,
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1/frontendendpoints/endpoint1",
+			Expected: &FrontendEndpointId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "endpoint1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1/FRONTENDENDPOINTS/endpoint1",
+			Expected: &FrontendEndpointId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "endpoint1",
+			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Frontendendpoints/endpoint1",
-			expected: nil,
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1/FrOnTeNdEnDpOiNtS/endpoint1",
+			Expected: &FrontendEndpointId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "endpoint1",
+			},
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := FrontendEndpointID(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := FrontendEndpointIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
-		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+			t.Fatalf("Expect a value but got an error: %s", err)
 		}
-
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index 58c34b0460f1..fdbb7a7b4ef4 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -2,3 +2,9 @@ package frontdoor
 
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=BackendPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontDoor -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontendEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1 -rewrite=true
+
+// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
+// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=LoadBalancing -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1 -rewrite=true
+// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=RoutingRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1 -rewrite=true
+// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=WebApplicationFirewallPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
index d86b8d970902..47ee9be373d9 100644
--- a/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
+++ b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id.go
@@ -1,22 +1,23 @@
 package validate
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"fmt"
 
 	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
 )
 
-func FrontendEndpointID(i interface{}, k string) (warnings []string, errors []error) {
-	v, ok := i.(string)
+func FrontendEndpointID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
 	if !ok {
-		errors = append(errors, fmt.Errorf("expected type of %q to be string", k))
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
 		return
 	}
 
 	if _, err := parse.FrontendEndpointID(v); err != nil {
-		errors = append(errors, fmt.Errorf("Can not parse %q as a resource id: %v", k, err))
-		return
+		errors = append(errors, err)
 	}
 
-	return warnings, errors
+	return
 }
diff --git a/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id_test.go b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id_test.go
new file mode 100644
index 000000000000..0eeb456c9e48
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/frontend_endpoint_id_test.go
@@ -0,0 +1,88 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestFrontendEndpointID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Valid: false,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/FRONTENDENDPOINTS/ENDPOINT1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := FrontendEndpointID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From 70148912aec840c12fa3b23c05cad8900242d853 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:09:57 +0100
Subject: [PATCH 20/24] frontdoor: generating the Resource ID
 Formatters/Parsers and Validators for HealthProbe

---
 .../services/frontdoor/parse/health_probe.go  | 126 +++++++--
 .../frontdoor/parse/health_probe_test.go      | 267 +++++++++++++++---
 .../services/frontdoor/resourceids.go         |   6 +-
 .../frontdoor/validate/health_probe_id.go     |  23 ++
 .../validate/health_probe_id_test.go          |  88 ++++++
 5 files changed, 442 insertions(+), 68 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/health_probe_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/health_probe_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/health_probe.go b/azurerm/internal/services/frontdoor/parse/health_probe.go
index cf0f9bc6bd00..5d50429ea668 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe.go
@@ -1,48 +1,130 @@
 package parse
 
-import "fmt"
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
+)
 
 type HealthProbeId struct {
-	ResourceGroup string
-	FrontDoorName string
-	Name          string
+	SubscriptionId         string
+	ResourceGroup          string
+	FrontDoorName          string
+	HealthProbeSettingName string
 }
 
-func NewHealthProbeID(subscriptionId, resourceGroup, frontDoorName, name string) HealthProbeId {
+func NewHealthProbeID(subscriptionId, resourceGroup, frontDoorName, healthProbeSettingName string) HealthProbeId {
 	return HealthProbeId{
-		ResourceGroup: resourceGroup,
-		FrontDoorName: frontDoorName,
-		Name:          name,
+		SubscriptionId:         subscriptionId,
+		ResourceGroup:          resourceGroup,
+		FrontDoorName:          frontDoorName,
+		HealthProbeSettingName: healthProbeSettingName,
+	}
+}
+
+func (id HealthProbeId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Name %q", id.FrontDoorName),
+		fmt.Sprintf("Health Probe Setting Name %q", id.HealthProbeSettingName),
 	}
+	return strings.Join(segments, " / ")
 }
 
-func (id HealthProbeId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
-	return fmt.Sprintf("%s/healthProbeSettings/%s", base, id.Name)
+func (id HealthProbeId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s/healthProbeSettings/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorName, id.HealthProbeSettingName)
+}
+
+// HealthProbeID parses a HealthProbe ID into an HealthProbeId struct
+func HealthProbeID(input string) (*HealthProbeId, error) {
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := HealthProbeId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorName, err = id.PopSegment("frontDoors"); err != nil {
+		return nil, err
+	}
+	if resourceId.HealthProbeSettingName, err = id.PopSegment("healthProbeSettings"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
+// HealthProbeIDInsensitively parses an HealthProbe ID into an HealthProbeId struct, insensitively
+// This should only be used to parse an ID for rewriting, the HealthProbeID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
 func HealthProbeIDInsensitively(input string) (*HealthProbeId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
+	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing FrontDoor Health Probe ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := HealthProbeId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	probeId := HealthProbeId{
-		ResourceGroup: frontDoorId.ResourceGroup,
-		FrontDoorName: frontDoorId.Name,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	// https://github.com/Azure/azure-sdk-for-go/issues/6762
-	// note: the ordering is important since the defined case (we want to error with) is healthProbeSettings
-	if probeId.Name, err = id.PopSegment("HealthProbeSettings"); err != nil {
-		if probeId.Name, err = id.PopSegment("healthProbeSettings"); err != nil {
-			return nil, err
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
+			break
 		}
 	}
+	if resourceId.FrontDoorName, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	// find the correct casing for the 'healthProbeSettings' segment
+	healthProbeSettingsKey := "healthProbeSettings"
+	for key := range id.Path {
+		if strings.EqualFold(key, healthProbeSettingsKey) {
+			healthProbeSettingsKey = key
+			break
+		}
+	}
+	if resourceId.HealthProbeSettingName, err = id.PopSegment(healthProbeSettingsKey); err != nil {
+		return nil, err
+	}
 
 	if err := id.ValidateNoEmptySegments(input); err != nil {
 		return nil, err
 	}
 
-	return &probeId, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/health_probe_test.go b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
index d776e60315f3..00f016cb28ba 100644
--- a/azurerm/internal/services/frontdoor/parse/health_probe_test.go
+++ b/azurerm/internal/services/frontdoor/parse/health_probe_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,71 +11,254 @@ import (
 var _ resourceid.Formatter = HealthProbeId{}
 
 func TestHealthProbeIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewHealthProbeID(subscriptionId, "group1", "frontdoor1", "probe1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1"
+	actual := NewHealthProbeID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1", "probe1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestHealthProbeIDParser(t *testing.T) {
+func TestHealthProbeID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *HealthProbeId
+		Input    string
+		Error    bool
+		Expected *HealthProbeId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/healthprobesettings/probe1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/healthProbeSettings/probe1",
-			expected: &HealthProbeId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "probe1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
 		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/HealthProbeSettings/probe1",
-			expected: &HealthProbeId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "probe1",
+			// missing value for HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1",
+			Expected: &HealthProbeId{
+				SubscriptionId:         "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:          "resGroup1",
+				FrontDoorName:          "frontdoor1",
+				HealthProbeSettingName: "probe1",
 			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Healthprobesettings/probe1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/HEALTHPROBESETTINGS/PROBE1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := HealthProbeIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := HealthProbeID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.HealthProbeSettingName != v.Expected.HealthProbeSettingName {
+			t.Fatalf("Expected %q but got %q for HealthProbeSettingName", v.Expected.HealthProbeSettingName, actual.HealthProbeSettingName)
 		}
+	}
+}
+
+func TestHealthProbeIDInsensitively(t *testing.T) {
+	testData := []struct {
+		Input    string
+		Error    bool
+		Expected *HealthProbeId
+	}{
+
+		{
+			// empty
+			Input: "",
+			Error: true,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
 
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1",
+			Expected: &HealthProbeId{
+				SubscriptionId:         "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:          "resGroup1",
+				FrontDoorName:          "frontdoor1",
+				HealthProbeSettingName: "probe1",
+			},
+		},
+
+		{
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1/healthprobesettings/probe1",
+			Expected: &HealthProbeId{
+				SubscriptionId:         "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:          "resGroup1",
+				FrontDoorName:          "frontdoor1",
+				HealthProbeSettingName: "probe1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1/HEALTHPROBESETTINGS/probe1",
+			Expected: &HealthProbeId{
+				SubscriptionId:         "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:          "resGroup1",
+				FrontDoorName:          "frontdoor1",
+				HealthProbeSettingName: "probe1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1/HeAlThPrObEsEtTiNgS/probe1",
+			Expected: &HealthProbeId{
+				SubscriptionId:         "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:          "resGroup1",
+				FrontDoorName:          "frontdoor1",
+				HealthProbeSettingName: "probe1",
+			},
+		},
+	}
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := HealthProbeIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
+			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.HealthProbeSettingName != v.Expected.HealthProbeSettingName {
+			t.Fatalf("Expected %q but got %q for HealthProbeSettingName", v.Expected.HealthProbeSettingName, actual.HealthProbeSettingName)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index fdbb7a7b4ef4..6e2e6b8a4709 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -3,8 +3,4 @@ package frontdoor
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=BackendPool -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/backendPools/pool1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontDoor -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontendEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1 -rewrite=true
-
-// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
-// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=LoadBalancing -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1 -rewrite=true
-// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=RoutingRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1 -rewrite=true
-// //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=WebApplicationFirewallPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/health_probe_id.go b/azurerm/internal/services/frontdoor/validate/health_probe_id.go
new file mode 100644
index 000000000000..3aa863a667f7
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/health_probe_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func HealthProbeID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.HealthProbeID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/health_probe_id_test.go b/azurerm/internal/services/frontdoor/validate/health_probe_id_test.go
new file mode 100644
index 000000000000..97a38fd28575
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/health_probe_id_test.go
@@ -0,0 +1,88 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestHealthProbeID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// missing HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Valid: false,
+		},
+
+		{
+			// missing value for HealthProbeSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/HEALTHPROBESETTINGS/PROBE1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := HealthProbeID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From 9ac09fe9b4f75c9ca76277e0b48efb5757bbf62e Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:11:26 +0100
Subject: [PATCH 21/24] frontdoor: generating the Resource ID
 Formatter/Parser/Validator for Load Balancing

---
 .../frontdoor/parse/load_balancing.go         | 126 +++++++--
 .../frontdoor/parse/load_balancing_test.go    | 267 +++++++++++++++---
 .../services/frontdoor/resourceids.go         |   1 +
 .../frontdoor/validate/load_balancing_id.go   |  23 ++
 .../validate/load_balancing_id_test.go        |  88 ++++++
 5 files changed, 442 insertions(+), 63 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/load_balancing_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/load_balancing_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing.go b/azurerm/internal/services/frontdoor/parse/load_balancing.go
index b927ad868269..f899e720a052 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing.go
@@ -1,48 +1,130 @@
 package parse
 
-import "fmt"
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
+)
 
 type LoadBalancingId struct {
-	ResourceGroup string
-	FrontDoorName string
-	Name          string
+	SubscriptionId           string
+	ResourceGroup            string
+	FrontDoorName            string
+	LoadBalancingSettingName string
 }
 
-func NewLoadBalancingID(subscriptionId, resourceGroup, frontDoorName, name string) LoadBalancingId {
+func NewLoadBalancingID(subscriptionId, resourceGroup, frontDoorName, loadBalancingSettingName string) LoadBalancingId {
 	return LoadBalancingId{
-		ResourceGroup: resourceGroup,
-		FrontDoorName: frontDoorName,
-		Name:          name,
+		SubscriptionId:           subscriptionId,
+		ResourceGroup:            resourceGroup,
+		FrontDoorName:            frontDoorName,
+		LoadBalancingSettingName: loadBalancingSettingName,
+	}
+}
+
+func (id LoadBalancingId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Name %q", id.FrontDoorName),
+		fmt.Sprintf("Load Balancing Setting Name %q", id.LoadBalancingSettingName),
 	}
+	return strings.Join(segments, " / ")
 }
 
-func (id LoadBalancingId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
-	return fmt.Sprintf("%s/loadBalancingSettings/%s", base, id.Name)
+func (id LoadBalancingId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s/loadBalancingSettings/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorName, id.LoadBalancingSettingName)
+}
+
+// LoadBalancingID parses a LoadBalancing ID into an LoadBalancingId struct
+func LoadBalancingID(input string) (*LoadBalancingId, error) {
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := LoadBalancingId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorName, err = id.PopSegment("frontDoors"); err != nil {
+		return nil, err
+	}
+	if resourceId.LoadBalancingSettingName, err = id.PopSegment("loadBalancingSettings"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
+// LoadBalancingIDInsensitively parses an LoadBalancing ID into an LoadBalancingId struct, insensitively
+// This should only be used to parse an ID for rewriting, the LoadBalancingID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
 func LoadBalancingIDInsensitively(input string) (*LoadBalancingId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
+	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing FrontDoor Load Balancing ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := LoadBalancingId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	loadBalancingId := LoadBalancingId{
-		ResourceGroup: frontDoorId.ResourceGroup,
-		FrontDoorName: frontDoorId.Name,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	// https://github.com/Azure/azure-sdk-for-go/issues/6762
-	// note: the ordering is important since the defined case (we want to error with) is loadBalancingSettings
-	if loadBalancingId.Name, err = id.PopSegment("LoadBalancingSettings"); err != nil {
-		if loadBalancingId.Name, err = id.PopSegment("loadBalancingSettings"); err != nil {
-			return nil, err
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
+			break
 		}
 	}
+	if resourceId.FrontDoorName, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	// find the correct casing for the 'loadBalancingSettings' segment
+	loadBalancingSettingsKey := "loadBalancingSettings"
+	for key := range id.Path {
+		if strings.EqualFold(key, loadBalancingSettingsKey) {
+			loadBalancingSettingsKey = key
+			break
+		}
+	}
+	if resourceId.LoadBalancingSettingName, err = id.PopSegment(loadBalancingSettingsKey); err != nil {
+		return nil, err
+	}
 
 	if err := id.ValidateNoEmptySegments(input); err != nil {
 		return nil, err
 	}
 
-	return &loadBalancingId, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
index 2dfa29d4999a..a321caa3084d 100644
--- a/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
+++ b/azurerm/internal/services/frontdoor/parse/load_balancing_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,71 +11,254 @@ import (
 var _ resourceid.Formatter = LoadBalancingId{}
 
 func TestLoadBalancingIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewLoadBalancingID(subscriptionId, "group1", "frontdoor1", "setting1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1"
+	actual := NewLoadBalancingID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1", "setting1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestLoadBalancingIDParser(t *testing.T) {
+func TestLoadBalancingID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *LoadBalancingId
+		Input    string
+		Error    bool
+		Expected *LoadBalancingId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/loadbalancingsettings/setting1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/loadBalancingSettings/setting1",
-			expected: &LoadBalancingId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "setting1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
 		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/LoadBalancingSettings/setting1",
-			expected: &LoadBalancingId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "setting1",
+			// missing value for LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1",
+			Expected: &LoadBalancingId{
+				SubscriptionId:           "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:            "resGroup1",
+				FrontDoorName:            "frontdoor1",
+				LoadBalancingSettingName: "setting1",
 			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Loadbalancingsettings/setting1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/LOADBALANCINGSETTINGS/SETTING1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := LoadBalancingIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := LoadBalancingID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.LoadBalancingSettingName != v.Expected.LoadBalancingSettingName {
+			t.Fatalf("Expected %q but got %q for LoadBalancingSettingName", v.Expected.LoadBalancingSettingName, actual.LoadBalancingSettingName)
 		}
+	}
+}
+
+func TestLoadBalancingIDInsensitively(t *testing.T) {
+	testData := []struct {
+		Input    string
+		Error    bool
+		Expected *LoadBalancingId
+	}{
+
+		{
+			// empty
+			Input: "",
+			Error: true,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
 
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1",
+			Expected: &LoadBalancingId{
+				SubscriptionId:           "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:            "resGroup1",
+				FrontDoorName:            "frontdoor1",
+				LoadBalancingSettingName: "setting1",
+			},
+		},
+
+		{
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1/loadbalancingsettings/setting1",
+			Expected: &LoadBalancingId{
+				SubscriptionId:           "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:            "resGroup1",
+				FrontDoorName:            "frontdoor1",
+				LoadBalancingSettingName: "setting1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1/LOADBALANCINGSETTINGS/setting1",
+			Expected: &LoadBalancingId{
+				SubscriptionId:           "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:            "resGroup1",
+				FrontDoorName:            "frontdoor1",
+				LoadBalancingSettingName: "setting1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1/LoAdBaLaNcInGsEtTiNgS/setting1",
+			Expected: &LoadBalancingId{
+				SubscriptionId:           "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:            "resGroup1",
+				FrontDoorName:            "frontdoor1",
+				LoadBalancingSettingName: "setting1",
+			},
+		},
+	}
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := LoadBalancingIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
+			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.LoadBalancingSettingName != v.Expected.LoadBalancingSettingName {
+			t.Fatalf("Expected %q but got %q for LoadBalancingSettingName", v.Expected.LoadBalancingSettingName, actual.LoadBalancingSettingName)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index 6e2e6b8a4709..ff009faa45ad 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -4,3 +4,4 @@ package frontdoor
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontDoor -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontendEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=LoadBalancing -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/load_balancing_id.go b/azurerm/internal/services/frontdoor/validate/load_balancing_id.go
new file mode 100644
index 000000000000..a85cb0a782f2
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/load_balancing_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func LoadBalancingID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.LoadBalancingID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/load_balancing_id_test.go b/azurerm/internal/services/frontdoor/validate/load_balancing_id_test.go
new file mode 100644
index 000000000000..393e0c0fcd0e
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/load_balancing_id_test.go
@@ -0,0 +1,88 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestLoadBalancingID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// missing LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Valid: false,
+		},
+
+		{
+			// missing value for LoadBalancingSettingName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/LOADBALANCINGSETTINGS/SETTING1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := LoadBalancingID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From b77eab5bd16086a53a4ad1eec6b2c3d690da3b1c Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:12:01 +0100
Subject: [PATCH 22/24] frontdoor: generating the Resource ID Formatter/Parser
 and Validator for Routing Rule

---
 .../services/frontdoor/parse/routing_rule.go  | 124 ++++++--
 .../frontdoor/parse/routing_rule_test.go      | 267 +++++++++++++++---
 .../services/frontdoor/resourceids.go         |   1 +
 .../frontdoor/validate/routing_rule_id.go     |  23 ++
 .../validate/routing_rule_id_test.go          |  88 ++++++
 5 files changed, 441 insertions(+), 62 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/routing_rule_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/routing_rule_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule.go b/azurerm/internal/services/frontdoor/parse/routing_rule.go
index 100a029fb840..d8e25be082bf 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule.go
@@ -1,48 +1,130 @@
 package parse
 
-import "fmt"
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
+)
 
 type RoutingRuleId struct {
-	ResourceGroup string
-	FrontDoorName string
-	Name          string
+	SubscriptionId string
+	ResourceGroup  string
+	FrontDoorName  string
+	Name           string
 }
 
 func NewRoutingRuleID(subscriptionId, resourceGroup, frontDoorName, name string) RoutingRuleId {
 	return RoutingRuleId{
-		ResourceGroup: resourceGroup,
-		FrontDoorName: frontDoorName,
-		Name:          name,
+		SubscriptionId: subscriptionId,
+		ResourceGroup:  resourceGroup,
+		FrontDoorName:  frontDoorName,
+		Name:           name,
+	}
+}
+
+func (id RoutingRuleId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Name %q", id.FrontDoorName),
+		fmt.Sprintf("Name %q", id.Name),
 	}
+	return strings.Join(segments, " / ")
 }
 
-func (id RoutingRuleId) ID(subscriptionId string) string {
-	base := NewFrontDoorID(subscriptionId, id.ResourceGroup, id.FrontDoorName).ID(subscriptionId)
-	return fmt.Sprintf("%s/routingRules/%s", base, id.Name)
+func (id RoutingRuleId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoors/%s/routingRules/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorName, id.Name)
+}
+
+// RoutingRuleID parses a RoutingRule ID into an RoutingRuleId struct
+func RoutingRuleID(input string) (*RoutingRuleId, error) {
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := RoutingRuleId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorName, err = id.PopSegment("frontDoors"); err != nil {
+		return nil, err
+	}
+	if resourceId.Name, err = id.PopSegment("routingRules"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
+// RoutingRuleIDInsensitively parses an RoutingRule ID into an RoutingRuleId struct, insensitively
+// This should only be used to parse an ID for rewriting, the RoutingRuleID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
 func RoutingRuleIDInsensitively(input string) (*RoutingRuleId, error) {
-	frontDoorId, id, err := parseFrontDoorChildResourceId(input)
+	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing Routing Rule ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := RoutingRuleId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	poolId := RoutingRuleId{
-		ResourceGroup: frontDoorId.ResourceGroup,
-		FrontDoorName: frontDoorId.Name,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	// API is broken - https://github.com/Azure/azure-sdk-for-go/issues/6762
-	// note: the ordering is important since the defined case (we want to error with) is routingRules
-	if poolId.Name, err = id.PopSegment("RoutingRules"); err != nil {
-		if poolId.Name, err = id.PopSegment("routingRules"); err != nil {
-			return nil, err
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoors' segment
+	frontDoorsKey := "frontDoors"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorsKey) {
+			frontDoorsKey = key
+			break
 		}
 	}
+	if resourceId.FrontDoorName, err = id.PopSegment(frontDoorsKey); err != nil {
+		return nil, err
+	}
+
+	// find the correct casing for the 'routingRules' segment
+	routingRulesKey := "routingRules"
+	for key := range id.Path {
+		if strings.EqualFold(key, routingRulesKey) {
+			routingRulesKey = key
+			break
+		}
+	}
+	if resourceId.Name, err = id.PopSegment(routingRulesKey); err != nil {
+		return nil, err
+	}
 
 	if err := id.ValidateNoEmptySegments(input); err != nil {
 		return nil, err
 	}
 
-	return &poolId, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
index c128bfcb969c..92231ce0662a 100644
--- a/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
+++ b/azurerm/internal/services/frontdoor/parse/routing_rule_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,71 +11,254 @@ import (
 var _ resourceid.Formatter = RoutingRuleId{}
 
 func TestRoutingRuleIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewRoutingRuleID(subscriptionId, "group1", "frontdoor1", "rule1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1"
+	actual := NewRoutingRuleID("12345678-1234-9876-4563-123456789012", "resGroup1", "frontdoor1", "rule1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestRoutingRuleIDParser(t *testing.T) {
+func TestRoutingRuleID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *RoutingRuleId
+		Input    string
+		Error    bool
+		Expected *RoutingRuleId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoors/frontDoor1/routingrules/rule1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoors/frontDoor1/routingRules/rule1",
-			expected: &RoutingRuleId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "rule1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
 		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoors/frontDoor1/RoutingRules/rule1",
-			expected: &RoutingRuleId{
-				ResourceGroup: "group1",
-				FrontDoorName: "frontDoor1",
-				Name:          "rule1",
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1",
+			Expected: &RoutingRuleId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "rule1",
 			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoors/frontDoor1/Routingrules/rule1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/ROUTINGRULES/RULE1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := RoutingRuleIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := RoutingRuleID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
+	}
+}
+
+func TestRoutingRuleIDInsensitively(t *testing.T) {
+	testData := []struct {
+		Input    string
+		Error    bool
+		Expected *RoutingRuleId
+	}{
+
+		{
+			// empty
+			Input: "",
+			Error: true,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
 
-		if actual.FrontDoorName != test.expected.FrontDoorName {
-			t.Fatalf("Expected FrontDoorName to be %q but was %q", test.expected.FrontDoorName, actual.FrontDoorName)
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Error: true,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Error: true,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1",
+			Expected: &RoutingRuleId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "rule1",
+			},
+		},
+
+		{
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoors/frontdoor1/routingrules/rule1",
+			Expected: &RoutingRuleId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "rule1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORS/frontdoor1/ROUTINGRULES/rule1",
+			Expected: &RoutingRuleId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "rule1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRs/frontdoor1/RoUtInGrUlEs/rule1",
+			Expected: &RoutingRuleId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorName:  "frontdoor1",
+				Name:           "rule1",
+			},
+		},
+	}
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := RoutingRuleIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
+			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorName != v.Expected.FrontDoorName {
+			t.Fatalf("Expected %q but got %q for FrontDoorName", v.Expected.FrontDoorName, actual.FrontDoorName)
+		}
+		if actual.Name != v.Expected.Name {
+			t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index ff009faa45ad..4e878b712b4b 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -5,3 +5,4 @@ package frontdoor
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FrontendEndpoint -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=LoadBalancing -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=RoutingRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/routing_rule_id.go b/azurerm/internal/services/frontdoor/validate/routing_rule_id.go
new file mode 100644
index 000000000000..2c65c2ac980e
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/routing_rule_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func RoutingRuleID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.RoutingRuleID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/routing_rule_id_test.go b/azurerm/internal/services/frontdoor/validate/routing_rule_id_test.go
new file mode 100644
index 000000000000..6a0b0ec4ca4a
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/routing_rule_id_test.go
@@ -0,0 +1,88 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestRoutingRuleID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/",
+			Valid: false,
+		},
+
+		{
+			// missing Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/",
+			Valid: false,
+		},
+
+		{
+			// missing value for Name
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORS/FRONTDOOR1/ROUTINGRULES/RULE1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := RoutingRuleID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From eb68c9f8db938443c491ad01ae4c4058ca479b9a Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:12:29 +0100
Subject: [PATCH 23/24] frontdoor: generating the Resource ID
 Formatter/Parser/Validator for Web Application Firewall Policy

---
 .../parse/web_application_firewall_policy.go  |  92 ++++++-
 .../web_application_firewall_policy_test.go   | 229 +++++++++++++++---
 .../services/frontdoor/resourceids.go         |   1 +
 .../web_application_firewall_policy_id.go     |  23 ++
 ...web_application_firewall_policy_id_test.go |  76 ++++++
 5 files changed, 374 insertions(+), 47 deletions(-)
 create mode 100644 azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id.go
 create mode 100644 azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id_test.go

diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
index 3dd9147f9532..3c60fe933b39 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy.go
@@ -1,38 +1,106 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"fmt"
+	"strings"
 
 	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
 )
 
 type WebApplicationFirewallPolicyId struct {
-	ResourceGroup string
-	Name          string
+	SubscriptionId                            string
+	ResourceGroup                             string
+	FrontDoorWebApplicationFirewallPolicyName string
 }
 
-func NewWebApplicationFirewallPolicyID(subscriptionId, resourceGroup, name string) WebApplicationFirewallPolicyId {
+func NewWebApplicationFirewallPolicyID(subscriptionId, resourceGroup, frontDoorWebApplicationFirewallPolicyName string) WebApplicationFirewallPolicyId {
 	return WebApplicationFirewallPolicyId{
-		ResourceGroup: resourceGroup,
-		Name:          name,
+		SubscriptionId: subscriptionId,
+		ResourceGroup:  resourceGroup,
+		FrontDoorWebApplicationFirewallPolicyName: frontDoorWebApplicationFirewallPolicyName,
+	}
+}
+
+func (id WebApplicationFirewallPolicyId) String() string {
+	segments := []string{
+		fmt.Sprintf("Resource Group %q", id.ResourceGroup),
+		fmt.Sprintf("Front Door Web Application Firewall Policy Name %q", id.FrontDoorWebApplicationFirewallPolicyName),
 	}
+	return strings.Join(segments, " / ")
 }
 
-func (id WebApplicationFirewallPolicyId) ID(subscriptionId string) string {
-	return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/%s", subscriptionId, id.ResourceGroup, id.Name)
+func (id WebApplicationFirewallPolicyId) ID(_ string) string {
+	fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/%s"
+	return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FrontDoorWebApplicationFirewallPolicyName)
+}
+
+// WebApplicationFirewallPolicyID parses a WebApplicationFirewallPolicy ID into an WebApplicationFirewallPolicyId struct
+func WebApplicationFirewallPolicyID(input string) (*WebApplicationFirewallPolicyId, error) {
+	id, err := azure.ParseAzureResourceID(input)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceId := WebApplicationFirewallPolicyId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
+	}
+
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
+	}
+
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	if resourceId.FrontDoorWebApplicationFirewallPolicyName, err = id.PopSegment("frontDoorWebApplicationFirewallPolicies"); err != nil {
+		return nil, err
+	}
+
+	if err := id.ValidateNoEmptySegments(input); err != nil {
+		return nil, err
+	}
+
+	return &resourceId, nil
 }
 
+// WebApplicationFirewallPolicyIDInsensitively parses an WebApplicationFirewallPolicy ID into an WebApplicationFirewallPolicyId struct, insensitively
+// This should only be used to parse an ID for rewriting, the WebApplicationFirewallPolicyID
+// method should be used instead for validation etc.
+//
+// Whilst this may seem strange, this enables Terraform have consistent casing
+// which works around issues in Core, whilst handling broken API responses.
 func WebApplicationFirewallPolicyIDInsensitively(input string) (*WebApplicationFirewallPolicyId, error) {
 	id, err := azure.ParseAzureResourceID(input)
 	if err != nil {
-		return nil, fmt.Errorf("parsing Web Application Firewall Policy ID %q: %+v", input, err)
+		return nil, err
+	}
+
+	resourceId := WebApplicationFirewallPolicyId{
+		SubscriptionId: id.SubscriptionID,
+		ResourceGroup:  id.ResourceGroup,
 	}
 
-	policy := WebApplicationFirewallPolicyId{
-		ResourceGroup: id.ResourceGroup,
+	if resourceId.SubscriptionId == "" {
+		return nil, fmt.Errorf("ID was missing the 'subscriptions' element")
 	}
 
-	if policy.Name, err = id.PopSegment("frontDoorWebApplicationFirewallPolicies"); err != nil {
+	if resourceId.ResourceGroup == "" {
+		return nil, fmt.Errorf("ID was missing the 'resourceGroups' element")
+	}
+
+	// find the correct casing for the 'frontDoorWebApplicationFirewallPolicies' segment
+	frontDoorWebApplicationFirewallPoliciesKey := "frontDoorWebApplicationFirewallPolicies"
+	for key := range id.Path {
+		if strings.EqualFold(key, frontDoorWebApplicationFirewallPoliciesKey) {
+			frontDoorWebApplicationFirewallPoliciesKey = key
+			break
+		}
+	}
+	if resourceId.FrontDoorWebApplicationFirewallPolicyName, err = id.PopSegment(frontDoorWebApplicationFirewallPoliciesKey); err != nil {
 		return nil, err
 	}
 
@@ -40,5 +108,5 @@ func WebApplicationFirewallPolicyIDInsensitively(input string) (*WebApplicationF
 		return nil, err
 	}
 
-	return &policy, nil
+	return &resourceId, nil
 }
diff --git a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
index e346ab2c00bf..f50c45a2c89b 100644
--- a/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
+++ b/azurerm/internal/services/frontdoor/parse/web_application_firewall_policy_test.go
@@ -1,5 +1,7 @@
 package parse
 
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
 import (
 	"testing"
 
@@ -9,62 +11,219 @@ import (
 var _ resourceid.Formatter = WebApplicationFirewallPolicyId{}
 
 func TestWebApplicationFirewallPolicyIDFormatter(t *testing.T) {
-	subscriptionId := "12345678-1234-5678-1234-123456789012"
-	actual := NewWebApplicationFirewallPolicyID(subscriptionId, "group1", "policy1").ID("")
-	expected := "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1"
+	actual := NewWebApplicationFirewallPolicyID("12345678-1234-9876-4563-123456789012", "resGroup1", "policy1").ID("")
+	expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1"
 	if actual != expected {
 		t.Fatalf("Expected %q but got %q", expected, actual)
 	}
 }
 
-func TestWebApplicationFirewallPolicyIDParser(t *testing.T) {
+func TestWebApplicationFirewallPolicyID(t *testing.T) {
 	testData := []struct {
-		input    string
-		expected *WebApplicationFirewallPolicyId
+		Input    string
+		Error    bool
+		Expected *WebApplicationFirewallPolicyId
 	}{
+
 		{
-			// lower case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontdoorwebapplicationfirewallpolicies/policy1",
-			expected: nil,
+			// empty
+			Input: "",
+			Error: true,
 		},
+
 		{
-			// camel case
-			input: "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1",
-			expected: &WebApplicationFirewallPolicyId{
-				ResourceGroup: "group1",
-				Name:          "policy1",
-			},
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
 		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/",
+			Error: true,
+		},
+
 		{
-			// title case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/FrontDoorWebApplicationFirewallPolicies/policy1",
-			expected: nil,
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1",
+			Expected: &WebApplicationFirewallPolicyId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorWebApplicationFirewallPolicyName: "policy1",
+			},
 		},
+
 		{
-			// pascal case
-			input:    "/subscriptions/12345678-1234-5678-1234-123456789012/resourceGroups/group1/providers/Microsoft.Network/Frontdoorwebapplicationfirewallpolicies/policy1",
-			expected: nil,
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES/POLICY1",
+			Error: true,
 		},
 	}
-	for _, test := range testData {
-		t.Logf("Testing %q..", test.input)
-		actual, err := WebApplicationFirewallPolicyIDInsensitively(test.input)
-		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)
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := WebApplicationFirewallPolicyID(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
 			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
 		}
 
-		if actual.ResourceGroup != test.expected.ResourceGroup {
-			t.Fatalf("Expected ResourceGroup to be %q but was %q", test.expected.ResourceGroup, actual.ResourceGroup)
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorWebApplicationFirewallPolicyName != v.Expected.FrontDoorWebApplicationFirewallPolicyName {
+			t.Fatalf("Expected %q but got %q for FrontDoorWebApplicationFirewallPolicyName", v.Expected.FrontDoorWebApplicationFirewallPolicyName, actual.FrontDoorWebApplicationFirewallPolicyName)
 		}
+	}
+}
 
-		if actual.Name != test.expected.Name {
-			t.Fatalf("Expected name to be %q but was %q", test.expected.Name, actual.Name)
+func TestWebApplicationFirewallPolicyIDInsensitively(t *testing.T) {
+	testData := []struct {
+		Input    string
+		Error    bool
+		Expected *WebApplicationFirewallPolicyId
+	}{
+
+		{
+			// empty
+			Input: "",
+			Error: true,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Error: true,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Error: true,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Error: true,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Error: true,
+		},
+
+		{
+			// missing FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Error: true,
+		},
+
+		{
+			// missing value for FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/",
+			Error: true,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1",
+			Expected: &WebApplicationFirewallPolicyId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorWebApplicationFirewallPolicyName: "policy1",
+			},
+		},
+
+		{
+			// lower-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontdoorwebapplicationfirewallpolicies/policy1",
+			Expected: &WebApplicationFirewallPolicyId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorWebApplicationFirewallPolicyName: "policy1",
+			},
+		},
+
+		{
+			// upper-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES/policy1",
+			Expected: &WebApplicationFirewallPolicyId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorWebApplicationFirewallPolicyName: "policy1",
+			},
+		},
+
+		{
+			// mixed-cased segment names
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/FrOnTdOoRwEbApPlIcAtIoNfIrEwAlLpOlIcIeS/policy1",
+			Expected: &WebApplicationFirewallPolicyId{
+				SubscriptionId: "12345678-1234-9876-4563-123456789012",
+				ResourceGroup:  "resGroup1",
+				FrontDoorWebApplicationFirewallPolicyName: "policy1",
+			},
+		},
+	}
+
+	for _, v := range testData {
+		t.Logf("[DEBUG] Testing %q", v.Input)
+
+		actual, err := WebApplicationFirewallPolicyIDInsensitively(v.Input)
+		if err != nil {
+			if v.Error {
+				continue
+			}
+
+			t.Fatalf("Expect a value but got an error: %s", err)
+		}
+		if v.Error {
+			t.Fatal("Expect an error but didn't get one")
+		}
+
+		if actual.SubscriptionId != v.Expected.SubscriptionId {
+			t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId)
+		}
+		if actual.ResourceGroup != v.Expected.ResourceGroup {
+			t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup)
+		}
+		if actual.FrontDoorWebApplicationFirewallPolicyName != v.Expected.FrontDoorWebApplicationFirewallPolicyName {
+			t.Fatalf("Expected %q but got %q for FrontDoorWebApplicationFirewallPolicyName", v.Expected.FrontDoorWebApplicationFirewallPolicyName, actual.FrontDoorWebApplicationFirewallPolicyName)
 		}
 	}
 }
diff --git a/azurerm/internal/services/frontdoor/resourceids.go b/azurerm/internal/services/frontdoor/resourceids.go
index 4e878b712b4b..6c7e75bcb749 100644
--- a/azurerm/internal/services/frontdoor/resourceids.go
+++ b/azurerm/internal/services/frontdoor/resourceids.go
@@ -6,3 +6,4 @@ package frontdoor
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=HealthProbe -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/healthProbeSettings/probe1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=LoadBalancing -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/loadBalancingSettings/setting1 -rewrite=true
 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=RoutingRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoors/frontdoor1/routingRules/rule1 -rewrite=true
+//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=WebApplicationFirewallPolicy -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1 -rewrite=true
diff --git a/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id.go b/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id.go
new file mode 100644
index 000000000000..5f533dd68d22
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id.go
@@ -0,0 +1,23 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import (
+	"fmt"
+
+	"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/frontdoor/parse"
+)
+
+func WebApplicationFirewallPolicyID(input interface{}, key string) (warnings []string, errors []error) {
+	v, ok := input.(string)
+	if !ok {
+		errors = append(errors, fmt.Errorf("expected %q to be a string", key))
+		return
+	}
+
+	if _, err := parse.WebApplicationFirewallPolicyID(v); err != nil {
+		errors = append(errors, err)
+	}
+
+	return
+}
diff --git a/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id_test.go b/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id_test.go
new file mode 100644
index 000000000000..076ec024088c
--- /dev/null
+++ b/azurerm/internal/services/frontdoor/validate/web_application_firewall_policy_id_test.go
@@ -0,0 +1,76 @@
+package validate
+
+// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten
+
+import "testing"
+
+func TestWebApplicationFirewallPolicyID(t *testing.T) {
+	cases := []struct {
+		Input string
+		Valid bool
+	}{
+
+		{
+			// empty
+			Input: "",
+			Valid: false,
+		},
+
+		{
+			// missing SubscriptionId
+			Input: "/",
+			Valid: false,
+		},
+
+		{
+			// missing value for SubscriptionId
+			Input: "/subscriptions/",
+			Valid: false,
+		},
+
+		{
+			// missing ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/",
+			Valid: false,
+		},
+
+		{
+			// missing value for ResourceGroup
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/",
+			Valid: false,
+		},
+
+		{
+			// missing FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/",
+			Valid: false,
+		},
+
+		{
+			// missing value for FrontDoorWebApplicationFirewallPolicyName
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/",
+			Valid: false,
+		},
+
+		{
+			// valid
+			Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/frontDoorWebApplicationFirewallPolicies/policy1",
+			Valid: true,
+		},
+
+		{
+			// upper-cased
+			Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES/POLICY1",
+			Valid: false,
+		},
+	}
+	for _, tc := range cases {
+		t.Logf("[DEBUG] Testing Value %s", tc.Input)
+		_, errors := WebApplicationFirewallPolicyID(tc.Input, "test")
+		valid := len(errors) == 0
+
+		if tc.Valid != valid {
+			t.Fatalf("Expected %t but got %t", tc.Valid, valid)
+		}
+	}
+}

From cc4082dbb50fd28e111cfde3494ae63f59fb6e02 Mon Sep 17 00:00:00 2001
From: tombuildsstuff <git@ibuildstuff.co.uk>
Date: Mon, 7 Dec 2020 20:15:06 +0100
Subject: [PATCH 24/24] frontdoor: fixing the build to match the generated code

---
 .../frontdoor/frontdoor_firewall_policy_resource.go  | 12 ++++++------
 .../frontdoor_firewall_policy_resource_test.go       |  4 ++--
 .../services/frontdoor/frontdoor_resource.go         |  4 ++--
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
index 74c50698f42a..ad9049d1ca52 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource.go
@@ -517,17 +517,17 @@ func resourceFrontDoorFirewallPolicyRead(d *schema.ResourceData, meta interface{
 		return err
 	}
 
-	resp, err := client.Get(ctx, id.ResourceGroup, id.Name)
+	resp, err := client.Get(ctx, id.ResourceGroup, id.FrontDoorWebApplicationFirewallPolicyName)
 	if err != nil {
 		if utils.ResponseWasNotFound(resp.Response) {
 			log.Printf("[INFO] Front Door Firewall Policy %q does not exist - removing from state", d.Id())
 			d.SetId("")
 			return nil
 		}
-		return fmt.Errorf("retrieving Front Door Firewall Policy %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
+		return fmt.Errorf("retrieving Front Door Firewall Policy %q (Resource Group %q): %+v", id.FrontDoorWebApplicationFirewallPolicyName, id.ResourceGroup, err)
 	}
 
-	d.Set("name", id.Name)
+	d.Set("name", id.FrontDoorWebApplicationFirewallPolicyName)
 	d.Set("resource_group_name", id.ResourceGroup)
 
 	if location := resp.Location; location != nil {
@@ -569,17 +569,17 @@ func resourceFrontDoorFirewallPolicyDelete(d *schema.ResourceData, meta interfac
 		return err
 	}
 
-	future, err := client.Delete(ctx, id.ResourceGroup, id.Name)
+	future, err := client.Delete(ctx, id.ResourceGroup, id.FrontDoorWebApplicationFirewallPolicyName)
 	if err != nil {
 		if response.WasNotFound(future.Response()) {
 			return nil
 		}
-		return fmt.Errorf("deleting Front Door Firewall %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
+		return fmt.Errorf("deleting Front Door Firewall %q (Resource Group %q): %+v", id.FrontDoorWebApplicationFirewallPolicyName, id.ResourceGroup, err)
 	}
 
 	if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
 		if !response.WasNotFound(future.Response()) {
-			return fmt.Errorf("waiting for deleting Front Door Firewall %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err)
+			return fmt.Errorf("waiting for deleting Front Door Firewall %q (Resource Group %q): %+v", id.FrontDoorWebApplicationFirewallPolicyName, id.ResourceGroup, err)
 		}
 	}
 
diff --git a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
index ce03f0a0b67e..25165d049112 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_firewall_policy_resource_test.go
@@ -114,9 +114,9 @@ func (FrontDoorFirewallPolicyResource) Exists(ctx context.Context, clients *clie
 		return nil, err
 	}
 
-	resp, err := clients.Frontdoor.FrontDoorsPolicyClient.Get(ctx, id.ResourceGroup, id.Name)
+	resp, err := clients.Frontdoor.FrontDoorsPolicyClient.Get(ctx, id.ResourceGroup, id.FrontDoorWebApplicationFirewallPolicyName)
 	if err != nil {
-		return nil, fmt.Errorf("retrieving Front Door Firewall Policy %q (Resource Group %q): %v", id.Name, id.ResourceGroup, err)
+		return nil, fmt.Errorf("retrieving Front Door Firewall Policy %q (Resource Group %q): %v", id.FrontDoorWebApplicationFirewallPolicyName, id.ResourceGroup, err)
 	}
 
 	return utils.Bool(resp.WebApplicationFirewallPolicyProperties != nil), nil
diff --git a/azurerm/internal/services/frontdoor/frontdoor_resource.go b/azurerm/internal/services/frontdoor/frontdoor_resource.go
index 536cad0d5eac..81681f3b1ee8 100644
--- a/azurerm/internal/services/frontdoor/frontdoor_resource.go
+++ b/azurerm/internal/services/frontdoor/frontdoor_resource.go
@@ -1119,7 +1119,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 					return nil, err
 				}
 
-				healthProbeName = name.Name
+				healthProbeName = name.HealthProbeSettingName
 			}
 
 			if props.LoadBalancingSettings != nil && props.LoadBalancingSettings.ID != nil {
@@ -1128,7 +1128,7 @@ func flattenFrontDoorBackendPools(input *[]frontdoor.BackendPool, frontDoorId pa
 					return nil, err
 				}
 
-				loadBalancingName = name.Name
+				loadBalancingName = name.LoadBalancingSettingName
 			}
 		}
 		output = append(output, map[string]interface{}{