Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New data sources azurerm_management_group_template_deployment, azurerm_resource_group_template_deployment, azurerm_subscription_template_deployment, azurerm_tenant_template_deployment #14524

Merged
merged 20 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package resource

import (
"fmt"
"time"

"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/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"
)

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_id": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: mgValidate.ManagementGroupID,
},

// 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()

managementGroupId := d.Get("management_group_id").(string)
deploymentName := d.Get("name").(string)

resp, err := client.GetAtManagementGroupScope(ctx, managementGroupId, deploymentName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("deployment %s in Management Group %s was not found", deploymentName, managementGroupId)
}

return fmt.Errorf("retrieving Management Group Template Deployment %s in management group %s: %+v", deploymentName, managementGroupId, err)
}

d.SetId(*resp.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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package resource_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
)

type ManagementGroupTemplateDeploymentDataSource struct{}

func TestAccDataSourceManagementGroupTemplateDeployment(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurerm_management_group_template_deployment", "test")
r := ManagementGroupTemplateDeploymentDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: r.withOutputsConfig(data),
},
{
Config: r.withDataSource(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("output_content").HasValue("{\"testOutput\":{\"type\":\"String\",\"value\":\"some-value\"}}"),
),
},
})
}

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 = <<TEMPLATE
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [],
"outputs": {
"testOutput": {
"type": "String",
"value": "some-value"
}
}
}
TEMPLATE
}
`, data.RandomInteger, data.Locations.Primary)
}

func (r ManagementGroupTemplateDeploymentDataSource) withDataSource(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

data "azurerm_management_group_template_deployment" "test" {
name = azurerm_management_group_template_deployment.test.name
management_group_id = azurerm_management_group.test.id
}
`, r.withOutputsConfig(data))
}
10 changes: 7 additions & 3 deletions internal/services/resource/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package resource

import (
"fmt"
"time"

"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"
)

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()

resourceGroupName := d.Get("resource_group_name").(string)
deploymentName := d.Get("name").(string)
id := parse.NewResourceGroupTemplateDeploymentID(subscriptionId, resourceGroupName, deploymentName)

resp, err := client.Get(ctx, id.ResourceGroup, id.DeploymentName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("template %s in resource Group %s was not found", deploymentName, resourceGroupName)
}

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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package resource_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check"
)

type ResourceGroupTemplateDeploymentDataSource struct{}

func TestAccDataSourceResourceGroupTemplateDeployment(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurerm_resource_group_template_deployment", "test")
r := ResourceGroupTemplateDeploymentDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: r.withOutputsConfig(data),
},
{
Config: r.withDataSource(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("output_content").HasValue("{\"testOutput\":{\"type\":\"String\",\"value\":\"some-value\"}}"),
),
},
})
}

func (ResourceGroupTemplateDeploymentDataSource) withOutputsConfig(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = %q
}

resource "azurerm_resource_group_template_deployment" "test" {
name = "acctest"
resource_group_name = azurerm_resource_group.test.name
deployment_mode = "Complete"

template_content = <<TEMPLATE
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [],
"outputs": {
"testOutput": {
"type": "String",
"value": "some-value"
}
}
}
TEMPLATE
}
`, data.RandomInteger, data.Locations.Primary)
}

func (r ResourceGroupTemplateDeploymentDataSource) withDataSource(data acceptance.TestData) string {
return fmt.Sprintf(`
%s

data "azurerm_resource_group_template_deployment" "test" {
name = azurerm_resource_group_template_deployment.test.name
resource_group_name = azurerm_resource_group.test.name
}
`, r.withOutputsConfig(data))
}
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ resource "azurerm_resource_group_template_deployment" "test" {
resource_group_name = azurerm_resource_group.test.name
deployment_mode = %q
tags = {
Hello = "World"
hello = "world"
}

template_content = <<TEMPLATE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package resource

import (
"fmt"
"time"

"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"
)

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) {
return fmt.Errorf("template %s in subscription %s was not found", id.DeploymentName, subscriptionId)
}

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
}
Loading