Skip to content

Commit 52a214c

Browse files
committed
New List Resource: azurerm_network_security_group
1 parent 897a228 commit 52a214c

File tree

6 files changed

+295
-5
lines changed

6 files changed

+295
-5
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package network
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
"github.com/hashicorp/go-azure-helpers/framework/typehelpers"
9+
"github.com/hashicorp/go-azure-helpers/lang/pointer"
10+
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
11+
"github.com/hashicorp/go-azure-helpers/resourcemanager/resourcegroups"
12+
"github.com/hashicorp/go-azure-sdk/resource-manager/network/2025-01-01/networksecuritygroups"
13+
"github.com/hashicorp/terraform-plugin-framework/list"
14+
"github.com/hashicorp/terraform-plugin-framework/list/schema"
15+
"github.com/hashicorp/terraform-plugin-framework/resource"
16+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
17+
"github.com/hashicorp/terraform-plugin-framework/types"
18+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
19+
"github.com/hashicorp/terraform-provider-azurerm/internal/sdk"
20+
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
21+
)
22+
23+
type NetworkSecurityGroupListResource struct {
24+
sdk.ListResourceMetadata
25+
}
26+
27+
type NetworkSecurityGroupListModel struct {
28+
ResourceGroupName types.String `tfsdk:"resource_group_name"`
29+
SubscriptionId types.String `tfsdk:"subscription_id"`
30+
}
31+
32+
var _ sdk.ListResourceWithRawV5Schemas = new(NetworkSecurityGroupListResource)
33+
34+
func NewNetworkSecurityGroupListResource() list.ListResource {
35+
return new(NetworkSecurityGroupListResource)
36+
}
37+
38+
func (r *NetworkSecurityGroupListResource) Metadata(_ context.Context, _ resource.MetadataRequest, response *resource.MetadataResponse) {
39+
response.TypeName = networkSecurityGroupResourceName
40+
}
41+
42+
func (r *NetworkSecurityGroupListResource) ListResourceConfigSchema(_ context.Context, _ list.ListResourceSchemaRequest, response *list.ListResourceSchemaResponse) {
43+
response.Schema = schema.Schema{
44+
Attributes: map[string]schema.Attribute{
45+
"resource_group_name": schema.StringAttribute{
46+
Optional: true,
47+
Validators: []validator.String{
48+
typehelpers.WrappedStringValidator{
49+
Func: resourcegroups.ValidateName,
50+
},
51+
},
52+
},
53+
"subscription_id": schema.StringAttribute{
54+
Optional: true,
55+
Validators: []validator.String{
56+
typehelpers.WrappedStringValidator{
57+
Func: validation.IsUUID,
58+
},
59+
},
60+
},
61+
},
62+
}
63+
}
64+
65+
func (r *NetworkSecurityGroupListResource) List(ctx context.Context, request list.ListRequest, stream *list.ListResultsStream) {
66+
client := r.Client.Network.NetworkSecurityGroups
67+
68+
ctx, cancel := context.WithTimeout(ctx, time.Minute*60)
69+
defer cancel()
70+
71+
var data NetworkSecurityGroupListModel
72+
diags := request.Config.Get(ctx, &data)
73+
if diags.HasError() {
74+
stream.Results = list.ListResultsStreamDiagnostics(diags)
75+
return
76+
}
77+
78+
results := make([]networksecuritygroups.NetworkSecurityGroup, 0)
79+
80+
subscriptionID := r.SubscriptionId
81+
if !data.SubscriptionId.IsNull() {
82+
subscriptionID = data.SubscriptionId.ValueString()
83+
}
84+
85+
switch {
86+
case !data.ResourceGroupName.IsNull():
87+
resp, err := client.ListComplete(ctx, commonids.NewResourceGroupID(subscriptionID, data.ResourceGroupName.ValueString()))
88+
if err != nil {
89+
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing `%s`", networkSecurityGroupResourceName), err)
90+
return
91+
}
92+
93+
results = resp.Items
94+
default:
95+
resp, err := client.ListAllComplete(ctx, commonids.NewSubscriptionID(subscriptionID))
96+
if err != nil {
97+
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("listing `%s`", networkSecurityGroupResourceName), err)
98+
return
99+
}
100+
101+
results = resp.Items
102+
}
103+
104+
stream.Results = func(push func(list.ListResult) bool) {
105+
for _, nsg := range results {
106+
result := request.NewListResult(ctx)
107+
result.DisplayName = pointer.From(nsg.Name)
108+
109+
id, err := networksecuritygroups.ParseNetworkSecurityGroupID(pointer.From(nsg.Id))
110+
if err != nil {
111+
sdk.SetResponseErrorDiagnostic(stream, "parsing Network Security Group ID", err)
112+
return
113+
}
114+
115+
rd := resourceNetworkSecurityGroup().Data(&terraform.InstanceState{})
116+
rd.SetId(id.ID())
117+
118+
if err := resourceNetworkSecurityGroupFlatten(rd, id, &nsg); err != nil {
119+
sdk.SetResponseErrorDiagnostic(stream, fmt.Sprintf("encoding `%s` resource data", networkSecurityGroupResourceName), err)
120+
return
121+
}
122+
123+
tfTypeIdentity, err := rd.TfTypeIdentityState()
124+
if err != nil {
125+
sdk.SetResponseErrorDiagnostic(stream, "converting Identity State", err)
126+
return
127+
}
128+
129+
if err := result.Identity.Set(ctx, *tfTypeIdentity); err != nil {
130+
sdk.SetResponseErrorDiagnostic(stream, "setting Identity Data", err)
131+
return
132+
}
133+
134+
tfTypeResourceState, err := rd.TfTypeResourceState()
135+
if err != nil {
136+
sdk.SetResponseErrorDiagnostic(stream, "converting Resource State", err)
137+
return
138+
}
139+
140+
if err := result.Resource.Set(ctx, *tfTypeResourceState); err != nil {
141+
sdk.SetResponseErrorDiagnostic(stream, "setting Resource Data", err)
142+
return
143+
}
144+
145+
if !push(result) {
146+
return
147+
}
148+
}
149+
}
150+
}
151+
152+
func (r *NetworkSecurityGroupListResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) {
153+
r.Defaults(request, response)
154+
}
155+
156+
func (r *NetworkSecurityGroupListResource) RawV5Schemas(ctx context.Context, _ list.RawV5SchemaRequest, response *list.RawV5SchemaResponse) {
157+
res := resourceNetworkSecurityGroup()
158+
response.ProtoV5Schema = res.ProtoSchema(ctx)()
159+
response.ProtoV5IdentitySchema = res.ProtoIdentitySchema(ctx)()
160+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package network_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-testing/querycheck"
10+
"github.com/hashicorp/terraform-plugin-testing/tfversion"
11+
"github.com/hashicorp/terraform-provider-azurerm/internal/acceptance"
12+
"github.com/hashicorp/terraform-provider-azurerm/internal/provider/framework"
13+
)
14+
15+
func TestAccNetworkSecurityGroup_list_basic(t *testing.T) {
16+
r := NetworkSecurityGroupResource{}
17+
18+
data := acceptance.BuildTestData(t, "azurerm_network_security_group", "test1")
19+
20+
resource.Test(t, resource.TestCase{
21+
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
22+
tfversion.SkipBelow(tfversion.Version1_14_0),
23+
},
24+
ProtoV5ProviderFactories: framework.ProtoV5ProviderFactoriesInit(context.Background(), "azurerm"),
25+
Steps: []resource.TestStep{
26+
{
27+
Config: r.basicList(data),
28+
},
29+
{
30+
Query: true,
31+
Config: r.basicListQuery(data),
32+
ConfigQueryChecks: []querycheck.QueryCheck{}, // TODO
33+
},
34+
},
35+
})
36+
}
37+
38+
func (r NetworkSecurityGroupResource) basicList(data acceptance.TestData) string {
39+
return fmt.Sprintf(`
40+
provider "azurerm" {
41+
features {}
42+
}
43+
44+
resource "azurerm_resource_group" "test" {
45+
name = "acctestRG-%[1]d"
46+
location = "%[2]s"
47+
}
48+
49+
resource "azurerm_network_security_group" "test1" {
50+
name = "acctestNSG1-%[1]d"
51+
location = azurerm_resource_group.test.location
52+
resource_group_name = azurerm_resource_group.test.name
53+
}
54+
55+
resource "azurerm_network_security_group" "tes2" {
56+
name = "acctestNSG2-%[1]d"
57+
location = azurerm_resource_group.test.location
58+
resource_group_name = azurerm_resource_group.test.name
59+
}
60+
61+
resource "azurerm_network_security_group" "test3" {
62+
name = "acctestNSG3-%[1]d"
63+
location = azurerm_resource_group.test.location
64+
resource_group_name = azurerm_resource_group.test.name
65+
}
66+
`, data.RandomInteger, data.Locations.Primary)
67+
}
68+
69+
func (r NetworkSecurityGroupResource) basicListQuery(data acceptance.TestData) string {
70+
return fmt.Sprintf(`
71+
list "azurerm_network_security_group" "list" {
72+
provider = azurerm
73+
config {
74+
resource_group_name = "acctestRG-%[1]d"
75+
}
76+
}
77+
`, data.RandomInteger)
78+
}

internal/services/network/network_security_group_resource.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,18 +300,26 @@ func resourceNetworkSecurityGroupRead(d *pluginsdk.ResourceData, meta interface{
300300
return fmt.Errorf("retrieving %s: %+v", id, err)
301301
}
302302

303+
if err := resourceNetworkSecurityGroupFlatten(d, id, resp.Model); err != nil {
304+
return fmt.Errorf("flattening %s: %+v", id, err)
305+
}
306+
307+
return nil
308+
}
309+
310+
func resourceNetworkSecurityGroupFlatten(d *pluginsdk.ResourceData, id *networksecuritygroups.NetworkSecurityGroupId, nsg *networksecuritygroups.NetworkSecurityGroup) error {
303311
d.Set("name", id.NetworkSecurityGroupName)
304312
d.Set("resource_group_name", id.ResourceGroupName)
305313

306-
if model := resp.Model; model != nil {
307-
d.Set("location", location.NormalizeNilable(model.Location))
308-
if props := model.Properties; props != nil {
314+
if nsg != nil {
315+
d.Set("location", location.NormalizeNilable(nsg.Location))
316+
if props := nsg.Properties; props != nil {
309317
flattenedRules := flattenNetworkSecurityRules(props.SecurityRules)
310318
if err := d.Set("security_rule", flattenedRules); err != nil {
311319
return fmt.Errorf("setting `security_rule`: %+v", err)
312320
}
313321
}
314-
if err := tags.FlattenAndSet(d, model.Tags); err != nil {
322+
if err := tags.FlattenAndSet(d, nsg.Tags); err != nil {
315323
return err
316324
}
317325
}

internal/services/network/network_security_group_resource_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func TestAccNetworkSecurityGroup_applicationSecurityGroup(t *testing.T) {
192192
})
193193
}
194194

195-
func (t NetworkSecurityGroupResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
195+
func (r NetworkSecurityGroupResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) {
196196
id, err := networksecuritygroups.ParseNetworkSecurityGroupID(state.ID)
197197
if err != nil {
198198
return nil, err

internal/services/network/registration.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ func (r Registration) Actions() []func() action.Action {
200200

201201
func (r Registration) ListResources() []func() list.ListResource {
202202
return []func() list.ListResource{
203+
NewNetworkSecurityGroupListResource,
203204
NewVirtualNetworkListResource,
204205
}
205206
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
subcategory: "Network"
3+
layout: "azurerm"
4+
page_title: "Azure Resource Manager: azurerm_network_security_group"
5+
description: |-
6+
Lists Network Security Group resources.
7+
---
8+
9+
# List resource: azurerm_network_security_group
10+
11+
~> **Note:** The `azurerm_network_security_group` List Resource is in beta. Its interface and behaviour may change as the feature evolves, and breaking changes are possible. It is offered as a technical preview without compatibility guarantees until Terraform 1.14 is generally available.
12+
13+
Lists Network Security Group resources.
14+
15+
## Example Usage
16+
17+
### List all Network Security Groups in the subscription
18+
19+
```hcl
20+
list "azurerm_network_security_group" "example" {
21+
provider = azurerm
22+
config {}
23+
}
24+
```
25+
26+
### List all Network Security Groups in a specific resource group
27+
28+
```hcl
29+
list "azurerm_network_security_group" "example" {
30+
provider = azurerm
31+
config {
32+
resource_group_name = "example-rg"
33+
}
34+
}
35+
```
36+
37+
## Argument Reference
38+
39+
This list resource supports the following arguments:
40+
41+
* `resource_group_name` - (Optional) The name of the resource group to query.
42+
43+
* `subscription_id` - (Optional) The Subscription ID to query. Defaults to the value specified in the Provider Configuration.

0 commit comments

Comments
 (0)