First few azure resources...
Only the azure_instance is fully working (for both Linux and Windows instances) now, but needs some tests. network and disk and pretty much empty, but the idea is clear so will not take too much time…
This commit is contained in:
parent
88f72aaf92
commit
84a870a255
|
@ -0,0 +1,12 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/builtin/providers/azure"
|
||||||
|
"github.com/hashicorp/terraform/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.Serve(&plugin.ServeOpts{
|
||||||
|
ProviderFunc: azure.Provider,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package main
|
|
@ -0,0 +1,29 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config is the configuration structure used to instantiate a
|
||||||
|
// new Azure management client.
|
||||||
|
type Config struct {
|
||||||
|
SettingsFile string
|
||||||
|
SubscriptionID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient returns a new Azure management client
|
||||||
|
func (c *Config) NewClient() (*management.Client, error) {
|
||||||
|
if _, err := os.Stat(c.SettingsFile); os.IsNotExist(err) {
|
||||||
|
return nil, fmt.Errorf("Publish Settings file %q does not exist!", c.SettingsFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
mc, err := management.ClientFromPublishSettingsFile(c.SettingsFile, c.SubscriptionID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Error creating management client: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mc, nil
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider returns a terraform.ResourceProvider.
|
||||||
|
func Provider() terraform.ResourceProvider {
|
||||||
|
return &schema.Provider{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"settings_file": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("AZURE_SETTINGS_FILE", nil),
|
||||||
|
},
|
||||||
|
|
||||||
|
"subscription_id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("AZURE_SUBSCRIPTION_ID", ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"azure_disk": resourceAzureDisk(),
|
||||||
|
"azure_instance": resourceAzureInstance(),
|
||||||
|
"azure_network": resourceAzureNetwork(),
|
||||||
|
},
|
||||||
|
|
||||||
|
ConfigureFunc: providerConfigure,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||||
|
config := Config{
|
||||||
|
SettingsFile: d.Get("settings_file").(string),
|
||||||
|
SubscriptionID: d.Get("subscription_id").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.NewClient()
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
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{
|
||||||
|
"azure": 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("AZURE_SETTINGS_FILE"); v == "" {
|
||||||
|
t.Fatal("AZURE_SETTINGS_FILE must be set for acceptance tests")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,497 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management"
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management/hostedservice"
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management/osimage"
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management/virtualmachine"
|
||||||
|
"github.com/MSOpenTech/azure-sdk-for-go/management/vmutils"
|
||||||
|
"github.com/hashicorp/terraform/helper/hashcode"
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
linux = "Linux"
|
||||||
|
windows = "Windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceAzureInstance() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAzureInstanceCreate,
|
||||||
|
Read: resourceAzureInstanceRead,
|
||||||
|
Update: resourceAzureInstanceUpdate,
|
||||||
|
Delete: resourceAzureInstanceDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"image": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"size": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"network": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"storage": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"reverse_dns": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"location": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"automatic_updates": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"time_zone": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"public_rdp": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"public_ssh": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"username": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"password": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ssh_key_thumbprint": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"endpoint": &schema.Schema{
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"protocol": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"port": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"local_port": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Set: resourceAzureEndpointHash,
|
||||||
|
},
|
||||||
|
|
||||||
|
"ip_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"vip_address": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err error) {
|
||||||
|
mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
name := d.Get("name").(string)
|
||||||
|
|
||||||
|
// Compute/set the description
|
||||||
|
description := d.Get("description").(string)
|
||||||
|
if description == "" {
|
||||||
|
description = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the needed details of the image
|
||||||
|
imageName, imageURL, osType, err := retrieveImageDetails(mc, d.Get("image").(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if imageURL == "" {
|
||||||
|
storage, ok := d.GetOk("storage")
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("When using a platform image, the 'storage' parameter is required")
|
||||||
|
}
|
||||||
|
imageURL = fmt.Sprintf("http://%s.blob.core.windows.net/vhds/%s.vhd", storage, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify if we have all parameters required for the image OS type
|
||||||
|
if err := verifyParameters(d, osType); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Creating Cloud Service for instance: %s", name)
|
||||||
|
req, err := hostedservice.NewClient(*mc).
|
||||||
|
CreateHostedService(
|
||||||
|
name,
|
||||||
|
d.Get("location").(string),
|
||||||
|
d.Get("reverse_dns").(string),
|
||||||
|
name,
|
||||||
|
fmt.Sprintf("Cloud Service created automatically for instance %s", name),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating Cloud Service for instance %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the Cloud Service is created
|
||||||
|
if err := mc.WaitAsyncOperation(req); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for Cloud Service of instance %s to be created: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put in this defer here, so we are sure to cleanup already created parts
|
||||||
|
// when we exit with an error
|
||||||
|
defer func(mc *management.Client) {
|
||||||
|
if err != nil {
|
||||||
|
req, err := hostedservice.NewClient(*mc).DeleteHostedService(name, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[DEBUG] Error cleaning up Cloud Service of instance %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the Cloud Service is deleted
|
||||||
|
if err := mc.WaitAsyncOperation(req); err != nil {
|
||||||
|
log.Printf(
|
||||||
|
"[DEBUG] Error waiting for Cloud Service of instance %s to be deleted : %s", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(mc)
|
||||||
|
|
||||||
|
// Create a new role for the instance
|
||||||
|
role := vmutils.NewVmConfiguration(name, d.Get("size").(string))
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Configuring deployment from image...")
|
||||||
|
err = vmutils.ConfigureDeploymentFromPlatformImage(
|
||||||
|
&role,
|
||||||
|
imageName,
|
||||||
|
imageURL,
|
||||||
|
d.Get("image").(string),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error configuring the deployment for %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if osType == linux {
|
||||||
|
// This is pretty ugly, but the Azure SDK leaves me no other choice...
|
||||||
|
if tp, ok := d.GetOk("ssh_key_thumbprint"); ok {
|
||||||
|
err = vmutils.ConfigureForLinux(
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
d.Get("username").(string),
|
||||||
|
d.Get("password").(string),
|
||||||
|
tp.(string),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
err = vmutils.ConfigureForLinux(
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
d.Get("username").(string),
|
||||||
|
d.Get("password").(string),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error configuring %s for Linux: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Get("public_ssh").(bool) {
|
||||||
|
if err := vmutils.ConfigureWithPublicSSH(&role); err != nil {
|
||||||
|
return fmt.Errorf("Error configuring %s for public SSH: %s", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if osType == windows {
|
||||||
|
err = vmutils.ConfigureForWindows(
|
||||||
|
&role,
|
||||||
|
name,
|
||||||
|
d.Get("username").(string),
|
||||||
|
d.Get("password").(string),
|
||||||
|
d.Get("automatic_updates").(bool),
|
||||||
|
d.Get("time_zone").(string),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error configuring %s for Windows: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.Get("public_rdp").(bool) {
|
||||||
|
if err := vmutils.ConfigureWithPublicRDP(&role); err != nil {
|
||||||
|
return fmt.Errorf("Error configuring %s for public RDP: %s", name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Creating the new instance...")
|
||||||
|
req, err = virtualmachine.NewClient(*mc).CreateDeployment(role, name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error creating instance %s: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Waiting for the new instance to be created...")
|
||||||
|
if err := mc.WaitAsyncOperation(req); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for instance %s to be created: %s", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if v := d.Get("endpoint").(*schema.Set); v.Len() > 0 {
|
||||||
|
log.Printf("[DEBUG] Adding Endpoints to the Azure Virtual Machine...")
|
||||||
|
endpoints := make([]vmClient.InputEndpoint, v.Len())
|
||||||
|
for i, v := range v.List() {
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
endpoint := vmClient.InputEndpoint{}
|
||||||
|
endpoint.Name = m["name"].(string)
|
||||||
|
endpoint.Protocol = m["protocol"].(string)
|
||||||
|
endpoint.Port = m["port"].(int)
|
||||||
|
endpoint.LocalPort = m["local_port"].(int)
|
||||||
|
endpoints[i] = endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
configSets := vmConfig.ConfigurationSets.ConfigurationSet
|
||||||
|
if len(configSets) == 0 {
|
||||||
|
return fmt.Errorf("Azure virtual machine does not have configuration sets")
|
||||||
|
}
|
||||||
|
for i := 0; i < len(configSets); i++ {
|
||||||
|
if configSets[i].ConfigurationSetType != "NetworkConfiguration" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
configSets[i].InputEndpoints.InputEndpoint =
|
||||||
|
append(configSets[i].InputEndpoints.InputEndpoint, endpoints...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
d.SetId(name)
|
||||||
|
|
||||||
|
return resourceAzureInstanceRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Retrieving Cloud Service for instance: %s", d.Id())
|
||||||
|
cs, err := hostedservice.NewClient(*mc).GetHostedService(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving Cloud Service of instance %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("reverse_dns", cs.ReverseDnsFqdn)
|
||||||
|
d.Set("location", cs.Location)
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Retrieving instance: %s", d.Id())
|
||||||
|
wi, err := virtualmachine.NewClient(*mc).GetDeployment(d.Id(), d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving instance %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(wi.RoleList) == 0 {
|
||||||
|
return fmt.Errorf("Instance %s does not have VIP addresses", d.Id())
|
||||||
|
}
|
||||||
|
role := wi.RoleList[0]
|
||||||
|
|
||||||
|
d.Set("size", role.RoleSize)
|
||||||
|
|
||||||
|
if len(wi.RoleInstanceList) == 0 {
|
||||||
|
return fmt.Errorf("Instance %s does not have IP addresses", d.Id())
|
||||||
|
}
|
||||||
|
d.Set("ip_address", wi.RoleInstanceList[0].IpAddress)
|
||||||
|
|
||||||
|
if len(wi.VirtualIPs) == 0 {
|
||||||
|
return fmt.Errorf("Instance %s does not have VIP addresses", d.Id())
|
||||||
|
}
|
||||||
|
d.Set("vip_address", wi.VirtualIPs[0].Address)
|
||||||
|
|
||||||
|
connType := "ssh"
|
||||||
|
if role.OSVirtualHardDisk.OS == windows {
|
||||||
|
connType = windows
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the connection info for any configured provisioners
|
||||||
|
d.SetConnInfo(map[string]string{
|
||||||
|
"type": connType,
|
||||||
|
"host": wi.VirtualIPs[0].Address,
|
||||||
|
"user": d.Get("username").(string),
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
if d.HasChange("size") {
|
||||||
|
role, err := virtualmachine.NewClient(*mc).GetRole(d.Id(), d.Id(), d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving role of instance %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
role.RoleSize = d.Get("size").(string)
|
||||||
|
|
||||||
|
req, err := virtualmachine.NewClient(*mc).UpdateRole(d.Id(), d.Id(), d.Id(), *role)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating role of instance %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mc.WaitAsyncOperation(req); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for role of instance %s to be updated: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("endpoint") {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceAzureInstanceRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureInstanceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Deleting instance: %s", d.Id())
|
||||||
|
req, err := hostedservice.NewClient(*mc).DeleteHostedService(d.Id(), true)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting instance %s: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until the instance is deleted
|
||||||
|
if err := mc.WaitAsyncOperation(req); err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Error waiting for instance %s to be deleted: %s", d.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureEndpointHash(v interface{}) int {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%s-", m["protocol"].(string)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%d-", m["port"].(int)))
|
||||||
|
buf.WriteString(fmt.Sprintf("%d-", m["local_port"].(int)))
|
||||||
|
|
||||||
|
return hashcode.String(buf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func retrieveImageDetails(mc *management.Client, label string) (string, string, string, error) {
|
||||||
|
imgs, err := osimage.NewClient(*mc).GetImageList()
|
||||||
|
if err != nil {
|
||||||
|
return "", "", "", fmt.Errorf("Error retrieving image details: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var labels []string
|
||||||
|
for _, img := range imgs {
|
||||||
|
if img.Label == label {
|
||||||
|
if img.OS != linux && img.OS != windows {
|
||||||
|
return "", "", "", fmt.Errorf("Unsupported image OS: %s", img.OS)
|
||||||
|
}
|
||||||
|
return img.Name, img.MediaLink, img.OS, nil
|
||||||
|
}
|
||||||
|
labels = append(labels, img.Label)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", "", "",
|
||||||
|
fmt.Errorf("Could not find image with label '%s', available labels are: %s",
|
||||||
|
label, strings.Join(labels, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyParameters(d *schema.ResourceData, osType string) error {
|
||||||
|
if osType == linux {
|
||||||
|
_, pass := d.GetOk("password")
|
||||||
|
_, key := d.GetOk("ssh_key_thumbprint")
|
||||||
|
|
||||||
|
if !pass && !key {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"You must supply a 'password' and/or a 'ssh_key_thumbprint' when using a Linux image")
|
||||||
|
}
|
||||||
|
|
||||||
|
if key {
|
||||||
|
// check if it's a file of a string containing the key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if osType == windows {
|
||||||
|
if _, ok := d.GetOk("password"); !ok {
|
||||||
|
return fmt.Errorf("You must supply a 'password' when using a Windows image")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := d.GetOk("time_zone"); !ok {
|
||||||
|
return fmt.Errorf("You must supply a 'time_zone' when using a Windows image")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package azure
|
|
@ -0,0 +1,51 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import "github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
func resourceAzureNetwork() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAzureNetworkCreate,
|
||||||
|
Read: resourceAzureNetworkRead,
|
||||||
|
Update: resourceAzureNetworkUpdate,
|
||||||
|
Delete: resourceAzureNetworkDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"virtual": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureNetworkCreate(d *schema.ResourceData, meta interface{}) (err error) {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return resourceAzureNetworkRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureNetworkRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return resourceAzureNetworkRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureNetworkDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package azure
|
|
@ -0,0 +1,44 @@
|
||||||
|
package azure
|
||||||
|
|
||||||
|
import "github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
func resourceAzureDisk() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceAzureNetworkCreate,
|
||||||
|
Read: resourceAzureNetworkRead,
|
||||||
|
Update: resourceAzureNetworkUpdate,
|
||||||
|
Delete: resourceAzureNetworkDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureDiskCreate(d *schema.ResourceData, meta interface{}) (err error) {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return resourceAzureDiskRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureDiskRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureDiskUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return resourceAzureDiskRead(d, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceAzureDiskDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
//mc := meta.(*management.Client)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package azure
|
|
@ -0,0 +1 @@
|
||||||
|
package azure
|
Loading…
Reference in New Issue