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 Resource: azurerm_policy_set_definition #2535

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b03a304
Added new resource: azurerm_policy_set_definition
olohmann Dec 18, 2018
1264f5a
Added documentation for azurerm_policy_set_definition.
olohmann Dec 18, 2018
e35cb85
Fixed goimports.
olohmann Dec 18, 2018
9565158
Update azurerm/resource_arm_policy_set_definition.go
katbyte Dec 18, 2018
fe23ffb
Update azurerm/resource_arm_policy_set_definition.go
katbyte Dec 18, 2018
a79d556
Update website/docs/r/policy_set_definition.html.markdown
katbyte Dec 18, 2018
71599cc
Update website/docs/r/policy_set_definition.html.markdown
katbyte Dec 18, 2018
7bed6de
Update website/docs/r/policy_set_definition.html.markdown
katbyte Dec 18, 2018
4538cf2
Update azurerm/resource_arm_policy_set_definition.go
katbyte Dec 18, 2018
a3a6066
Update azurerm/resource_arm_policy_set_definition.go
katbyte Dec 18, 2018
2994601
Update azurerm/resource_arm_policy_set_definition_test.go
katbyte Dec 18, 2018
14c7a11
Added parameter validation.
olohmann Dec 18, 2018
5e29dae
Clean up formatting and import sample.
olohmann Dec 18, 2018
ef48757
Fixed whitespace.
olohmann Dec 18, 2018
67bd3e9
Update website/docs/r/policy_set_definition.html.markdown
tombuildsstuff Dec 19, 2018
5f25b44
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
a3f42a0
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
551a7a7
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
32da510
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
faabcf3
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
78372b8
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
73720f3
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
f277daf
Update website/docs/r/policy_set_definition.html.markdown
tombuildsstuff Dec 19, 2018
c11d20d
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
e105206
Update azurerm/resource_arm_policy_set_definition.go
tombuildsstuff Dec 19, 2018
2d4cd01
Additional acceptance test case for custom policies.
olohmann Dec 19, 2018
f20e2a1
Merge branch 'azurerm_policy_set_definition' of github.com:olohmann/t…
olohmann Dec 19, 2018
ea98e6d
Fixing issues from code review
tombuildsstuff Dec 20, 2018
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
9 changes: 7 additions & 2 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,8 +321,9 @@ type ArmClient struct {
appServicesClient web.AppsClient

// Policy
policyAssignmentsClient policy.AssignmentsClient
policyDefinitionsClient policy.DefinitionsClient
policyAssignmentsClient policy.AssignmentsClient
policyDefinitionsClient policy.DefinitionsClient
policySetDefinitionsClient policy.SetDefinitionsClient
}

var (
Expand Down Expand Up @@ -1165,6 +1166,10 @@ func (c *ArmClient) registerPolicyClients(endpoint, subscriptionId string, auth
policyDefinitionsClient := policy.NewDefinitionsClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&policyDefinitionsClient.Client, auth)
c.policyDefinitionsClient = policyDefinitionsClient

policySetDefinitionsClient := policy.NewSetDefinitionsClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&policySetDefinitionsClient.Client, auth)
c.policySetDefinitionsClient = policySetDefinitionsClient
}

func (c *ArmClient) registerManagementGroupClients(endpoint string, auth autorest.Authorizer) {
Expand Down
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_packet_capture": resourceArmPacketCapture(),
"azurerm_policy_assignment": resourceArmPolicyAssignment(),
"azurerm_policy_definition": resourceArmPolicyDefinition(),
"azurerm_policy_set_definition": resourceArmPolicySetDefinition(),
"azurerm_postgresql_configuration": resourceArmPostgreSQLConfiguration(),
"azurerm_postgresql_database": resourceArmPostgreSQLDatabase(),
"azurerm_postgresql_firewall_rule": resourceArmPostgreSQLFirewallRule(),
Expand Down
279 changes: 279 additions & 0 deletions azurerm/resource_arm_policy_set_definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
package azurerm

import (
"context"
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
"strings"
"time"

"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/policy"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/structure"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmPolicySetDefinition() *schema.Resource {
return &schema.Resource{
Create: resourceArmPolicySetDefinitionCreateUpdate,
Update: resourceArmPolicySetDefinitionCreateUpdate,
Read: resourceArmPolicySetDefinitionRead,
Delete: resourceArmPolicySetDefinitionDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.NoEmptyStrings,
},
olohmann marked this conversation as resolved.
Show resolved Hide resolved

"policy_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(policy.TypeBuiltIn),
string(policy.TypeCustom),
}, false),
},

"display_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validate.NoEmptyStrings,
},
olohmann marked this conversation as resolved.
Show resolved Hide resolved

"description": {
Type: schema.TypeString,
Optional: true,
},

"metadata": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.ValidateJsonString,
DiffSuppressFunc: structure.SuppressJsonDiff,
},

"parameters": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.ValidateJsonString,
DiffSuppressFunc: structure.SuppressJsonDiff,
},

"policy_definitions": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.ValidateJsonString,
DiffSuppressFunc: policyDefinitionsDiffSuppressFunc,
olohmann marked this conversation as resolved.
Show resolved Hide resolved
},
},
}
}

func policyDefinitionsDiffSuppressFunc(k, old, new string, d *schema.ResourceData) bool {
var oldPolicyDefinitions []policy.DefinitionReference
errOld := json.Unmarshal([]byte(old), &oldPolicyDefinitions)
if errOld != nil {
return false
}

var newPolicyDefinitions []policy.DefinitionReference
errNew := json.Unmarshal([]byte(new), &newPolicyDefinitions)
if errNew != nil {
return false
}

return reflect.DeepEqual(oldPolicyDefinitions, newPolicyDefinitions)
}

func resourceArmPolicySetDefinitionCreateUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).policySetDefinitionsClient
ctx := meta.(*ArmClient).StopContext

name := d.Get("name").(string)
policyType := d.Get("policy_type").(string)
displayName := d.Get("display_name").(string)
description := d.Get("description").(string)

properties := policy.SetDefinitionProperties{
PolicyType: policy.Type(policyType),
DisplayName: utils.String(displayName),
Description: utils.String(description),
}

if metaDataString := d.Get("metadata").(string); metaDataString != "" {
metaData, err := structure.ExpandJsonFromString(metaDataString)
if err != nil {
return fmt.Errorf("unable to expand metadata json: %s", err)
}
properties.Metadata = &metaData
}

if parametersString := d.Get("parameters").(string); parametersString != "" {
parameters, err := structure.ExpandJsonFromString(parametersString)
if err != nil {
return fmt.Errorf("unable to expand parameters json: %s", err)
}
properties.Parameters = &parameters
}

if policyDefinitionsString := d.Get("policy_definitions").(string); policyDefinitionsString != "" {
var policyDefinitions []policy.DefinitionReference
err := json.Unmarshal([]byte(policyDefinitionsString), &policyDefinitions)
if err != nil {
return fmt.Errorf("unable to expand parameters json: %s", err)
}
properties.PolicyDefinitions = &policyDefinitions
}

definition := policy.SetDefinition{
Name: utils.String(name),
SetDefinitionProperties: &properties,
}

if _, err := client.CreateOrUpdate(ctx, name, definition); err != nil {
return fmt.Errorf("Error creating/updating Policy Set Definition %q: %s", name, err)
}

// Policy Definitions are eventually consistent; wait for them to stabilize
log.Printf("[DEBUG] Waiting for Policy Set Definition %q to become available", name)
stateConf := &resource.StateChangeConf{
Pending: []string{"404"},
Target: []string{"200"},
Refresh: policySetDefinitionRefreshFunc(ctx, client, name),
Timeout: 5 * time.Minute,
MinTimeout: 10 * time.Second,
ContinuousTargetOccurence: 10,
}
if _, err := stateConf.WaitForState(); err != nil {
return fmt.Errorf("Error waiting for Policy Set Definition %q to become available: %s", name, err)
}

resp, err := client.Get(ctx, name)
if err != nil {
return fmt.Errorf("Error retrieving Policy Set Definition %q: %s", name, err)
}

d.SetId(*resp.ID)

return resourceArmPolicySetDefinitionRead(d, meta)
}

func resourceArmPolicySetDefinitionRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).policySetDefinitionsClient
ctx := meta.(*ArmClient).StopContext

name, err := parsePolicySetDefinitionNameFromId(d.Id())
if err != nil {
return err
}

resp, err := client.Get(ctx, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
log.Printf("[INFO] Error reading Policy Set Definition %q - removing from state", d.Id())
d.SetId("")
return nil
}

return fmt.Errorf("Error reading Policy Set Definition %+v", err)
}

d.Set("name", resp.Name)

if props := resp.SetDefinitionProperties; props != nil {
d.Set("policy_type", string(props.PolicyType))
d.Set("display_name", props.DisplayName)
d.Set("description", props.Description)

if metadata := props.Metadata; metadata != nil {
metadataVal := metadata.(map[string]interface{})
metadataStr, err := structure.FlattenJsonToString(metadataVal)
if err != nil {
return fmt.Errorf("unable to flatten JSON for `metadata`: %s", err)
}

d.Set("metadata", metadataStr)
}

if parameters := props.Parameters; parameters != nil {
paramsVal := parameters.(map[string]interface{})
parametersStr, err := structure.FlattenJsonToString(paramsVal)
if err != nil {
return fmt.Errorf("unable to flatten JSON for `parameters`: %s", err)
}

d.Set("parameters", parametersStr)
}

if policyDefinitions := props.PolicyDefinitions; policyDefinitions != nil {
policyDefinitionsRes, err := json.Marshal(policyDefinitions)
if err != nil {
return fmt.Errorf("unable to flatten JSON for `policy_defintions`: %s", err)
}

policyDefinitionsStr := string(policyDefinitionsRes)
d.Set("policy_definitions", policyDefinitionsStr)
}
}

return nil
}

func resourceArmPolicySetDefinitionDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient).policySetDefinitionsClient
ctx := meta.(*ArmClient).StopContext

name, err := parsePolicySetDefinitionNameFromId(d.Id())
if err != nil {
return err
}

resp, err := client.Delete(ctx, name)
if err != nil {
if utils.ResponseWasNotFound(resp) {
return nil
}

return fmt.Errorf("Error deleting Policy Set Definition %q: %+v", name, err)
}

return nil
}

func parsePolicySetDefinitionNameFromId(id string) (string, error) {
components := strings.Split(id, "/")

if len(components) == 0 {
return "", fmt.Errorf("Azure Policy Set Definition Id is empty or not formatted correctly: %s", id)
}

if len(components) != 7 {
return "", fmt.Errorf("Azure Policy Set Definition Id should have 6 segments, got %d: '%s'", len(components)-1, id)
}

return components[6], nil
}

func policySetDefinitionRefreshFunc(ctx context.Context, client policy.SetDefinitionsClient, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
res, err := client.Get(ctx, name)
if err != nil {
return nil, strconv.Itoa(res.StatusCode), fmt.Errorf("Error issuing read request in policySetDefinitionRefreshFunc for Policy Set Definition %q: %s", name, err)
}

return res, strconv.Itoa(res.StatusCode), nil
}
}
Loading