Skip to content

Commit

Permalink
Add terraform-provider support for Notification policies
Browse files Browse the repository at this point in the history
  • Loading branch information
Revathy Ramasundaram committed Jul 28, 2021
1 parent 9087090 commit 8af93a0
Show file tree
Hide file tree
Showing 3 changed files with 351 additions and 0 deletions.
1 change: 1 addition & 0 deletions cloudflare/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func Provider() terraform.ResourceProvider {
"cloudflare_zone_settings_override": resourceCloudflareZoneSettingsOverride(),
"cloudflare_zone": resourceCloudflareZone(),
"cloudflare_zone_dnssec": resourceCloudflareZoneDNSSEC(),
"cloudflare_notification_policy": resourceCloudflareNotificationPolicy(),
},
}

Expand Down
252 changes: 252 additions & 0 deletions cloudflare/resource_cloudflare_notification_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
package cloudflare

import (
"context"
"fmt"
"strings"
"time"

"github.com/cloudflare/cloudflare-go"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

func resourceCloudflareNotificationPolicy() *schema.Resource {
return &schema.Resource{
Create: resourceCloudflareNotificationPolicyCreate,
Read: resourceCloudflareNotificationPolicyRead,
Update: resourceCloudflareNotificationPolicyUpdate,
Delete: resourceCloudflareNotificationPolicyDelete,
Importer: &schema.ResourceImporter{
State: resourceNotificationPolicyImport,
},

Schema: map[string]*schema.Schema{
"account_id": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Required: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"enabled": {
Type: schema.TypeBool,
Required: true,
},
"alert_type": {
Type: schema.TypeString,
Required: true,
},
"filters": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeList,
Elem: schema.TypeString,
},
},
"created": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsRFC3339Time,
},
"modified": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.IsRFC3339Time,
},
"conditions": {
Type: schema.TypeMap,
Optional: true,
},
"email_integration": {
Type: schema.TypeSet,
Optional: true,
Elem: mechanismData,
},
"webhooks_integration": {
Type: schema.TypeSet,
Optional: true,
Elem: mechanismData,
},
"pagerduty_integration": {
Type: schema.TypeSet,
Optional: true,
Elem: mechanismData,
},
},
}
}

var mechanismData = &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Optional: true,
},
},
}

func resourceCloudflareNotificationPolicyCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
accountID := d.Get("account_id").(string)

notificationPolicy := buildNotificationPolicy(d)

policy, err := client.CreateNotificationPolicy(context.Background(), accountID, notificationPolicy)

if err != nil {
return fmt.Errorf("error creating policy %s: %s", notificationPolicy.Name, err)
}
d.SetId(policy.Result.ID)

return resourceCloudflareNotificationPolicyRead(d, meta)
}
func resourceCloudflareNotificationPolicyRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
policyID := d.Id()
accountID := d.Get("account_id").(string)

policy, err := client.GetNotificationPolicy(context.Background(), accountID, policyID)

name := d.Get("name").(string)
if err != nil {
return fmt.Errorf("error retrieving notification policy %s: %s", name, err)
}

err = setNotificationPolicy(d, policy)
if err != nil {
return fmt.Errorf("error setting notification policy object for %s: %s", name, err)
}
return nil
}

func resourceCloudflareNotificationPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
policyID := d.Id()
accountID := d.Get("account_id").(string)

notificationPolicy := buildNotificationPolicy(d)
notificationPolicy.ID = policyID

_, err := client.UpdateNotificationPolicy(context.Background(), accountID, &notificationPolicy)

if err != nil {
return fmt.Errorf("error updating notification policy %s: %s", policyID, err)
}

return resourceCloudflareNotificationPolicyRead(d, meta)
}
func resourceCloudflareNotificationPolicyDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*cloudflare.API)
policyID := d.Id()
accountID := d.Get("account_id").(string)

_, err := client.DeleteNotificationPolicy(context.Background(), accountID, policyID)

if err != nil {
return fmt.Errorf("error deleting notification policy %s: %s", policyID, err)
}
return nil
}
func resourceNotificationPolicyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
attributes := strings.SplitN(d.Id(), "/", 2)

if len(attributes) != 2 {
return nil, fmt.Errorf("invalid id (\"%s\") specified, should be in format \"accountID/policyID\"", d.Id())
}

accountID, policyID := attributes[0], attributes[1]
d.SetId(policyID)
d.Set("account_id", accountID)

resourceCloudflareNotificationPolicyRead(d, meta)

return []*schema.ResourceData{d}, nil

}
func buildNotificationPolicy(d *schema.ResourceData) cloudflare.NotificationPolicy {
notificationPolicy := cloudflare.NotificationPolicy{}
notificationPolicy.Mechanisms = make(map[string]cloudflare.NotificationMechanismIntegrations)
notificationPolicy.Conditions = make(map[string]interface{})
notificationPolicy.Filters = make(map[string][]string)

if name, ok := d.GetOk("name"); ok {
notificationPolicy.Name = name.(string)
}
if description, ok := d.GetOk("description"); ok {
notificationPolicy.Description = description.(string)
}
if enabled, ok := d.GetOk("enabled"); ok {
notificationPolicy.Enabled = enabled.(bool)
}
if alertType, ok := d.GetOk("alert_type"); ok {
notificationPolicy.AlertType = alertType.(string)
}
if emails, ok := d.GetOk("email_integration"); ok {
notificationPolicy.Mechanisms["email"] = getNotificationMechanisms(emails.(*schema.Set))
}
if webhooks, ok := d.GetOk("webhooks_integration"); ok {
notificationPolicy.Mechanisms["webhooks"] = getNotificationMechanisms(webhooks.(*schema.Set))
}
if pagerduty, ok := d.GetOk("pagerduty_integration"); ok {
notificationPolicy.Mechanisms["pagerduty"] = getNotificationMechanisms(pagerduty.(*schema.Set))
}
if filters, ok := d.GetOk("filters"); ok {
notificationPolicy.Filters = filters.(map[string][]string)
}
if conditions, ok := d.GetOk("conditions"); ok {
notificationPolicy.Conditions = conditions.(map[string]interface{})
}
return notificationPolicy
}

func setNotificationPolicy(d *schema.ResourceData, policy cloudflare.NotificationPolicyResponse) error {
var e error
e = d.Set("id", policy.Result.ID)
e = d.Set("name", policy.Result.Name)
e = d.Set("enabled", policy.Result.Enabled)
e = d.Set("alert_type", policy.Result.AlertType)
e = d.Set("description", policy.Result.Description)
e = d.Set("filters", policy.Result.Filters)
e = d.Set("conditions", policy.Result.Conditions)
e = d.Set("created", policy.Result.Created.Format(time.RFC3339))
e = d.Set("modified", policy.Result.Modified.Format(time.RFC3339))
e = d.Set("email_integration", setNotificationMechanisms(policy.Result.Mechanisms["email"]))
e = d.Set("pagerduty_integration", setNotificationMechanisms(policy.Result.Mechanisms["pagerduty"]))
e = d.Set("webhooks_integration", setNotificationMechanisms(policy.Result.Mechanisms["webhooks"]))
return e
}

func getNotificationMechanisms(s *schema.Set) []cloudflare.NotificationMechanismData {
var notificationMechanisms []cloudflare.NotificationMechanismData
for _, m := range s.List() {
mechanism := m.(map[string]interface{})
data := cloudflare.NotificationMechanismData{
ID: mechanism["id"].(string),
Name: mechanism["name"].(string),
}
notificationMechanisms = append(notificationMechanisms, data)
}
return notificationMechanisms
}

func setNotificationMechanisms(md []cloudflare.NotificationMechanismData) *schema.Set {
mechanisms := make([]interface{}, 0)
data := make(map[string]interface{})
for _, m := range md {
data["id"] = m.Name
data["name"] = m.ID
mechanisms = append(mechanisms, data)
}
return schema.NewSet(schema.HashResource(mechanismData), mechanisms)
}
98 changes: 98 additions & 0 deletions cloudflare/resource_cloudflare_notification_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package cloudflare

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)

func TestCloudflareCreateNotificationPolicy(t *testing.T) {
rnd := generateRandomResourceName()
resourceName := "cloudflare_notification_policy." + rnd

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckAccount(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testCheckCloudflareNotificationPolicy(rnd),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "test SSL policy from terraform provider"),
resource.TestCheckResourceAttr(resourceName, "description", "test description"),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "alert_type", "universal_ssl_event_type"),
resource.TestCheckResourceAttr(resourceName, "account_id", "a67e14daa5f8dceeb91fe5449ba496eb"),
),
},
},
})
}

func TestCloudflareCreateNotificationPolicyUpdate(t *testing.T) {
rnd := generateRandomResourceName()
resourceName := "cloudflare_notification_policy." + rnd
updatedPolicyName := "*updated* test SSL policy from terraform provider"
updatedPolicyDesc := "*updated* description"

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckAccount(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testCheckCloudflareNotificationPolicy(rnd),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "test SSL policy from terraform provider"),
resource.TestCheckResourceAttr(resourceName, "description", "test description"),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "alert_type", "universal_ssl_event_type"),
resource.TestCheckResourceAttr(resourceName, "account_id", "a67e14daa5f8dceeb91fe5449ba496eb"),
),
},
{
Config: testCheckCloudflareNotificationPolicyUpdated(rnd, updatedPolicyName, updatedPolicyDesc),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", updatedPolicyName),
resource.TestCheckResourceAttr(resourceName, "description", updatedPolicyDesc),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "alert_type", "universal_ssl_event_type"),
resource.TestCheckResourceAttr(resourceName, "account_id", "a67e14daa5f8dceeb91fe5449ba496eb"),
),
},
},
})
}

func testCheckCloudflareNotificationPolicy(name string) string {
return fmt.Sprintf(`
resource "cloudflare_notification_policy" "%[1]s" {
name = "test SSL policy from terraform provider"
account_id = "a67e14daa5f8dceeb91fe5449ba496eb"
description = "test description"
enabled = true
alert_type = "universal_ssl_event_type"
webhooks_integration {
id = "garrett webhook"
name = "7877572c5e764d27aa0f379d13645945"
}
}`, name)
}

func testCheckCloudflareNotificationPolicyUpdated(resName, policyName, policyDesc string) string {
return fmt.Sprintf(`
resource "cloudflare_notification_policy" "%[1]s" {
name = "%[2]s"
account_id = "a67e14daa5f8dceeb91fe5449ba496eb"
description = "%[3]s"
enabled = true
alert_type = "universal_ssl_event_type"
webhooks_integration {
id = "garrett webhook"
name = "7877572c5e764d27aa0f379d13645945"
}
}`, resName, policyName, policyDesc)
}

0 comments on commit 8af93a0

Please sign in to comment.