github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/arukas/resource_arukas_container.go (about)

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