github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/arukas/resource_arukas_container.go (about) 1 package arukas 2 3 import ( 4 "fmt" 5 API "github.com/arukasio/cli" 6 "github.com/hashicorp/terraform/helper/schema" 7 "strings" 8 "time" 9 ) 10 11 func resourceArukasContainer() *schema.Resource { 12 return &schema.Resource{ 13 Create: resourceArukasContainerCreate, 14 Read: resourceArukasContainerRead, 15 Update: resourceArukasContainerUpdate, 16 Delete: resourceArukasContainerDelete, 17 Importer: &schema.ResourceImporter{ 18 State: schema.ImportStatePassthrough, 19 }, 20 Schema: map[string]*schema.Schema{ 21 "name": &schema.Schema{ 22 Type: schema.TypeString, 23 Required: true, 24 ForceNew: true, 25 }, 26 "image": &schema.Schema{ 27 Type: schema.TypeString, 28 Required: true, 29 }, 30 "instances": &schema.Schema{ 31 Type: schema.TypeInt, 32 Optional: true, 33 Default: 1, 34 ValidateFunc: validateIntegerInRange(1, 10), 35 }, 36 "memory": &schema.Schema{ 37 Type: schema.TypeInt, 38 Optional: true, 39 Default: 256, 40 ValidateFunc: validateIntInWord([]string{"256", "512"}), 41 }, 42 "endpoint": &schema.Schema{ 43 Type: schema.TypeString, 44 Optional: true, 45 Computed: true, 46 }, 47 "ports": &schema.Schema{ 48 Type: schema.TypeList, 49 Required: true, 50 MaxItems: 20, 51 Elem: &schema.Resource{ 52 Schema: map[string]*schema.Schema{ 53 "protocol": &schema.Schema{ 54 Type: schema.TypeString, 55 Optional: true, 56 Default: "tcp", 57 ValidateFunc: validateStringInWord([]string{"tcp", "udp"}), 58 }, 59 "number": &schema.Schema{ 60 Type: schema.TypeInt, 61 Optional: true, 62 Default: "80", 63 ValidateFunc: validateIntegerInRange(1, 65535), 64 }, 65 }, 66 }, 67 }, 68 "environments": &schema.Schema{ 69 Type: schema.TypeList, 70 Optional: true, 71 MaxItems: 20, 72 Elem: &schema.Resource{ 73 Schema: map[string]*schema.Schema{ 74 "key": &schema.Schema{ 75 Type: schema.TypeString, 76 Required: true, 77 }, 78 "value": &schema.Schema{ 79 Type: schema.TypeString, 80 Required: true, 81 }, 82 }, 83 }, 84 }, 85 "cmd": &schema.Schema{ 86 Type: schema.TypeString, 87 Optional: true, 88 }, 89 "port_mappings": &schema.Schema{ 90 Type: schema.TypeList, 91 Computed: true, 92 Elem: &schema.Resource{ 93 Schema: map[string]*schema.Schema{ 94 "host": &schema.Schema{ 95 Type: schema.TypeString, 96 Computed: true, 97 }, 98 "ipaddress": &schema.Schema{ 99 Type: schema.TypeString, 100 Computed: true, 101 }, 102 "container_port": &schema.Schema{ 103 Type: schema.TypeInt, 104 Computed: true, 105 }, 106 "service_port": &schema.Schema{ 107 Type: schema.TypeInt, 108 Computed: true, 109 }, 110 }, 111 }, 112 }, 113 "endpoint_full_hostname": &schema.Schema{ 114 Type: schema.TypeString, 115 Computed: true, 116 }, 117 "endpoint_full_url": &schema.Schema{ 118 Type: schema.TypeString, 119 Computed: true, 120 }, 121 "app_id": &schema.Schema{ 122 Type: schema.TypeString, 123 Computed: true, 124 }, 125 }, 126 } 127 } 128 129 func resourceArukasContainerCreate(d *schema.ResourceData, meta interface{}) error { 130 client := meta.(*ArukasClient) 131 132 var appSet API.AppSet 133 134 // create an app 135 newApp := API.App{Name: d.Get("name").(string)} 136 137 var parsedEnvs API.Envs 138 var parsedPorts API.Ports 139 140 if rawEnvs, ok := d.GetOk("environments"); ok { 141 parsedEnvs = expandEnvs(rawEnvs) 142 } 143 if rawPorts, ok := d.GetOk("ports"); ok { 144 parsedPorts = expandPorts(rawPorts) 145 } 146 147 newContainer := API.Container{ 148 Envs: parsedEnvs, 149 Ports: parsedPorts, 150 ImageName: d.Get("image").(string), 151 Mem: d.Get("memory").(int), 152 Instances: d.Get("instances").(int), 153 Cmd: d.Get("cmd").(string), 154 155 Name: d.Get("endpoint").(string), 156 } 157 newAppSet := API.AppSet{ 158 App: newApp, 159 Container: newContainer, 160 } 161 162 // create 163 if err := client.Post(&appSet, "/app-sets", newAppSet); err != nil { 164 return err 165 } 166 167 // start container 168 if err := client.Post(nil, fmt.Sprintf("/containers/%s/power", appSet.Container.ID), nil); err != nil { 169 return err 170 } 171 172 if err := sleepUntilUp(client, appSet.Container.ID, client.Timeout); err != nil { 173 return err 174 } 175 176 d.SetId(appSet.Container.ID) 177 return resourceArukasContainerRead(d, meta) 178 } 179 180 func resourceArukasContainerRead(d *schema.ResourceData, meta interface{}) error { 181 client := meta.(*ArukasClient) 182 183 var container API.Container 184 var app API.App 185 186 if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil { 187 return err 188 } 189 if err := client.Get(&app, fmt.Sprintf("/apps/%s", container.AppID)); err != nil { 190 return err 191 } 192 193 d.Set("app_id", container.AppID) 194 d.Set("name", app.Name) 195 d.Set("image", container.ImageName) 196 d.Set("instances", container.Instances) 197 d.Set("memory", container.Mem) 198 endpoint := container.Endpoint 199 if strings.HasSuffix(endpoint, ".arukascloud.io") { 200 endpoint = strings.Replace(endpoint, ".arukascloud.io", "", -1) 201 } 202 203 d.Set("endpoint", endpoint) 204 d.Set("endpoint_full_hostname", container.Endpoint) 205 d.Set("endpoint_full_url", fmt.Sprintf("https://%s", container.Endpoint)) 206 207 d.Set("cmd", container.Cmd) 208 209 //ports 210 d.Set("ports", flattenPorts(container.Ports)) 211 212 //port mappings 213 d.Set("port_mappings", flattenPortMappings(container.PortMappings)) 214 215 //envs 216 d.Set("environments", flattenEnvs(container.Envs)) 217 218 return nil 219 } 220 221 func resourceArukasContainerUpdate(d *schema.ResourceData, meta interface{}) error { 222 223 client := meta.(*ArukasClient) 224 var container API.Container 225 226 if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil { 227 return err 228 } 229 230 var parsedEnvs API.Envs 231 var parsedPorts API.Ports 232 233 if rawEnvs, ok := d.GetOk("environments"); ok { 234 parsedEnvs = expandEnvs(rawEnvs) 235 } 236 if rawPorts, ok := d.GetOk("ports"); ok { 237 parsedPorts = expandPorts(rawPorts) 238 } 239 240 newContainer := API.Container{ 241 Envs: parsedEnvs, 242 Ports: parsedPorts, 243 ImageName: d.Get("image").(string), 244 Mem: d.Get("memory").(int), 245 Instances: d.Get("instances").(int), 246 Cmd: d.Get("cmd").(string), 247 Name: d.Get("endpoint").(string), 248 } 249 250 // update 251 if err := client.Patch(nil, fmt.Sprintf("/containers/%s", d.Id()), newContainer); err != nil { 252 return err 253 } 254 255 return resourceArukasContainerRead(d, meta) 256 257 } 258 259 func resourceArukasContainerDelete(d *schema.ResourceData, meta interface{}) error { 260 client := meta.(*ArukasClient) 261 var container API.Container 262 263 if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil { 264 return err 265 } 266 267 if err := client.Delete(fmt.Sprintf("/apps/%s", container.AppID)); err != nil { 268 return err 269 } 270 271 return nil 272 } 273 274 func sleepUntilUp(client *ArukasClient, containerID string, timeout time.Duration) error { 275 current := 0 * time.Second 276 interval := 5 * time.Second 277 for { 278 var container API.Container 279 if err := client.Get(&container, fmt.Sprintf("/containers/%s", containerID)); err != nil { 280 return err 281 } 282 283 if container.IsRunning { 284 return nil 285 } 286 time.Sleep(interval) 287 current += interval 288 289 if timeout > 0 && current > timeout { 290 return fmt.Errorf("Timeout: sleepUntilUp") 291 } 292 } 293 }