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

     1  package heroku
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/cyberdelia/heroku-go/v3"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  // Global lock to prevent parallelism for heroku_addon since
    15  // the Heroku API cannot handle a single application requesting
    16  // multiple addons simultaneously.
    17  var addonLock sync.Mutex
    18  
    19  func resourceHerokuAddon() *schema.Resource {
    20  	return &schema.Resource{
    21  		Create: resourceHerokuAddonCreate,
    22  		Read:   resourceHerokuAddonRead,
    23  		Update: resourceHerokuAddonUpdate,
    24  		Delete: resourceHerokuAddonDelete,
    25  
    26  		Schema: map[string]*schema.Schema{
    27  			"app": {
    28  				Type:     schema.TypeString,
    29  				Required: true,
    30  				ForceNew: true,
    31  			},
    32  
    33  			"plan": {
    34  				Type:     schema.TypeString,
    35  				Required: true,
    36  			},
    37  
    38  			"config": {
    39  				Type:     schema.TypeList,
    40  				Optional: true,
    41  				ForceNew: true,
    42  				Elem: &schema.Schema{
    43  					Type: schema.TypeMap,
    44  				},
    45  			},
    46  
    47  			"provider_id": {
    48  				Type:     schema.TypeString,
    49  				Computed: true,
    50  			},
    51  
    52  			"config_vars": {
    53  				Type:     schema.TypeList,
    54  				Computed: true,
    55  				Elem: &schema.Schema{
    56  					Type: schema.TypeString,
    57  				},
    58  			},
    59  		},
    60  	}
    61  }
    62  
    63  func resourceHerokuAddonCreate(d *schema.ResourceData, meta interface{}) error {
    64  	addonLock.Lock()
    65  	defer addonLock.Unlock()
    66  
    67  	client := meta.(*heroku.Service)
    68  
    69  	app := d.Get("app").(string)
    70  	opts := heroku.AddOnCreateOpts{Plan: d.Get("plan").(string)}
    71  
    72  	if v := d.Get("config"); v != nil {
    73  		config := make(map[string]string)
    74  		for _, v := range v.([]interface{}) {
    75  			for k, v := range v.(map[string]interface{}) {
    76  				config[k] = v.(string)
    77  			}
    78  		}
    79  
    80  		opts.Config = &config
    81  	}
    82  
    83  	log.Printf("[DEBUG] Addon create configuration: %#v, %#v", app, opts)
    84  	a, err := client.AddOnCreate(context.TODO(), app, opts)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	d.SetId(a.ID)
    90  	log.Printf("[INFO] Addon ID: %s", d.Id())
    91  
    92  	return resourceHerokuAddonRead(d, meta)
    93  }
    94  
    95  func resourceHerokuAddonRead(d *schema.ResourceData, meta interface{}) error {
    96  	client := meta.(*heroku.Service)
    97  
    98  	addon, err := resourceHerokuAddonRetrieve(
    99  		d.Get("app").(string), d.Id(), client)
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	// Determine the plan. If we were configured without a specific plan,
   105  	// then just avoid the plan altogether (accepting anything that
   106  	// Heroku sends down).
   107  	plan := addon.Plan.Name
   108  	if v := d.Get("plan").(string); v != "" {
   109  		if idx := strings.IndexRune(v, ':'); idx == -1 {
   110  			idx = strings.IndexRune(plan, ':')
   111  			if idx > -1 {
   112  				plan = plan[:idx]
   113  			}
   114  		}
   115  	}
   116  
   117  	d.Set("name", addon.Name)
   118  	d.Set("plan", plan)
   119  	d.Set("provider_id", addon.ProviderID)
   120  	if err := d.Set("config_vars", addon.ConfigVars); err != nil {
   121  		return err
   122  	}
   123  
   124  	return nil
   125  }
   126  
   127  func resourceHerokuAddonUpdate(d *schema.ResourceData, meta interface{}) error {
   128  	client := meta.(*heroku.Service)
   129  
   130  	app := d.Get("app").(string)
   131  
   132  	if d.HasChange("plan") {
   133  		ad, err := client.AddOnUpdate(
   134  			context.TODO(), app, d.Id(), heroku.AddOnUpdateOpts{Plan: d.Get("plan").(string)})
   135  		if err != nil {
   136  			return err
   137  		}
   138  
   139  		// Store the new ID
   140  		d.SetId(ad.ID)
   141  	}
   142  
   143  	return resourceHerokuAddonRead(d, meta)
   144  }
   145  
   146  func resourceHerokuAddonDelete(d *schema.ResourceData, meta interface{}) error {
   147  	client := meta.(*heroku.Service)
   148  
   149  	log.Printf("[INFO] Deleting Addon: %s", d.Id())
   150  
   151  	// Destroy the app
   152  	_, err := client.AddOnDelete(context.TODO(), d.Get("app").(string), d.Id())
   153  	if err != nil {
   154  		return fmt.Errorf("Error deleting addon: %s", err)
   155  	}
   156  
   157  	d.SetId("")
   158  	return nil
   159  }
   160  
   161  func resourceHerokuAddonRetrieve(app string, id string, client *heroku.Service) (*heroku.AddOnInfoResult, error) {
   162  	addon, err := client.AddOnInfo(context.TODO(), app, id)
   163  
   164  	if err != nil {
   165  		return nil, fmt.Errorf("Error retrieving addon: %s", err)
   166  	}
   167  
   168  	return addon, nil
   169  }