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 }