github.com/danrjohnson/terraform@v0.7.0-rc2.0.20160627135212-d0fc1fa086ff/builtin/providers/aws/resource_aws_cloudwatch_event_rule.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "regexp" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws/awserr" 10 "github.com/hashicorp/terraform/helper/resource" 11 "github.com/hashicorp/terraform/helper/schema" 12 13 "github.com/aws/aws-sdk-go/aws" 14 events "github.com/aws/aws-sdk-go/service/cloudwatchevents" 15 ) 16 17 func resourceAwsCloudWatchEventRule() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsCloudWatchEventRuleCreate, 20 Read: resourceAwsCloudWatchEventRuleRead, 21 Update: resourceAwsCloudWatchEventRuleUpdate, 22 Delete: resourceAwsCloudWatchEventRuleDelete, 23 Importer: &schema.ResourceImporter{ 24 State: schema.ImportStatePassthrough, 25 }, 26 27 Schema: map[string]*schema.Schema{ 28 "name": &schema.Schema{ 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 ValidateFunc: validateCloudWatchEventRuleName, 33 }, 34 "schedule_expression": &schema.Schema{ 35 Type: schema.TypeString, 36 Optional: true, 37 ValidateFunc: validateMaxLength(256), 38 }, 39 "event_pattern": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 ValidateFunc: validateMaxLength(2048), 43 StateFunc: normalizeJson, 44 }, 45 "description": &schema.Schema{ 46 Type: schema.TypeString, 47 Optional: true, 48 ValidateFunc: validateMaxLength(512), 49 }, 50 "role_arn": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 ValidateFunc: validateMaxLength(1600), 54 }, 55 "is_enabled": &schema.Schema{ 56 Type: schema.TypeBool, 57 Optional: true, 58 Default: true, 59 }, 60 "arn": &schema.Schema{ 61 Type: schema.TypeString, 62 Computed: true, 63 }, 64 }, 65 } 66 } 67 68 func resourceAwsCloudWatchEventRuleCreate(d *schema.ResourceData, meta interface{}) error { 69 conn := meta.(*AWSClient).cloudwatcheventsconn 70 71 input := buildPutRuleInputStruct(d) 72 log.Printf("[DEBUG] Creating CloudWatch Event Rule: %s", input) 73 74 // IAM Roles take some time to propagate 75 var out *events.PutRuleOutput 76 err := resource.Retry(30*time.Second, func() *resource.RetryError { 77 var err error 78 out, err = conn.PutRule(input) 79 pattern := regexp.MustCompile("cannot be assumed by principal '[a-z]+\\.amazonaws\\.com'\\.$") 80 if err != nil { 81 if awsErr, ok := err.(awserr.Error); ok { 82 if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) { 83 log.Printf("[DEBUG] Retrying creation of CloudWatch Event Rule %q", *input.Name) 84 return resource.RetryableError(err) 85 } 86 } 87 return resource.NonRetryableError(err) 88 } 89 return nil 90 }) 91 if err != nil { 92 return fmt.Errorf("Creating CloudWatch Event Rule failed: %s", err) 93 } 94 95 d.Set("arn", out.RuleArn) 96 d.SetId(d.Get("name").(string)) 97 98 log.Printf("[INFO] CloudWatch Event Rule %q created", *out.RuleArn) 99 100 return resourceAwsCloudWatchEventRuleUpdate(d, meta) 101 } 102 103 func resourceAwsCloudWatchEventRuleRead(d *schema.ResourceData, meta interface{}) error { 104 conn := meta.(*AWSClient).cloudwatcheventsconn 105 106 input := events.DescribeRuleInput{ 107 Name: aws.String(d.Id()), 108 } 109 log.Printf("[DEBUG] Reading CloudWatch Event Rule: %s", input) 110 out, err := conn.DescribeRule(&input) 111 if awsErr, ok := err.(awserr.Error); ok { 112 if awsErr.Code() == "ResourceNotFoundException" { 113 log.Printf("[WARN] Removing CloudWatch Event Rule %q because it's gone.", d.Id()) 114 d.SetId("") 115 return nil 116 } 117 } 118 if err != nil { 119 return err 120 } 121 log.Printf("[DEBUG] Found Event Rule: %s", out) 122 123 d.Set("arn", out.Arn) 124 d.Set("description", out.Description) 125 if out.EventPattern != nil { 126 d.Set("event_pattern", normalizeJson(*out.EventPattern)) 127 } 128 d.Set("name", out.Name) 129 d.Set("role_arn", out.RoleArn) 130 d.Set("schedule_expression", out.ScheduleExpression) 131 132 boolState, err := getBooleanStateFromString(*out.State) 133 if err != nil { 134 return err 135 } 136 log.Printf("[DEBUG] Setting boolean state: %t", boolState) 137 d.Set("is_enabled", boolState) 138 139 return nil 140 } 141 142 func resourceAwsCloudWatchEventRuleUpdate(d *schema.ResourceData, meta interface{}) error { 143 conn := meta.(*AWSClient).cloudwatcheventsconn 144 145 if d.HasChange("is_enabled") && d.Get("is_enabled").(bool) { 146 log.Printf("[DEBUG] Enabling CloudWatch Event Rule %q", d.Id()) 147 _, err := conn.EnableRule(&events.EnableRuleInput{ 148 Name: aws.String(d.Id()), 149 }) 150 if err != nil { 151 return err 152 } 153 log.Printf("[DEBUG] CloudWatch Event Rule (%q) enabled", d.Id()) 154 } 155 156 input := buildPutRuleInputStruct(d) 157 log.Printf("[DEBUG] Updating CloudWatch Event Rule: %s", input) 158 159 // IAM Roles take some time to propagate 160 var out *events.PutRuleOutput 161 err := resource.Retry(30*time.Second, func() *resource.RetryError { 162 var err error 163 out, err = conn.PutRule(input) 164 pattern := regexp.MustCompile("cannot be assumed by principal '[a-z]+\\.amazonaws\\.com'\\.$") 165 if err != nil { 166 if awsErr, ok := err.(awserr.Error); ok { 167 if awsErr.Code() == "ValidationException" && pattern.MatchString(awsErr.Message()) { 168 log.Printf("[DEBUG] Retrying update of CloudWatch Event Rule %q", *input.Name) 169 return resource.RetryableError(err) 170 } 171 } 172 return resource.NonRetryableError(err) 173 } 174 return nil 175 }) 176 if err != nil { 177 return fmt.Errorf("Updating CloudWatch Event Rule failed: %s", err) 178 } 179 180 if d.HasChange("is_enabled") && !d.Get("is_enabled").(bool) { 181 log.Printf("[DEBUG] Disabling CloudWatch Event Rule %q", d.Id()) 182 _, err := conn.DisableRule(&events.DisableRuleInput{ 183 Name: aws.String(d.Id()), 184 }) 185 if err != nil { 186 return err 187 } 188 log.Printf("[DEBUG] CloudWatch Event Rule (%q) disabled", d.Id()) 189 } 190 191 return resourceAwsCloudWatchEventRuleRead(d, meta) 192 } 193 194 func resourceAwsCloudWatchEventRuleDelete(d *schema.ResourceData, meta interface{}) error { 195 conn := meta.(*AWSClient).cloudwatcheventsconn 196 197 log.Printf("[INFO] Deleting CloudWatch Event Rule: %s", d.Id()) 198 _, err := conn.DeleteRule(&events.DeleteRuleInput{ 199 Name: aws.String(d.Id()), 200 }) 201 if err != nil { 202 return fmt.Errorf("Error deleting CloudWatch Event Rule: %s", err) 203 } 204 log.Println("[INFO] CloudWatch Event Rule deleted") 205 206 d.SetId("") 207 208 return nil 209 } 210 211 func buildPutRuleInputStruct(d *schema.ResourceData) *events.PutRuleInput { 212 input := events.PutRuleInput{ 213 Name: aws.String(d.Get("name").(string)), 214 } 215 if v, ok := d.GetOk("description"); ok { 216 input.Description = aws.String(v.(string)) 217 } 218 if v, ok := d.GetOk("event_pattern"); ok { 219 input.EventPattern = aws.String(normalizeJson(v.(string))) 220 } 221 if v, ok := d.GetOk("role_arn"); ok { 222 input.RoleArn = aws.String(v.(string)) 223 } 224 if v, ok := d.GetOk("schedule_expression"); ok { 225 input.ScheduleExpression = aws.String(v.(string)) 226 } 227 228 input.State = aws.String(getStringStateFromBoolean(d.Get("is_enabled").(bool))) 229 230 return &input 231 } 232 233 // State is represented as (ENABLED|DISABLED) in the API 234 func getBooleanStateFromString(state string) (bool, error) { 235 if state == "ENABLED" { 236 return true, nil 237 } else if state == "DISABLED" { 238 return false, nil 239 } 240 // We don't just blindly trust AWS as they tend to return 241 // unexpected values in similar cases (different casing etc.) 242 return false, fmt.Errorf("Failed converting state %q into boolean", state) 243 } 244 245 // State is represented as (ENABLED|DISABLED) in the API 246 func getStringStateFromBoolean(isEnabled bool) string { 247 if isEnabled { 248 return "ENABLED" 249 } 250 return "DISABLED" 251 }