diff --git a/builtin/providers/aws/resource_aws_db_option_group.go b/builtin/providers/aws/resource_aws_db_option_group.go index 202542f40..50f969220 100644 --- a/builtin/providers/aws/resource_aws_db_option_group.go +++ b/builtin/providers/aws/resource_aws_db_option_group.go @@ -56,6 +56,22 @@ func resourceAwsDbOptionGroup() *schema.Resource { Type: schema.TypeString, Required: true, }, + "option_settings": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, "port": &schema.Schema{ Type: schema.TypeInt, Optional: true, @@ -172,6 +188,15 @@ func resourceAwsDbOptionGroupRead(d *schema.ResourceData, meta interface{}) erro return nil } +func optionInList(optionName string, list []*string) bool { + for _, opt := range list { + if *opt == optionName { + return true + } + } + return false +} + func resourceAwsDbOptionGroupUpdate(d *schema.ResourceData, meta interface{}) error { rdsconn := meta.(*AWSClient).rdsconn if d.HasChange("option") { @@ -190,9 +215,22 @@ func resourceAwsDbOptionGroupUpdate(d *schema.ResourceData, meta interface{}) er return addErr } - removeOptions, removeErr := flattenOptionConfigurationNames(os.Difference(ns).List()) - if removeErr != nil { - return removeErr + addingOptionNames, err := flattenOptionNames(ns.Difference(os).List()) + if err != nil { + return err + } + + removeOptions := []*string{} + opts, err := flattenOptionNames(os.Difference(ns).List()) + if err != nil { + return err + } + + for _, optionName := range opts { + if optionInList(*optionName, addingOptionNames) { + continue + } + removeOptions = append(removeOptions, optionName) } modifyOpts := &rds.ModifyOptionGroupInput{ @@ -209,7 +247,7 @@ func resourceAwsDbOptionGroupUpdate(d *schema.ResourceData, meta interface{}) er } log.Printf("[DEBUG] Modify DB Option Group: %s", modifyOpts) - _, err := rdsconn.ModifyOptionGroup(modifyOpts) + _, err = rdsconn.ModifyOptionGroup(modifyOpts) if err != nil { return fmt.Errorf("Error modifying DB Option Group: %s", err) } @@ -244,7 +282,7 @@ func resourceAwsDbOptionGroupDelete(d *schema.ResourceData, meta interface{}) er return nil } -func flattenOptionConfigurationNames(configured []interface{}) ([]*string, error) { +func flattenOptionNames(configured []interface{}) ([]*string, error) { var optionNames []*string for _, pRaw := range configured { data := pRaw.(map[string]interface{}) @@ -262,6 +300,19 @@ func resourceAwsDbOptionHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%d-", m["port"].(int))) } + for _, oRaw := range m["option_settings"].(*schema.Set).List() { + o := oRaw.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", o["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", o["value"].(string))) + } + + for _, vpcRaw := range m["vpc_security_group_memberships"].(*schema.Set).List() { + buf.WriteString(fmt.Sprintf("%s-", vpcRaw.(string))) + } + + for _, sgRaw := range m["db_security_group_memberships"].(*schema.Set).List() { + buf.WriteString(fmt.Sprintf("%s-", sgRaw.(string))) + } return hashcode.String(buf.String()) } diff --git a/builtin/providers/aws/resource_aws_db_option_group_test.go b/builtin/providers/aws/resource_aws_db_option_group_test.go index e9611f90b..3bc9f1e41 100644 --- a/builtin/providers/aws/resource_aws_db_option_group_test.go +++ b/builtin/providers/aws/resource_aws_db_option_group_test.go @@ -32,6 +32,42 @@ func TestAccAWSDBOptionGroup_basic(t *testing.T) { }) } +func TestAccAWSDBOptionGroup_OptionSettings(t *testing.T) { + var v rds.OptionGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDBOptionGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSDBOptionGroupOptionSettings, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBOptionGroupExists("aws_db_option_group.bar", &v), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "name", "option-group-test-terraform"), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "option.#", "1"), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "option.2422743510.option_settings.1350509764.value", "UTC"), + ), + }, + resource.TestStep{ + Config: testAccAWSDBOptionGroupOptionSettings_update, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBOptionGroupExists("aws_db_option_group.bar", &v), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "name", "option-group-test-terraform"), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "option.#", "1"), + resource.TestCheckResourceAttr( + "aws_db_option_group.bar", "option.2422743510.option_settings.1350509764.value", "US/Pacific"), + ), + }, + }, + }) +} + func TestAccAWSDBOptionGroup_sqlServerOptionsUpdate(t *testing.T) { var v rds.OptionGroup @@ -216,6 +252,40 @@ resource "aws_db_option_group" "bar" { } ` +const testAccAWSDBOptionGroupOptionSettings = ` +resource "aws_db_option_group" "bar" { + name = "option-group-test-terraform" + option_group_description = "Test option group for terraform" + engine_name = "oracle-ee" + major_engine_version = "11.2" + + option { + option_name = "Timezone" + option_settings { + name = "TIME_ZONE" + value = "UTC" + } + } +} +` + +const testAccAWSDBOptionGroupOptionSettings_update = ` +resource "aws_db_option_group" "bar" { + name = "option-group-test-terraform" + option_group_description = "Test option group for terraform" + engine_name = "oracle-ee" + major_engine_version = "11.2" + + option { + option_name = "Timezone" + option_settings { + name = "TIME_ZONE" + value = "US/Pacific" + } + } +} +` + const testAccAWSDBOptionGroupSqlServerEEOptions = ` resource "aws_db_option_group" "bar" { name = "option-group-test-terraform" diff --git a/builtin/providers/aws/structure.go b/builtin/providers/aws/structure.go index abff5a7a3..40b0ff4ea 100644 --- a/builtin/providers/aws/structure.go +++ b/builtin/providers/aws/structure.go @@ -293,12 +293,33 @@ func expandOptionConfiguration(configured []interface{}) ([]*rds.OptionConfigura } } + if raw, ok := data["option_settings"]; ok { + o.OptionSettings = expandOptionSetting(raw.(*schema.Set).List()) + } + option = append(option, o) } return option, nil } +func expandOptionSetting(list []interface{}) []*rds.OptionSetting { + options := make([]*rds.OptionSetting, 0, len(list)) + + for _, oRaw := range list { + data := oRaw.(map[string]interface{}) + + o := &rds.OptionSetting{ + Name: aws.String(data["name"].(string)), + Value: aws.String(data["value"].(string)), + } + + options = append(options, o) + } + + return options +} + // Takes the result of flatmap.Expand for an array of parameters and // returns Parameter API compatible objects func expandElastiCacheParameters(configured []interface{}) ([]*elasticache.ParameterNameValue, error) { @@ -543,6 +564,7 @@ func flattenEcsContainerDefinitions(definitions []*ecs.ContainerDefinition) (str return string(byteArray[:n]), nil } +// Flattens an array of Options into a []map[string]interface{} func flattenOptions(list []*rds.Option) []map[string]interface{} { result := make([]map[string]interface{}, 0, len(list)) for _, i := range list { @@ -572,6 +594,17 @@ func flattenOptions(list []*rds.Option) []map[string]interface{} { r["db_security_group_memberships"] = dbs } + if i.OptionSettings != nil { + settings := make([]map[string]interface{}, 0, len(i.OptionSettings)) + for _, j := range i.OptionSettings { + settings = append(settings, map[string]interface{}{ + "name": *j.Name, + "value": *j.Value, + }) + } + + r["option_settings"] = settings + } result = append(result, r) } } diff --git a/website/source/docs/providers/aws/r/db_option_group.html.markdown b/website/source/docs/providers/aws/r/db_option_group.html.markdown index b30ac4f33..209663cec 100644 --- a/website/source/docs/providers/aws/r/db_option_group.html.markdown +++ b/website/source/docs/providers/aws/r/db_option_group.html.markdown @@ -18,13 +18,17 @@ resource "aws_db_option_group" "bar" { major_engine_version = "11.00" option { - option_name = "mirroring" + option_name = "Timezone" + option_settings { + name = "TIME_ZONE" + value = "UTC" + } } option { - option_name = "TDE" + option_name = "TDE" } - + apply_immediately = true } ``` @@ -43,10 +47,16 @@ The following arguments are supported: Option blocks support the following: * `option_name` - (Required) The Name of the Option (e.g. MEMCACHED). +* `option_settings` - (Optional) A list of option settings to apply. * `port` - (Optional) The Port number when connecting to the Option (e.g. 11211). * `db_security_group_memberships` - (Optional) A list of DB Security Groups for which the option is enabled. * `vpc_security_group_memberships` - (Optional) A list of VPC Security Groups for which the option is enabled. +Option Settings blocks support the following: + +* `name` - (Optional) The Name of the setting. +* `value` - (Optional) The Value of the setting. + ## Attributes Reference The following attributes are exported: