From 30c4ec3c6134fd17f79e044b80e0af2cd3699f47 Mon Sep 17 00:00:00 2001 From: Sam Debruyn Date: Wed, 8 Dec 2021 00:28:19 +0100 Subject: [PATCH 01/20] template data sources implementation --- ...t_group_template_deployment_data_source.go | 76 +++++++++++++++++++ ...up_template_deployment_data_source_test.go | 1 + internal/services/resource/registration.go | 10 ++- ...e_group_template_deployment_data_source.go | 74 ++++++++++++++++++ ...up_template_deployment_data_source_test.go | 1 + ...ription_template_deployment_data_source.go | 70 +++++++++++++++++ ...on_template_deployment_data_source_test.go | 1 + .../tenant_template_deployment_data_source.go | 69 +++++++++++++++++ ...nt_template_deployment_data_source_test.go | 1 + 9 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 internal/services/resource/management_group_template_deployment_data_source.go create mode 100644 internal/services/resource/management_group_template_deployment_data_source_test.go create mode 100644 internal/services/resource/resource_group_template_deployment_data_source.go create mode 100644 internal/services/resource/resource_group_template_deployment_data_source_test.go create mode 100644 internal/services/resource/subscription_template_deployment_data_source.go create mode 100644 internal/services/resource/subscription_template_deployment_data_source_test.go create mode 100644 internal/services/resource/tenant_template_deployment_data_source.go create mode 100644 internal/services/resource/tenant_template_deployment_data_source_test.go diff --git a/internal/services/resource/management_group_template_deployment_data_source.go b/internal/services/resource/management_group_template_deployment_data_source.go new file mode 100644 index 000000000000..83c3f8919bf4 --- /dev/null +++ b/internal/services/resource/management_group_template_deployment_data_source.go @@ -0,0 +1,76 @@ +package resource + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + mgValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/managementgroup/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "log" + "time" +) + +func dataSourceManagementGroupTemplateDeployment() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceManagementGroupTemplateDeploymentRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.TemplateDeploymentName, + }, + + "management_group_name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: mgValidate.ManagementGroupName, + }, + + // Computed + "output_content": { + Type: pluginsdk.TypeString, + Computed: true, + // NOTE: outputs can be strings, ints, objects etc - whilst using a nested object was considered + // parsing the JSON using `jsondecode` allows the users to interact with/map objects as required + }, + }, + } +} + +func dataSourceManagementGroupTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.DeploymentsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewManagementGroupTemplateDeploymentID(d.Get("management_group_name").(string), d.Get("name").(string)) + + resp, err := client.GetAtManagementGroupScope(ctx, id.ManagementGroupName, id.DeploymentName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Management Group Template Deployment %q was not found", id.DeploymentName) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Management Group Template Deployment %q: %+v", id.DeploymentName, err) + } + + if props := resp.Properties; props != nil { + flattenedOutputs, err := flattenTemplateDeploymentBody(props.Outputs) + if err != nil { + return fmt.Errorf("flattening `output_content`: %+v", err) + } + return d.Set("output_content", flattenedOutputs) + } + + return nil +} diff --git a/internal/services/resource/management_group_template_deployment_data_source_test.go b/internal/services/resource/management_group_template_deployment_data_source_test.go new file mode 100644 index 000000000000..6be08ff1cda1 --- /dev/null +++ b/internal/services/resource/management_group_template_deployment_data_source_test.go @@ -0,0 +1 @@ +package resource_test diff --git a/internal/services/resource/registration.go b/internal/services/resource/registration.go index 04e8a80cbfde..bb187c38f04a 100644 --- a/internal/services/resource/registration.go +++ b/internal/services/resource/registration.go @@ -29,9 +29,13 @@ func (r Registration) WebsiteCategories() []string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*pluginsdk.Resource { return map[string]*pluginsdk.Resource{ - "azurerm_resources": dataSourceResources(), - "azurerm_resource_group": dataSourceResourceGroup(), - "azurerm_template_spec_version": dataSourceTemplateSpecVersion(), + "azurerm_resources": dataSourceResources(), + "azurerm_resource_group": dataSourceResourceGroup(), + "azurerm_template_spec_version": dataSourceTemplateSpecVersion(), + "azurerm_management_group_template_deployment": dataSourceManagementGroupTemplateDeployment(), + "azurerm_resource_group_template_deployment": dataSourceResourceGroupTemplateDeployment(), + "azurerm_subscription_template_deployment": dataSourceSubscriptionTemplateDeployment(), + "azurerm_tenant_template_deployment": dataSourceTenantTemplateDeployment(), } } diff --git a/internal/services/resource/resource_group_template_deployment_data_source.go b/internal/services/resource/resource_group_template_deployment_data_source.go new file mode 100644 index 000000000000..7be64d4f24b9 --- /dev/null +++ b/internal/services/resource/resource_group_template_deployment_data_source.go @@ -0,0 +1,74 @@ +package resource + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "log" + "time" +) + +func dataSourceResourceGroupTemplateDeployment() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceResourceGroupTemplateDeploymentRead, + + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.TemplateDeploymentName, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + // Computed + "output_content": { + Type: pluginsdk.TypeString, + Computed: true, + // NOTE: outputs can be strings, ints, objects etc - whilst using a nested object was considered + // parsing the JSON using `jsondecode` allows the users to interact with/map objects as required + }, + }, + } +} + +func dataSourceResourceGroupTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.DeploymentsClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewResourceGroupTemplateDeploymentID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + resp, err := client.Get(ctx, id.ResourceGroup, id.DeploymentName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Template Deployment %q (Resource Group %q) was not found", id.DeploymentName, id.ResourceGroup) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Template Deployment %q (Resource Group %q): %+v", id.DeploymentName, id.ResourceGroup, err) + } + + d.SetId(id.ID()) + + if props := resp.Properties; props != nil { + flattenedOutputs, err := flattenTemplateDeploymentBody(props.Outputs) + if err != nil { + return fmt.Errorf("flattening `output_content`: %+v", err) + } + return d.Set("output_content", flattenedOutputs) + } + + return nil +} diff --git a/internal/services/resource/resource_group_template_deployment_data_source_test.go b/internal/services/resource/resource_group_template_deployment_data_source_test.go new file mode 100644 index 000000000000..6be08ff1cda1 --- /dev/null +++ b/internal/services/resource/resource_group_template_deployment_data_source_test.go @@ -0,0 +1 @@ +package resource_test diff --git a/internal/services/resource/subscription_template_deployment_data_source.go b/internal/services/resource/subscription_template_deployment_data_source.go new file mode 100644 index 000000000000..f260d702df8a --- /dev/null +++ b/internal/services/resource/subscription_template_deployment_data_source.go @@ -0,0 +1,70 @@ +package resource + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "log" + "time" +) + +func dataSourceSubscriptionTemplateDeployment() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceSubscriptionTemplateDeploymentRead, + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.TemplateDeploymentName, + }, + + // Computed + "output_content": { + Type: pluginsdk.TypeString, + Computed: true, + // NOTE: outputs can be strings, ints, objects etc - whilst using a nested object was considered + // parsing the JSON using `jsondecode` allows the users to interact with/map objects as required + }, + }, + } +} + +func dataSourceSubscriptionTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.DeploymentsClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewSubscriptionTemplateDeploymentID(subscriptionId, d.Get("name").(string)) + + resp, err := client.GetAtSubscriptionScope(ctx, id.DeploymentName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Subscription Template Deployment %q was not found", id.DeploymentName) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Subscription Template Deployment %q: %+v", id.DeploymentName, err) + } + + d.SetId(id.ID()) + + if props := resp.Properties; props != nil { + flattenedOutputs, err := flattenTemplateDeploymentBody(props.Outputs) + if err != nil { + return fmt.Errorf("flattening `output_content`: %+v", err) + } + return d.Set("output_content", flattenedOutputs) + } + + return nil +} diff --git a/internal/services/resource/subscription_template_deployment_data_source_test.go b/internal/services/resource/subscription_template_deployment_data_source_test.go new file mode 100644 index 000000000000..958e3540f767 --- /dev/null +++ b/internal/services/resource/subscription_template_deployment_data_source_test.go @@ -0,0 +1 @@ +package resource diff --git a/internal/services/resource/tenant_template_deployment_data_source.go b/internal/services/resource/tenant_template_deployment_data_source.go new file mode 100644 index 000000000000..4af5154a0a3c --- /dev/null +++ b/internal/services/resource/tenant_template_deployment_data_source.go @@ -0,0 +1,69 @@ +package resource + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" + "log" + "time" +) + +func dataSourceTenantTemplateDeployment() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Read: dataSourceTenantTemplateDeploymentRead, + Timeouts: &pluginsdk.ResourceTimeout{ + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + }, + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.TemplateDeploymentName, + }, + + // Computed + "output_content": { + Type: pluginsdk.TypeString, + Computed: true, + // NOTE: outputs can be strings, ints, objects etc - whilst using a nested object was considered + // parsing the JSON using `jsondecode` allows the users to interact with/map objects as required + }, + }, + } +} + +func dataSourceTenantTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Resource.DeploymentsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id := parse.NewTenantTemplateDeploymentID(d.Get("name").(string)) + + resp, err := client.GetAtTenantScope(ctx, id.DeploymentName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Tenant Template Deployment %q was not found", id.DeploymentName) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving Tenant Template Deployment %q: %+v", id.DeploymentName, err) + } + + d.SetId(id.ID()) + + if props := resp.Properties; props != nil { + flattenedOutputs, err := flattenTemplateDeploymentBody(props.Outputs) + if err != nil { + return fmt.Errorf("flattening `output_content`: %+v", err) + } + return d.Set("output_content", flattenedOutputs) + } + + return nil +} diff --git a/internal/services/resource/tenant_template_deployment_data_source_test.go b/internal/services/resource/tenant_template_deployment_data_source_test.go new file mode 100644 index 000000000000..6be08ff1cda1 --- /dev/null +++ b/internal/services/resource/tenant_template_deployment_data_source_test.go @@ -0,0 +1 @@ +package resource_test From 0d65bf6cb06826408d046edb9cd1e99ee7fee35a Mon Sep 17 00:00:00 2001 From: Sam Debruyn Date: Wed, 8 Dec 2021 00:59:09 +0100 Subject: [PATCH 02/20] add test configs --- ...up_template_deployment_data_source_test.go | 53 ++++++++++++++++++ ...up_template_deployment_data_source_test.go | 54 +++++++++++++++++++ ...on_template_deployment_data_source_test.go | 49 ++++++++++++++++- ...nt_template_deployment_data_source_test.go | 47 ++++++++++++++++ 4 files changed, 202 insertions(+), 1 deletion(-) diff --git a/internal/services/resource/management_group_template_deployment_data_source_test.go b/internal/services/resource/management_group_template_deployment_data_source_test.go index 6be08ff1cda1..803bbe55f78c 100644 --- a/internal/services/resource/management_group_template_deployment_data_source_test.go +++ b/internal/services/resource/management_group_template_deployment_data_source_test.go @@ -1 +1,54 @@ package resource_test + +import ( + "fmt" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" +) + +type ManagementGroupTemplateDeploymentDataSource struct { +} + +func (ManagementGroupTemplateDeploymentDataSource) withOutputsConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_management_group" "test" { + name = "TestAcc-Deployment-%[1]d" +} + +resource "azurerm_management_group_template_deployment" "test" { + name = "acctestMGdeploy-%[1]d" + management_group_id = azurerm_management_group.test.id + location = %[2]q + + template_content = <