github.com/pmcatominey/terraform@v0.7.0-rc2.0.20160708105029-1401a52a5cc5/builtin/providers/aws/resource_aws_elastic_beanstalk_configuration_template.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/hashicorp/terraform/helper/schema" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/elasticbeanstalk" 13 ) 14 15 func resourceAwsElasticBeanstalkConfigurationTemplate() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceAwsElasticBeanstalkConfigurationTemplateCreate, 18 Read: resourceAwsElasticBeanstalkConfigurationTemplateRead, 19 Update: resourceAwsElasticBeanstalkConfigurationTemplateUpdate, 20 Delete: resourceAwsElasticBeanstalkConfigurationTemplateDelete, 21 22 Schema: map[string]*schema.Schema{ 23 "name": &schema.Schema{ 24 Type: schema.TypeString, 25 Required: true, 26 ForceNew: true, 27 }, 28 "application": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 }, 33 "description": &schema.Schema{ 34 Type: schema.TypeString, 35 Optional: true, 36 }, 37 "environment_id": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 ForceNew: true, 41 }, 42 "setting": &schema.Schema{ 43 Type: schema.TypeSet, 44 Optional: true, 45 Computed: true, 46 Elem: resourceAwsElasticBeanstalkOptionSetting(), 47 Set: optionSettingValueHash, 48 }, 49 "solution_stack_name": &schema.Schema{ 50 Type: schema.TypeString, 51 Optional: true, 52 ForceNew: true, 53 }, 54 }, 55 } 56 } 57 58 func resourceAwsElasticBeanstalkConfigurationTemplateCreate(d *schema.ResourceData, meta interface{}) error { 59 conn := meta.(*AWSClient).elasticbeanstalkconn 60 61 // Get the relevant properties 62 name := d.Get("name").(string) 63 appName := d.Get("application").(string) 64 65 optionSettings := gatherOptionSettings(d) 66 67 opts := elasticbeanstalk.CreateConfigurationTemplateInput{ 68 ApplicationName: aws.String(appName), 69 TemplateName: aws.String(name), 70 OptionSettings: optionSettings, 71 } 72 73 if attr, ok := d.GetOk("description"); ok { 74 opts.Description = aws.String(attr.(string)) 75 } 76 77 if attr, ok := d.GetOk("environment_id"); ok { 78 opts.EnvironmentId = aws.String(attr.(string)) 79 } 80 81 if attr, ok := d.GetOk("solution_stack_name"); ok { 82 opts.SolutionStackName = aws.String(attr.(string)) 83 } 84 85 log.Printf("[DEBUG] Elastic Beanstalk configuration template create opts: %s", opts) 86 if _, err := conn.CreateConfigurationTemplate(&opts); err != nil { 87 return fmt.Errorf("Error creating Elastic Beanstalk configuration template: %s", err) 88 } 89 90 d.SetId(name) 91 92 return resourceAwsElasticBeanstalkConfigurationTemplateRead(d, meta) 93 } 94 95 func resourceAwsElasticBeanstalkConfigurationTemplateRead(d *schema.ResourceData, meta interface{}) error { 96 conn := meta.(*AWSClient).elasticbeanstalkconn 97 98 log.Printf("[DEBUG] Elastic Beanstalk configuration template read: %s", d.Get("name").(string)) 99 100 resp, err := conn.DescribeConfigurationSettings(&elasticbeanstalk.DescribeConfigurationSettingsInput{ 101 TemplateName: aws.String(d.Id()), 102 ApplicationName: aws.String(d.Get("application").(string)), 103 }) 104 105 if err != nil { 106 if awsErr, ok := err.(awserr.Error); ok { 107 if awsErr.Code() == "InvalidParameterValue" && strings.Contains(awsErr.Message(), "No Configuration Template named") { 108 log.Printf("[WARN] No Configuration Template named (%s) found", d.Id()) 109 d.SetId("") 110 return nil 111 } 112 } 113 return err 114 } 115 116 if len(resp.ConfigurationSettings) != 1 { 117 log.Printf("[DEBUG] Elastic Beanstalk unexpected describe configuration template response: %+v", resp) 118 return fmt.Errorf("Error reading application properties: found %d applications, expected 1", len(resp.ConfigurationSettings)) 119 } 120 121 d.Set("description", resp.ConfigurationSettings[0].Description) 122 return nil 123 } 124 125 func resourceAwsElasticBeanstalkConfigurationTemplateUpdate(d *schema.ResourceData, meta interface{}) error { 126 conn := meta.(*AWSClient).elasticbeanstalkconn 127 128 log.Printf("[DEBUG] Elastic Beanstalk configuration template update: %s", d.Get("name").(string)) 129 130 if d.HasChange("description") { 131 if err := resourceAwsElasticBeanstalkConfigurationTemplateDescriptionUpdate(conn, d); err != nil { 132 return err 133 } 134 } 135 136 if d.HasChange("setting") { 137 if err := resourceAwsElasticBeanstalkConfigurationTemplateOptionSettingsUpdate(conn, d); err != nil { 138 return err 139 } 140 } 141 142 return resourceAwsElasticBeanstalkConfigurationTemplateRead(d, meta) 143 } 144 145 func resourceAwsElasticBeanstalkConfigurationTemplateDescriptionUpdate(conn *elasticbeanstalk.ElasticBeanstalk, d *schema.ResourceData) error { 146 _, err := conn.UpdateConfigurationTemplate(&elasticbeanstalk.UpdateConfigurationTemplateInput{ 147 ApplicationName: aws.String(d.Get("application").(string)), 148 TemplateName: aws.String(d.Get("name").(string)), 149 Description: aws.String(d.Get("description").(string)), 150 }) 151 152 return err 153 } 154 155 func resourceAwsElasticBeanstalkConfigurationTemplateOptionSettingsUpdate(conn *elasticbeanstalk.ElasticBeanstalk, d *schema.ResourceData) error { 156 if d.HasChange("setting") { 157 _, err := conn.ValidateConfigurationSettings(&elasticbeanstalk.ValidateConfigurationSettingsInput{ 158 ApplicationName: aws.String(d.Get("application").(string)), 159 TemplateName: aws.String(d.Get("name").(string)), 160 OptionSettings: gatherOptionSettings(d), 161 }) 162 if err != nil { 163 return err 164 } 165 166 o, n := d.GetChange("setting") 167 if o == nil { 168 o = new(schema.Set) 169 } 170 if n == nil { 171 n = new(schema.Set) 172 } 173 174 os := o.(*schema.Set) 175 ns := n.(*schema.Set) 176 177 rm := extractOptionSettings(os.Difference(ns)) 178 add := extractOptionSettings(ns.Difference(os)) 179 180 // Additions and removals of options are done in a single API call, so we 181 // can't do our normal "remove these" and then later "add these", re-adding 182 // any updated settings. 183 // Because of this, we need to remove any settings in the "removable" 184 // settings that are also found in the "add" settings, otherwise they 185 // conflict. Here we loop through all the initial removables from the set 186 // difference, and we build up a slice of settings not found in the "add" 187 // set 188 var remove []*elasticbeanstalk.ConfigurationOptionSetting 189 for _, r := range rm { 190 for _, a := range add { 191 if *r.Namespace == *a.Namespace && *r.OptionName == *a.OptionName { 192 continue 193 } 194 remove = append(remove, r) 195 } 196 } 197 198 req := &elasticbeanstalk.UpdateConfigurationTemplateInput{ 199 ApplicationName: aws.String(d.Get("application").(string)), 200 TemplateName: aws.String(d.Get("name").(string)), 201 OptionSettings: add, 202 } 203 204 for _, elem := range remove { 205 req.OptionsToRemove = append(req.OptionsToRemove, &elasticbeanstalk.OptionSpecification{ 206 Namespace: elem.Namespace, 207 OptionName: elem.OptionName, 208 }) 209 } 210 211 log.Printf("[DEBUG] Update Configuration Template request: %s", req) 212 if _, err := conn.UpdateConfigurationTemplate(req); err != nil { 213 return err 214 } 215 } 216 217 return nil 218 } 219 220 func resourceAwsElasticBeanstalkConfigurationTemplateDelete(d *schema.ResourceData, meta interface{}) error { 221 conn := meta.(*AWSClient).elasticbeanstalkconn 222 223 application := d.Get("application").(string) 224 225 _, err := conn.DeleteConfigurationTemplate(&elasticbeanstalk.DeleteConfigurationTemplateInput{ 226 ApplicationName: aws.String(application), 227 TemplateName: aws.String(d.Id()), 228 }) 229 230 return err 231 } 232 233 func gatherOptionSettings(d *schema.ResourceData) []*elasticbeanstalk.ConfigurationOptionSetting { 234 optionSettingsSet, ok := d.Get("setting").(*schema.Set) 235 if !ok || optionSettingsSet == nil { 236 optionSettingsSet = new(schema.Set) 237 } 238 239 return extractOptionSettings(optionSettingsSet) 240 }