github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/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  }