Skip to content

Commit

Permalink
feat(vpc): add networking rules data source (#3930)
Browse files Browse the repository at this point in the history
  • Loading branch information
jinyangyang222 authored Jan 3, 2024
1 parent c3e4ca2 commit a240974
Show file tree
Hide file tree
Showing 5 changed files with 385 additions and 3 deletions.
91 changes: 91 additions & 0 deletions docs/data-sources/networking_secgroup_rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
subcategory: "Virtual Private Cloud (VPC)"
---

# huaweicloud_networking_secgroup_rules

Use this data source to get the list of the available HuaweiCloud security group rules.

## Example Usage

```hcl
variable "security_group_id" {}
data "huaweicloud_networking_secgroup_rules" "test" {
security_group_id = var.security_group_id
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional, String) Specifies the region in which to obtain the security group rules. If omitted, the
provider-level region will be used.

* `security_group_id` - (Required, String) Specifies the security group ID that the rule should belong to.

* `rule_id` - (Optional, String) Specifies the security group rule ID used for query.

* `protocol` - (Optional, String) Specifies the security group rule protocol type used for query.
The value can be **tcp**, **udp**, **icmp**, **icmpv6** or IP protocol number, if empty, it indicates support for
all protocols.

* `description` - (Optional, String) Specifies the security group rule description used for query.

* `remote_group_id` - (Optional, String) Specifies the remote security group ID used for query.

* `direction` - (Optional, String) Specifies the direction of the security group rule used for query.
The valid values are as follows:
+ **ingress**
+ **egress**

* `action` - (Optional, String) Specifies the effective policy of the security group rule used for query.
The valid values are as follows:
+ **allow**
+ **deny**

## Attribute Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The data source ID in UUID format.

* `rules` - All security group rules that match the filter parameters.
The [rules](#secgroup_rules) structure is documented below.

<a name="secgroup_rules"></a>
The `rules` block supports:

* `id` - The ID of the security group rule.

* `description` - The description of the security group rule.

* `security_group_id` - The security group ID that the rule should belong to.

* `direction` - The direction of the security group rule.

* `protocol` - The security group rule protocol type.

* `ethertype` - The security group rule IP address protocol type. The value can be **IPv4** or **IPv6**.

* `ports` - The range of port values for security group rule. Which supports single port (80), continuous port (1-30)
and discontinuous port (22, 3389, 80).

* `action` - The effective policy of the security group rule.

* `priority` - The priority of security group rule. The valid value ranges from `1` to `100`, `1` represents the
highest priority.

* `remote_group_id` - The remote security group ID.
This field is mutually exclusive with `remote_ip_prefix` and `remote_address_group_id`.

* `remote_ip_prefix` - The remote IP address. The value can be in the CIDR format or IP addresses.
This field is mutually exclusive with `remote_group_id` and `remote_address_group_id`.

* `remote_address_group_id` - The remote address group ID.
This field is mutually exclusive with `remote_group_id` and `remote_ip_prefix`.

* `created_at` - The creation time, in UTC format.

* `updated_at` - The latest update time, in UTC format.
7 changes: 4 additions & 3 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,10 @@ func Provider() *schema.Provider {
"huaweicloud_nat_private_gateways": nat.DataSourcePrivateGateways(),
"huaweicloud_nat_private_transit_ips": nat.DataSourcePrivateTransitIps(),

"huaweicloud_networking_port": vpc.DataSourceNetworkingPortV2(),
"huaweicloud_networking_secgroup": vpc.DataSourceNetworkingSecGroup(),
"huaweicloud_networking_secgroups": vpc.DataSourceNetworkingSecGroups(),
"huaweicloud_networking_port": vpc.DataSourceNetworkingPortV2(),
"huaweicloud_networking_secgroup": vpc.DataSourceNetworkingSecGroup(),
"huaweicloud_networking_secgroups": vpc.DataSourceNetworkingSecGroups(),
"huaweicloud_networking_secgroup_rules": vpc.DataSourceNetworkingSecGroupRules(),

"huaweicloud_mapreduce_versions": mrs.DataSourceMrsVersions(),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package vpc

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
)

func TestAccNetworkingSecGroupRulesDataSource_basic(t *testing.T) {
var (
dataSourceName = "data.huaweicloud_networking_secgroup_rules.test"
baseConfig = testAccNetworkingSecGroupRulesDataSource_base()
dc = acceptance.InitDataSourceCheck(dataSourceName)
)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acceptance.TestAccPreCheck(t)
},
ProviderFactories: acceptance.TestAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccNetworkingSecGroupRulesDataSource_basic(baseConfig),
Check: resource.ComposeTestCheckFunc(
dc.CheckResourceExists(),
resource.TestCheckOutput("is_rule_id_filter_useful", "true"),
resource.TestCheckOutput("is_direction_filter_useful", "true"),
resource.TestCheckOutput("is_action_filter_useful", "true"),
),
},
},
})
}

func testAccNetworkingSecGroupRulesDataSource_base() string {
name := acceptance.RandomAccResourceNameWithDash()

return fmt.Sprintf(`
resource "huaweicloud_networking_secgroup" "test" {
name = "%s-secgroup"
description = "terraform security group rule acceptance test"
}
resource "huaweicloud_networking_secgroup_rule" "test" {
security_group_id = huaweicloud_networking_secgroup.test.id
description = "description test"
direction = "ingress"
ethertype = "IPv4"
ports = 80
protocol = "tcp"
action = "allow"
remote_ip_prefix = "0.0.0.0/0"
}
`, name)
}

func testAccNetworkingSecGroupRulesDataSource_basic(baseConfig string) string {
return fmt.Sprintf(`
%s
data "huaweicloud_networking_secgroup_rules" "test" {
security_group_id = huaweicloud_networking_secgroup.test.id
}
locals {
rule_id = data.huaweicloud_networking_secgroup_rules.test.rules[0].id
}
data "huaweicloud_networking_secgroup_rules" "rule_id_filter" {
security_group_id = huaweicloud_networking_secgroup.test.id
rule_id = local.rule_id
}
output "is_rule_id_filter_useful" {
value = length(data.huaweicloud_networking_secgroup_rules.rule_id_filter.rules) > 0 && alltrue(
[for v in data.huaweicloud_networking_secgroup_rules.rule_id_filter.rules[*].id : v == local.rule_id]
)
}
locals {
direction = data.huaweicloud_networking_secgroup_rules.test.rules[0].direction
}
data "huaweicloud_networking_secgroup_rules" "direction_filter" {
security_group_id = huaweicloud_networking_secgroup.test.id
direction = local.direction
}
output "is_direction_filter_useful" {
value = length(data.huaweicloud_networking_secgroup_rules.direction_filter.rules) > 0 && alltrue(
[for v in data.huaweicloud_networking_secgroup_rules.direction_filter.rules[*].direction : v == local.direction]
)
}
locals {
action = data.huaweicloud_networking_secgroup_rules.test.rules[0].action
}
data "huaweicloud_networking_secgroup_rules" "action_filter" {
security_group_id = huaweicloud_networking_secgroup.test.id
action = local.action
}
output "is_action_filter_useful" {
value = length(data.huaweicloud_networking_secgroup_rules.action_filter.rules) > 0 && alltrue(
[for v in data.huaweicloud_networking_secgroup_rules.action_filter.rules[*].action : v == local.action]
)
}
`, baseConfig)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package vpc

import (
"context"

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

v3rules "github.com/chnsz/golangsdk/openstack/networking/v3/security/rules"

"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/common"
"github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
)

// API: VPC GET /v3/{project_id}/vpc/security-group-rules
func DataSourceNetworkingSecGroupRules() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceNetworkingSecGroupRulesRead,

Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"security_group_id": {
Type: schema.TypeString,
Required: true,
},
"rule_id": {
Type: schema.TypeString,
Optional: true,
},
"protocol": {
Type: schema.TypeString,
Optional: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
},
"remote_group_id": {
Type: schema.TypeString,
Optional: true,
},
"direction": {
Type: schema.TypeString,
Optional: true,
},
"action": {
Type: schema.TypeString,
Optional: true,
},
"rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"security_group_id": {
Type: schema.TypeString,
Computed: true,
},
"direction": {
Type: schema.TypeString,
Computed: true,
},
"protocol": {
Type: schema.TypeString,
Computed: true,
},
"ethertype": {
Type: schema.TypeString,
Computed: true,
},
"ports": {
Type: schema.TypeString,
Computed: true,
},
"action": {
Type: schema.TypeString,
Computed: true,
},
"priority": {
Type: schema.TypeInt,
Computed: true,
},
"remote_group_id": {
Type: schema.TypeString,
Computed: true,
},
"remote_ip_prefix": {
Type: schema.TypeString,
Computed: true,
},
"remote_address_group_id": {
Type: schema.TypeString,
Computed: true,
},
"created_at": {
Type: schema.TypeString,
Computed: true,
},
"updated_at": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataSourceNetworkingSecGroupRulesRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var (
cfg = meta.(*config.Config)
region = cfg.GetRegion(d)
)
client, err := cfg.NetworkingV3Client(region)
if err != nil {
return diag.Errorf("error creating networking v3 client: %s", err)
}

listOpts := v3rules.ListOpts{
SecurityGroupId: d.Get("security_group_id").(string),
ID: d.Get("rule_id").(string),
Protocol: d.Get("protocol").(string),
Description: d.Get("description").(string),
RemoteGroupId: d.Get("remote_group_id").(string),
Direction: d.Get("direction").(string),
Action: d.Get("action").(string),
}
resp, err := v3rules.List(client, listOpts)
if err != nil {
return common.CheckDeletedDiag(d, err, "Security Group rules")
}
rules := make([]map[string]interface{}, len(resp))
for i, rule := range resp {
ruleInfo := map[string]interface{}{
"id": rule.ID,
"description": rule.Description,
"security_group_id": rule.SecurityGroupId,
"direction": rule.Direction,
"protocol": rule.Protocol,
"ethertype": rule.Ethertype,
"ports": rule.MultiPort,
"action": rule.Action,
"priority": rule.Priority,
"remote_group_id": rule.RemoteGroupId,
"remote_ip_prefix": rule.RemoteIpPrefix,
"remote_address_group_id": rule.RemoteAddressGroupId,
"created_at": rule.CreateAt,
"updated_at": rule.UpdateAt,
}
rules[i] = ruleInfo
}

randUUID, err := uuid.GenerateUUID()
if err != nil {
return diag.Errorf("unable to generate ID: %s", err)
}
d.SetId(randUUID)
mErr := multierror.Append(nil,
d.Set("region", region),
d.Set("rules", rules),
)
if mErr.ErrorOrNil() != nil {
return diag.Errorf("error saving Security Group rules data source fields: %s", mErr)
}
return nil
}
Loading

0 comments on commit a240974

Please sign in to comment.