github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/aws/resource_aws_config_config_rule.go (about)

     1  package aws
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/hashcode"
    10  	"github.com/hashicorp/terraform/helper/resource"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  
    13  	"github.com/aws/aws-sdk-go/aws"
    14  	"github.com/aws/aws-sdk-go/aws/awserr"
    15  	"github.com/aws/aws-sdk-go/service/configservice"
    16  )
    17  
    18  func resourceAwsConfigConfigRule() *schema.Resource {
    19  	return &schema.Resource{
    20  		Create: resourceAwsConfigConfigRulePut,
    21  		Read:   resourceAwsConfigConfigRuleRead,
    22  		Update: resourceAwsConfigConfigRulePut,
    23  		Delete: resourceAwsConfigConfigRuleDelete,
    24  
    25  		Importer: &schema.ResourceImporter{
    26  			State: schema.ImportStatePassthrough,
    27  		},
    28  
    29  		Schema: map[string]*schema.Schema{
    30  			"name": {
    31  				Type:         schema.TypeString,
    32  				Required:     true,
    33  				ValidateFunc: validateMaxLength(64),
    34  			},
    35  			"rule_id": {
    36  				Type:     schema.TypeString,
    37  				Computed: true,
    38  			},
    39  			"arn": {
    40  				Type:     schema.TypeString,
    41  				Computed: true,
    42  			},
    43  			"description": {
    44  				Type:         schema.TypeString,
    45  				Optional:     true,
    46  				ValidateFunc: validateMaxLength(256),
    47  			},
    48  			"input_parameters": {
    49  				Type:         schema.TypeString,
    50  				Optional:     true,
    51  				ValidateFunc: validateJsonString,
    52  			},
    53  			"maximum_execution_frequency": {
    54  				Type:         schema.TypeString,
    55  				Optional:     true,
    56  				ValidateFunc: validateConfigExecutionFrequency,
    57  			},
    58  			"scope": {
    59  				Type:     schema.TypeList,
    60  				MaxItems: 1,
    61  				Optional: true,
    62  				Elem: &schema.Resource{
    63  					Schema: map[string]*schema.Schema{
    64  						"compliance_resource_id": {
    65  							Type:         schema.TypeString,
    66  							Optional:     true,
    67  							ValidateFunc: validateMaxLength(256),
    68  						},
    69  						"compliance_resource_types": {
    70  							Type:     schema.TypeSet,
    71  							Optional: true,
    72  							MaxItems: 100,
    73  							Elem: &schema.Schema{
    74  								Type:         schema.TypeString,
    75  								ValidateFunc: validateMaxLength(256),
    76  							},
    77  							Set: schema.HashString,
    78  						},
    79  						"tag_key": {
    80  							Type:         schema.TypeString,
    81  							Optional:     true,
    82  							ValidateFunc: validateMaxLength(128),
    83  						},
    84  						"tag_value": {
    85  							Type:         schema.TypeString,
    86  							Optional:     true,
    87  							ValidateFunc: validateMaxLength(256),
    88  						},
    89  					},
    90  				},
    91  			},
    92  			"source": {
    93  				Type:     schema.TypeList,
    94  				MaxItems: 1,
    95  				Required: true,
    96  				Elem: &schema.Resource{
    97  					Schema: map[string]*schema.Schema{
    98  						"owner": {
    99  							Type:         schema.TypeString,
   100  							Required:     true,
   101  							ValidateFunc: validateConfigRuleSourceOwner,
   102  						},
   103  						"source_detail": {
   104  							Type:     schema.TypeSet,
   105  							Set:      configRuleSourceDetailsHash,
   106  							Optional: true,
   107  							MaxItems: 25,
   108  							Elem: &schema.Resource{
   109  								Schema: map[string]*schema.Schema{
   110  									"event_source": {
   111  										Type:     schema.TypeString,
   112  										Optional: true,
   113  										Default:  "aws.config",
   114  									},
   115  									"maximum_execution_frequency": {
   116  										Type:         schema.TypeString,
   117  										Optional:     true,
   118  										ValidateFunc: validateConfigExecutionFrequency,
   119  									},
   120  									"message_type": {
   121  										Type:     schema.TypeString,
   122  										Optional: true,
   123  									},
   124  								},
   125  							},
   126  						},
   127  						"source_identifier": {
   128  							Type:         schema.TypeString,
   129  							Required:     true,
   130  							ValidateFunc: validateMaxLength(256),
   131  						},
   132  					},
   133  				},
   134  			},
   135  		},
   136  	}
   137  }
   138  
   139  func resourceAwsConfigConfigRulePut(d *schema.ResourceData, meta interface{}) error {
   140  	conn := meta.(*AWSClient).configconn
   141  
   142  	name := d.Get("name").(string)
   143  	ruleInput := configservice.ConfigRule{
   144  		ConfigRuleName: aws.String(name),
   145  		Source:         expandConfigRuleSource(d.Get("source").([]interface{})),
   146  	}
   147  
   148  	scopes := d.Get("scope").([]interface{})
   149  	if len(scopes) > 0 {
   150  		ruleInput.Scope = expandConfigRuleScope(scopes[0].(map[string]interface{}))
   151  	}
   152  
   153  	if v, ok := d.GetOk("description"); ok {
   154  		ruleInput.Description = aws.String(v.(string))
   155  	}
   156  	if v, ok := d.GetOk("input_parameters"); ok {
   157  		ruleInput.InputParameters = aws.String(v.(string))
   158  	}
   159  	if v, ok := d.GetOk("maximum_execution_frequency"); ok {
   160  		ruleInput.MaximumExecutionFrequency = aws.String(v.(string))
   161  	}
   162  
   163  	input := configservice.PutConfigRuleInput{
   164  		ConfigRule: &ruleInput,
   165  	}
   166  	log.Printf("[DEBUG] Creating AWSConfig config rule: %s", input)
   167  	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
   168  		_, err := conn.PutConfigRule(&input)
   169  		if err != nil {
   170  			if awsErr, ok := err.(awserr.Error); ok {
   171  				if awsErr.Code() == "InsufficientPermissionsException" {
   172  					// IAM is eventually consistent
   173  					return resource.RetryableError(err)
   174  				}
   175  			}
   176  
   177  			return resource.NonRetryableError(fmt.Errorf("Failed to create AWSConfig rule: %s", err))
   178  		}
   179  
   180  		return nil
   181  	})
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	d.SetId(name)
   187  
   188  	log.Printf("[DEBUG] AWSConfig config rule %q created", name)
   189  
   190  	return resourceAwsConfigConfigRuleRead(d, meta)
   191  }
   192  
   193  func resourceAwsConfigConfigRuleRead(d *schema.ResourceData, meta interface{}) error {
   194  	conn := meta.(*AWSClient).configconn
   195  
   196  	out, err := conn.DescribeConfigRules(&configservice.DescribeConfigRulesInput{
   197  		ConfigRuleNames: []*string{aws.String(d.Id())},
   198  	})
   199  	if err != nil {
   200  		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoSuchConfigRuleException" {
   201  			log.Printf("[WARN] Config Rule %q is gone (NoSuchConfigRuleException)", d.Id())
   202  			d.SetId("")
   203  			return nil
   204  		}
   205  		return err
   206  	}
   207  
   208  	numberOfRules := len(out.ConfigRules)
   209  	if numberOfRules < 1 {
   210  		log.Printf("[WARN] Config Rule %q is gone (no rules found)", d.Id())
   211  		d.SetId("")
   212  		return nil
   213  	}
   214  
   215  	if numberOfRules > 1 {
   216  		return fmt.Errorf("Expected exactly 1 Config Rule, received %d: %#v",
   217  			numberOfRules, out.ConfigRules)
   218  	}
   219  
   220  	log.Printf("[DEBUG] AWS Config config rule received: %s", out)
   221  
   222  	rule := out.ConfigRules[0]
   223  	d.Set("arn", rule.ConfigRuleArn)
   224  	d.Set("rule_id", rule.ConfigRuleId)
   225  	d.Set("name", rule.ConfigRuleName)
   226  	d.Set("description", rule.Description)
   227  	d.Set("input_parameters", rule.InputParameters)
   228  	d.Set("maximum_execution_frequency", rule.MaximumExecutionFrequency)
   229  
   230  	if rule.Scope != nil {
   231  		d.Set("scope", flattenConfigRuleScope(rule.Scope))
   232  	}
   233  
   234  	d.Set("source", flattenConfigRuleSource(rule.Source))
   235  
   236  	return nil
   237  }
   238  
   239  func resourceAwsConfigConfigRuleDelete(d *schema.ResourceData, meta interface{}) error {
   240  	conn := meta.(*AWSClient).configconn
   241  
   242  	name := d.Get("name").(string)
   243  
   244  	log.Printf("[DEBUG] Deleting AWS Config config rule %q", name)
   245  	err := resource.Retry(2*time.Minute, func() *resource.RetryError {
   246  		_, err := conn.DeleteConfigRule(&configservice.DeleteConfigRuleInput{
   247  			ConfigRuleName: aws.String(name),
   248  		})
   249  		if err != nil {
   250  			if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceInUseException" {
   251  				return resource.RetryableError(err)
   252  			}
   253  			return resource.NonRetryableError(err)
   254  		}
   255  		return nil
   256  	})
   257  	if err != nil {
   258  		return fmt.Errorf("Deleting Config Rule failed: %s", err)
   259  	}
   260  
   261  	conf := resource.StateChangeConf{
   262  		Pending: []string{
   263  			configservice.ConfigRuleStateActive,
   264  			configservice.ConfigRuleStateDeleting,
   265  			configservice.ConfigRuleStateDeletingResults,
   266  			configservice.ConfigRuleStateEvaluating,
   267  		},
   268  		Target:  []string{""},
   269  		Timeout: 5 * time.Minute,
   270  		Refresh: func() (interface{}, string, error) {
   271  			out, err := conn.DescribeConfigRules(&configservice.DescribeConfigRulesInput{
   272  				ConfigRuleNames: []*string{aws.String(d.Id())},
   273  			})
   274  			if err != nil {
   275  				if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoSuchConfigRuleException" {
   276  					return 42, "", nil
   277  				}
   278  				return 42, "", fmt.Errorf("Failed to describe config rule %q: %s", d.Id(), err)
   279  			}
   280  			if len(out.ConfigRules) < 1 {
   281  				return 42, "", nil
   282  			}
   283  			rule := out.ConfigRules[0]
   284  			return out, *rule.ConfigRuleState, nil
   285  		},
   286  	}
   287  	_, err = conf.WaitForState()
   288  	if err != nil {
   289  		return err
   290  	}
   291  
   292  	log.Printf("[DEBUG] AWS Config config rule %q deleted", name)
   293  
   294  	d.SetId("")
   295  	return nil
   296  }
   297  
   298  func configRuleSourceDetailsHash(v interface{}) int {
   299  	var buf bytes.Buffer
   300  	m := v.(map[string]interface{})
   301  	if v, ok := m["message_type"]; ok {
   302  		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
   303  	}
   304  	if v, ok := m["event_source"]; ok {
   305  		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
   306  	}
   307  	if v, ok := m["maximum_execution_frequency"]; ok {
   308  		buf.WriteString(fmt.Sprintf("%s-", v.(string)))
   309  	}
   310  	return hashcode.String(buf.String())
   311  }