2017-02-13 20:11:30 +01:00
|
|
|
package arukas
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2017-03-19 19:55:11 +01:00
|
|
|
"strings"
|
|
|
|
|
2017-02-13 20:11:30 +01:00
|
|
|
API "github.com/arukasio/cli"
|
2017-03-19 19:55:11 +01:00
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
2017-02-13 20:11:30 +01:00
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
)
|
|
|
|
|
|
|
|
func resourceArukasContainer() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceArukasContainerCreate,
|
|
|
|
Read: resourceArukasContainerRead,
|
|
|
|
Update: resourceArukasContainerUpdate,
|
|
|
|
Delete: resourceArukasContainerDelete,
|
|
|
|
Importer: &schema.ResourceImporter{
|
|
|
|
State: schema.ImportStatePassthrough,
|
|
|
|
},
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"image": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"instances": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: 1,
|
|
|
|
ValidateFunc: validateIntegerInRange(1, 10),
|
|
|
|
},
|
|
|
|
"memory": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: 256,
|
|
|
|
ValidateFunc: validateIntInWord([]string{"256", "512"}),
|
|
|
|
},
|
|
|
|
"endpoint": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"ports": &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Required: true,
|
|
|
|
MaxItems: 20,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"protocol": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Default: "tcp",
|
|
|
|
ValidateFunc: validateStringInWord([]string{"tcp", "udp"}),
|
|
|
|
},
|
|
|
|
"number": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Default: "80",
|
|
|
|
ValidateFunc: validateIntegerInRange(1, 65535),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"environments": &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Optional: true,
|
|
|
|
MaxItems: 20,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"key": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"value": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"cmd": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"port_mappings": &schema.Schema{
|
|
|
|
Type: schema.TypeList,
|
|
|
|
Computed: true,
|
|
|
|
Elem: &schema.Resource{
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"host": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"ipaddress": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"container_port": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"service_port": &schema.Schema{
|
|
|
|
Type: schema.TypeInt,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"endpoint_full_hostname": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"endpoint_full_url": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"app_id": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceArukasContainerCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
client := meta.(*ArukasClient)
|
|
|
|
|
|
|
|
var appSet API.AppSet
|
|
|
|
|
|
|
|
// create an app
|
|
|
|
newApp := API.App{Name: d.Get("name").(string)}
|
|
|
|
|
|
|
|
var parsedEnvs API.Envs
|
|
|
|
var parsedPorts API.Ports
|
|
|
|
|
|
|
|
if rawEnvs, ok := d.GetOk("environments"); ok {
|
|
|
|
parsedEnvs = expandEnvs(rawEnvs)
|
|
|
|
}
|
|
|
|
if rawPorts, ok := d.GetOk("ports"); ok {
|
|
|
|
parsedPorts = expandPorts(rawPorts)
|
|
|
|
}
|
|
|
|
|
|
|
|
newContainer := API.Container{
|
|
|
|
Envs: parsedEnvs,
|
|
|
|
Ports: parsedPorts,
|
|
|
|
ImageName: d.Get("image").(string),
|
|
|
|
Mem: d.Get("memory").(int),
|
|
|
|
Instances: d.Get("instances").(int),
|
|
|
|
Cmd: d.Get("cmd").(string),
|
|
|
|
|
|
|
|
Name: d.Get("endpoint").(string),
|
|
|
|
}
|
|
|
|
newAppSet := API.AppSet{
|
|
|
|
App: newApp,
|
|
|
|
Container: newContainer,
|
|
|
|
}
|
|
|
|
|
|
|
|
// create
|
|
|
|
if err := client.Post(&appSet, "/app-sets", newAppSet); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// start container
|
|
|
|
if err := client.Post(nil, fmt.Sprintf("/containers/%s/power", appSet.Container.ID), nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-03-19 19:55:11 +01:00
|
|
|
d.SetId(appSet.Container.ID)
|
|
|
|
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
|
|
Target: []string{"running"},
|
|
|
|
Pending: []string{"stopped", "booting"},
|
|
|
|
Timeout: client.Timeout,
|
|
|
|
Refresh: func() (interface{}, string, error) {
|
|
|
|
var container API.Container
|
|
|
|
err := client.Get(&container, fmt.Sprintf("/containers/%s", appSet.Container.ID))
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return container, container.StatusText, nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
_, err := stateConf.WaitForState()
|
|
|
|
if err != nil {
|
2017-02-13 20:11:30 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return resourceArukasContainerRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceArukasContainerRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
client := meta.(*ArukasClient)
|
|
|
|
|
|
|
|
var container API.Container
|
|
|
|
var app API.App
|
|
|
|
|
|
|
|
if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := client.Get(&app, fmt.Sprintf("/apps/%s", container.AppID)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Set("app_id", container.AppID)
|
|
|
|
d.Set("name", app.Name)
|
|
|
|
d.Set("image", container.ImageName)
|
|
|
|
d.Set("instances", container.Instances)
|
|
|
|
d.Set("memory", container.Mem)
|
|
|
|
endpoint := container.Endpoint
|
|
|
|
if strings.HasSuffix(endpoint, ".arukascloud.io") {
|
|
|
|
endpoint = strings.Replace(endpoint, ".arukascloud.io", "", -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Set("endpoint", endpoint)
|
|
|
|
d.Set("endpoint_full_hostname", container.Endpoint)
|
|
|
|
d.Set("endpoint_full_url", fmt.Sprintf("https://%s", container.Endpoint))
|
|
|
|
|
|
|
|
d.Set("cmd", container.Cmd)
|
|
|
|
|
|
|
|
//ports
|
|
|
|
d.Set("ports", flattenPorts(container.Ports))
|
|
|
|
|
|
|
|
//port mappings
|
|
|
|
d.Set("port_mappings", flattenPortMappings(container.PortMappings))
|
|
|
|
|
|
|
|
//envs
|
|
|
|
d.Set("environments", flattenEnvs(container.Envs))
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceArukasContainerUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
|
|
|
|
client := meta.(*ArukasClient)
|
|
|
|
var container API.Container
|
|
|
|
|
|
|
|
if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var parsedEnvs API.Envs
|
|
|
|
var parsedPorts API.Ports
|
|
|
|
|
|
|
|
if rawEnvs, ok := d.GetOk("environments"); ok {
|
|
|
|
parsedEnvs = expandEnvs(rawEnvs)
|
|
|
|
}
|
|
|
|
if rawPorts, ok := d.GetOk("ports"); ok {
|
|
|
|
parsedPorts = expandPorts(rawPorts)
|
|
|
|
}
|
|
|
|
|
|
|
|
newContainer := API.Container{
|
|
|
|
Envs: parsedEnvs,
|
|
|
|
Ports: parsedPorts,
|
|
|
|
ImageName: d.Get("image").(string),
|
|
|
|
Mem: d.Get("memory").(int),
|
|
|
|
Instances: d.Get("instances").(int),
|
|
|
|
Cmd: d.Get("cmd").(string),
|
|
|
|
Name: d.Get("endpoint").(string),
|
|
|
|
}
|
|
|
|
|
|
|
|
// update
|
|
|
|
if err := client.Patch(nil, fmt.Sprintf("/containers/%s", d.Id()), newContainer); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return resourceArukasContainerRead(d, meta)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceArukasContainerDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
client := meta.(*ArukasClient)
|
|
|
|
var container API.Container
|
|
|
|
|
|
|
|
if err := client.Get(&container, fmt.Sprintf("/containers/%s", d.Id())); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := client.Delete(fmt.Sprintf("/apps/%s", container.AppID)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|