github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/alicloud/resource_alicloud_disk.go (about)

     1  package alicloud
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/denverdino/aliyungo/common"
     7  	"github.com/denverdino/aliyungo/ecs"
     8  	"github.com/hashicorp/terraform/helper/resource"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"log"
    11  	"time"
    12  )
    13  
    14  func resourceAliyunDisk() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAliyunDiskCreate,
    17  		Read:   resourceAliyunDiskRead,
    18  		Update: resourceAliyunDiskUpdate,
    19  		Delete: resourceAliyunDiskDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"availability_zone": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  			"name": &schema.Schema{
    28  				Type:         schema.TypeString,
    29  				Optional:     true,
    30  				ValidateFunc: validateDiskName,
    31  			},
    32  
    33  			"description": &schema.Schema{
    34  				Type:         schema.TypeString,
    35  				Optional:     true,
    36  				ValidateFunc: validateDiskDescription,
    37  			},
    38  
    39  			"category": &schema.Schema{
    40  				Type:         schema.TypeString,
    41  				Optional:     true,
    42  				ForceNew:     true,
    43  				ValidateFunc: validateDiskCategory,
    44  				Default:      "cloud",
    45  			},
    46  
    47  			"size": &schema.Schema{
    48  				Type:     schema.TypeInt,
    49  				Optional: true,
    50  			},
    51  
    52  			"snapshot_id": &schema.Schema{
    53  				Type:     schema.TypeString,
    54  				Optional: true,
    55  			},
    56  
    57  			"status": &schema.Schema{
    58  				Type:     schema.TypeString,
    59  				Computed: true,
    60  			},
    61  
    62  			"tags": tagsSchema(),
    63  		},
    64  	}
    65  }
    66  
    67  func resourceAliyunDiskCreate(d *schema.ResourceData, meta interface{}) error {
    68  	client := meta.(*AliyunClient)
    69  
    70  	conn := client.ecsconn
    71  
    72  	availabilityZone, err := client.DescribeZone(d.Get("availability_zone").(string))
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	args := &ecs.CreateDiskArgs{
    78  		RegionId: getRegion(d, meta),
    79  		ZoneId:   availabilityZone.ZoneId,
    80  	}
    81  
    82  	if v, ok := d.GetOk("category"); ok && v.(string) != "" {
    83  		category := ecs.DiskCategory(v.(string))
    84  		if err := client.DiskAvailable(availabilityZone, category); err != nil {
    85  			return err
    86  		}
    87  		args.DiskCategory = category
    88  	}
    89  
    90  	if v, ok := d.GetOk("size"); ok {
    91  		size := v.(int)
    92  		if args.DiskCategory == ecs.DiskCategoryCloud && (size < 5 || size > 2000) {
    93  			return fmt.Errorf("the size of cloud disk must between 5 to 2000")
    94  		}
    95  
    96  		if (args.DiskCategory == ecs.DiskCategoryCloudEfficiency ||
    97  			args.DiskCategory == ecs.DiskCategoryCloudSSD) && (size < 20 || size > 32768) {
    98  			return fmt.Errorf("the size of %s disk must between 20 to 32768", args.DiskCategory)
    99  		}
   100  		args.Size = size
   101  
   102  		d.Set("size", args.Size)
   103  	}
   104  
   105  	if v, ok := d.GetOk("snapshot_id"); ok && v.(string) != "" {
   106  		args.SnapshotId = v.(string)
   107  	}
   108  
   109  	if args.Size <= 0 && args.SnapshotId == "" {
   110  		return fmt.Errorf("One of size or snapshot_id is required when specifying an ECS disk.")
   111  	}
   112  
   113  	if v, ok := d.GetOk("name"); ok && v.(string) != "" {
   114  		args.DiskName = v.(string)
   115  	}
   116  
   117  	if v, ok := d.GetOk("description"); ok && v.(string) != "" {
   118  		args.Description = v.(string)
   119  	}
   120  
   121  	diskID, err := conn.CreateDisk(args)
   122  	if err != nil {
   123  		return fmt.Errorf("CreateDisk got a error: %#v", err)
   124  	}
   125  
   126  	d.SetId(diskID)
   127  
   128  	return resourceAliyunDiskUpdate(d, meta)
   129  }
   130  
   131  func resourceAliyunDiskRead(d *schema.ResourceData, meta interface{}) error {
   132  	conn := meta.(*AliyunClient).ecsconn
   133  
   134  	disks, _, err := conn.DescribeDisks(&ecs.DescribeDisksArgs{
   135  		RegionId: getRegion(d, meta),
   136  		DiskIds:  []string{d.Id()},
   137  	})
   138  
   139  	if err != nil {
   140  		if notFoundError(err) {
   141  			d.SetId("")
   142  			return nil
   143  		}
   144  		return fmt.Errorf("Error DescribeDiskAttribute: %#v", err)
   145  	}
   146  
   147  	log.Printf("[DEBUG] DescribeDiskAttribute for instance: %#v", disks)
   148  
   149  	if disks == nil || len(disks) <= 0 {
   150  		return fmt.Errorf("No disks found.")
   151  	}
   152  
   153  	disk := disks[0]
   154  	d.Set("availability_zone", disk.ZoneId)
   155  	d.Set("category", disk.Category)
   156  	d.Set("size", disk.Size)
   157  	d.Set("status", disk.Status)
   158  	d.Set("name", disk.DiskName)
   159  	d.Set("description", disk.Description)
   160  	d.Set("snapshot_id", disk.SourceSnapshotId)
   161  
   162  	tags, _, err := conn.DescribeTags(&ecs.DescribeTagsArgs{
   163  		RegionId:     getRegion(d, meta),
   164  		ResourceType: ecs.TagResourceDisk,
   165  		ResourceId:   d.Id(),
   166  	})
   167  
   168  	if err != nil {
   169  		log.Printf("[DEBUG] DescribeTags for disk got error: %#v", err)
   170  	}
   171  
   172  	d.Set("tags", tagsToMap(tags))
   173  
   174  	return nil
   175  }
   176  
   177  func resourceAliyunDiskUpdate(d *schema.ResourceData, meta interface{}) error {
   178  	client := meta.(*AliyunClient)
   179  	conn := client.ecsconn
   180  
   181  	d.Partial(true)
   182  
   183  	if err := setTags(client, ecs.TagResourceDisk, d); err != nil {
   184  		log.Printf("[DEBUG] Set tags for instance got error: %#v", err)
   185  		return fmt.Errorf("Set tags for instance got error: %#v", err)
   186  	} else {
   187  		d.SetPartial("tags")
   188  	}
   189  	attributeUpdate := false
   190  	args := &ecs.ModifyDiskAttributeArgs{
   191  		DiskId: d.Id(),
   192  	}
   193  
   194  	if d.HasChange("name") {
   195  		d.SetPartial("name")
   196  		val := d.Get("name").(string)
   197  		args.DiskName = val
   198  
   199  		attributeUpdate = true
   200  	}
   201  
   202  	if d.HasChange("description") {
   203  		d.SetPartial("description")
   204  		val := d.Get("description").(string)
   205  		args.Description = val
   206  
   207  		attributeUpdate = true
   208  	}
   209  	if attributeUpdate {
   210  		if err := conn.ModifyDiskAttribute(args); err != nil {
   211  			return err
   212  		}
   213  	}
   214  
   215  	d.Partial(false)
   216  
   217  	return resourceAliyunDiskRead(d, meta)
   218  }
   219  
   220  func resourceAliyunDiskDelete(d *schema.ResourceData, meta interface{}) error {
   221  	conn := meta.(*AliyunClient).ecsconn
   222  
   223  	return resource.Retry(5*time.Minute, func() *resource.RetryError {
   224  		err := conn.DeleteDisk(d.Id())
   225  		if err != nil {
   226  			e, _ := err.(*common.Error)
   227  			if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == DiskCreatingSnapshot {
   228  				return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
   229  			}
   230  		}
   231  
   232  		disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
   233  			RegionId: getRegion(d, meta),
   234  			DiskIds:  []string{d.Id()},
   235  		})
   236  
   237  		if descErr != nil {
   238  			log.Printf("[ERROR] Delete disk is failed.")
   239  			return resource.NonRetryableError(descErr)
   240  		}
   241  		if disks == nil || len(disks) < 1 {
   242  			return nil
   243  		}
   244  
   245  		return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
   246  	})
   247  }