From 158348ac0216ec06d989a33fdf2fa5f9d93789d9 Mon Sep 17 00:00:00 2001 From: Puneet Singh Sarna Date: Wed, 17 Jan 2024 20:11:03 -0800 Subject: [PATCH] add `azurerm_nginx_deployment` data source (#24492) --- .../nginx/nginx_deployment_data_source.go | 277 ++++++++++++++++++ .../nginx_deployment_data_source_test.go | 44 +++ internal/services/nginx/registration.go | 4 +- website/docs/d/nginx_deployment.html.markdown | 110 +++++++ website/docs/r/nginx_deployment.html.markdown | 4 +- 5 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 internal/services/nginx/nginx_deployment_data_source.go create mode 100644 internal/services/nginx/nginx_deployment_data_source_test.go create mode 100644 website/docs/d/nginx_deployment.html.markdown diff --git a/internal/services/nginx/nginx_deployment_data_source.go b/internal/services/nginx/nginx_deployment_data_source.go new file mode 100644 index 000000000000..f6e9e4c61911 --- /dev/null +++ b/internal/services/nginx/nginx_deployment_data_source.go @@ -0,0 +1,277 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package nginx + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" + "github.com/hashicorp/go-azure-sdk/resource-manager/nginx/2023-04-01/nginxdeployment" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type DeploymentDataSourceModel struct { + ResourceGroupName string `tfschema:"resource_group_name"` + Name string `tfschema:"name"` + NginxVersion string `tfschema:"nginx_version"` + Identity []identity.ModelSystemAssignedUserAssigned `tfschema:"identity"` + Sku string `tfschema:"sku"` + ManagedResourceGroup string `tfschema:"managed_resource_group"` + Location string `tfschema:"location"` + Capacity int64 `tfschema:"capacity"` + DiagnoseSupportEnabled bool `tfschema:"diagnose_support_enabled"` + Email string `tfschema:"email"` + IpAddress string `tfschema:"ip_address"` + LoggingStorageAccount []LoggingStorageAccount `tfschema:"logging_storage_account"` + FrontendPublic []FrontendPublic `tfschema:"frontend_public"` + FrontendPrivate []FrontendPrivate `tfschema:"frontend_private"` + NetworkInterface []NetworkInterface `tfschema:"network_interface"` + Tags map[string]string `tfschema:"tags"` +} + +type DeploymentDataSource struct{} + +var _ sdk.DataSource = DeploymentDataSource{} + +func (m DeploymentDataSource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "resource_group_name": commonschema.ResourceGroupNameForDataSource(), + + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + } +} + +func (m DeploymentDataSource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "nginx_version": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "identity": commonschema.SystemOrUserAssignedIdentityComputed(), + + "sku": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "managed_resource_group": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "location": commonschema.LocationComputed(), + + "capacity": { + Type: pluginsdk.TypeInt, + Computed: true, + }, + + "diagnose_support_enabled": { + Type: pluginsdk.TypeBool, + Computed: true, + }, + + "email": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "ip_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "logging_storage_account": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "container_name": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "frontend_public": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ip_address": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Schema{ + Type: pluginsdk.TypeString, + }, + }, + }, + }, + }, + + "frontend_private": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "ip_address": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "allocation_method": { + Type: pluginsdk.TypeString, + Computed: true, + }, + + "subnet_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "network_interface": { + Type: pluginsdk.TypeList, + Computed: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "subnet_id": { + Type: pluginsdk.TypeString, + Computed: true, + }, + }, + }, + }, + + "tags": commonschema.TagsDataSource(), + } +} + +func (m DeploymentDataSource) ModelObject() interface{} { + return &DeploymentDataSourceModel{} +} + +func (m DeploymentDataSource) ResourceType() string { + return "azurerm_nginx_deployment" +} + +func (m DeploymentDataSource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Nginx.NginxDeployment + subscriptionId := metadata.Client.Account.SubscriptionId + var model DeploymentDataSourceModel + if err := metadata.Decode(&model); err != nil { + return err + } + id := nginxdeployment.NewNginxDeploymentID(subscriptionId, model.ResourceGroupName, model.Name) + result, err := client.DeploymentsGet(ctx, id) + if err != nil { + if response.WasNotFound(result.HttpResponse) { + return fmt.Errorf("%s was not found", id) + } + return fmt.Errorf("reading %s: %+v", id, err) + } + + output := DeploymentDataSourceModel{ + Name: id.NginxDeploymentName, + ResourceGroupName: id.ResourceGroupName, + } + + if model := result.Model; model != nil { + output.Location = pointer.ToString(model.Location) + if tags := model.Tags; tags != nil { + output.Tags = pointer.ToMapOfStringStrings(model.Tags) + } + if model.Sku != nil { + output.Sku = model.Sku.Name + } + flattenedIdentity, err := identity.FlattenSystemAndUserAssignedMapToModel(model.Identity) + if err != nil { + return fmt.Errorf("flattening `identity`: %v", err) + } + output.Identity = *flattenedIdentity + if props := model.Properties; props != nil { + output.IpAddress = pointer.ToString(props.IPAddress) + output.ManagedResourceGroup = pointer.ToString(props.ManagedResourceGroup) + output.NginxVersion = pointer.ToString(props.NginxVersion) + output.DiagnoseSupportEnabled = pointer.ToBool(props.EnableDiagnosticsSupport) + + if props.Logging != nil && props.Logging.StorageAccount != nil { + output.LoggingStorageAccount = []LoggingStorageAccount{ + { + Name: pointer.ToString(props.Logging.StorageAccount.AccountName), + ContainerName: pointer.ToString(props.Logging.StorageAccount.ContainerName), + }, + } + } + + if profile := props.NetworkProfile; profile != nil { + if frontend := profile.FrontEndIPConfiguration; frontend != nil { + if publicIps := frontend.PublicIPAddresses; publicIps != nil && len(*publicIps) > 0 { + output.FrontendPublic = append(output.FrontendPublic, FrontendPublic{}) + for _, ip := range *publicIps { + output.FrontendPublic[0].IpAddress = append(output.FrontendPublic[0].IpAddress, pointer.ToString(ip.Id)) + } + } + + if privateIPs := frontend.PrivateIPAddresses; privateIPs != nil && len(*privateIPs) > 0 { + for _, ip := range *privateIPs { + method := "" + if ip.PrivateIPAllocationMethod != nil { + method = string(*ip.PrivateIPAllocationMethod) + } + + output.FrontendPrivate = append(output.FrontendPrivate, FrontendPrivate{ + IpAddress: pointer.ToString(ip.PrivateIPAddress), + AllocationMethod: method, + SubnetId: pointer.ToString(ip.SubnetId), + }) + } + } + } + + if netIf := profile.NetworkInterfaceConfiguration; netIf != nil { + output.NetworkInterface = []NetworkInterface{ + {SubnetId: pointer.ToString(netIf.SubnetId)}, + } + } + } + + if scaling := props.ScalingProperties; scaling != nil { + output.Capacity = pointer.ToInt64(props.ScalingProperties.Capacity) + } + + if userProfile := props.UserProfile; userProfile != nil && userProfile.PreferredEmail != nil { + output.Email = pointer.ToString(props.UserProfile.PreferredEmail) + } + } + } + + metadata.SetID(id) + return metadata.Encode(&output) + }, + } +} diff --git a/internal/services/nginx/nginx_deployment_data_source_test.go b/internal/services/nginx/nginx_deployment_data_source_test.go new file mode 100644 index 000000000000..174fbe294808 --- /dev/null +++ b/internal/services/nginx/nginx_deployment_data_source_test.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package nginx_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" +) + +type NginxDeploymentDataSource struct{} + +func TestAccNginxDeploymentDataSource_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_nginx_deployment", "test") + r := NginxDeploymentDataSource{} + + data.DataSourceTest(t, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).Key("location").Exists(), + check.That(data.ResourceName).Key("nginx_version").Exists(), + check.That(data.ResourceName).Key("sku").Exists(), + check.That(data.ResourceName).Key("capacity").Exists(), + check.That(data.ResourceName).Key("managed_resource_group").Exists(), + check.That(data.ResourceName).Key("ip_address").Exists(), + ), + }, + }) +} + +func (d NginxDeploymentDataSource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +data "azurerm_nginx_deployment" "test" { + name = azurerm_nginx_deployment.test.name + resource_group_name = azurerm_nginx_deployment.test.resource_group_name +} +`, DeploymentResource{}.basic(data)) +} diff --git a/internal/services/nginx/registration.go b/internal/services/nginx/registration.go index a368d88ce9f7..399d439c6fa1 100644 --- a/internal/services/nginx/registration.go +++ b/internal/services/nginx/registration.go @@ -29,7 +29,9 @@ func (r Registration) WebsiteCategories() []string { // DataSources ... func (r Registration) DataSources() []sdk.DataSource { - return []sdk.DataSource{} + return []sdk.DataSource{ + DeploymentDataSource{}, + } } // Resources ... diff --git a/website/docs/d/nginx_deployment.html.markdown b/website/docs/d/nginx_deployment.html.markdown new file mode 100644 index 000000000000..2a75e72e7f62 --- /dev/null +++ b/website/docs/d/nginx_deployment.html.markdown @@ -0,0 +1,110 @@ +--- +subcategory: "Nginx" +layout: "azurerm" +page_title: "Azure Resource Manager: Data Source: azurerm_nginx_deployment" +description: |- + Gets information about an existing Nginx Deployment. +--- + +# Data Source: azurerm_nginx_deployment + +Use this data source to access information about an existing Nginx Deployment. + +## Example Usage + +```hcl +data "azurerm_nginx_deployment" "example" { + name = "existing" + resource_group_name = "existing" +} + +output "id" { + value = data.azurerm_nginx_deployment.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name of this Nginx Deployment. + +* `resource_group_name` - (Required) The name of the Resource Group where the Nginx Deployment exists. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Nginx Deployment. + +* `capacity` - The number of NGINX capacity units for this Nginx Deployment. + +* `diagnose_support_enabled` - Whether diagnostic settings are enabled. + +* `email` - Preferred email associated with the Nginx Deployment. + +* `frontend_private` - A `frontend_private` block as defined below. + +* `frontend_public` - A `frontend_public` block as defined below. + +* `identity` - A `identity` block as defined below. + +* `ip_address` - The IP address of the Nginx Deployment. + +* `location` - The Azure Region where the Nginx Deployment exists. + +* `logging_storage_account` - A `logging_storage_account` block as defined below. + +* `managed_resource_group` - Auto-generated managed resource group for the Nginx Deployment. + +* `network_interface` - A `network_interface` block as defined below. + +* `nginx_version` - NGINX version of the Nginx Deployment. + +* `sku` - Name of the SKU for this Nginx Deployment. + +* `tags` - A mapping of tags assigned to the Nginx Deployment. + +--- + +A `frontend_private` block exports the following: + +* `allocation_method` - The method of allocating the private IP to the Nginx Deployment. + +* `ip_address` - Private IP address of the Nginx Deployment. + +* `subnet_id` - The subnet ID of the Nginx Deployment. + +--- + +A `frontend_public` block exports the following: + +* `ip_address` - List of public IPs of the Ngix Deployment. + +--- + +A `identity` block exports the following: + +* `identity_ids` - List of identities attached to the Nginx Deployment. + +* `type` - Type of identity attached to the Nginx Deployment. + +--- + +A `logging_storage_account` block exports the following: + +* `container_name` - the container name of Storage Account for logging. + +* `name` - The account name of the StorageAccount for logging. + +--- + +A `network_interface` block exports the following: + +* `subnet_id` - The subnet resource ID of the Nginx Deployment. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `read` - (Defaults to 5 minutes) Used when retrieving the Nginx Deployment. diff --git a/website/docs/r/nginx_deployment.html.markdown b/website/docs/r/nginx_deployment.html.markdown index 8468c1c05fe9..330a74f17468 100644 --- a/website/docs/r/nginx_deployment.html.markdown +++ b/website/docs/r/nginx_deployment.html.markdown @@ -125,7 +125,7 @@ A `identity` block supports the following: A `frontend_private` block supports the following: -* `allocation_method` - (Required) Specify the methos of allocating the private IP. Possible values are `Static` and `Dynamic`. +* `allocation_method` - (Required) Specify the method of allocating the private IP. Possible values are `Static` and `Dynamic`. * `ip_address` - (Required) Specify the IP Address of this private IP. @@ -141,7 +141,7 @@ A `frontend_public` block supports the following: A `logging_storage_account` block supports the following: -* `container_name` - (Optional) Specify the container name of Stoage Account for logging. +* `container_name` - (Optional) Specify the container name of Storage Account for logging. * `name` - (Optional) The account name of the StorageAccount for Nginx Logging.