diff --git a/builtin/providers/azure/config.go b/builtin/providers/azure/config.go index b62ab435e..c21f6f705 100644 --- a/builtin/providers/azure/config.go +++ b/builtin/providers/azure/config.go @@ -3,6 +3,7 @@ package azure import ( "fmt" "os" + "sync" "github.com/svanharmelen/azure-sdk-for-go/management" ) @@ -16,30 +17,42 @@ type Config struct { ManagementURL string } -// NewClient returns a new Azure management client which is created -// using different functions depending on the supplied settings -func (c *Config) NewClient() (management.Client, error) { - if c.SettingsFile != "" { - if _, err := os.Stat(c.SettingsFile); os.IsNotExist(err) { - return nil, fmt.Errorf("Publish Settings file %q does not exist!", c.SettingsFile) - } - - return management.ClientFromPublishSettingsFile(c.SettingsFile, c.SubscriptionID) - } - - if c.ManagementURL != "" { - return management.NewClientFromConfig( - c.SubscriptionID, - c.Certificate, - management.ClientConfig{ManagementURL: c.ManagementURL}, - ) - } - - if c.SubscriptionID != "" && len(c.Certificate) > 0 { - return management.NewClient(c.SubscriptionID, c.Certificate) - } - - return nil, fmt.Errorf( - "Insufficient configuration data. Please specify either a 'settings_file'\n" + - "or both a 'subscription_id' and 'certificate' with an optional 'management_url'.") +// Client contains all the handles required for managing Azure services. +type Client struct { + // unfortunately; because of how Azure's network API works; doing networking operations + // concurrently is very hazardous, and we need a mutex to guard the management.Client. + mutex *sync.Mutex + mgmtClient management.Client +} + +// NewClientFromSettingsFile returns a new Azure management +// client created using a publish settings file. +func (c *Config) NewClientFromSettingsFile() (*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, nil + } + + return &Client{ + mutex: &sync.Mutex{}, + mgmtClient: mc, + }, nil +} + +// NewClient returns a new Azure management client created +// using a subscription ID and certificate. +func (c *Config) NewClient() (*Client, error) { + mc, err := management.NewClient(c.SubscriptionID, c.Certificate) + if err != nil { + return nil, nil + } + + return &Client{ + mutex: &sync.Mutex{}, + mgmtClient: mc, + }, nil } diff --git a/builtin/providers/azure/provider.go b/builtin/providers/azure/provider.go index 1bf8233fa..bba65fcfd 100644 --- a/builtin/providers/azure/provider.go +++ b/builtin/providers/azure/provider.go @@ -1,6 +1,8 @@ package azure import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" ) @@ -26,12 +28,6 @@ func Provider() terraform.ResourceProvider { Optional: true, DefaultFunc: schema.EnvDefaultFunc("AZURE_CERTIFICATE", ""), }, - - "management_url": &schema.Schema{ - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("AZURE_MANAGEMENT_URL", ""), - }, }, ResourcesMap: map[string]*schema.Resource{ @@ -50,8 +46,17 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { SettingsFile: d.Get("settings_file").(string), SubscriptionID: d.Get("subscription_id").(string), Certificate: []byte(d.Get("certificate").(string)), - ManagementURL: d.Get("management_url").(string), } - return config.NewClient() + if config.SettingsFile != "" { + return config.NewClientFromSettingsFile() + } + + if config.SubscriptionID != "" && len(config.Certificate) > 0 { + return config.NewClient() + } + + return nil, fmt.Errorf( + "Insufficient configuration data. Please specify either a 'settings_file'\n" + + "or both a 'subscription_id' and 'certificate'.") } diff --git a/builtin/providers/azure/resource_azure_data_disk.go b/builtin/providers/azure/resource_azure_data_disk.go index a306e96f0..f73821783 100644 --- a/builtin/providers/azure/resource_azure_data_disk.go +++ b/builtin/providers/azure/resource_azure_data_disk.go @@ -41,7 +41,7 @@ func resourceAzureDataDisk() *schema.Resource { "size": &schema.Schema{ Type: schema.TypeInt, - Required: true, + Optional: true, }, "caching": &schema.Schema{ @@ -78,7 +78,7 @@ func resourceAzureDataDisk() *schema.Resource { } func resourceAzureDataDiskCreate(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient if err := verifyDataDiskParameters(d); err != nil { return err @@ -129,7 +129,7 @@ func resourceAzureDataDiskCreate(d *schema.ResourceData, meta interface{}) error } func resourceAzureDataDiskRead(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient lun := d.Get("lun").(int) vm := d.Get("virtual_machine").(string) @@ -163,7 +163,9 @@ func resourceAzureDataDiskRead(d *schema.ResourceData, meta interface{}) error { } func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient + diskClient := virtualmachinedisk.NewClient(mc) + lun := d.Get("lun").(int) vm := d.Get("virtual_machine").(string) @@ -172,7 +174,7 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error ovm, _ := d.GetChange("virtual_machine") log.Printf("[DEBUG] Detaching data disk: %s", d.Id()) - req, err := virtualmachinedisk.NewClient(mc). + req, err := diskClient. DeleteDataDisk(ovm.(string), ovm.(string), ovm.(string), olun.(int), false) if err != nil { return fmt.Errorf("Error detaching data disk %s: %s", d.Id(), err) @@ -186,7 +188,7 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error log.Printf("[DEBUG] Verifying data disk %s is properly detached...", d.Id()) for i := 0; i < 6; i++ { - disk, err := virtualmachinedisk.NewClient(mc).GetDisk(d.Id()) + disk, err := diskClient.GetDisk(d.Id()) if err != nil { return fmt.Errorf("Error retrieving disk %s: %s", d.Id(), err) } @@ -208,7 +210,7 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error } log.Printf("[DEBUG] Updating disk: %s", d.Id()) - req, err := virtualmachinedisk.NewClient(mc).UpdateDisk(d.Id(), p) + req, err := diskClient.UpdateDisk(d.Id(), p) if err != nil { return fmt.Errorf("Error updating disk %s: %s", d.Id(), err) } @@ -228,7 +230,7 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error } log.Printf("[DEBUG] Attaching data disk: %s", d.Id()) - req, err = virtualmachinedisk.NewClient(mc).AddDataDisk(vm, vm, vm, p) + req, err = diskClient.AddDataDisk(vm, vm, vm, p) if err != nil { return fmt.Errorf("Error attaching data disk %s to instance %s: %s", d.Id(), vm, err) } @@ -253,7 +255,7 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error } log.Printf("[DEBUG] Updating data disk: %s", d.Id()) - req, err := virtualmachinedisk.NewClient(mc).UpdateDataDisk(vm, vm, vm, lun, p) + req, err := diskClient.UpdateDataDisk(vm, vm, vm, lun, p) if err != nil { return fmt.Errorf("Error updating data disk %s: %s", d.Id(), err) } @@ -269,7 +271,8 @@ func resourceAzureDataDiskUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAzureDataDiskDelete(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient + lun := d.Get("lun").(int) vm := d.Get("virtual_machine").(string) diff --git a/builtin/providers/azure/resource_azure_data_disk_test.go b/builtin/providers/azure/resource_azure_data_disk_test.go index 1e1fb3132..2aa5e474c 100644 --- a/builtin/providers/azure/resource_azure_data_disk_test.go +++ b/builtin/providers/azure/resource_azure_data_disk_test.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/svanharmelen/azure-sdk-for-go/management" "github.com/svanharmelen/azure-sdk-for-go/management/virtualmachinedisk" ) @@ -102,7 +101,7 @@ func testAccCheckAzureDataDiskExists( return err } - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient d, err := virtualmachinedisk.NewClient(mc).GetDataDisk(vm, vm, vm, lun) if err != nil { return err @@ -139,7 +138,7 @@ func testAccCheckAzureDataDiskAttributes( } func testAccCheckAzureDataDiskDestroy(s *terraform.State) error { - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient for _, rs := range s.RootModule().Resources { if rs.Type != "azure_data_disk" { diff --git a/builtin/providers/azure/resource_azure_instance.go b/builtin/providers/azure/resource_azure_instance.go index ed34d9fc2..7ad150c3d 100644 --- a/builtin/providers/azure/resource_azure_instance.go +++ b/builtin/providers/azure/resource_azure_instance.go @@ -89,6 +89,7 @@ func resourceAzureInstance() *schema.Resource { "automatic_updates": &schema.Schema{ Type: schema.TypeBool, Optional: true, + Default: false, ForceNew: true, }, @@ -129,7 +130,8 @@ func resourceAzureInstance() *schema.Resource { "protocol": &schema.Schema{ Type: schema.TypeString, - Required: true, + Optional: true, + Default: "tcp", }, "public_port": &schema.Schema{ @@ -166,7 +168,7 @@ func resourceAzureInstance() *schema.Resource { } func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err error) { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient name := d.Get("name").(string) @@ -324,7 +326,7 @@ func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err } func resourceAzureInstanceRead(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient log.Printf("[DEBUG] Retrieving Cloud Service for instance: %s", d.Id()) cs, err := hostedservice.NewClient(mc).GetHostedService(d.Id()) @@ -414,7 +416,7 @@ func resourceAzureInstanceRead(d *schema.ResourceData, meta interface{}) error { } func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient // First check if anything we can update changed, and if not just return if !d.HasChange("size") && !d.HasChange("endpoint") && !d.HasChange("security_group") { @@ -490,7 +492,7 @@ func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error } func resourceAzureInstanceDelete(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient log.Printf("[DEBUG] Deleting instance: %s", d.Id()) req, err := hostedservice.NewClient(mc).DeleteHostedService(d.Id(), true) diff --git a/builtin/providers/azure/resource_azure_instance_test.go b/builtin/providers/azure/resource_azure_instance_test.go index 0a272baa2..d6c92fe72 100644 --- a/builtin/providers/azure/resource_azure_instance_test.go +++ b/builtin/providers/azure/resource_azure_instance_test.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/svanharmelen/azure-sdk-for-go/management" "github.com/svanharmelen/azure-sdk-for-go/management/hostedservice" "github.com/svanharmelen/azure-sdk-for-go/management/virtualmachine" ) @@ -132,7 +131,7 @@ func testAccCheckAzureInstanceExists( return fmt.Errorf("No instance ID is set") } - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient vm, err := virtualmachine.NewClient(mc).GetDeployment(rs.Primary.ID, rs.Primary.ID) if err != nil { return err @@ -284,7 +283,7 @@ func testAccCheckAzureInstanceUpdatedAttributes( } func testAccCheckAzureInstanceDestroy(s *terraform.State) error { - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient for _, rs := range s.RootModule().Resources { if rs.Type != "azure_instance" { diff --git a/builtin/providers/azure/resource_azure_security_group.go b/builtin/providers/azure/resource_azure_security_group.go index 98d79bad0..0d7e8a0a1 100644 --- a/builtin/providers/azure/resource_azure_security_group.go +++ b/builtin/providers/azure/resource_azure_security_group.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" - "github.com/svanharmelen/azure-sdk-for-go/management" "github.com/svanharmelen/azure-sdk-for-go/management/networksecuritygroup" ) @@ -100,7 +99,7 @@ func resourceAzureSecurityGroup() *schema.Resource { } func resourceAzureSecurityGroupCreate(d *schema.ResourceData, meta interface{}) (err error) { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient name := d.Get("name").(string) @@ -152,8 +151,10 @@ func resourceAzureSecurityGroupCreate(d *schema.ResourceData, meta interface{}) } func resourceAzureSecurityGroupRuleCreate( - d *schema.ResourceData, meta interface{}, rule map[string]interface{}) error { - mc := meta.(management.Client) + d *schema.ResourceData, + meta interface{}, + rule map[string]interface{}) error { + mc := meta.(*Client).mgmtClient // Make sure all required parameters are there if err := verifySecurityGroupRuleParams(rule); err != nil { @@ -189,7 +190,7 @@ func resourceAzureSecurityGroupRuleCreate( } func resourceAzureSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient sg, err := networksecuritygroup.NewClient(mc).GetNetworkSecurityGroup(d.Id()) if err != nil { @@ -264,7 +265,7 @@ func resourceAzureSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) } func resourceAzureSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient log.Printf("[DEBUG] Deleting Network Security Group: %s", d.Id()) req, err := networksecuritygroup.NewClient(mc).DeleteNetworkSecurityGroup(d.Id()) @@ -285,7 +286,7 @@ func resourceAzureSecurityGroupDelete(d *schema.ResourceData, meta interface{}) func resourceAzureSecurityGroupRuleDelete( d *schema.ResourceData, meta interface{}, rule map[string]interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient name := rule["name"].(string) diff --git a/builtin/providers/azure/resource_azure_security_group_test.go b/builtin/providers/azure/resource_azure_security_group_test.go index 1e48faad8..b4e79ebb9 100644 --- a/builtin/providers/azure/resource_azure_security_group_test.go +++ b/builtin/providers/azure/resource_azure_security_group_test.go @@ -6,7 +6,6 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/svanharmelen/azure-sdk-for-go/management" "github.com/svanharmelen/azure-sdk-for-go/management/networksecuritygroup" ) @@ -104,7 +103,7 @@ func testAccCheckAzureSecurityGroupExists( return fmt.Errorf("No Network Security Group ID is set") } - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient sg, err := networksecuritygroup.NewClient(mc).GetNetworkSecurityGroup(rs.Primary.ID) if err != nil { return err @@ -204,7 +203,7 @@ func testAccCheckAzureSecurityGroupUpdatedAttributes( } func testAccCheckAzureSecurityGroupDestroy(s *terraform.State) error { - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient for _, rs := range s.RootModule().Resources { if rs.Type != "azure_security_group" { diff --git a/builtin/providers/azure/resource_azure_virtual_network.go b/builtin/providers/azure/resource_azure_virtual_network.go index 7125f24a0..be66c1a42 100644 --- a/builtin/providers/azure/resource_azure_virtual_network.go +++ b/builtin/providers/azure/resource_azure_virtual_network.go @@ -69,10 +69,16 @@ func resourceAzureVirtualNetwork() *schema.Resource { } func resourceAzureVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + ac := meta.(*Client) + mc := ac.mgmtClient name := d.Get("name").(string) + // Lock the client just before we get the virtual network configuration and immediately + // set an defer to unlock the client again whenever this function exits + ac.mutex.Lock() + defer ac.mutex.Unlock() + nc, err := virtualnetwork.NewClient(mc).GetVirtualNetworkConfiguration() if err != nil { if strings.Contains(err.Error(), "ResourceNotFound") { @@ -115,7 +121,7 @@ func resourceAzureVirtualNetworkCreate(d *schema.ResourceData, meta interface{}) } func resourceAzureVirtualNetworkRead(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient nc, err := virtualnetwork.NewClient(mc).GetVirtualNetworkConfiguration() if err != nil { @@ -165,7 +171,13 @@ func resourceAzureVirtualNetworkRead(d *schema.ResourceData, meta interface{}) e } func resourceAzureVirtualNetworkUpdate(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + ac := meta.(*Client) + mc := ac.mgmtClient + + // Lock the client just before we get the virtual network configuration and immediately + // set an defer to unlock the client again whenever this function exits + ac.mutex.Lock() + defer ac.mutex.Unlock() nc, err := virtualnetwork.NewClient(mc).GetVirtualNetworkConfiguration() if err != nil { @@ -208,7 +220,13 @@ func resourceAzureVirtualNetworkUpdate(d *schema.ResourceData, meta interface{}) } func resourceAzureVirtualNetworkDelete(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + ac := meta.(*Client) + mc := ac.mgmtClient + + // Lock the client just before we get the virtual network configuration and immediately + // set an defer to unlock the client again whenever this function exits + ac.mutex.Lock() + defer ac.mutex.Unlock() nc, err := virtualnetwork.NewClient(mc).GetVirtualNetworkConfiguration() if err != nil { @@ -277,7 +295,8 @@ func createVirtualNetwork(d *schema.ResourceData) (virtualnetwork.VirtualNetwork } func associateSecurityGroups(d *schema.ResourceData, meta interface{}) error { - mc := meta.(management.Client) + mc := meta.(*Client).mgmtClient + nsgClient := networksecuritygroup.NewClient(mc) virtualNetwork := d.Get("name").(string) @@ -288,8 +307,7 @@ func associateSecurityGroups(d *schema.ResourceData, meta interface{}) error { subnetName := subnet["name"].(string) // Get the associated (if any) security group - sg, err := networksecuritygroup.NewClient(mc). - GetNetworkSecurityGroupForSubnet(subnetName, d.Id()) + sg, err := nsgClient.GetNetworkSecurityGroupForSubnet(subnetName, d.Id()) if err != nil && !management.IsResourceNotFoundError(err) { return fmt.Errorf( "Error retrieving Network Security Group associations of subnet %s: %s", subnetName, err) @@ -302,8 +320,7 @@ func associateSecurityGroups(d *schema.ResourceData, meta interface{}) error { // If there is an associated security group, make sure we first remove it from the subnet if sg.Name != "" { - req, err := networksecuritygroup.NewClient(mc). - RemoveNetworkSecurityGroupFromSubnet(sg.Name, subnetName, virtualNetwork) + req, err := nsgClient.RemoveNetworkSecurityGroupFromSubnet(sg.Name, subnetName, virtualNetwork) if err != nil { return fmt.Errorf("Error removing Network Security Group %s from subnet %s: %s", securityGroup, subnetName, err) @@ -319,8 +336,7 @@ func associateSecurityGroups(d *schema.ResourceData, meta interface{}) error { // If the desired security group is not empty, assign the security group to the subnet if securityGroup != "" { - req, err := networksecuritygroup.NewClient(mc). - AddNetworkSecurityToSubnet(securityGroup, subnetName, virtualNetwork) + req, err := nsgClient.AddNetworkSecurityToSubnet(securityGroup, subnetName, virtualNetwork) if err != nil { return fmt.Errorf("Error associating Network Security Group %s to subnet %s: %s", securityGroup, subnetName, err) diff --git a/builtin/providers/azure/resource_azure_virtual_network_test.go b/builtin/providers/azure/resource_azure_virtual_network_test.go index 2ade3de00..c6787f3fe 100644 --- a/builtin/providers/azure/resource_azure_virtual_network_test.go +++ b/builtin/providers/azure/resource_azure_virtual_network_test.go @@ -6,7 +6,6 @@ import ( "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/svanharmelen/azure-sdk-for-go/management" "github.com/svanharmelen/azure-sdk-for-go/management/virtualnetwork" ) @@ -138,7 +137,7 @@ func testAccCheckAzureVirtualNetworkExists( return fmt.Errorf("No Virtual Network ID is set") } - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient nc, err := virtualnetwork.NewClient(mc).GetVirtualNetworkConfiguration() if err != nil { return err @@ -173,7 +172,7 @@ func testAccCheckAzureVirtualNetworkAttributes( } func testAccCheckAzureVirtualNetworkDestroy(s *terraform.State) error { - mc := testAccProvider.Meta().(management.Client) + mc := testAccProvider.Meta().(*Client).mgmtClient for _, rs := range s.RootModule().Resources { if rs.Type != "azure_virtual_network" { diff --git a/website/source/docs/providers/azure/index.html.markdown b/website/source/docs/providers/azure/index.html.markdown index fd4081a67..ea38e472e 100644 --- a/website/source/docs/providers/azure/index.html.markdown +++ b/website/source/docs/providers/azure/index.html.markdown @@ -33,11 +33,16 @@ resource "azure_instance" "web" { The following arguments are supported: -* `settings_file` - (Required) The path to a publish settings file used to +* `settings_file` - (Optional) The path to a publish settings file used to authenticate with the Azure API. You can download the settings file here: - https://manage.windowsazure.com/publishsettings. It must be provided, but - it can also be sourced from the `AZURE_SETTINGS_FILE` environment variable. + https://manage.windowsazure.com/publishsettings. You must either provide + (or source from the `AZURE_SETTINGS_FILE` environment variable) a settings + file or both a `subscription_id` and `certificate`. -* `subscription_id` - (Optional) The subscription ID to use. If not provided - the first subscription ID in publish settings file will be used. It can - also be sourced from the `AZURE_SUBSCRIPTION_ID` environment variable. +* `subscription_id` - (Optional) The subscription ID to use. If a + `settings_file` is not provided `subscription_id` is required. It can also + be sourced from the `AZURE_SUBSCRIPTION_ID` environment variable. + +* `certificate` - (Optional) The certificate used to authenticate with the + Azure API. If a `settings_file` is not provided `certificate` is required. + It can also be sourced from the `AZURE_CERTIFICATE` environment variable. diff --git a/website/source/docs/providers/azure/r/data_disk.html.markdown b/website/source/docs/providers/azure/r/data_disk.html.markdown new file mode 100644 index 000000000..3e95c5736 --- /dev/null +++ b/website/source/docs/providers/azure/r/data_disk.html.markdown @@ -0,0 +1,70 @@ +--- +layout: "azure" +page_title: "Azure: azure_data_disk" +sidebar_current: "docs-azure-resource-data-disk" +description: |- + Adds a data disk to a virtual machine. If the name of an existing disk is given, it will attach that disk. Otherwise it will create and attach a new empty disk. +--- + +# azure\_data\_disk + +Adds a data disk to a virtual machine. If the name of an existing disk is given, +it will attach that disk. Otherwise it will create and attach a new empty disk. + +## Example Usage + +``` +resource "azure_data_disk" "data" { + lun = 0 + size = 10 + storage = "yourstorage" + virtual_machine = "server1" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Optional) The name of an existing registered disk to attach to the + virtual machine. If left empty, a new empty disk will be created and + attached instead. Changing this forces a new resource to be created. + +* `label` - (Optional) The identifier of the data disk. Changing this forces a + new resource to be created (defaults to "virtual_machine-lun") + +* `lun` - (Required) The Logical Unit Number (LUN) for the disk. The LUN + specifies the slot in which the data drive appears when mounted for usage + by the virtual machine. Valid LUN values are 0 through 31. + +* `size` - (Optional) The size, in GB, of an empty disk to be attached to the + virtual machine. Required when creating a new disk, not used otherwise. + +* `caching` - (Optional) The caching behavior of data disk. Valid options are: + `None`, `ReadOnly` and `ReadWrite` (defaults `None`) + +* `storage ` - (Optional) The name of an existing storage account within the + subscription which will be used to store the VHD of this disk. Required + if no value is supplied for `media_link`. Changing this forces a new + resource to be created. + +* `media_link` - (Optional) The location of the blob in storage where the VHD + of this disk will be created. The storage account where must be associated + with the subscription. Changing this forces a new resource to be created. + +* `source_media_link` - (Optional) The location of a blob in storage where a + VHD file is located that is imported and registered as a disk. If a value + is supplied, `media_link` will not be used. + +* `virtual_machine` - (Required) The name of the virtual machine the disk will + be attached to. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The security group ID. +* `name` - The name of the disk. +* `label` - The identifier for the disk. +* `media_link` - The location of the blob in storage where the VHD of this disk + is created. diff --git a/website/source/docs/providers/azure/r/disk.html.markdown b/website/source/docs/providers/azure/r/disk.html.markdown deleted file mode 100644 index 53ae73656..000000000 --- a/website/source/docs/providers/azure/r/disk.html.markdown +++ /dev/null @@ -1,58 +0,0 @@ ---- -layout: "cloudstack" -page_title: "CloudStack: cloudstack_disk" -sidebar_current: "docs-cloudstack-resource-disk" -description: |- - Creates a disk volume from a disk offering. This disk volume will be attached to a virtual machine if the optional parameters are configured. ---- - -# cloudstack\_disk - -Creates a disk volume from a disk offering. This disk volume will be attached to -a virtual machine if the optional parameters are configured. - -## Example Usage - -``` -resource "cloudstack_disk" "default" { - name = "test-disk" - attach = "true" - disk_offering = "custom" - size = 50 - virtual-machine = "server-1" - zone = "zone-1" -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) The name of the disk volume. Changing this forces a new - resource to be created. - -* `attach` - (Optional) Determines whether or not to attach the disk volume to a - virtual machine (defaults false). - -* `device` - (Optional) The device to map the disk volume to within the guest OS. - -* `disk_offering` - (Required) The name or ID of the disk offering to use for - this disk volume. - -* `size` - (Optional) The size of the disk volume in gigabytes. - -* `shrink_ok` - (Optional) Verifies if the disk volume is allowed to shrink when - resizing (defaults false). - -* `virtual_machine` - (Optional) The name of the virtual machine to which you - want to attach the disk volume. - -* `zone` - (Required) The name or ID of the zone where this disk volume will be available. - Changing this forces a new resource to be created. - -## Attributes Reference - -The following attributes are exported: - -* `id` - The ID of the disk volume. -* `device` - The device the disk volume is mapped to within the guest OS. diff --git a/website/source/docs/providers/azure/r/instance.html.markdown b/website/source/docs/providers/azure/r/instance.html.markdown index 8779494e4..0ece7668d 100644 --- a/website/source/docs/providers/azure/r/instance.html.markdown +++ b/website/source/docs/providers/azure/r/instance.html.markdown @@ -3,23 +3,32 @@ layout: "azure" page_title: "Azure: azure_instance" sidebar_current: "docs-azure-resource-instance" description: |- - Creates and automatically starts a virtual machine based on a service offering, disk offering, and template. + Creates a hosted service, role and deployment and then creates a virtual machine in the deployment based on the specified configuration. --- # azure\_instance -Creates and automatically starts a virtual machine based on a service offering, -disk offering, and template. +Creates a hosted service, role and deployment and then creates a virtual +machine in the deployment based on the specified configuration. ## Example Usage ``` resource "azure_instance" "web" { - name = "server-1" - service_offering= "small" - network = "network-1" - template = "CentOS 6.5" - zone = "zone-1" + name = "terraform-test" + image = "Ubuntu Server 14.04 LTS" + size = "Basic_A1" + storage = "yourstorage" + location = "West US" + username = "terraform" + password = "Pass!admin123" + + endpoint { + name = "SSH" + protocol = "tcp" + public_port = 22 + private_port = 22 + } } ``` @@ -30,30 +39,81 @@ The following arguments are supported: * `name` - (Required) The name of the instance. Changing this forces a new resource to be created. -* `display_name` - (Optional) The display name of the instance. +* `description` - (Optional) The description for the associated hosted service. + Changing this forces a new resource to be created (defaults to the instance + name). -* `service_offering` - (Required) The name or ID of the service offering used for this instance. +* `image` - (Required) The name of an existing VM or OS image to use for this + instance. Changing this forces a new resource to be created. -* `network` - (Optional) The name or ID of the network to connect this instance to. +* `size` - (Required) The size of the instance. + +* `subnet` - (Optional) The name of the subnet to connect this instance to. If + a value is supplied `virtual_network` is required. Changing this forces a + new resource to be created. + +* `virtual_network` - (Optional) The name of the virtual network the `subnet` + belongs to. If a value is supplied `subnet` is required. Changing this + forces a new resource to be created. + +* `storage` - (Optional) The name of an existing storage account within the + subscription which will be used to store the VHDs of this instance. Changing this forces a new resource to be created. -* `ipaddress` - (Optional) The IP address to assign to this instance. Changing +* `reverse_dns` - (Optional) The DNS address to which the IP address of the + hosted service resolves when queried using a reverse DNS query. Changing this forces a new resource to be created. -* `template` - (Required) The name or ID of the template used for this instance. +* `location` - (Required) The location/region where the cloud service is + created. Changing this forces a new resource to be created. + +* `automatic_updates` - (Optional) If true this will enable automatic updates. + This attribute is only used when creating a Windows instance. Changing this + forces a new resource to be created (defaults false) + +* `time_zone` - (Optional) The appropriate time zone for this instance in the + format 'America/Los_Angeles'. This attribute is only used when creating a + Windows instance. Changing this forces a new resource to be created + (defaults false) + +* `username` - (Required) The username of a new user that will be created while + creating the instance. Changing this forces a new resource to be created. + +* `password` - (Optional) The password of the new user that will be created + while creating the instance. Required when creating a Windows instance or + when not supplying an `ssh_key_thumbprint` while creating a Linux instance. Changing this forces a new resource to be created. -* `zone` - (Required) The name of the zone where this instance will be created. - Changing this forces a new resource to be created. +* `ssh_key_thumbprint` - (Optional) The SSH thumbprint of an existing SSH key + within the subscription. This attribute is only used when creating a Linux + instance. Changing this forces a new resource to be created. -* `user_data` - (Optional) The user data to provide when launching the instance. +* `security_group` - (Optional) The Network Security Group to associate with + this instance. -* `expunge` - (Optional) This determines if the instance is expunged when it is - destroyed (defaults false) +* `endpoint` - (Optional) Can be specified multiple times to define multiple + endpoints. Each `endpoint` block supports fields documented below. + +The `endpoint` block supports: + +* `name` - (Required) The name of the external endpoint. + +* `protocol` - (Optional) The transport protocol for the endpoint. Valid + options are: `tcp` and `udp` (defaults `tcp`) + +* `public_port` - (Required) The external port to use for the endpoint. + +* `private_port` - (Required) The private port on which the instance is + listening. ## Attributes Reference The following attributes are exported: * `id` - The instance ID. -* `display_name` - The display name of the instance. +* `description` - The description for the associated hosted service. +* `subnet` - The subnet the instance is connected to. +* `endpoint` - The complete set of configured endpoints. +* `security_group` - The associated Network Security Group. +* `ip_address` - The private IP address assigned to the instance. +* `vip_address` - The public IP address assigned to the instance. diff --git a/website/source/docs/providers/azure/r/security_group.markdown b/website/source/docs/providers/azure/r/security_group.markdown index f82b8f446..c4699f716 100644 --- a/website/source/docs/providers/azure/r/security_group.markdown +++ b/website/source/docs/providers/azure/r/security_group.markdown @@ -1,28 +1,32 @@ --- -layout: "cloudstack" -page_title: "CloudStack: cloudstack_network_acl_rule" -sidebar_current: "docs-cloudstack-resource-network-acl-rule" +layout: "azure" +page_title: "Azure: azure_security_group" +sidebar_current: "docs-azure-resource-security-group" description: |- - Creates network ACL rules for a given network ACL. + Creates a new network security group within the context of the specified subscription. --- -# cloudstack\_network\_acl\_rule +# azure\_security\_group -Creates network ACL rules for a given network ACL. +Creates a new network security group within the context of the specified +subscription. ## Example Usage ``` -resource "cloudstack_network_acl_rule" "default" { - aclid = "f3843ce0-334c-4586-bbd3-0c2e2bc946c6" +resource "azure_security_group" "web" { + name = "webservers" + location = "West US" - rule { - action = "allow" - source_cidr = "10.0.0.0/8" - protocol = "tcp" - ports = ["80", "1000-2000"] - traffic_type = "ingress" - } + rule { + name = "HTTPS" + priority = 101 + source_cidr = "*" + source_port = "*" + destination_cidr = "*" + destination_port = "443" + protocol = "TCP" + } } ``` @@ -30,40 +34,51 @@ resource "cloudstack_network_acl_rule" "default" { The following arguments are supported: -* `aclid` - (Required) The network ACL ID for which to create the rules. - Changing this forces a new resource to be created. +* `name` - (Required) The name of the security group. Changing this forces a + new resource to be created. -* `managed` - (Optional) USE WITH CAUTION! If enabled all the firewall rules for - this network ACL will be managed by this resource. This means it will delete - all firewall rules that are not in your config! (defaults false) +* `label` - (Optional) The identifier for the security group. The label can be + up to 1024 characters long. Changing this forces a new resource to be + created (defaults to the security group name) -* `rule` - (Optional) Can be specified multiple times. Each rule block supports - fields documented below. If `managed = false` at least one rule is required! +* `location` - (Required) The location/region where the security group is + created. Changing this forces a new resource to be created. + +* `rule` - (Required) Can be specified multiple times to define multiple + rules. Each `rule` block supports fields documented below. The `rule` block supports: -* `action` - (Optional) The action for the rule. Valid options are: `allow` and - `deny` (defaults allow). +* `name` - (Required) The name of the security rule. -* `source_cidr` - (Required) The source CIDR to allow access to the given ports. +* `type ` - (Optional) The type of the security rule. Valid options are: + `Inbound` and `Outbound` (defaults `Inbound`) -* `protocol` - (Required) The name of the protocol to allow. Valid options are: - `tcp`, `udp`, `icmp`, `all` or a valid protocol number. +* `priority` - (Required) The priority of the network security rule. Rules with + lower priority are evaluated first. This value can be between 100 and 4096. -* `icmp_type` - (Optional) The ICMP type to allow. This can only be specified if - the protocol is ICMP. +* `action` - (Optional) The action that is performed when the security rule is + matched. Valid options are: `Allow` and `Deny` (defaults `Allow`) -* `icmp_code` - (Optional) The ICMP code to allow. This can only be specified if - the protocol is ICMP. +* `source_cidr` - (Required) The CIDR or source IP range. An asterisk (\*) can + also be used to match all source IPs. -* `ports` - (Optional) List of ports and/or port ranges to allow. This can only - be specified if the protocol is TCP, UDP, ALL or a valid protocol number. +* `source_port` - (Required) The source port or range. This value can be + between 0 and 65535. An asterisk (\*) can also be used to match all ports. -* `traffic_type` - (Optional) The traffic type for the rule. Valid options are: - `ingress` or `egress` (defaults ingress). +* `destination_cidr` - (Required) The CIDR or destination IP range. An asterisk + (\*) can also be used to match all destination IPs. + +* `destination_port` - (Required) The destination port or range. This value can + be between 0 and 65535. An asterisk (\*) can also be used to match all + ports. + +* `protocol` - (Optional) The protocol of the security rule. Valid options are: + `TCP`, `UDP` and `*` (defaults `TCP`) ## Attributes Reference The following attributes are exported: -* `id` - The ACL ID for which the rules are created. +* `id` - The security group ID. +* `label` - The identifier for the security group. diff --git a/website/source/docs/providers/azure/r/virtual_network.html.markdown b/website/source/docs/providers/azure/r/virtual_network.html.markdown index 9819a8ce3..66140c73d 100644 --- a/website/source/docs/providers/azure/r/virtual_network.html.markdown +++ b/website/source/docs/providers/azure/r/virtual_network.html.markdown @@ -1,25 +1,28 @@ --- -layout: "cloudstack" -page_title: "CloudStack: cloudstack_network" -sidebar_current: "docs-cloudstack-resource-network" +layout: "azure" +page_title: "Azure: azure_virtual_network" +sidebar_current: "docs-azure-resource-virtual-network" description: |- - Creates a network. + Creates a new virtual network including any configured subnets. Each subnet can optionally be configured with a security group to be associated with the subnet. --- -# cloudstack\_network +# azure\_virtual\_network -Creates a network. +Creates a new virtual network including any configured subnets. Each subnet can +optionally be configured with a security group to be associated with the subnet. ## Example Usage -Basic usage: - ``` -resource "cloudstack_network" "default" { +resource "azure_virtual_network" "default" { name = "test-network" - cidr = "10.0.0.0/16" - network_offering = "Default Network" - zone = "zone-1" + address_space = ["10.1.2.0/24"] + location = "West US" + + subnet { + name = "subnet1" + address_prefix = "10.1.2.0/25" + } } ``` @@ -27,28 +30,30 @@ resource "cloudstack_network" "default" { The following arguments are supported: -* `name` - (Required) The name of the network. +* `name` - (Required) The name of the virtual network. Changing this forces a + new resource to be created. -* `display_text` - (Optional) The display text of the network. +* `address_space` - (Required) The address space that is used the virtual + network. You can supply more than one address space. Changing this forces + a new resource to be created. -* `cidr` - (Required) The CIDR block for the network. Changing this forces a new - resource to be created. +* `location` - (Required) The location/region where the virtual network is + created. Changing this forces a new resource to be created. -* `network_offering` - (Required) The name or ID of the network offering to use - for this network. +* `subnet` - (Required) Can be specified multiple times to define multiple + subnets. Each `subnet` block supports fields documented below. -* `vpc` - (Optional) The name of the VPC to create this network for. Changing - this forces a new resource to be created. +The `subnet` block supports: -* `aclid` - (Optional) The ID of a network ACL that should be attached to the - network. Changing this forces a new resource to be created. +* `name` - (Required) The name of the subnet. -* `zone` - (Required) The name or ID of the zone where this disk volume will be - available. Changing this forces a new resource to be created. +* `address_prefix` - (Required) The address prefix to use for the subnet. + +* `security_group` - (Optional) The Network Security Group to associate with + the subnet. ## Attributes Reference The following attributes are exported: -* `id` - The ID of the network. -* `display_text` - The display text of the network. +* `id` - The virtual NetworkConfiguration ID. diff --git a/website/source/layouts/azure.erb b/website/source/layouts/azure.erb index 9d60e3f90..4699b354d 100644 --- a/website/source/layouts/azure.erb +++ b/website/source/layouts/azure.erb @@ -13,8 +13,8 @@ > Resources