-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New data source
azurerm_images
(#8629)
- Loading branch information
1 parent
7690961
commit a7157e4
Showing
4 changed files
with
451 additions
and
0 deletions.
There are no files selected for viewing
199 changes: 199 additions & 0 deletions
199
azurerm/internal/services/compute/images_data_source.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,199 @@ | ||
package compute | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/location" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func dataSourceArmImages() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceArmImagesRead, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Read: schema.DefaultTimeout(5 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"resource_group_name": azure.SchemaResourceGroupNameForDataSource(), | ||
|
||
"tags_filter": tags.Schema(), | ||
|
||
"images": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"location": location.SchemaComputed(), | ||
|
||
"zone_resilient": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
|
||
"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": tags.SchemaDataSource(), | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceArmImagesRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Compute.ImagesClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
resourceGroup := d.Get("resource_group_name").(string) | ||
filterTags := tags.Expand(d.Get("tags_filter").(map[string]interface{})) | ||
|
||
resp, err := client.ListByResourceGroupComplete(ctx, resourceGroup) | ||
if err != nil { | ||
if utils.ResponseWasNotFound(resp.Response().Response) { | ||
return fmt.Errorf("no images were found in Resource Group %q", resourceGroup) | ||
} | ||
return fmt.Errorf("retrieving Images (Resource Group %q): %+v", resourceGroup, err) | ||
} | ||
|
||
images, err := flattenImagesResult(ctx, resp, filterTags) | ||
if err != nil { | ||
return fmt.Errorf("parsing Images (Resource Group %q): %+v", resourceGroup, err) | ||
} | ||
if len(images) == 0 { | ||
return fmt.Errorf("no images were found that match the specified tags") | ||
} | ||
|
||
d.SetId(time.Now().UTC().String()) | ||
|
||
d.Set("resource_group_name", resourceGroup) | ||
|
||
if err := d.Set("images", images); err != nil { | ||
return fmt.Errorf("setting `images`: %+v", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func flattenImagesResult(ctx context.Context, iterator compute.ImageListResultIterator, filterTags map[string]*string) ([]interface{}, error) { | ||
results := make([]interface{}, 0) | ||
|
||
for iterator.NotDone() { | ||
image := iterator.Value() | ||
found := true | ||
// Loop through our filter tags and see if they match | ||
for k, v := range filterTags { | ||
if v != nil { | ||
// If the tags do not match return false | ||
if image.Tags[k] == nil || *v != *image.Tags[k] { | ||
found = false | ||
} | ||
} | ||
} | ||
|
||
if found { | ||
results = append(results, flattenImage(image)) | ||
} | ||
if err := iterator.NextWithContext(ctx); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
return results, nil | ||
} | ||
|
||
func flattenImage(input compute.Image) map[string]interface{} { | ||
output := make(map[string]interface{}) | ||
|
||
output["name"] = input.Name | ||
output["location"] = location.NormalizeNilable(input.Location) | ||
|
||
if input.ImageProperties != nil { | ||
if storageProfile := input.ImageProperties.StorageProfile; storageProfile != nil { | ||
output["zone_resilient"] = storageProfile.ZoneResilient | ||
|
||
output["os_disk"] = flattenAzureRmImageOSDisk(storageProfile.OsDisk) | ||
|
||
output["data_disk"] = flattenAzureRmImageDataDisks(storageProfile.DataDisks) | ||
} | ||
} | ||
|
||
output["tags"] = tags.Flatten(input.Tags) | ||
|
||
return output | ||
} |
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
165 changes: 165 additions & 0 deletions
165
azurerm/internal/services/compute/tests/images_data_source_test.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,165 @@ | ||
package tests | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" | ||
) | ||
|
||
func TestAccDataSourceAzureRMImages_basic(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "data.azurerm_images", "test") | ||
|
||
resourceGroup := fmt.Sprintf("acctestRG-%d", data.RandomInteger) | ||
userName := "testadmin" | ||
password := "Password1234!" | ||
hostName := fmt.Sprintf("tftestcustomimagesrc%d", data.RandomInteger) | ||
sshPort := "22" | ||
storageType := "LRS" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acceptance.PreCheck(t) }, | ||
Providers: acceptance.SupportedProviders, | ||
CheckDestroy: testCheckAzureRMImageDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
// need to create a vm and then reference it in the image creation | ||
Config: testAccAzureRMImage_standaloneImage_setup(data, userName, password, hostName, storageType), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureVMExists("azurerm_virtual_machine.testsource", true), | ||
testGeneralizeVMImage(resourceGroup, "testsource", userName, password, hostName, sshPort, data.Locations.Primary), | ||
), | ||
}, | ||
{ | ||
Config: testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, ""), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureRMImageExists("azurerm_image.test", true), | ||
), | ||
}, | ||
{ | ||
Config: testAccDataSourceImages_basic(data, userName, password, hostName, storageType), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(data.ResourceName, "images.#", "1"), | ||
resource.TestCheckResourceAttr(data.ResourceName, "images.0.os_disk.0.os_type", "Linux"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccDataSourceAzureRMImages_tagsFilterError(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "data.azurerm_images", "test") | ||
|
||
resourceGroup := fmt.Sprintf("acctestRG-%d", data.RandomInteger) | ||
userName := "testadmin" | ||
password := "Password1234!" | ||
hostName := fmt.Sprintf("tftestcustomimagesrc%d", data.RandomInteger) | ||
sshPort := "22" | ||
storageType := "LRS" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acceptance.PreCheck(t) }, | ||
Providers: acceptance.SupportedProviders, | ||
CheckDestroy: testCheckAzureRMImageDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
// need to create a vm and then reference it in the image creation | ||
Config: testAccAzureRMImage_standaloneImage_setup(data, userName, password, hostName, storageType), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureVMExists("azurerm_virtual_machine.testsource", true), | ||
testGeneralizeVMImage(resourceGroup, "testsource", userName, password, hostName, sshPort, data.Locations.Primary), | ||
), | ||
}, | ||
{ | ||
Config: testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, ""), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureRMImageExists("azurerm_image.test", true), | ||
), | ||
}, | ||
{ | ||
Config: testAccDataSourceImages_tagsFilterError(data, userName, password, hostName, storageType), | ||
ExpectError: regexp.MustCompile("no images were found that match the specified tags"), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccDataSourceAzureRMImages_tagsFilter(t *testing.T) { | ||
data := acceptance.BuildTestData(t, "data.azurerm_images", "test") | ||
|
||
resourceGroup := fmt.Sprintf("acctestRG-%d", data.RandomInteger) | ||
userName := "testadmin" | ||
password := "Password1234!" | ||
hostName := fmt.Sprintf("tftestcustomimagesrc%d", data.RandomInteger) | ||
sshPort := "22" | ||
storageType := "LRS" | ||
|
||
resource.ParallelTest(t, resource.TestCase{ | ||
PreCheck: func() { acceptance.PreCheck(t) }, | ||
Providers: acceptance.SupportedProviders, | ||
CheckDestroy: testCheckAzureRMImageDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
// need to create a vm and then reference it in the image creation | ||
Config: testAccAzureRMImage_standaloneImage_setup(data, userName, password, hostName, storageType), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureVMExists("azurerm_virtual_machine.testsource", true), | ||
testGeneralizeVMImage(resourceGroup, "testsource", userName, password, hostName, sshPort, data.Locations.Primary), | ||
), | ||
}, | ||
{ | ||
Config: testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, ""), | ||
Check: resource.ComposeTestCheckFunc( | ||
testCheckAzureRMImageExists("azurerm_image.test", true), | ||
), | ||
}, | ||
{ | ||
Config: testAccDataSourceImages_tagsFilter(data, userName, password, hostName, storageType), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr(data.ResourceName, "images.#", "1"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDataSourceImages_basic(data acceptance.TestData, userName, password, hostName, storageType string) string { | ||
template := testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, "") | ||
return fmt.Sprintf(` | ||
%s | ||
data "azurerm_images" "test" { | ||
resource_group_name = azurerm_image.test.resource_group_name | ||
} | ||
`, template) | ||
} | ||
|
||
func testAccDataSourceImages_tagsFilterError(data acceptance.TestData, userName, password, hostName, storageType string) string { | ||
template := testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, "") | ||
return fmt.Sprintf(` | ||
%s | ||
data "azurerm_images" "test" { | ||
resource_group_name = azurerm_image.test.resource_group_name | ||
tags_filter = { | ||
environment = "error" | ||
} | ||
} | ||
`, template) | ||
} | ||
|
||
func testAccDataSourceImages_tagsFilter(data acceptance.TestData, userName, password, hostName, storageType string) string { | ||
template := testAccAzureRMImage_standaloneImage_provision(data, userName, password, hostName, storageType, "") | ||
return fmt.Sprintf(` | ||
%s | ||
data "azurerm_images" "test" { | ||
resource_group_name = azurerm_image.test.resource_group_name | ||
tags_filter = { | ||
environment = "Dev" | ||
} | ||
} | ||
`, template) | ||
} |
Oops, something went wrong.