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_definition #1010

Merged
merged 10 commits into from
Mar 27, 2018
11 changes: 11 additions & 0 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/Azure/azure-sdk-for-go/services/redis/mgmt/2016-04-01/redis"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-06-01/subscriptions"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-09-01/locks"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-12-01/policy"
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2017-05-10/resources"
"github.com/Azure/azure-sdk-for-go/services/scheduler/mgmt/2016-03-01/scheduler"
"github.com/Azure/azure-sdk-for-go/services/search/mgmt/2015-08-19/search"
Expand Down Expand Up @@ -193,6 +194,9 @@ type ArmClient struct {
// Web
appServicePlansClient web.AppServicePlansClient
appServicesClient web.AppsClient

// Policy
policyDefinitionsClient policy.DefinitionsClient
}

func (c *ArmClient) configureClient(client *autorest.Client, auth autorest.Authorizer) {
Expand Down Expand Up @@ -372,6 +376,7 @@ func getArmClient(c *authentication.Config) (*ArmClient, error) {
client.registerStorageClients(endpoint, c.SubscriptionID, auth)
client.registerTrafficManagerClients(endpoint, c.SubscriptionID, auth)
client.registerWebClients(endpoint, c.SubscriptionID, auth)
client.registerPolicyClients(endpoint, c.SubscriptionID, auth)

return &client, nil
}
Expand Down Expand Up @@ -864,6 +869,12 @@ func (c *ArmClient) registerWebClients(endpoint, subscriptionId string, auth aut
c.appServicesClient = appsClient
}

func (c *ArmClient) registerPolicyClients(endpoint, subscriptionId string, auth autorest.Authorizer) {
policyDefinitionsClient := policy.NewDefinitionsClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&policyDefinitionsClient.Client, auth)
c.policyDefinitionsClient = policyDefinitionsClient
}

var (
storageKeyCacheMu sync.RWMutex
storageKeyCache = make(map[string]string)
Expand Down
29 changes: 29 additions & 0 deletions azurerm/import_arm_policy_definition_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package azurerm

import (
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
)

func TestAccAzureRMPolicyDefinition_importBasic(t *testing.T) {
rInt := acctest.RandInt()
resourceName := "azurerm_policy_definition.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMPolicyDefinitionDestroy,
Steps: []resource.TestStep{
{
Config: testAzureRMPolicyDefinition_basic(rInt),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
1 change: 1 addition & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_network_security_group": resourceArmNetworkSecurityGroup(),
"azurerm_network_security_rule": resourceArmNetworkSecurityRule(),
"azurerm_network_watcher": resourceArmNetworkWatcher(),
"azurerm_policy_definition": resourceArmPolicyDefinition(),
"azurerm_postgresql_configuration": resourceArmPostgreSQLConfiguration(),
"azurerm_postgresql_database": resourceArmPostgreSQLDatabase(),
"azurerm_postgresql_firewall_rule": resourceArmPostgreSQLFirewallRule(),
Expand Down
241 changes: 241 additions & 0 deletions azurerm/resource_arm_policy_definition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
package azurerm

import (
"fmt"
"log"
"strings"

"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2016-12-01/policy"
"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/utils"
)

func resourceArmPolicyDefinition() *schema.Resource {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add some documentation for this resource in the website folder?

return &schema.Resource{
Create: resourceArmPolicyDefinitionCreateUpdate,
Update: resourceArmPolicyDefinitionCreateUpdate,
Read: resourceArmPolicyDefinitionRead,
Delete: resourceArmPolicyDefinitionDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

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

"mode": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
string(policy.All),
string(policy.Indexed),
string(policy.NotSpecified),
}, true),
},

"display_name": {
Type: schema.TypeString,
Required: true,
},

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

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

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

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

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

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

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

if policyRuleString := d.Get("policy_rule").(string); policyRuleString != "" {
policyRule, err := structure.ExpandJsonFromString(policyRuleString)
if err != nil {
return fmt.Errorf("unable to parse policy_rule: %s", err)
}
properties.PolicyRule = &policyRule
}

if metaDataString := d.Get("metadata").(string); metaDataString != "" {
metaData, err := structure.ExpandJsonFromString(metaDataString)
if err != nil {
return fmt.Errorf("unable to parse metadata: %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 parse parameters: %s", err)
}
properties.Parameters = &parameters
}

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

_, err := client.CreateOrUpdate(ctx, name, definition)
if err != nil {
return err
}

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

d.SetId(*resp.ID)

return resourceArmPolicyDefinitionRead(d, meta)
}

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

name, err := parsePolicyDefinitionNameFromId(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 Definition %q - removing from state", d.Id())
d.SetId("")
return nil
}

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

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

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

if policyRule := props.PolicyRule; policyRule != nil {
policyRuleStr, err := structure.FlattenJsonToString(*policyRule)
if err != nil {
return fmt.Errorf("unable to flatten JSON for `policy_rule`: %s", err)
}

d.Set("policy_rule", policyRuleStr)
}

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

d.Set("metadata", metadataStr)
}

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

d.Set("parameters", parametersStr)
}
}

return nil
}

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

name, err := parsePolicyDefinitionNameFromId(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 Definition %q: %+v", name, err)
}

return nil
}

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

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

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

return components[6], nil
}
Loading