github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/rancher/resource_rancher_host.go (about)

     1  package rancher
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/hashicorp/terraform/helper/resource"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	rancher "github.com/rancher/go-rancher/client"
    11  )
    12  
    13  // ro_labels are used internally by Rancher
    14  // They are not documented and should not be set in Terraform
    15  var ro_labels = []string{
    16  	"io.rancher.host.agent_image",
    17  	"io.rancher.host.docker_version",
    18  	"io.rancher.host.kvm",
    19  	"io.rancher.host.linux_kernel_version",
    20  }
    21  
    22  func resourceRancherHost() *schema.Resource {
    23  	return &schema.Resource{
    24  		Create: resourceRancherHostCreate,
    25  		Read:   resourceRancherHostRead,
    26  		Update: resourceRancherHostUpdate,
    27  		Delete: resourceRancherHostDelete,
    28  		Importer: &schema.ResourceImporter{
    29  			State: schema.ImportStatePassthrough,
    30  		},
    31  
    32  		Schema: map[string]*schema.Schema{
    33  			"id": &schema.Schema{
    34  				Type:     schema.TypeString,
    35  				Computed: true,
    36  			},
    37  			"name": &schema.Schema{
    38  				Type:     schema.TypeString,
    39  				Required: true,
    40  			},
    41  			"description": &schema.Schema{
    42  				Type:     schema.TypeString,
    43  				Optional: true,
    44  			},
    45  			"environment_id": &schema.Schema{
    46  				Type:     schema.TypeString,
    47  				Required: true,
    48  			},
    49  			"hostname": &schema.Schema{
    50  				Type:     schema.TypeString,
    51  				Required: true,
    52  			},
    53  			"labels": {
    54  				Type:     schema.TypeMap,
    55  				Optional: true,
    56  			},
    57  		},
    58  	}
    59  }
    60  
    61  func resourceRancherHostCreate(d *schema.ResourceData, meta interface{}) error {
    62  	log.Printf("[INFO][rancher] Creating Host: %s", d.Id())
    63  	client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	hosts, _ := client.Host.List(NewListOpts())
    69  	hostname := d.Get("hostname").(string)
    70  	var host rancher.Host
    71  
    72  	for _, h := range hosts.Data {
    73  		if h.Hostname == hostname {
    74  			host = h
    75  			break
    76  		}
    77  	}
    78  
    79  	if host.Hostname == "" {
    80  		return fmt.Errorf("Failed to find host %s", hostname)
    81  	}
    82  
    83  	d.SetId(host.Id)
    84  
    85  	return resourceRancherHostUpdate(d, meta)
    86  }
    87  
    88  func resourceRancherHostRead(d *schema.ResourceData, meta interface{}) error {
    89  	log.Printf("[INFO] Refreshing Host: %s", d.Id())
    90  	client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	host, err := client.Host.ById(d.Id())
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	if host == nil {
   101  		log.Printf("[INFO] Host %s not found", d.Id())
   102  		d.SetId("")
   103  		return nil
   104  	}
   105  
   106  	if removed(host.State) {
   107  		log.Printf("[INFO] Host %s was removed on %v", d.Id(), host.Removed)
   108  		d.SetId("")
   109  		return nil
   110  	}
   111  
   112  	log.Printf("[INFO] Host Name: %s", host.Name)
   113  
   114  	d.Set("description", host.Description)
   115  	d.Set("name", host.Name)
   116  	d.Set("hostname", host.Hostname)
   117  
   118  	labels := host.Labels
   119  	// Remove read-only labels
   120  	for _, lbl := range ro_labels {
   121  		delete(labels, lbl)
   122  	}
   123  	d.Set("labels", host.Labels)
   124  
   125  	return nil
   126  }
   127  
   128  func resourceRancherHostUpdate(d *schema.ResourceData, meta interface{}) error {
   129  	log.Printf("[INFO] Updating Host: %s", d.Id())
   130  	client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
   131  	if err != nil {
   132  		return err
   133  	}
   134  
   135  	name := d.Get("name").(string)
   136  	description := d.Get("description").(string)
   137  
   138  	// Process labels: merge ro_labels into new labels
   139  	labels := d.Get("labels").(map[string]interface{})
   140  	host, err := client.Host.ById(d.Id())
   141  	if err != nil {
   142  		return err
   143  	}
   144  	for _, lbl := range ro_labels {
   145  		labels[lbl] = host.Labels[lbl]
   146  	}
   147  
   148  	data := map[string]interface{}{
   149  		"name":        &name,
   150  		"description": &description,
   151  		"labels":      &labels,
   152  	}
   153  
   154  	var newHost rancher.Host
   155  	if err := client.Update("host", &host.Resource, data, &newHost); err != nil {
   156  		return err
   157  	}
   158  
   159  	return resourceRancherHostRead(d, meta)
   160  }
   161  
   162  func resourceRancherHostDelete(d *schema.ResourceData, meta interface{}) error {
   163  	log.Printf("[INFO] Deleting Host: %s", d.Id())
   164  	id := d.Id()
   165  	client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	host, err := client.Host.ById(id)
   171  	if err != nil {
   172  		return err
   173  	}
   174  
   175  	if err := client.Host.Delete(host); err != nil {
   176  		return fmt.Errorf("Error deleting Host: %s", err)
   177  	}
   178  
   179  	log.Printf("[DEBUG] Waiting for host (%s) to be removed", id)
   180  
   181  	stateConf := &resource.StateChangeConf{
   182  		Pending:    []string{"active", "removed", "removing"},
   183  		Target:     []string{"removed"},
   184  		Refresh:    HostStateRefreshFunc(client, id),
   185  		Timeout:    10 * time.Minute,
   186  		Delay:      1 * time.Second,
   187  		MinTimeout: 3 * time.Second,
   188  	}
   189  
   190  	_, waitErr := stateConf.WaitForState()
   191  	if waitErr != nil {
   192  		return fmt.Errorf(
   193  			"Error waiting for host (%s) to be removed: %s", id, waitErr)
   194  	}
   195  
   196  	d.SetId("")
   197  	return nil
   198  }
   199  
   200  // HostStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
   201  // a Rancher Host.
   202  func HostStateRefreshFunc(client *rancher.RancherClient, hostID string) resource.StateRefreshFunc {
   203  	return func() (interface{}, string, error) {
   204  		host, err := client.Host.ById(hostID)
   205  
   206  		if err != nil {
   207  			return nil, "", err
   208  		}
   209  
   210  		return host, host.State, nil
   211  	}
   212  }