github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/builtin/providers/cloudstack/resource_cloudstack_template.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/xanzy/go-cloudstack/cloudstack"
    11  )
    12  
    13  func resourceCloudStackTemplate() *schema.Resource {
    14  	return &schema.Resource{
    15  		Create: resourceCloudStackTemplateCreate,
    16  		Read:   resourceCloudStackTemplateRead,
    17  		Update: resourceCloudStackTemplateUpdate,
    18  		Delete: resourceCloudStackTemplateDelete,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"name": &schema.Schema{
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  			},
    25  
    26  			"display_text": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Optional: true,
    29  				Computed: true,
    30  			},
    31  
    32  			"format": &schema.Schema{
    33  				Type:     schema.TypeString,
    34  				Required: true,
    35  			},
    36  
    37  			"hypervisor": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Required: true,
    40  				ForceNew: true,
    41  			},
    42  
    43  			"os_type": &schema.Schema{
    44  				Type:     schema.TypeString,
    45  				Required: true,
    46  			},
    47  
    48  			"url": &schema.Schema{
    49  				Type:     schema.TypeString,
    50  				Required: true,
    51  				ForceNew: true,
    52  			},
    53  
    54  			"zone": &schema.Schema{
    55  				Type:     schema.TypeString,
    56  				Required: true,
    57  				ForceNew: true,
    58  			},
    59  
    60  			"is_dynamically_scalable": &schema.Schema{
    61  				Type:     schema.TypeBool,
    62  				Optional: true,
    63  				Computed: true,
    64  			},
    65  
    66  			"is_extractable": &schema.Schema{
    67  				Type:     schema.TypeBool,
    68  				Optional: true,
    69  				Computed: true,
    70  				ForceNew: true,
    71  			},
    72  
    73  			"is_featured": &schema.Schema{
    74  				Type:     schema.TypeBool,
    75  				Optional: true,
    76  				Computed: true,
    77  				ForceNew: true,
    78  			},
    79  
    80  			"is_public": &schema.Schema{
    81  				Type:     schema.TypeBool,
    82  				Optional: true,
    83  				Computed: true,
    84  			},
    85  
    86  			"password_enabled": &schema.Schema{
    87  				Type:     schema.TypeBool,
    88  				Optional: true,
    89  				Computed: true,
    90  			},
    91  
    92  			"is_ready": &schema.Schema{
    93  				Type:     schema.TypeBool,
    94  				Computed: true,
    95  			},
    96  
    97  			"is_ready_timeout": &schema.Schema{
    98  				Type:     schema.TypeInt,
    99  				Optional: true,
   100  				Default:  300,
   101  			},
   102  		},
   103  	}
   104  }
   105  
   106  func resourceCloudStackTemplateCreate(d *schema.ResourceData, meta interface{}) error {
   107  	cs := meta.(*cloudstack.CloudStackClient)
   108  
   109  	name := d.Get("name").(string)
   110  
   111  	// Compute/set the display text
   112  	displaytext := d.Get("display_text").(string)
   113  	if displaytext == "" {
   114  		displaytext = name
   115  	}
   116  
   117  	// Retrieve the os_type UUID
   118  	ostypeid, e := retrieveUUID(cs, "os_type", d.Get("os_type").(string))
   119  	if e != nil {
   120  		return e.Error()
   121  	}
   122  
   123  	// Retrieve the zone UUID
   124  	zoneid, e := retrieveUUID(cs, "zone", d.Get("zone").(string))
   125  	if e != nil {
   126  		return e.Error()
   127  	}
   128  
   129  	// Create a new parameter struct
   130  	p := cs.Template.NewRegisterTemplateParams(
   131  		displaytext,
   132  		d.Get("format").(string),
   133  		d.Get("hypervisor").(string),
   134  		name,
   135  		ostypeid,
   136  		d.Get("url").(string),
   137  		zoneid)
   138  
   139  	// Set optional parameters
   140  	if v, ok := d.GetOk("is_dynamically_scalable"); ok {
   141  		p.SetIsdynamicallyscalable(v.(bool))
   142  	}
   143  
   144  	if v, ok := d.GetOk("is_extractable"); ok {
   145  		p.SetIsextractable(v.(bool))
   146  	}
   147  
   148  	if v, ok := d.GetOk("is_featured"); ok {
   149  		p.SetIsfeatured(v.(bool))
   150  	}
   151  
   152  	if v, ok := d.GetOk("is_public"); ok {
   153  		p.SetIspublic(v.(bool))
   154  	}
   155  
   156  	if v, ok := d.GetOk("password_enabled"); ok {
   157  		p.SetPasswordenabled(v.(bool))
   158  	}
   159  
   160  	// Create the new template
   161  	r, err := cs.Template.RegisterTemplate(p)
   162  	if err != nil {
   163  		return fmt.Errorf("Error creating template %s: %s", name, err)
   164  	}
   165  
   166  	d.SetId(r.RegisterTemplate[0].Id)
   167  
   168  	// Wait until the template is ready to use, or timeout with an error...
   169  	currentTime := time.Now().Unix()
   170  	timeout := int64(d.Get("is_ready_timeout").(int))
   171  	for {
   172  		err := resourceCloudStackTemplateRead(d, meta)
   173  		if err != nil {
   174  			return err
   175  		}
   176  
   177  		if d.Get("is_ready").(bool) {
   178  			return nil
   179  		}
   180  
   181  		if time.Now().Unix()-currentTime > timeout {
   182  			return fmt.Errorf("Timeout while waiting for template to become ready")
   183  		}
   184  		time.Sleep(5 * time.Second)
   185  	}
   186  }
   187  
   188  func resourceCloudStackTemplateRead(d *schema.ResourceData, meta interface{}) error {
   189  	cs := meta.(*cloudstack.CloudStackClient)
   190  
   191  	// Get the template details
   192  	t, count, err := cs.Template.GetTemplateByID(d.Id(), "executable")
   193  	if err != nil {
   194  		if count == 0 {
   195  			log.Printf(
   196  				"[DEBUG] Template %s no longer exists", d.Get("name").(string))
   197  			d.SetId("")
   198  			return nil
   199  		}
   200  
   201  		return err
   202  	}
   203  
   204  	d.Set("name", t.Name)
   205  	d.Set("display_text", t.Displaytext)
   206  	d.Set("format", t.Format)
   207  	d.Set("hypervisor", t.Hypervisor)
   208  	d.Set("os_type", t.Ostypename)
   209  	d.Set("zone", t.Zonename)
   210  	d.Set("is_dynamically_scalable", t.Isdynamicallyscalable)
   211  	d.Set("is_extractable", t.Isextractable)
   212  	d.Set("is_featured", t.Isfeatured)
   213  	d.Set("is_public", t.Ispublic)
   214  	d.Set("password_enabled", t.Passwordenabled)
   215  	d.Set("is_ready", t.Isready)
   216  
   217  	return nil
   218  }
   219  
   220  func resourceCloudStackTemplateUpdate(d *schema.ResourceData, meta interface{}) error {
   221  	cs := meta.(*cloudstack.CloudStackClient)
   222  	name := d.Get("name").(string)
   223  
   224  	// Create a new parameter struct
   225  	p := cs.Template.NewUpdateTemplateParams(d.Id())
   226  
   227  	if d.HasChange("name") {
   228  		p.SetName(name)
   229  	}
   230  
   231  	if d.HasChange("display_text") {
   232  		p.SetDisplaytext(d.Get("display_text").(string))
   233  	}
   234  
   235  	if d.HasChange("format") {
   236  		p.SetFormat(d.Get("format").(string))
   237  	}
   238  
   239  	if d.HasChange("is_dynamically_scalable") {
   240  		p.SetIsdynamicallyscalable(d.Get("is_dynamically_scalable").(bool))
   241  	}
   242  
   243  	if d.HasChange("os_type") {
   244  		ostypeid, e := retrieveUUID(cs, "os_type", d.Get("os_type").(string))
   245  		if e != nil {
   246  			return e.Error()
   247  		}
   248  		p.SetOstypeid(ostypeid)
   249  	}
   250  
   251  	if d.HasChange("password_enabled") {
   252  		p.SetPasswordenabled(d.Get("password_enabled").(bool))
   253  	}
   254  
   255  	_, err := cs.Template.UpdateTemplate(p)
   256  	if err != nil {
   257  		return fmt.Errorf("Error updating template %s: %s", name, err)
   258  	}
   259  
   260  	return resourceCloudStackTemplateRead(d, meta)
   261  }
   262  
   263  func resourceCloudStackTemplateDelete(d *schema.ResourceData, meta interface{}) error {
   264  	cs := meta.(*cloudstack.CloudStackClient)
   265  
   266  	// Create a new parameter struct
   267  	p := cs.Template.NewDeleteTemplateParams(d.Id())
   268  
   269  	// Delete the template
   270  	log.Printf("[INFO] Deleting template: %s", d.Get("name").(string))
   271  	_, err := cs.Template.DeleteTemplate(p)
   272  	if err != nil {
   273  		// This is a very poor way to be told the UUID does no longer exist :(
   274  		if strings.Contains(err.Error(), fmt.Sprintf(
   275  			"Invalid parameter id value=%s due to incorrect long value format, "+
   276  				"or entity does not exist", d.Id())) {
   277  			return nil
   278  		}
   279  
   280  		return fmt.Errorf("Error deleting template %s: %s", d.Get("name").(string), err)
   281  	}
   282  	return nil
   283  }