Skip to content

Commit

Permalink
add new data source for built-in policy definition
Browse files Browse the repository at this point in the history
  • Loading branch information
wuxu92 committed Feb 16, 2023
1 parent c06cb90 commit ba5ea18
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 123 deletions.
8 changes: 4 additions & 4 deletions internal/services/policy/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import (
)

func getPolicyDefinitionByDisplayName(ctx context.Context, client *policy.DefinitionsClient, displayName, managementGroupName string,
typ policy.Type) (policy.Definition, error) {
builtInOnly bool) (policy.Definition, error) {
var policyDefinitions policy.DefinitionListResultIterator
var err error

if managementGroupName != "" {
policyDefinitions, err = client.ListByManagementGroupComplete(ctx, managementGroupName, "", nil)
} else {
if typ == policy.TypeBuiltIn {
if builtInOnly {
policyDefinitions, err = client.ListBuiltInComplete(ctx, "", nil)
} else {
policyDefinitions, err = client.ListComplete(ctx, "", nil)
Expand Down Expand Up @@ -53,10 +53,10 @@ func getPolicyDefinitionByDisplayName(ctx context.Context, client *policy.Defini
return results[0], nil
}

func getPolicyDefinitionByName(ctx context.Context, client *policy.DefinitionsClient, name, managementGroupName string, typ policy.Type) (res policy.Definition, err error) {
func getPolicyDefinitionByName(ctx context.Context, client *policy.DefinitionsClient, name, managementGroupName string) (res policy.Definition, err error) {
if managementGroupName == "" {
res, err = client.GetBuiltIn(ctx, name)
if utils.ResponseWasNotFound(res.Response) && typ != policy.TypeBuiltIn {
if utils.ResponseWasNotFound(res.Response) {
res, err = client.Get(ctx, name)
}
} else {
Expand Down
20 changes: 20 additions & 0 deletions internal/services/policy/policy_definition_built_in_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package policy

import (
"time"

"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
)

// dataSourceArmPolicyDefinitionBuiltIn read built-in policy definition only
func dataSourceArmPolicyDefinitionBuiltIn() *pluginsdk.Resource {
return &pluginsdk.Resource{
Read: policyDefinitionReadFunc(true),

Timeouts: &pluginsdk.ResourceTimeout{
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
},

Schema: policyDefinitionDataSourceSchema(),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package policy_test

import (
"fmt"
"testing"

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

type PolicyDefinitionBuiltInDataSource struct{}

func TestAccDataSourceAzureRMPolicyDefinitionBuiltIn_basic(t *testing.T) {
data := acceptance.BuildTestData(t, "data.azurerm_policy_definition_built_in", "test")
d := PolicyDefinitionBuiltInDataSource{}

data.DataSourceTest(t, []acceptance.TestStep{
{
Config: d.basic("Allowed resource types"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).Key("id").HasValue("/providers/Microsoft.Authorization/policyDefinitions/a08ec900-254a-4555-9bf5-e42af04b5c5c"),
check.That(data.ResourceName).Key("name").HasValue("a08ec900-254a-4555-9bf5-e42af04b5c5c"),
check.That(data.ResourceName).Key("display_name").HasValue("Allowed resource types"),
check.That(data.ResourceName).Key("type").HasValue("Microsoft.Authorization/policyDefinitions"),
check.That(data.ResourceName).Key("description").HasValue("This policy enables you to specify the resource types that your organization can deploy. Only resource types that support 'tags' and 'location' will be affected by this policy. To restrict all resources please duplicate this policy and change the 'mode' to 'All'."),
check.That(data.ResourceName).Key("mode").HasValue("Indexed"),
),
},
})
}

func (d PolicyDefinitionBuiltInDataSource) basic(name string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
data "azurerm_policy_definition_built_in" "test" {
display_name = "%s"
}
`, name)
}
230 changes: 116 additions & 114 deletions internal/services/policy/policy_definition_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,147 +14,149 @@ import (

func dataSourceArmPolicyDefinition() *pluginsdk.Resource {
return &pluginsdk.Resource{
Read: dataSourceArmPolicyDefinitionRead,
Read: policyDefinitionReadFunc(false),

Timeouts: &pluginsdk.ResourceTimeout{
Read: pluginsdk.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*pluginsdk.Schema{
"display_name": {
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"name", "display_name"},
},
Schema: policyDefinitionDataSourceSchema(),
}
}

"name": {
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"name", "display_name"},
},
func policyDefinitionDataSourceSchema() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
"display_name": {
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"name", "display_name"},
},

"management_group_name": {
Type: pluginsdk.TypeString,
Optional: true,
},
"name": {
Type: pluginsdk.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringIsNotEmpty,
ExactlyOneOf: []string{"name", "display_name"},
},

"type": {
Type: pluginsdk.TypeString,
Computed: true,
},
"management_group_name": {
Type: pluginsdk.TypeString,
Optional: true,
},

"description": {
Type: pluginsdk.TypeString,
Computed: true,
},
"type": {
Type: pluginsdk.TypeString,
Computed: true,
},

"policy_type": {
Type: pluginsdk.TypeString,
Computed: true,
Optional: true,
ValidateFunc: validation.StringInSlice(func() (res []string) {
for _, val := range policy.PossibleTypeValues() {
res = append(res, string(val))
}
return
}(), false),
},
"description": {
Type: pluginsdk.TypeString,
Computed: true,
},

"policy_rule": {
Type: pluginsdk.TypeString,
Computed: true,
},
"policy_type": {
Type: pluginsdk.TypeString,
Computed: true,
},

"parameters": {
Type: pluginsdk.TypeString,
Computed: true,
},
"policy_rule": {
Type: pluginsdk.TypeString,
Computed: true,
},

"metadata": {
Type: pluginsdk.TypeString,
Computed: true,
},
"parameters": {
Type: pluginsdk.TypeString,
Computed: true,
},

"role_definition_ids": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},
"metadata": {
Type: pluginsdk.TypeString,
Computed: true,
},

"mode": {
Type: pluginsdk.TypeString,
Computed: true,
"role_definition_ids": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
},

"mode": {
Type: pluginsdk.TypeString,
Computed: true,
},
}
}

func dataSourceArmPolicyDefinitionRead(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Policy.DefinitionsClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

displayName := d.Get("display_name").(string)
name := d.Get("name").(string)
managementGroupName := ""
if v, ok := d.GetOk("management_group_name"); ok {
managementGroupName = v.(string)
}
func policyDefinitionReadFunc(builtInOnly bool) func(d *pluginsdk.ResourceData, meta interface{}) error {
return func(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Policy.DefinitionsClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

displayName := d.Get("display_name").(string)
name := d.Get("name").(string)
managementGroupName := ""
if v, ok := d.GetOk("management_group_name"); ok {
managementGroupName = v.(string)
}

var policyDefinition policy.Definition
var err error
// one of display_name and name must be non-empty, this is guaranteed by schema
policyType := policy.Type(d.Get("policy_type").(string))
if displayName != "" {
policyDefinition, err = getPolicyDefinitionByDisplayName(ctx, client, displayName, managementGroupName, policyType)
if err != nil {
return fmt.Errorf("reading Policy Definition (Display Name %q): %+v", displayName, err)
var policyDefinition policy.Definition
var err error
// one of display_name and name must be non-empty, this is guaranteed by schema
if displayName != "" {
policyDefinition, err = getPolicyDefinitionByDisplayName(ctx, client, displayName, managementGroupName, builtInOnly)
if err != nil {
return fmt.Errorf("reading Policy Definition (Display Name %q): %+v", displayName, err)
}
}
}
if name != "" {
policyDefinition, err = getPolicyDefinitionByName(ctx, client, name, managementGroupName, policyType)
if name != "" {
if builtInOnly && managementGroupName == "" {
policyDefinition, err = client.GetBuiltIn(ctx, name)
} else {
policyDefinition, err = getPolicyDefinitionByName(ctx, client, name, managementGroupName)
}
if err != nil {
return fmt.Errorf("reading Policy Definition %q: %+v", name, err)
}
}

id, err := parse.PolicyDefinitionID(*policyDefinition.ID)
if err != nil {
return fmt.Errorf("reading Policy Definition %q: %+v", name, err)
return fmt.Errorf("parsing Policy Definition %q: %+v", *policyDefinition.ID, err)
}
}

id, err := parse.PolicyDefinitionID(*policyDefinition.ID)
if err != nil {
return fmt.Errorf("parsing Policy Definition %q: %+v", *policyDefinition.ID, err)
}
d.SetId(id.Id)
d.Set("name", policyDefinition.Name)
d.Set("display_name", policyDefinition.DisplayName)
d.Set("description", policyDefinition.Description)
d.Set("type", policyDefinition.Type)
d.Set("policy_type", policyDefinition.PolicyType)
d.Set("mode", policyDefinition.Mode)

policyRule := policyDefinition.PolicyRule.(map[string]interface{})
if policyRuleStr := flattenJSON(policyRule); policyRuleStr != "" {
d.Set("policy_rule", policyRuleStr)
roleIDs, _ := getPolicyRoleDefinitionIDs(policyRuleStr)
d.Set("role_definition_ids", roleIDs)
} else {
return fmt.Errorf("flattening Policy Definition Rule %q: %+v", name, err)
}

d.SetId(id.Id)
d.Set("name", policyDefinition.Name)
d.Set("display_name", policyDefinition.DisplayName)
d.Set("description", policyDefinition.Description)
d.Set("type", policyDefinition.Type)
d.Set("policy_type", policyDefinition.PolicyType)
d.Set("mode", policyDefinition.Mode)

policyRule := policyDefinition.PolicyRule.(map[string]interface{})
if policyRuleStr := flattenJSON(policyRule); policyRuleStr != "" {
d.Set("policy_rule", policyRuleStr)
roleIDs, _ := getPolicyRoleDefinitionIDs(policyRuleStr)
d.Set("role_definition_ids", roleIDs)
} else {
return fmt.Errorf("flattening Policy Definition Rule %q: %+v", name, err)
}
if metadataStr := flattenJSON(policyDefinition.Metadata); metadataStr != "" {
d.Set("metadata", metadataStr)
}

if metadataStr := flattenJSON(policyDefinition.Metadata); metadataStr != "" {
d.Set("metadata", metadataStr)
}
if parametersStr, err := flattenParameterDefinitionsValueToString(policyDefinition.Parameters); err == nil {
d.Set("parameters", parametersStr)
} else {
return fmt.Errorf("failed to flatten Policy Parameters %q: %+v", name, err)
}

if parametersStr, err := flattenParameterDefinitionsValueToString(policyDefinition.Parameters); err == nil {
d.Set("parameters", parametersStr)
} else {
return fmt.Errorf("failed to flatten Policy Parameters %q: %+v", name, err)
return nil
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ provider "azurerm" {
data "azurerm_policy_definition" "test" {
display_name = "%s"
policy_type = "BuiltIn"
}
`, name)
}
Expand Down
Loading

0 comments on commit ba5ea18

Please sign in to comment.