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  }