213 lines
4.8 KiB
Go
213 lines
4.8 KiB
Go
package rancher
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
rancher "github.com/rancher/go-rancher/v2"
|
|
)
|
|
|
|
// ro_labels are used internally by Rancher
|
|
// They are not documented and should not be set in Terraform
|
|
var roLabels = []string{
|
|
"io.rancher.host.agent_image",
|
|
"io.rancher.host.docker_version",
|
|
"io.rancher.host.kvm",
|
|
"io.rancher.host.linux_kernel_version",
|
|
}
|
|
|
|
func resourceRancherHost() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceRancherHostCreate,
|
|
Read: resourceRancherHostRead,
|
|
Update: resourceRancherHostUpdate,
|
|
Delete: resourceRancherHostDelete,
|
|
Importer: &schema.ResourceImporter{
|
|
State: schema.ImportStatePassthrough,
|
|
},
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"id": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
"description": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
"environment_id": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
"hostname": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
"labels": {
|
|
Type: schema.TypeMap,
|
|
Optional: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceRancherHostCreate(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[INFO][rancher] Creating Host: %s", d.Id())
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hosts, _ := client.Host.List(NewListOpts())
|
|
hostname := d.Get("hostname").(string)
|
|
var host rancher.Host
|
|
|
|
for _, h := range hosts.Data {
|
|
if h.Hostname == hostname {
|
|
host = h
|
|
break
|
|
}
|
|
}
|
|
|
|
if host.Hostname == "" {
|
|
return fmt.Errorf("Failed to find host %s", hostname)
|
|
}
|
|
|
|
d.SetId(host.Id)
|
|
|
|
return resourceRancherHostUpdate(d, meta)
|
|
}
|
|
|
|
func resourceRancherHostRead(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[INFO] Refreshing Host: %s", d.Id())
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
host, err := client.Host.ById(d.Id())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if host == nil {
|
|
log.Printf("[INFO] Host %s not found", d.Id())
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
if removed(host.State) {
|
|
log.Printf("[INFO] Host %s was removed on %v", d.Id(), host.Removed)
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
log.Printf("[INFO] Host Name: %s", host.Name)
|
|
|
|
d.Set("description", host.Description)
|
|
d.Set("name", host.Name)
|
|
d.Set("hostname", host.Hostname)
|
|
|
|
labels := host.Labels
|
|
// Remove read-only labels
|
|
for _, lbl := range roLabels {
|
|
delete(labels, lbl)
|
|
}
|
|
d.Set("labels", host.Labels)
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceRancherHostUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[INFO] Updating Host: %s", d.Id())
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
name := d.Get("name").(string)
|
|
description := d.Get("description").(string)
|
|
|
|
// Process labels: merge ro_labels into new labels
|
|
labels := d.Get("labels").(map[string]interface{})
|
|
host, err := client.Host.ById(d.Id())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, lbl := range roLabels {
|
|
labels[lbl] = host.Labels[lbl]
|
|
}
|
|
|
|
data := map[string]interface{}{
|
|
"name": &name,
|
|
"description": &description,
|
|
"labels": &labels,
|
|
}
|
|
|
|
var newHost rancher.Host
|
|
if err := client.Update("host", &host.Resource, data, &newHost); err != nil {
|
|
return err
|
|
}
|
|
|
|
return resourceRancherHostRead(d, meta)
|
|
}
|
|
|
|
func resourceRancherHostDelete(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[INFO] Deleting Host: %s", d.Id())
|
|
id := d.Id()
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
host, err := client.Host.ById(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := client.Host.Delete(host); err != nil {
|
|
return fmt.Errorf("Error deleting Host: %s", err)
|
|
}
|
|
|
|
log.Printf("[DEBUG] Waiting for host (%s) to be removed", id)
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
Pending: []string{"active", "removed", "removing"},
|
|
Target: []string{"removed"},
|
|
Refresh: HostStateRefreshFunc(client, id),
|
|
Timeout: 10 * time.Minute,
|
|
Delay: 1 * time.Second,
|
|
MinTimeout: 3 * time.Second,
|
|
}
|
|
|
|
_, waitErr := stateConf.WaitForState()
|
|
if waitErr != nil {
|
|
return fmt.Errorf(
|
|
"Error waiting for host (%s) to be removed: %s", id, waitErr)
|
|
}
|
|
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
// HostStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
|
|
// a Rancher Host.
|
|
func HostStateRefreshFunc(client *rancher.RancherClient, hostID string) resource.StateRefreshFunc {
|
|
return func() (interface{}, string, error) {
|
|
host, err := client.Host.ById(hostID)
|
|
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
return host, host.State, nil
|
|
}
|
|
}
|