Skip to content

Commit

Permalink
Merge pull request #540 from terraform-providers/redis-patch-schedules
Browse files Browse the repository at this point in the history
`azurerm_redis_cache`: support for Patch Schedules
  • Loading branch information
tombuildsstuff authored Nov 9, 2017
2 parents 7753506 + 4beb9c2 commit 441ce31
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 33 deletions.
33 changes: 20 additions & 13 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ type ArmClient struct {

deploymentsClient resources.DeploymentsClient

redisClient redis.GroupClient
redisFirewallClient redis.FirewallRuleClient
redisClient redis.GroupClient
redisFirewallClient redis.FirewallRuleClient
redisPatchSchedulesClient redis.PatchSchedulesClient

trafficManagerProfilesClient trafficmanager.ProfilesClient
trafficManagerEndpointsClient trafficmanager.EndpointsClient
Expand Down Expand Up @@ -787,17 +788,23 @@ func (c *ArmClient) registerKeyVaultClients(endpoint, subscriptionId string, aut
}

func (c *ArmClient) registerRedisClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) {
rdc := redis.NewGroupClientWithBaseURI(endpoint, subscriptionId)
setUserAgent(&rdc.Client)
rdc.Authorizer = auth
rdc.Sender = sender
c.redisClient = rdc

rdfc := redis.NewFirewallRuleClientWithBaseURI(endpoint, subscriptionId)
setUserAgent(&rdfc.Client)
rdfc.Authorizer = auth
rdfc.Sender = sender
c.redisFirewallClient = rdfc
groupsClient := redis.NewGroupClientWithBaseURI(endpoint, subscriptionId)
setUserAgent(&groupsClient.Client)
groupsClient.Authorizer = auth
groupsClient.Sender = sender
c.redisClient = groupsClient

firewallRuleClient := redis.NewFirewallRuleClientWithBaseURI(endpoint, subscriptionId)
setUserAgent(&firewallRuleClient.Client)
firewallRuleClient.Authorizer = auth
firewallRuleClient.Sender = sender
c.redisFirewallClient = firewallRuleClient

patchSchedulesClient := redis.NewPatchSchedulesClientWithBaseURI(endpoint, subscriptionId)
setUserAgent(&patchSchedulesClient.Client)
patchSchedulesClient.Authorizer = auth
patchSchedulesClient.Sender = sender
c.redisPatchSchedulesClient = patchSchedulesClient
}

func (armClient *ArmClient) getKeyForStorageAccount(resourceGroupName, storageAccountName string) (string, bool, error) {
Expand Down
123 changes: 119 additions & 4 deletions azurerm/resource_arm_redis_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,34 @@ func resourceArmRedisCache() *schema.Resource {
},
},

"patch_schedule": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"day_of_week": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
}, true),
},
"start_hour_utc": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(0, 23),
},
},
},
},

"hostname": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -170,6 +198,11 @@ func resourceArmRedisCacheCreate(d *schema.ResourceData, meta interface{}) error
tags := d.Get("tags").(map[string]interface{})
expandedTags := expandTags(tags)

patchSchedule, err := expandRedisPatchSchedule(d)
if err != nil {
return fmt.Errorf("Error parsing Patch Schedule: %+v", err)
}

parameters := redis.CreateParameters{
Name: &name,
Location: &location,
Expand All @@ -191,7 +224,7 @@ func resourceArmRedisCacheCreate(d *schema.ResourceData, meta interface{}) error
}

_, error := client.Create(resGroup, name, parameters, make(chan struct{}))
err := <-error
err = <-error
if err != nil {
return err
}
Expand All @@ -218,6 +251,14 @@ func resourceArmRedisCacheCreate(d *schema.ResourceData, meta interface{}) error

d.SetId(*read.ID)

if schedule := patchSchedule; schedule != nil {
patchClient := meta.(*ArmClient).redisPatchSchedulesClient
_, err = patchClient.CreateOrUpdate(resGroup, name, *schedule)
if err != nil {
return fmt.Errorf("Error setting Redis Patch Schedule: %+v", err)
}
}

return resourceArmRedisCacheRead(d, meta)
}

Expand Down Expand Up @@ -288,6 +329,24 @@ func resourceArmRedisCacheUpdate(d *schema.ResourceData, meta interface{}) error

d.SetId(*read.ID)

patchSchedule, err := expandRedisPatchSchedule(d)
if err != nil {
return fmt.Errorf("Error parsing Patch Schedule: %+v", err)
}

patchClient := meta.(*ArmClient).redisPatchSchedulesClient
if patchSchedule == nil || len(*patchSchedule.ScheduleEntries.ScheduleEntries) == 0 {
_, err = patchClient.Delete(resGroup, name)
if err != nil {
return fmt.Errorf("Error deleting Redis Patch Schedule: %+v", err)
}
} else {
_, err = patchClient.CreateOrUpdate(resGroup, name, *patchSchedule)
if err != nil {
return fmt.Errorf("Error setting Redis Patch Schedule: %+v", err)
}
}

return resourceArmRedisCacheRead(d, meta)
}

Expand Down Expand Up @@ -318,16 +377,29 @@ func resourceArmRedisCacheRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error making ListKeys request on Azure Redis Cache %s: %s", name, err)
}

patchSchedulesClient := meta.(*ArmClient).redisPatchSchedulesClient

schedule, err := patchSchedulesClient.Get(resGroup, name)
if err == nil {
patchSchedule := flattenRedisPatchSchedules(schedule)
if err := d.Set("patch_schedule", patchSchedule); err != nil {
return fmt.Errorf("Error setting `patch_schedule`: %+v", err)
}
}

d.Set("name", name)
d.Set("resource_group_name", resGroup)
d.Set("location", azureRMNormalizeLocation(*resp.Location))
d.Set("ssl_port", resp.SslPort)
d.Set("hostname", resp.HostName)
d.Set("port", resp.Port)
d.Set("enable_non_ssl_port", resp.EnableNonSslPort)
d.Set("capacity", resp.Sku.Capacity)
d.Set("family", resp.Sku.Family)
d.Set("sku_name", resp.Sku.Name)

if sku := resp.Sku; sku != nil {
d.Set("capacity", sku.Capacity)
d.Set("family", sku.Family)
d.Set("sku_name", sku.Name)
}

if resp.ShardCount != nil {
d.Set("shard_count", resp.ShardCount)
Expand Down Expand Up @@ -426,6 +498,34 @@ func expandRedisConfiguration(d *schema.ResourceData) *map[string]*string {
return &output
}

func expandRedisPatchSchedule(d *schema.ResourceData) (*redis.PatchSchedule, error) {
v, ok := d.GetOk("patch_schedule")
if !ok {
return nil, nil
}

scheduleValues := v.([]interface{})
entries := make([]redis.ScheduleEntry, 0)
for _, scheduleValue := range scheduleValues {
vals := scheduleValue.(map[string]interface{})
dayOfWeek := vals["day_of_week"].(string)
startHourUtc := vals["start_hour_utc"].(int)

entry := redis.ScheduleEntry{
DayOfWeek: redis.DayOfWeek(dayOfWeek),
StartHourUtc: utils.Int32(int32(startHourUtc)),
}
entries = append(entries, entry)
}

schedule := redis.PatchSchedule{
ScheduleEntries: &redis.ScheduleEntries{
ScheduleEntries: &entries,
},
}
return &schedule, nil
}

func flattenRedisConfiguration(configuration *map[string]*string) map[string]*string {
redisConfiguration := make(map[string]*string, len(*configuration))
config := *configuration
Expand All @@ -443,6 +543,21 @@ func flattenRedisConfiguration(configuration *map[string]*string) map[string]*st
return redisConfiguration
}

func flattenRedisPatchSchedules(schedule redis.PatchSchedule) []interface{} {
outputs := make([]interface{}, 0)

for _, entry := range *schedule.ScheduleEntries.ScheduleEntries {
output := make(map[string]interface{}, 0)

output["day_of_week"] = string(entry.DayOfWeek)
output["start_hour_utc"] = int(*entry.StartHourUtc)

outputs = append(outputs, output)
}

return outputs
}

func validateRedisFamily(v interface{}, k string) (ws []string, errors []error) {
value := strings.ToLower(v.(string))
families := map[string]bool{
Expand Down
77 changes: 77 additions & 0 deletions azurerm/resource_arm_redis_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,53 @@ func TestAccAzureRMRedisCache_BackupEnabledDisabled(t *testing.T) {
})
}

func TestAccAzureRMRedisCache_PatchSchedule(t *testing.T) {
ri := acctest.RandInt()
location := testLocation()
config := testAccAzureRMRedisCachePatchSchedule(ri, location)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMRedisCacheDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMRedisCacheExists("azurerm_redis_cache.test"),
),
},
},
})
}

func TestAccAzureRMRedisCache_PatchScheduleUpdated(t *testing.T) {
ri := acctest.RandInt()
location := testLocation()
config := testAccAzureRMRedisCachePatchSchedule(ri, location)
updatedConfig := testAccAzureRMRedisCache_premium(ri, location)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMRedisCacheDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMRedisCacheExists("azurerm_redis_cache.test"),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMRedisCacheExists("azurerm_redis_cache.test"),
),
},
},
})
}

func testCheckAzureRMRedisCacheExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
// Ensure we have enough information in state to look up in API
Expand Down Expand Up @@ -507,3 +554,33 @@ resource "azurerm_redis_cache" "test" {
}
`, rInt, location, rString, rInt)
}

func testAccAzureRMRedisCachePatchSchedule(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_redis_cache" "test" {
name = "acctestRedis-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
capacity = 1
family = "P"
sku_name = "Premium"
enable_non_ssl_port = false
redis_configuration {
maxclients = 256,
maxmemory_reserved = 2,
maxmemory_delta = 2
maxmemory_policy = "allkeys-lru"
}
patch_schedule {
day_of_week = "Tuesday"
start_hour_utc = 8
}
}
`, rInt, location, rInt)
}
43 changes: 27 additions & 16 deletions website/docs/r/redis_cache.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -111,31 +111,33 @@ resource "azurerm_redis_cache" "test" {

```hcl
resource "azurerm_resource_group" "test" {
name = "redisrg"
location = "West US"
name = "redisrg"
location = "West US"
}
resource "azurerm_storage_account" "test" {
name = "redissa"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
account_tier = "Standard"
account_replication_type = "GRS"
}
resource "azurerm_redis_cache" "test" {
name = "example-redis"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
capacity = 3
family = "P"
sku_name = "Premium"
enable_non_ssl_port = false
redis_configuration {
maxclients = 256
rdb_backup_enabled = true
rdb_backup_frequency = 60
rdb_backup_max_snapshot_count = 1
rdb_storage_connection_string = "DefaultEndpointsProtocol=https;BlobEndpoint=${azurerm_storage_account.test.primary_blob_endpoint};AccountName=${azurerm_storage_account.test.name};AccountKey=${azurerm_storage_account.test.primary_access_key}"
}
name = "example-redis"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
capacity = 3
family = "P"
sku_name = "Premium"
enable_non_ssl_port = false
redis_configuration {
maxclients = 256
rdb_backup_enabled = true
rdb_backup_frequency = 60
rdb_backup_max_snapshot_count = 1
rdb_storage_connection_string = "DefaultEndpointsProtocol=https;BlobEndpoint=${azurerm_storage_account.test.primary_blob_endpoint};AccountName=${azurerm_storage_account.test.name};AccountKey=${azurerm_storage_account.test.primary_access_key}"
}
}
```

Expand Down Expand Up @@ -165,6 +167,8 @@ The pricing group for the Redis Family - either "C" or "P" at present.

* `redis_configuration` - (Required) A `redis_configuration` as defined below - with some limitations by SKU - defaults/details are shown below.

* `patch_schedule` - (Optional) A list of `patch_schedule` blocks as defined below - only available for Premium SKU's.

---

* `redis_configuration` supports the following:
Expand Down Expand Up @@ -198,6 +202,13 @@ redis_configuration {

_*Important*: The maxmemory_reserved setting is only available for Standard and Premium caches. More details are available in the Relevant Links section below._

* `patch_schedule` supports the following:

* `day_of_week` (Required) the Weekday name - possible values include `Monday`, `Tuesday`, `Wednesday` etc.
* `start_hour_utc` - (Optional) the Start Hour for maintenance in UTC - possible values range from `0 - 23`.

~> **Note:** The Patch Window lasts for 5 hours from the `start_hour_utc`.

## Attributes Reference

The following attributes are exported:
Expand Down

0 comments on commit 441ce31

Please sign in to comment.