-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(vpc): add networking rules data source (#3930)
- Loading branch information
1 parent
c3e4ca2
commit a240974
Showing
5 changed files
with
385 additions
and
3 deletions.
There are no files selected for viewing
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,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. |
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
107 changes: 107 additions & 0 deletions
107
...eicloud/services/acceptance/vpc/data_source_huaweicloud_networking_secgroup_rules_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,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) | ||
} |
181 changes: 181 additions & 0 deletions
181
huaweicloud/services/vpc/data_source_huaweicloud_networking_secgroup_rules.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,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 | ||
} |
Oops, something went wrong.