diff --git a/azurerm/data_source_image.go b/azurerm/data_source_image.go new file mode 100644 index 000000000000..e131acf2bcad --- /dev/null +++ b/azurerm/data_source_image.go @@ -0,0 +1,128 @@ +package azurerm + +import ( + "fmt" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmImage() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmImageRead, + Schema: map[string]*schema.Schema{ + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": resourceGroupNameForDataSourceSchema(), + + "location": locationForDataSourceSchema(), + + "os_disk": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "blob_uri": { + Type: schema.TypeString, + Computed: true, + }, + "caching": { + Type: schema.TypeString, + Computed: true, + }, + "managed_disk_id": { + Type: schema.TypeString, + Computed: true, + }, + "os_state": { + Type: schema.TypeString, + Computed: true, + }, + "os_type": { + Type: schema.TypeString, + Computed: true, + }, + "size_gb": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + + "data_disk": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "blob_uri": { + Type: schema.TypeString, + Computed: true, + }, + "caching": { + Type: schema.TypeString, + Computed: true, + }, + "lun": { + Type: schema.TypeInt, + Computed: true, + }, + "managed_disk_id": { + Type: schema.TypeString, + Computed: true, + }, + "size_gb": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + + "tags": tagsForDataSourceSchema(), + }, + } +} + +func dataSourceArmImageRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).imageClient + + resGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) + + resp, err := client.Get(resGroup, name, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("[ERROR] Error making Read request on Azure Image %q (resource group %q): %+v", name, resGroup, err) + } + + d.SetId(*resp.ID) + d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) + d.Set("location", azureRMNormalizeLocation(*resp.Location)) + + if profile := resp.StorageProfile; profile != nil { + if disk := profile.OsDisk; disk != nil { + if err := d.Set("os_disk", flattenAzureRmImageOSDisk(d, disk)); err != nil { + return fmt.Errorf("[DEBUG] Error setting AzureRM Image OS Disk error: %+v", err) + } + } + + if disks := resp.StorageProfile.DataDisks; disks != nil { + if err := d.Set("data_disk", flattenAzureRmImageDataDisks(d, disks)); err != nil { + return fmt.Errorf("[DEBUG] Error setting AzureRM Image Data Disks error: %+v", err) + } + } + } + + flattenAndSetTags(d, resp.Tags) + + return nil +} diff --git a/azurerm/data_source_image_test.go b/azurerm/data_source_image_test.go new file mode 100644 index 000000000000..a25c66779983 --- /dev/null +++ b/azurerm/data_source_image_test.go @@ -0,0 +1,171 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceAzureRMImage_basic(t *testing.T) { + dataSourceName := "data.azurerm_image.test" + + config := testAccDataSourceAzureRMImageBasic(acctest.RandInt(), acctest.RandString(4), testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "name"), + resource.TestCheckResourceAttrSet(dataSourceName, "resource_group_name"), + resource.TestCheckResourceAttr(dataSourceName, "os_disk.#", "1"), + resource.TestCheckResourceAttrSet(dataSourceName, "os_disk.0.blob_uri"), + resource.TestCheckResourceAttr(dataSourceName, "os_disk.0.caching", "None"), + resource.TestCheckResourceAttr(dataSourceName, "os_disk.0.os_type", "Linux"), + resource.TestCheckResourceAttr(dataSourceName, "os_disk.0.os_state", "Generalized"), + resource.TestCheckResourceAttr(dataSourceName, "os_disk.0.size_gb", "30"), + resource.TestCheckResourceAttr(dataSourceName, "data_disk.#", "0"), + resource.TestCheckResourceAttr(dataSourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(dataSourceName, "tags.environment", "Dev"), + resource.TestCheckResourceAttr(dataSourceName, "tags.cost-center", "Ops"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMImageBasic(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "%s" +} + +resource "azurerm_virtual_network" "test" { + name = "acctestvn-%d" + address_space = ["10.0.0.0/16"] + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_subnet" "test" { + name = "internal" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.2.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctestpip%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "Dynamic" + domain_name_label = "acctestpip%d" +} + +resource "azurerm_network_interface" "testsource" { + name = "acctestnic-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + ip_configuration { + name = "testconfigurationsource" + subnet_id = "${azurerm_subnet.test.id}" + private_ip_address_allocation = "dynamic" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } +} + +resource "azurerm_storage_account" "test" { + name = "acctestsa%s" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + account_tier = "Standard" + account_replication_type = "LRS" + + tags { + environment = "Dev" + } +} + +resource "azurerm_storage_container" "test" { + name = "vhds" + resource_group_name = "${azurerm_resource_group.test.name}" + storage_account_name = "${azurerm_storage_account.test.name}" + container_access_type = "blob" +} + +resource "azurerm_virtual_machine" "testsource" { + name = "acctestvm-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + network_interface_ids = ["${azurerm_network_interface.testsource.id}"] + vm_size = "Standard_D1_v2" + + storage_image_reference { + publisher = "Canonical" + offer = "UbuntuServer" + sku = "16.04-LTS" + version = "latest" + } + + storage_os_disk { + name = "myosdisk1" + vhd_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" + caching = "ReadWrite" + create_option = "FromImage" + disk_size_gb = "30" + } + + os_profile { + computer_name = "acctest-%d" + admin_username = "tfuser" + admin_password = "P@ssW0RD7890" + } + + os_profile_linux_config { + disable_password_authentication = false + } + + tags { + environment = "Dev" + cost-center = "Ops" + } +} + +resource "azurerm_image" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + os_disk { + os_type = "Linux" + os_state = "Generalized" + blob_uri = "${azurerm_storage_account.test.primary_blob_endpoint}${azurerm_storage_container.test.name}/myosdisk1.vhd" + size_gb = 30 + caching = "None" + } + + tags { + environment = "Dev" + cost-center = "Ops" + } + + depends_on = ["azurerm_virtual_machine.testsource"] +} + +data "azurerm_image" "test" { + name = "${azurerm_image.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +output "location" { + value = "${data.azurerm_image.test.location}" +} + +`, rInt, location, rInt, rInt, rInt, rInt, rString, rInt, rInt, rInt) +} diff --git a/azurerm/data_source_managed_disk_test.go b/azurerm/data_source_managed_disk_test.go index 07a203be7657..fef13c78c8a0 100644 --- a/azurerm/data_source_managed_disk_test.go +++ b/azurerm/data_source_managed_disk_test.go @@ -18,9 +18,8 @@ func TestAccDataSourceAzureRMManagedDisk_basic(t *testing.T) { config := testAccDataSourceAzureRMManagedDiskBasic(name, resourceGroupName, testLocation()) resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMPublicIpDestroy, + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, Steps: []resource.TestStep{ { Config: config, diff --git a/azurerm/provider.go b/azurerm/provider.go index 0d1d7ff48308..663def51c6a6 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -69,6 +69,7 @@ func Provider() terraform.ResourceProvider { DataSourcesMap: map[string]*schema.Resource{ "azurerm_client_config": dataSourceArmClientConfig(), + "azurerm_image": dataSourceArmImage(), "azurerm_managed_disk": dataSourceArmManagedDisk(), "azurerm_platform_image": dataSourceArmPlatformImage(), "azurerm_public_ip": dataSourceArmPublicIP(), diff --git a/azurerm/resource_arm_image.go b/azurerm/resource_arm_image.go index 6d04db4ddfeb..c5fa840a8e4e 100644 --- a/azurerm/resource_arm_image.go +++ b/azurerm/resource_arm_image.go @@ -43,7 +43,6 @@ func resourceArmImage() *schema.Resource { ForceNew: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "os_type": { Type: schema.TypeString, Optional: true, @@ -104,7 +103,7 @@ func resourceArmImage() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "lun": &schema.Schema{ + "lun": { Type: schema.TypeInt, Optional: true, }, @@ -242,7 +241,7 @@ func resourceArmImageRead(d *schema.ResourceData, meta interface{}) error { d.SetId("") return nil } - return fmt.Errorf("[ERROR] Error making Read request on AzureRM Image %s (resource group %s): %+v", name, resGroup, err) + return fmt.Errorf("[ERROR] Error making Read request on AzureRM Image %q (resource group %q): %+v", name, resGroup, err) } d.Set("name", resp.Name) @@ -253,13 +252,15 @@ func resourceArmImageRead(d *schema.ResourceData, meta interface{}) error { if resp.SourceVirtualMachine != nil { d.Set("source_virtual_machine_id", resp.SourceVirtualMachine.ID) } else if resp.StorageProfile != nil { - if err := d.Set("os_disk", flattenAzureRmStorageProfileOsDisk(d, resp.StorageProfile)); err != nil { - return fmt.Errorf("[DEBUG] Error setting AzureRM Image OS Disk error: %#v", err) + if disk := resp.StorageProfile.OsDisk; disk != nil { + if err := d.Set("os_disk", flattenAzureRmImageOSDisk(d, disk)); err != nil { + return fmt.Errorf("[DEBUG] Error setting AzureRM Image OS Disk error: %+v", err) + } } - if resp.StorageProfile.DataDisks != nil { - if err := d.Set("data_disk", flattenAzureRmStorageProfileDataDisks(d, resp.StorageProfile)); err != nil { - return fmt.Errorf("[DEBUG] Error setting AzureRM Image Data Disks error: %#v", err) + if disks := resp.StorageProfile.DataDisks; disks != nil { + if err := d.Set("data_disk", flattenAzureRmImageDataDisks(d, disks)); err != nil { + return fmt.Errorf("[DEBUG] Error setting AzureRM Image Data Disks error: %+v", err) } } } @@ -288,42 +289,45 @@ func resourceArmImageDelete(d *schema.ResourceData, meta interface{}) error { return nil } -func flattenAzureRmStorageProfileOsDisk(d *schema.ResourceData, storageProfile *compute.ImageStorageProfile) []interface{} { +func flattenAzureRmImageOSDisk(d *schema.ResourceData, osDisk *compute.ImageOSDisk) []interface{} { result := make(map[string]interface{}) - if storageProfile.OsDisk != nil { - osDisk := *storageProfile.OsDisk - result["os_type"] = osDisk.OsType - result["os_state"] = osDisk.OsState - if osDisk.ManagedDisk != nil { - result["managed_disk_id"] = *osDisk.ManagedDisk.ID - } + + if disk := osDisk; disk != nil { result["blob_uri"] = *osDisk.BlobURI result["caching"] = string(osDisk.Caching) if osDisk.DiskSizeGB != nil { result["size_gb"] = *osDisk.DiskSizeGB } + if osDisk.ManagedDisk != nil { + result["managed_disk_id"] = *osDisk.ManagedDisk.ID + } + result["os_type"] = osDisk.OsType + result["os_state"] = osDisk.OsState } return []interface{}{result} } -func flattenAzureRmStorageProfileDataDisks(d *schema.ResourceData, storageProfile *compute.ImageStorageProfile) []interface{} { - disks := storageProfile.DataDisks - result := make([]interface{}, len(*disks)) - for i, disk := range *disks { - l := make(map[string]interface{}) - if disk.ManagedDisk != nil { - l["managed_disk_id"] = *disk.ManagedDisk.ID - } - l["blob_uri"] = disk.BlobURI - l["caching"] = string(disk.Caching) - if disk.DiskSizeGB != nil { - l["size_gb"] = *disk.DiskSizeGB - } - l["lun"] = *disk.Lun +func flattenAzureRmImageDataDisks(d *schema.ResourceData, diskImages *[]compute.ImageDataDisk) []interface{} { + result := make([]interface{}, 0) - result[i] = l + if images := diskImages; images != nil { + for i, disk := range *images { + l := make(map[string]interface{}) + l["blob_uri"] = disk.BlobURI + l["caching"] = string(disk.Caching) + if disk.DiskSizeGB != nil { + l["size_gb"] = *disk.DiskSizeGB + } + l["lun"] = *disk.Lun + if disk.ManagedDisk != nil { + l["managed_disk_id"] = *disk.ManagedDisk.ID + } + + result[i] = l + } } + return result } diff --git a/website/azurerm.erb b/website/azurerm.erb index c4b0db1c733d..18a17ba1b6f8 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -27,6 +27,10 @@ azurerm_client_config +