add update support for redis (#1590)

* add update support for redis

* add test for redis update
This commit is contained in:
The Magician 2018-06-04 17:41:48 -07:00 committed by Dana Hoffman
parent 04b62b33e8
commit 164936e4a5
4 changed files with 190 additions and 8 deletions

View File

@ -18,6 +18,7 @@ import (
"fmt"
"log"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform/helper/schema"
@ -29,6 +30,7 @@ func resourceRedisInstance() *schema.Resource {
return &schema.Resource{
Create: resourceRedisInstanceCreate,
Read: resourceRedisInstanceRead,
Update: resourceRedisInstanceUpdate,
Delete: resourceRedisInstanceDelete,
Importer: &schema.ResourceImporter{
@ -37,6 +39,7 @@ func resourceRedisInstance() *schema.Resource {
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(360 * time.Second),
Update: schema.DefaultTimeout(240 * time.Second),
Delete: schema.DefaultTimeout(240 * time.Second),
},
@ -44,7 +47,6 @@ func resourceRedisInstance() *schema.Resource {
"memory_size_gb": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
@ -65,12 +67,10 @@ func resourceRedisInstance() *schema.Resource {
"display_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"labels": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"location_id": {
@ -315,6 +315,119 @@ func resourceRedisInstanceRead(d *schema.ResourceData, meta interface{}) error {
return nil
}
func resourceRedisInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
project, err := getProject(d, config)
if err != nil {
return err
}
alternativeLocationIdProp, err := expandRedisInstanceAlternativeLocationId(d.Get("alternative_location_id"), d, config)
if err != nil {
return err
}
authorizedNetworkProp, err := expandRedisInstanceAuthorizedNetwork(d.Get("authorized_network"), d, config)
if err != nil {
return err
}
displayNameProp, err := expandRedisInstanceDisplayName(d.Get("display_name"), d, config)
if err != nil {
return err
}
labelsProp, err := expandRedisInstanceLabels(d.Get("labels"), d, config)
if err != nil {
return err
}
locationIdProp, err := expandRedisInstanceLocationId(d.Get("location_id"), d, config)
if err != nil {
return err
}
nameProp, err := expandRedisInstanceName(d.Get("name"), d, config)
if err != nil {
return err
}
memorySizeGbProp, err := expandRedisInstanceMemorySizeGb(d.Get("memory_size_gb"), d, config)
if err != nil {
return err
}
redisVersionProp, err := expandRedisInstanceRedisVersion(d.Get("redis_version"), d, config)
if err != nil {
return err
}
reservedIpRangeProp, err := expandRedisInstanceReservedIpRange(d.Get("reserved_ip_range"), d, config)
if err != nil {
return err
}
tierProp, err := expandRedisInstanceTier(d.Get("tier"), d, config)
if err != nil {
return err
}
regionProp, err := expandRedisInstanceRegion(d.Get("region"), d, config)
if err != nil {
return err
}
obj := map[string]interface{}{
"alternativeLocationId": alternativeLocationIdProp,
"authorizedNetwork": authorizedNetworkProp,
"displayName": displayNameProp,
"labels": labelsProp,
"locationId": locationIdProp,
"name": nameProp,
"memorySizeGb": memorySizeGbProp,
"redisVersion": redisVersionProp,
"reservedIpRange": reservedIpRangeProp,
"tier": tierProp,
"region": regionProp,
}
obj, err = resourceRedisInstanceEncoder(d, meta, obj)
url, err := replaceVars(d, config, "https://redis.googleapis.com/v1beta1/projects/{{project}}/locations/{{region}}/instances/{{name}}")
if err != nil {
return err
}
log.Printf("[DEBUG] Updating Instance %q: %#v", d.Id(), obj)
updateMask := []string{}
if d.HasChange("display_name") {
updateMask = append(updateMask, "displayName")
}
if d.HasChange("labels") {
updateMask = append(updateMask, "labels")
}
if d.HasChange("memory_size_gb") {
updateMask = append(updateMask, "memorySizeGb")
}
// updateMask is a URL parameter but not present in the schema, so replaceVars
// won't set it
url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
if err != nil {
return err
}
res, err := sendRequest(config, "PATCH", url, obj)
if err != nil {
return fmt.Errorf("Error updating Instance %q: %s", d.Id(), err)
}
op := &redis.Operation{}
err = Convert(res, op)
if err != nil {
return err
}
err = redisOperationWaitTime(
config.clientRedis, op, project, "Updating Instance",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if err != nil {
return err
}
return resourceRedisInstanceRead(d, meta)
}
func resourceRedisInstanceDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

View File

@ -30,6 +30,36 @@ func TestAccRedisInstance_basic(t *testing.T) {
})
}
func TestAccRedisInstance_update(t *testing.T) {
t.Parallel()
name := acctest.RandomWithPrefix("tf-test")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeAddressDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccRedisInstance_update(name),
},
resource.TestStep{
ResourceName: "google_redis_instance.test",
ImportState: true,
ImportStateVerify: true,
},
resource.TestStep{
Config: testAccRedisInstance_update2(name),
},
resource.TestStep{
ResourceName: "google_redis_instance.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
func TestAccRedisInstance_full(t *testing.T) {
t.Parallel()
@ -61,6 +91,34 @@ resource "google_redis_instance" "test" {
}`, name)
}
func testAccRedisInstance_update(name string) string {
return fmt.Sprintf(`
resource "google_redis_instance" "test" {
name = "%s"
display_name = "pre-update"
memory_size_gb = 1
labels {
my_key = "my_val"
other_key = "other_val"
}
}`, name)
}
func testAccRedisInstance_update2(name string) string {
return fmt.Sprintf(`
resource "google_redis_instance" "test" {
name = "%s"
display_name = "post-update"
memory_size_gb = 1
labels {
my_key = "my_val"
other_key = "new_val"
}
}`, name)
}
func testAccRedisInstance_full(name, network string) string {
return fmt.Sprintf(`
resource "google_compute_network" "test" {

View File

@ -106,15 +106,12 @@ func sendRequest(config *Config, method, rawurl string, body map[string]interfac
}
}
u, err := url.Parse(rawurl)
u, err := addQueryParams(rawurl, map[string]string{"alt": "json"})
if err != nil {
return nil, err
}
q := u.Query()
q.Set("alt", "json")
u.RawQuery = q.Encode()
req, err := http.NewRequest(method, u.String(), &buf)
req, err := http.NewRequest(method, u, &buf)
if err != nil {
return nil, err
}
@ -136,6 +133,19 @@ func sendRequest(config *Config, method, rawurl string, body map[string]interfac
return result, nil
}
func addQueryParams(rawurl string, params map[string]string) (string, error) {
u, err := url.Parse(rawurl)
if err != nil {
return "", err
}
q := u.Query()
for k, v := range params {
q.Set(k, v)
}
u.RawQuery = q.Encode()
return u.String(), nil
}
func replaceVars(d TerraformResourceData, config *Config, linkTmpl string) (string, error) {
re := regexp.MustCompile("{{([[:word:]]+)}}")
var project, region, zone string

View File

@ -155,6 +155,7 @@ This resource provides the following
[Timeouts](/docs/configuration/resources.html#timeouts) configuration options:
- `create` - Default is 6 minutes.
- `update` - Default is 4 minutes.
- `delete` - Default is 4 minutes.
## Import