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