providers/heroku: addon

This commit is contained in:
Mitchell Hashimoto 2014-08-18 15:49:54 -07:00
parent e70522f4ca
commit 5fc308d934
3 changed files with 264 additions and 1 deletions

View File

@ -24,6 +24,7 @@ func Provider() *schema.Provider {
ResourcesMap: map[string]*schema.Resource{
"heroku_app": resourceHerokuApp(),
"heroku_addon": resourceHerokuAddon(),
},
ConfigureFunc: providerConfigure,

View File

@ -0,0 +1,155 @@
package heroku
import (
"fmt"
"log"
"sync"
"github.com/bgentry/heroku-go"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
// Global lock to prevent parallelism for heroku_addon since
// the Heroku API cannot handle a single application requesting
// multiple addons simultaneously.
var addonLock sync.Mutex
func resourceHerokuAddon() *schema.Resource {
return &schema.Resource{
Create: resourceHerokuAddonCreate,
Read: resourceHerokuAddonRead,
Update: resourceHerokuAddonUpdate,
Delete: resourceHerokuAddonDelete,
Schema: map[string]*schema.Schema{
"app": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"plan": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"config": &schema.Schema{
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeMap,
},
},
"provider_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"config_vars": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeMap},
},
},
}
}
func resourceHerokuAddonCreate(d *schema.ResourceData, meta interface{}) error {
addonLock.Lock()
defer addonLock.Unlock()
client := meta.(*heroku.Client)
app := d.Get("app").(string)
plan := d.Get("plan").(string)
opts := heroku.AddonCreateOpts{}
if v := d.Get("config"); v != nil {
config := make(map[string]string)
for _, v := range v.([]interface{}) {
for k, v := range v.(map[string]interface{}) {
config[k] = v.(string)
}
}
opts.Config = &config
}
log.Printf("[DEBUG] Addon create configuration: %#v, %#v, %#v", app, plan, opts)
a, err := client.AddonCreate(app, plan, &opts)
if err != nil {
return err
}
d.SetId(a.Id)
log.Printf("[INFO] Addon ID: %s", d.Id())
return resourceHerokuAddonRead(d, meta)
}
func resourceHerokuAddonRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*heroku.Client)
addon, err := resource_heroku_addon_retrieve(
d.Get("app").(string), d.Id(), client)
if err != nil {
return err
}
d.Set("name", addon.Name)
d.Set("plan", addon.Plan.Name)
d.Set("provider_id", addon.ProviderId)
d.Set("config_vars", []interface{}{addon.ConfigVars})
d.SetDependencies([]terraform.ResourceDependency{
terraform.ResourceDependency{ID: d.Get("app").(string)},
})
return nil
}
func resourceHerokuAddonUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*heroku.Client)
app := d.Get("app").(string)
if d.HasChange("plan") {
ad, err := client.AddonUpdate(
app, d.Id(), d.Get("plan").(string))
if err != nil {
return err
}
// Store the new ID
d.SetId(ad.Id)
}
return resourceHerokuAddonRead(d, meta)
}
func resourceHerokuAddonDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*heroku.Client)
log.Printf("[INFO] Deleting Addon: %s", d.Id())
// Destroy the app
err := client.AddonDelete(d.Get("app").(string), d.Id())
if err != nil {
return fmt.Errorf("Error deleting addon: %s", err)
}
d.SetId("")
return nil
}
func resource_heroku_addon_retrieve(app string, id string, client *heroku.Client) (*heroku.Addon, error) {
addon, err := client.AddonInfo(app, id)
if err != nil {
return nil, fmt.Errorf("Error retrieving addon: %s", err)
}
return addon, nil
}

View File

@ -0,0 +1,107 @@
package heroku
import (
"fmt"
"testing"
"github.com/bgentry/heroku-go"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccHerokuAddon_Basic(t *testing.T) {
var addon heroku.Addon
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckHerokuAddonDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckHerokuAddonConfig_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckHerokuAddonExists("heroku_addon.foobar", &addon),
testAccCheckHerokuAddonAttributes(&addon),
resource.TestCheckResourceAttr(
"heroku_addon.foobar", "config.0.url", "http://google.com"),
resource.TestCheckResourceAttr(
"heroku_addon.foobar", "app", "terraform-test-app"),
resource.TestCheckResourceAttr(
"heroku_addon.foobar", "plan", "deployhooks:http"),
),
},
},
})
}
func testAccCheckHerokuAddonDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*heroku.Client)
for _, rs := range s.Resources {
if rs.Type != "heroku_addon" {
continue
}
_, err := client.AddonInfo(rs.Attributes["app"], rs.ID)
if err == nil {
return fmt.Errorf("Addon still exists")
}
}
return nil
}
func testAccCheckHerokuAddonAttributes(addon *heroku.Addon) resource.TestCheckFunc {
return func(s *terraform.State) error {
if addon.Plan.Name != "deployhooks:http" {
return fmt.Errorf("Bad plan: %s", addon.Plan)
}
return nil
}
}
func testAccCheckHerokuAddonExists(n string, addon *heroku.Addon) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.ID == "" {
return fmt.Errorf("No Addon ID is set")
}
client := testAccProvider.Meta().(*heroku.Client)
foundAddon, err := client.AddonInfo(rs.Attributes["app"], rs.ID)
if err != nil {
return err
}
if foundAddon.Id != rs.ID {
return fmt.Errorf("Addon not found")
}
*addon = *foundAddon
return nil
}
}
const testAccCheckHerokuAddonConfig_basic = `
resource "heroku_app" "foobar" {
name = "terraform-test-app"
}
resource "heroku_addon" "foobar" {
app = "${heroku_app.foobar.name}"
plan = "deployhooks:http"
config {
url = "http://google.com"
}
}`