github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_ssm_document.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/ssm" 12 "github.com/hashicorp/errwrap" 13 "github.com/hashicorp/terraform/helper/resource" 14 "github.com/hashicorp/terraform/helper/schema" 15 ) 16 17 func resourceAwsSsmDocument() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsSsmDocumentCreate, 20 Read: resourceAwsSsmDocumentRead, 21 Update: resourceAwsSsmDocumentUpdate, 22 Delete: resourceAwsSsmDocumentDelete, 23 24 Schema: map[string]*schema.Schema{ 25 "name": { 26 Type: schema.TypeString, 27 ForceNew: true, 28 Required: true, 29 }, 30 "content": { 31 Type: schema.TypeString, 32 ForceNew: true, 33 Required: true, 34 }, 35 "created_date": { 36 Type: schema.TypeString, 37 Computed: true, 38 }, 39 "description": { 40 Type: schema.TypeString, 41 Computed: true, 42 }, 43 "hash": { 44 Type: schema.TypeString, 45 Computed: true, 46 }, 47 "hash_type": { 48 Type: schema.TypeString, 49 Computed: true, 50 }, 51 "owner": { 52 Type: schema.TypeString, 53 Computed: true, 54 }, 55 "status": { 56 Type: schema.TypeString, 57 Computed: true, 58 }, 59 "platform_type": { 60 Type: schema.TypeString, 61 Computed: true, 62 }, 63 "parameter": { 64 Type: schema.TypeList, 65 Computed: true, 66 Elem: &schema.Resource{ 67 Schema: map[string]*schema.Schema{ 68 "name": { 69 Type: schema.TypeString, 70 Optional: true, 71 }, 72 "default_value": { 73 Type: schema.TypeString, 74 Optional: true, 75 }, 76 "description": { 77 Type: schema.TypeString, 78 Optional: true, 79 }, 80 "type": { 81 Type: schema.TypeString, 82 Optional: true, 83 }, 84 }, 85 }, 86 }, 87 "permissions": { 88 Type: schema.TypeMap, 89 Optional: true, 90 Elem: &schema.Resource{ 91 Schema: map[string]*schema.Schema{ 92 "type": { 93 Type: schema.TypeString, 94 Required: true, 95 }, 96 "account_ids": { 97 Type: schema.TypeString, 98 Required: true, 99 }, 100 }, 101 }, 102 }, 103 }, 104 } 105 } 106 107 func resourceAwsSsmDocumentCreate(d *schema.ResourceData, meta interface{}) error { 108 ssmconn := meta.(*AWSClient).ssmconn 109 110 log.Printf("[INFO] Creating SSM Document: %s", d.Get("name").(string)) 111 112 docInput := &ssm.CreateDocumentInput{ 113 Name: aws.String(d.Get("name").(string)), 114 Content: aws.String(d.Get("content").(string)), 115 } 116 117 resp, err := ssmconn.CreateDocument(docInput) 118 119 if err != nil { 120 return errwrap.Wrapf("[ERROR] Error creating SSM document: {{err}}", err) 121 } 122 123 d.SetId(*resp.DocumentDescription.Name) 124 125 if v, ok := d.GetOk("permissions"); ok && v != nil { 126 if err := setDocumentPermissions(d, meta); err != nil { 127 return err 128 } 129 } else { 130 log.Printf("[DEBUG] Not setting permissions for %q", d.Id()) 131 } 132 133 return resourceAwsSsmDocumentRead(d, meta) 134 } 135 136 func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error { 137 ssmconn := meta.(*AWSClient).ssmconn 138 139 log.Printf("[DEBUG] Reading SSM Document: %s", d.Id()) 140 141 docInput := &ssm.DescribeDocumentInput{ 142 Name: aws.String(d.Get("name").(string)), 143 } 144 145 resp, err := ssmconn.DescribeDocument(docInput) 146 147 if err != nil { 148 return errwrap.Wrapf("[ERROR] Error describing SSM document: {{err}}", err) 149 } 150 151 doc := resp.Document 152 d.Set("created_date", doc.CreatedDate) 153 d.Set("description", doc.Description) 154 d.Set("hash", doc.Hash) 155 d.Set("hash_type", doc.HashType) 156 d.Set("name", doc.Name) 157 d.Set("owner", doc.Owner) 158 d.Set("platform_type", doc.PlatformTypes[0]) 159 d.Set("status", doc.Status) 160 161 gp, err := getDocumentPermissions(d, meta) 162 163 if err != nil { 164 return errwrap.Wrapf("[ERROR] Error reading SSM document permissions: {{err}}", err) 165 } 166 167 d.Set("permissions", gp) 168 169 params := make([]map[string]interface{}, 0) 170 for i := 0; i < len(doc.Parameters); i++ { 171 172 dp := doc.Parameters[i] 173 param := make(map[string]interface{}) 174 175 if dp.DefaultValue != nil { 176 param["default_value"] = *dp.DefaultValue 177 } 178 param["description"] = *dp.Description 179 param["name"] = *dp.Name 180 param["type"] = *dp.Type 181 params = append(params, param) 182 } 183 184 if len(params) == 0 { 185 params = make([]map[string]interface{}, 1) 186 } 187 188 if err := d.Set("parameter", params); err != nil { 189 return err 190 } 191 192 return nil 193 } 194 195 func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) error { 196 197 if _, ok := d.GetOk("permissions"); ok { 198 if err := setDocumentPermissions(d, meta); err != nil { 199 return err 200 } 201 } else { 202 log.Printf("[DEBUG] Not setting document permissions on %q", d.Id()) 203 } 204 205 return resourceAwsSsmDocumentRead(d, meta) 206 } 207 208 func resourceAwsSsmDocumentDelete(d *schema.ResourceData, meta interface{}) error { 209 ssmconn := meta.(*AWSClient).ssmconn 210 211 if err := deleteDocumentPermissions(d, meta); err != nil { 212 return err 213 } 214 215 log.Printf("[INFO] Deleting SSM Document: %s", d.Id()) 216 217 params := &ssm.DeleteDocumentInput{ 218 Name: aws.String(d.Get("name").(string)), 219 } 220 221 _, err := ssmconn.DeleteDocument(params) 222 if err != nil { 223 return err 224 } 225 226 log.Printf("[DEBUG] Waiting for SSM Document %q to be deleted", d.Get("name").(string)) 227 err = resource.Retry(10*time.Minute, func() *resource.RetryError { 228 _, err := ssmconn.DescribeDocument(&ssm.DescribeDocumentInput{ 229 Name: aws.String(d.Get("name").(string)), 230 }) 231 232 if err != nil { 233 awsErr, ok := err.(awserr.Error) 234 if !ok { 235 return resource.NonRetryableError(err) 236 } 237 238 if awsErr.Code() == "InvalidDocument" { 239 return nil 240 } 241 242 return resource.NonRetryableError(err) 243 } 244 245 return resource.RetryableError( 246 fmt.Errorf("%q: Timeout while waiting for the document to be deleted", d.Id())) 247 }) 248 if err != nil { 249 return err 250 } 251 252 d.SetId("") 253 254 return nil 255 } 256 257 func setDocumentPermissions(d *schema.ResourceData, meta interface{}) error { 258 ssmconn := meta.(*AWSClient).ssmconn 259 260 log.Printf("[INFO] Setting permissions for document: %s", d.Id()) 261 permission := d.Get("permissions").(map[string]interface{}) 262 263 ids := aws.StringSlice([]string{permission["account_ids"].(string)}) 264 265 if strings.Contains(permission["account_ids"].(string), ",") { 266 ids = aws.StringSlice(strings.Split(permission["account_ids"].(string), ",")) 267 } 268 269 permInput := &ssm.ModifyDocumentPermissionInput{ 270 Name: aws.String(d.Get("name").(string)), 271 PermissionType: aws.String(permission["type"].(string)), 272 AccountIdsToAdd: ids, 273 } 274 275 _, err := ssmconn.ModifyDocumentPermission(permInput) 276 277 if err != nil { 278 return errwrap.Wrapf("[ERROR] Error setting permissions for SSM document: {{err}}", err) 279 } 280 281 return nil 282 } 283 284 func getDocumentPermissions(d *schema.ResourceData, meta interface{}) (map[string]interface{}, error) { 285 ssmconn := meta.(*AWSClient).ssmconn 286 287 log.Printf("[INFO] Getting permissions for document: %s", d.Id()) 288 289 //How to get from nested scheme resource? 290 permissionType := "Share" 291 292 permInput := &ssm.DescribeDocumentPermissionInput{ 293 Name: aws.String(d.Get("name").(string)), 294 PermissionType: aws.String(permissionType), 295 } 296 297 resp, err := ssmconn.DescribeDocumentPermission(permInput) 298 299 if err != nil { 300 return nil, errwrap.Wrapf("[ERROR] Error setting permissions for SSM document: {{err}}", err) 301 } 302 303 var account_ids = make([]string, len(resp.AccountIds)) 304 for i := 0; i < len(resp.AccountIds); i++ { 305 account_ids[i] = *resp.AccountIds[i] 306 } 307 308 var ids = "" 309 if len(account_ids) == 1 { 310 ids = account_ids[0] 311 } else if len(account_ids) > 1 { 312 ids = strings.Join(account_ids, ",") 313 } else { 314 ids = "" 315 } 316 317 if ids == "" { 318 return nil, nil 319 } 320 321 perms := make(map[string]interface{}) 322 perms["type"] = permissionType 323 perms["account_ids"] = ids 324 325 return perms, nil 326 } 327 328 func deleteDocumentPermissions(d *schema.ResourceData, meta interface{}) error { 329 ssmconn := meta.(*AWSClient).ssmconn 330 331 log.Printf("[INFO] Removing permissions from document: %s", d.Id()) 332 333 permInput := &ssm.ModifyDocumentPermissionInput{ 334 Name: aws.String(d.Get("name").(string)), 335 PermissionType: aws.String("Share"), 336 AccountIdsToRemove: aws.StringSlice(strings.Split("all", ",")), 337 } 338 339 _, err := ssmconn.ModifyDocumentPermission(permInput) 340 341 if err != nil { 342 return errwrap.Wrapf("[ERROR] Error removing permissions for SSM document: {{err}}", err) 343 } 344 345 return nil 346 }