-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Terraform ProfitBricks Builder (#7943)
* Terraform ProfitBricks Builder * make fmt * Merge remote-tracking branch 'upstream/master' into terraform-provider-profitbricks # Conflicts: # command/internal_plugin_list.go * Addressing PR remarks * Removed importers
- Loading branch information
Showing
51 changed files
with
5,854 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package provider_profitbricks | ||
|
||
import ( | ||
"github.com/hashicorp/terraform/builtin/providers/profitbricks" | ||
"github.com/hashicorp/terraform/plugin" | ||
) | ||
|
||
func main() { | ||
plugin.Serve(&plugin.ServeOpts{ | ||
ProviderFunc: profitbricks.Provider, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package profitbricks | ||
|
||
import ( | ||
"github.com/profitbricks/profitbricks-sdk-go" | ||
) | ||
|
||
type Config struct { | ||
Username string | ||
Password string | ||
Retries int | ||
} | ||
|
||
// Client() returns a new client for accessing digital ocean. | ||
func (c *Config) Client() (*Config, error) { | ||
profitbricks.SetAuth(c.Username, c.Password) | ||
profitbricks.SetDepth("5") | ||
|
||
return c, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package profitbricks | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
// Provider returns a schema.Provider for DigitalOcean. | ||
func Provider() terraform.ResourceProvider { | ||
return &schema.Provider{ | ||
Schema: map[string]*schema.Schema{ | ||
"username": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
DefaultFunc: schema.EnvDefaultFunc("PROFITBRICKS_USERNAME", nil), | ||
Description: "Profitbricks username for API operations.", | ||
}, | ||
"password": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
DefaultFunc: schema.EnvDefaultFunc("PROFITBRICKS_PASSWORD", nil), | ||
Description: "Profitbricks password for API operations.", | ||
}, | ||
"retries": { | ||
Type: schema.TypeInt, | ||
Optional: true, | ||
Default: 50, | ||
}, | ||
}, | ||
|
||
ResourcesMap: map[string]*schema.Resource{ | ||
"profitbricks_datacenter": resourceProfitBricksDatacenter(), | ||
"profitbricks_ipblock": resourceProfitBricksIPBlock(), | ||
"profitbricks_firewall": resourceProfitBricksFirewall(), | ||
"profitbricks_lan": resourceProfitBricksLan(), | ||
"profitbricks_loadbalancer": resourceProfitBricksLoadbalancer(), | ||
"profitbricks_nic": resourceProfitBricksNic(), | ||
"profitbricks_server": resourceProfitBricksServer(), | ||
"profitbricks_volume": resourceProfitBricksVolume(), | ||
}, | ||
|
||
ConfigureFunc: providerConfigure, | ||
} | ||
} | ||
|
||
func providerConfigure(d *schema.ResourceData) (interface{}, error) { | ||
|
||
if _, ok := d.GetOk("username"); !ok { | ||
return nil, fmt.Errorf("ProfitBricks username has not been provided.") | ||
} | ||
|
||
if _, ok := d.GetOk("password"); !ok { | ||
return nil, fmt.Errorf("ProfitBricks password has not been provided.") | ||
} | ||
|
||
config := Config{ | ||
Username: d.Get("username").(string), | ||
Password: d.Get("password").(string), | ||
Retries: d.Get("retries").(int), | ||
} | ||
|
||
return config.Client() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package profitbricks | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
var testAccProviders map[string]terraform.ResourceProvider | ||
var testAccProvider *schema.Provider | ||
|
||
func init() { | ||
testAccProvider = Provider().(*schema.Provider) | ||
testAccProviders = map[string]terraform.ResourceProvider{ | ||
"profitbricks": testAccProvider, | ||
} | ||
} | ||
|
||
func TestProvider(t *testing.T) { | ||
if err := Provider().(*schema.Provider).InternalValidate(); err != nil { | ||
t.Fatalf("err: %s", err) | ||
} | ||
} | ||
|
||
func TestProvider_impl(t *testing.T) { | ||
var _ terraform.ResourceProvider = Provider() | ||
} | ||
|
||
func testAccPreCheck(t *testing.T) { | ||
if v := os.Getenv("PROFITBRICKS_USERNAME"); v == "" { | ||
t.Fatal("PROFITBRICKS_USERNAME must be set for acceptance tests") | ||
} | ||
|
||
if v := os.Getenv("PROFITBRICKS_PASSWORD"); v == "" { | ||
t.Fatal("PROFITBRICKS_PASSWORD must be set for acceptance tests") | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
builtin/providers/profitbricks/resource_profitbricks_datacenter.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package profitbricks | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/profitbricks/profitbricks-sdk-go" | ||
"log" | ||
"runtime" | ||
"strings" | ||
"time" | ||
) | ||
|
||
func resourceProfitBricksDatacenter() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceProfitBricksDatacenterCreate, | ||
Read: resourceProfitBricksDatacenterRead, | ||
Update: resourceProfitBricksDatacenterUpdate, | ||
Delete: resourceProfitBricksDatacenterDelete, | ||
Schema: map[string]*schema.Schema{ | ||
|
||
//Datacenter parameters | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
|
||
"location": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceProfitBricksDatacenterCreate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
profitbricks.SetAuth(config.Username, config.Password) | ||
|
||
datacenter := profitbricks.Datacenter{ | ||
Properties: profitbricks.DatacenterProperties{ | ||
Name: d.Get("name").(string), | ||
Location: d.Get("location").(string), | ||
}, | ||
} | ||
|
||
if attr, ok := d.GetOk("description"); ok { | ||
datacenter.Properties.Description = attr.(string) | ||
} | ||
dc := profitbricks.CreateDatacenter(datacenter) | ||
|
||
if dc.StatusCode > 299 { | ||
return fmt.Errorf( | ||
"Error creating data center (%s) (%s)", d.Id(), dc.Response) | ||
} | ||
d.SetId(dc.Id) | ||
|
||
log.Printf("[INFO] DataCenter Id: %s", d.Id()) | ||
|
||
err := waitTillProvisioned(meta, dc.Headers.Get("Location")) | ||
if err != nil { | ||
return err | ||
} | ||
return resourceProfitBricksDatacenterRead(d, meta) | ||
} | ||
|
||
func resourceProfitBricksDatacenterRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
profitbricks.SetAuth(config.Username, config.Password) | ||
datacenter := profitbricks.GetDatacenter(d.Id()) | ||
if datacenter.StatusCode > 299 { | ||
return fmt.Errorf("Error while fetching a data center ID %s %s", d.Id(), datacenter.Response) | ||
} | ||
|
||
d.Set("name", datacenter.Properties.Name) | ||
d.Set("location", datacenter.Properties.Location) | ||
d.Set("description", datacenter.Properties.Description) | ||
return nil | ||
} | ||
|
||
func resourceProfitBricksDatacenterUpdate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
profitbricks.SetAuth(config.Username, config.Password) | ||
|
||
obj := profitbricks.DatacenterProperties{} | ||
|
||
if d.HasChange("name") { | ||
_, newName := d.GetChange("name") | ||
|
||
obj.Name = newName.(string) | ||
} | ||
|
||
if d.HasChange("description") { | ||
_, newDescription := d.GetChange("description") | ||
obj.Description = newDescription.(string) | ||
} | ||
|
||
resp := profitbricks.PatchDatacenter(d.Id(), obj) | ||
waitTillProvisioned(meta, resp.Headers.Get("Location")) | ||
return resourceProfitBricksDatacenterRead(d, meta) | ||
} | ||
|
||
func resourceProfitBricksDatacenterDelete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
profitbricks.SetAuth(config.Username, config.Password) | ||
dcid := d.Id() | ||
resp := profitbricks.DeleteDatacenter(dcid) | ||
|
||
if resp.StatusCode > 299 { | ||
return fmt.Errorf("An error occured while deleting the data center ID %s %s", d.Id(), string(resp.Body)) | ||
} | ||
err := waitTillProvisioned(meta, resp.Headers.Get("Location")) | ||
if err != nil { | ||
return err | ||
} | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func waitTillProvisioned(meta interface{}, path string) error { | ||
config := meta.(*Config) | ||
profitbricks.SetAuth(config.Username, config.Password) | ||
|
||
for i := 0; i < config.Retries; i++ { | ||
request := profitbricks.GetRequestStatus(path) | ||
pc, _, _, ok := runtime.Caller(1) | ||
details := runtime.FuncForPC(pc) | ||
if ok && details != nil { | ||
log.Printf("[DEBUG] Called from %s", details.Name()) | ||
} | ||
log.Printf("[DEBUG] Request status: %s", request.Metadata.Status) | ||
log.Printf("[DEBUG] Request status path: %s", path) | ||
|
||
if request.Metadata.Status == "DONE" { | ||
return nil | ||
} | ||
if request.Metadata.Status == "FAILED" { | ||
|
||
return fmt.Errorf("Request failed with following error: %s", request.Metadata.Message) | ||
} | ||
time.Sleep(10 * time.Second) | ||
i++ | ||
} | ||
return fmt.Errorf("Timeout has expired") | ||
} | ||
|
||
func getImageId(dcId string, imageName string, imageType string) string { | ||
if imageName == "" { | ||
return "" | ||
} | ||
dc := profitbricks.GetDatacenter(dcId) | ||
if dc.StatusCode > 299 { | ||
log.Print(fmt.Errorf("Error while fetching a data center ID %s %s", dcId, dc.Response)) | ||
} | ||
|
||
images := profitbricks.ListImages() | ||
if images.StatusCode > 299 { | ||
log.Print(fmt.Errorf("Error while fetching the list of images %s", images.Response)) | ||
} | ||
|
||
if len(images.Items) > 0 { | ||
for _, i := range images.Items { | ||
imgName := "" | ||
if i.Properties.Name != "" { | ||
imgName = i.Properties.Name | ||
} | ||
|
||
if imageType == "SSD" { | ||
imageType = "HDD" | ||
} | ||
if imgName != "" && strings.Contains(strings.ToLower(imgName), strings.ToLower(imageName)) && i.Properties.ImageType == imageType && i.Properties.Location == dc.Properties.Location && i.Properties.Public == true { | ||
return i.Id | ||
} | ||
} | ||
} | ||
return "" | ||
} |
Oops, something went wrong.