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 }