github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/aws/resource_aws_cloudwatch_event_target.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "regexp" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 11 "github.com/aws/aws-sdk-go/aws" 12 "github.com/aws/aws-sdk-go/aws/awserr" 13 events "github.com/aws/aws-sdk-go/service/cloudwatchevents" 14 "github.com/hashicorp/terraform/helper/validation" 15 ) 16 17 func resourceAwsCloudWatchEventTarget() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsCloudWatchEventTargetCreate, 20 Read: resourceAwsCloudWatchEventTargetRead, 21 Update: resourceAwsCloudWatchEventTargetUpdate, 22 Delete: resourceAwsCloudWatchEventTargetDelete, 23 24 Schema: map[string]*schema.Schema{ 25 "rule": { 26 Type: schema.TypeString, 27 Required: true, 28 ForceNew: true, 29 ValidateFunc: validateCloudWatchEventRuleName, 30 }, 31 32 "target_id": { 33 Type: schema.TypeString, 34 Optional: true, 35 Computed: true, 36 ForceNew: true, 37 ValidateFunc: validateCloudWatchEventTargetId, 38 }, 39 40 "arn": { 41 Type: schema.TypeString, 42 Required: true, 43 }, 44 45 "input": { 46 Type: schema.TypeString, 47 Optional: true, 48 ConflictsWith: []string{"input_path"}, 49 // We could be normalizing the JSON here, 50 // but for built-in targets input may not be JSON 51 }, 52 53 "input_path": { 54 Type: schema.TypeString, 55 Optional: true, 56 ConflictsWith: []string{"input"}, 57 }, 58 59 "role_arn": { 60 Type: schema.TypeString, 61 Optional: true, 62 }, 63 64 "run_command_targets": { 65 Type: schema.TypeList, 66 Optional: true, 67 MaxItems: 5, 68 Elem: &schema.Resource{ 69 Schema: map[string]*schema.Schema{ 70 "key": { 71 Type: schema.TypeString, 72 Required: true, 73 ValidateFunc: validation.StringLenBetween(1, 128), 74 }, 75 "values": { 76 Type: schema.TypeList, 77 Required: true, 78 Elem: &schema.Schema{Type: schema.TypeString}, 79 }, 80 }, 81 }, 82 }, 83 }, 84 } 85 } 86 87 func resourceAwsCloudWatchEventTargetCreate(d *schema.ResourceData, meta interface{}) error { 88 conn := meta.(*AWSClient).cloudwatcheventsconn 89 90 rule := d.Get("rule").(string) 91 92 var targetId string 93 if v, ok := d.GetOk("target_id"); ok { 94 targetId = v.(string) 95 } else { 96 targetId = resource.UniqueId() 97 d.Set("target_id", targetId) 98 } 99 100 input := buildPutTargetInputStruct(d) 101 102 log.Printf("[DEBUG] Creating CloudWatch Event Target: %s", input) 103 out, err := conn.PutTargets(input) 104 if err != nil { 105 return fmt.Errorf("Creating CloudWatch Event Target failed: %s", err) 106 } 107 108 if len(out.FailedEntries) > 0 { 109 return fmt.Errorf("Creating CloudWatch Event Target failed: %s", 110 out.FailedEntries) 111 } 112 113 id := rule + "-" + targetId 114 d.SetId(id) 115 116 log.Printf("[INFO] CloudWatch Event Target %q created", d.Id()) 117 118 return resourceAwsCloudWatchEventTargetRead(d, meta) 119 } 120 121 func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface{}) error { 122 conn := meta.(*AWSClient).cloudwatcheventsconn 123 124 t, err := findEventTargetById( 125 d.Get("target_id").(string), 126 d.Get("rule").(string), 127 nil, conn) 128 if err != nil { 129 if regexp.MustCompile(" not found$").MatchString(err.Error()) { 130 log.Printf("[WARN] Removing CloudWatch Event Target %q because it's gone.", d.Id()) 131 d.SetId("") 132 return nil 133 } 134 if awsErr, ok := err.(awserr.Error); ok { 135 // This should never happen, but it's useful 136 // for recovering from https://github.com/hashicorp/terraform/issues/5389 137 if awsErr.Code() == "ValidationException" { 138 log.Printf("[WARN] Removing CloudWatch Event Target %q because it never existed.", d.Id()) 139 d.SetId("") 140 return nil 141 } 142 143 if awsErr.Code() == "ResourceNotFoundException" { 144 log.Printf("[WARN] CloudWatch Event Target (%q) not found. Removing it from state.", d.Id()) 145 d.SetId("") 146 return nil 147 } 148 149 } 150 return err 151 } 152 log.Printf("[DEBUG] Found Event Target: %s", t) 153 154 d.Set("arn", t.Arn) 155 d.Set("target_id", t.Id) 156 d.Set("input", t.Input) 157 d.Set("input_path", t.InputPath) 158 d.Set("role_arn", t.RoleArn) 159 160 if t.RunCommandParameters != nil { 161 if err := d.Set("run_command_targets", flattenAwsCloudWatchEventTargetRunParameters(t.RunCommandParameters)); err != nil { 162 return fmt.Errorf("[DEBUG] Error setting run_command_targets error: %#v", err) 163 } 164 } 165 166 return nil 167 } 168 169 func findEventTargetById(id, rule string, nextToken *string, conn *events.CloudWatchEvents) ( 170 *events.Target, error) { 171 input := events.ListTargetsByRuleInput{ 172 Rule: aws.String(rule), 173 NextToken: nextToken, 174 Limit: aws.Int64(100), // Set limit to allowed maximum to prevent API throttling 175 } 176 log.Printf("[DEBUG] Reading CloudWatch Event Target: %s", input) 177 out, err := conn.ListTargetsByRule(&input) 178 if err != nil { 179 return nil, err 180 } 181 182 for _, t := range out.Targets { 183 if *t.Id == id { 184 return t, nil 185 } 186 } 187 188 if out.NextToken != nil { 189 return findEventTargetById(id, rule, nextToken, conn) 190 } 191 192 return nil, fmt.Errorf("CloudWatch Event Target %q (%q) not found", id, rule) 193 } 194 195 func resourceAwsCloudWatchEventTargetUpdate(d *schema.ResourceData, meta interface{}) error { 196 conn := meta.(*AWSClient).cloudwatcheventsconn 197 198 input := buildPutTargetInputStruct(d) 199 200 log.Printf("[DEBUG] Updating CloudWatch Event Target: %s", input) 201 _, err := conn.PutTargets(input) 202 if err != nil { 203 return fmt.Errorf("Updating CloudWatch Event Target failed: %s", err) 204 } 205 206 return resourceAwsCloudWatchEventTargetRead(d, meta) 207 } 208 209 func resourceAwsCloudWatchEventTargetDelete(d *schema.ResourceData, meta interface{}) error { 210 conn := meta.(*AWSClient).cloudwatcheventsconn 211 212 input := events.RemoveTargetsInput{ 213 Ids: []*string{aws.String(d.Get("target_id").(string))}, 214 Rule: aws.String(d.Get("rule").(string)), 215 } 216 log.Printf("[INFO] Deleting CloudWatch Event Target: %s", input) 217 _, err := conn.RemoveTargets(&input) 218 if err != nil { 219 return fmt.Errorf("Error deleting CloudWatch Event Target: %s", err) 220 } 221 log.Println("[INFO] CloudWatch Event Target deleted") 222 223 d.SetId("") 224 225 return nil 226 } 227 228 func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput { 229 e := &events.Target{ 230 Arn: aws.String(d.Get("arn").(string)), 231 Id: aws.String(d.Get("target_id").(string)), 232 } 233 234 if v, ok := d.GetOk("input"); ok { 235 e.Input = aws.String(v.(string)) 236 } 237 if v, ok := d.GetOk("input_path"); ok { 238 e.InputPath = aws.String(v.(string)) 239 } 240 241 if v, ok := d.GetOk("role_arn"); ok { 242 e.RoleArn = aws.String(v.(string)) 243 } 244 245 if v, ok := d.GetOk("run_command_targets"); ok { 246 e.RunCommandParameters = expandAwsCloudWatchEventTargetRunParameters(v.([]interface{})) 247 } 248 249 input := events.PutTargetsInput{ 250 Rule: aws.String(d.Get("rule").(string)), 251 Targets: []*events.Target{e}, 252 } 253 254 return &input 255 } 256 257 func expandAwsCloudWatchEventTargetRunParameters(config []interface{}) *events.RunCommandParameters { 258 259 commands := make([]*events.RunCommandTarget, 0) 260 261 for _, c := range config { 262 param := c.(map[string]interface{}) 263 command := &events.RunCommandTarget{ 264 Key: aws.String(param["key"].(string)), 265 Values: expandStringList(param["values"].([]interface{})), 266 } 267 268 commands = append(commands, command) 269 } 270 271 command := &events.RunCommandParameters{ 272 RunCommandTargets: commands, 273 } 274 275 return command 276 } 277 278 func flattenAwsCloudWatchEventTargetRunParameters(runCommand *events.RunCommandParameters) []map[string]interface{} { 279 result := make([]map[string]interface{}, 0) 280 281 for _, x := range runCommand.RunCommandTargets { 282 config := make(map[string]interface{}) 283 284 config["key"] = *x.Key 285 config["values"] = flattenStringList(x.Values) 286 287 result = append(result, config) 288 } 289 290 return result 291 }