diff --git a/azurerm/resource_arm_redis_cache.go b/azurerm/resource_arm_redis_cache.go index c5637226370fa..3d24854cffb86 100644 --- a/azurerm/resource_arm_redis_cache.go +++ b/azurerm/resource_arm_redis_cache.go @@ -74,6 +74,17 @@ func resourceArmRedisCache() *schema.Resource { Optional: true, }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + }, + + "private_static_ip_address": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "redis_configuration": { Type: schema.TypeList, Required: true, @@ -211,12 +222,12 @@ func resourceArmRedisCacheCreate(d *schema.ResourceData, meta interface{}) error } parameters := redis.CreateParameters{ - Name: &name, - Location: &location, + Name: utils.String(name), + Location: utils.String(location), CreateProperties: &redis.CreateProperties{ - EnableNonSslPort: &enableNonSSLPort, + EnableNonSslPort: utils.Bool(enableNonSSLPort), Sku: &redis.Sku{ - Capacity: &capacity, + Capacity: utils.Int32(capacity), Family: family, Name: sku, }, @@ -230,6 +241,14 @@ func resourceArmRedisCacheCreate(d *schema.ResourceData, meta interface{}) error parameters.ShardCount = &shardCount } + if v, ok := d.GetOk("private_static_ip_address"); ok { + parameters.StaticIP = utils.String(v.(string)) + } + + if v, ok := d.GetOk("subnet_id"); ok { + parameters.SubnetID = utils.String(v.(string)) + } + future, err := client.Create(ctx, resGroup, name, parameters) if err != nil { return err @@ -282,6 +301,8 @@ func resourceArmRedisCacheUpdate(d *schema.ResourceData, meta interface{}) error resGroup := d.Get("resource_group_name").(string) enableNonSSLPort := d.Get("enable_non_ssl_port").(bool) + staticIPAddress := d.Get("private_static_ip_address").(string) + subnetId := d.Get("subnet_id").(string) capacity := int32(d.Get("capacity").(int)) family := redis.SkuFamily(d.Get("family").(string)) @@ -292,9 +313,9 @@ func resourceArmRedisCacheUpdate(d *schema.ResourceData, meta interface{}) error parameters := redis.UpdateParameters{ UpdateProperties: &redis.UpdateProperties{ - EnableNonSslPort: &enableNonSSLPort, + EnableNonSslPort: utils.Bool(enableNonSSLPort), Sku: &redis.Sku{ - Capacity: &capacity, + Capacity: utils.Int32(capacity), Family: family, Name: sku, }, @@ -309,6 +330,18 @@ func resourceArmRedisCacheUpdate(d *schema.ResourceData, meta interface{}) error } } + if v, ok := d.GetOk("private_static_ip_address"); ok { + if d.HasChange("private_static_ip_address") { + parameters.StaticIP = utils.String(v.(string)) + } + } + + if v, ok := d.GetOk("subnet_id"); ok { + if d.HasChange("subnet_id") { + parameters.SubnetID = utils.String(v.(string)) + } + } + if d.HasChange("redis_configuration") { redisConfiguration := expandRedisConfiguration(d) parameters.RedisConfiguration = redisConfiguration @@ -406,19 +439,22 @@ func resourceArmRedisCacheRead(d *schema.ResourceData, meta interface{}) error { d.Set("location", azureRMNormalizeLocation(*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) - 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) + if props := resp.ResourceProperties; props != nil { + d.Set("ssl_port", props.SslPort) + d.Set("hostname", props.HostName) + d.Set("port", props.Port) + d.Set("enable_non_ssl_port", props.EnableNonSslPort) + if props.ShardCount != nil { + d.Set("shard_count", props.ShardCount) + } + d.Set("private_static_ip_address", props.StaticIP) + d.Set("subnet_id", props.SubnetID) } redisConfiguration := flattenRedisConfiguration(resp.RedisConfiguration) diff --git a/azurerm/resource_arm_redis_cache_test.go b/azurerm/resource_arm_redis_cache_test.go index 63c1f26e718d4..25fd5c993d74d 100644 --- a/azurerm/resource_arm_redis_cache_test.go +++ b/azurerm/resource_arm_redis_cache_test.go @@ -318,6 +318,82 @@ func TestAccAzureRMRedisCache_PatchScheduleUpdated(t *testing.T) { }) } +func TestAccAzureRMRedisCache_InternalSubnet(t *testing.T) { + ri := acctest.RandInt() + config := testAccAzureRMRedisCache_internalSubnet(ri, testLocation()) + + 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_InternalSubnetStaticIP(t *testing.T) { + ri := acctest.RandInt() + config := testAccAzureRMRedisCache_internalSubnetStaticIP(ri, testLocation()) + + 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_InternalSubnetUpdate(t *testing.T) { + resourceName := "azurerm_redis_cache.test" + ri := acctest.RandInt() + location := testLocation() + + config := testAccAzureRMRedisCache_basic(ri, location) + updatedConfig := testAccAzureRMRedisCache_internalSubnet(ri, location) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMRedisCacheDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRedisCacheExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "subnet_id", ""), + ), + }, + { + Config: updatedConfig, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRedisCacheExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "subnet_id"), + ), + }, + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMRedisCacheExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "subnet_id", ""), + ), + }, + }, + }) +} + func testCheckAzureRMRedisCacheExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API @@ -635,3 +711,77 @@ resource "azurerm_redis_cache" "test" { } `, rInt, location, rString, rInt) } +func testAccAzureRMRedisCache_internalSubnet(ri int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnw-%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "testsubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +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 + subnet_id = "${azurerm_subnet.test.id}" + redis_configuration { + maxclients = "256" + } +} +`, ri, location, ri, ri) +} + +func testAccAzureRMRedisCache_internalSubnetStaticIP(ri int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestnw-%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "testsubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" +} + +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 + subnet_id = "${azurerm_subnet.test.id}" + privatestatic_ip_address = "10.0.1.20" + redis_configuration { + maxclients = "256" + } +} +`, ri, location, ri, ri) +} diff --git a/website/docs/r/redis_cache.html.markdown b/website/docs/r/redis_cache.html.markdown index 7fb4d856cc1e0..0e6efa655e2b5 100644 --- a/website/docs/r/redis_cache.html.markdown +++ b/website/docs/r/redis_cache.html.markdown @@ -163,11 +163,15 @@ The pricing group for the Redis Family - either "C" or "P" at present. * `enable_non_ssl_port` - (Optional) Enable the non-SSL port (6789) - disabled by default. -* `shard_count` - (Optional) *Only available when using the Premium SKU* The number of Shards to create on the Redis Cluster. +* `patch_schedule` - (Optional) A list of `patch_schedule` blocks as defined below - only available for Premium SKU's. + +* `private_static_ip_address` - (Optional) The Static IP Address to assign to the Redis Cache when hosted inside the Virtual Network. * `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. +* `shard_count` - (Optional) *Only available when using the Premium SKU* The number of Shards to create on the Redis Cluster. + +* `subnet_id` - (Optional) The ID of the Subnet within which the Redis Cache should be deployed. ---