Skip to content

Commit

Permalink
datasource/alicloud_security_groups: Adds three internal parameters c…
Browse files Browse the repository at this point in the history
…urrent_pagepage_size total_count to support paging
  • Loading branch information
thisnihonglei authored and xiaozhu36 committed Jan 27, 2022
1 parent cc43ae1 commit e9e4bbb
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 96 deletions.
238 changes: 142 additions & 96 deletions alicloud/data_source_alicloud_security_groups.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
package alicloud

import (
"regexp"

"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"fmt"
"github.com/PaesslerAG/jsonpath"
util "github.com/alibabacloud-go/tea-utils/service"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"regexp"
"time"
)

type SecurityGroup struct {
Attributes ecs.DescribeSecurityGroupAttributeResponse
CreationTime string
SecurityGroupType string
ResourceGroupId string
Tags ecs.TagsInDescribeSecurityGroups
}

func dataSourceAlicloudSecurityGroups() *schema.Resource {
return &schema.Resource{
Read: dataSourceAlicloudSecurityGroupsRead,
Expand All @@ -41,6 +35,15 @@ func dataSourceAlicloudSecurityGroups() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"page_number": {
Type: schema.TypeInt,
Optional: true,
},
"page_size": {
Type: schema.TypeInt,
Optional: true,
Default: 50,
},
"tags": tagsSchema(),
"ids": {
Type: schema.TypeList,
Expand Down Expand Up @@ -95,141 +98,184 @@ func dataSourceAlicloudSecurityGroups() *schema.Resource {
},
},
},
"enable_details": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"total_count": {
Type: schema.TypeInt,
Computed: true,
},
},
}
}

func dataSourceAlicloudSecurityGroupsRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ecsService := EcsService{client}

request := ecs.CreateDescribeSecurityGroupsRequest()
request.RegionId = client.RegionId
request.VpcId = d.Get("vpc_id").(string)
request.PageNumber = requests.NewInteger(1)
request.PageSize = requests.NewInteger(PageSizeLarge)
request.ResourceGroupId = d.Get("resource_group_id").(string)
var sg []SecurityGroup
var nameRegex *regexp.Regexp
if v, ok := d.GetOk("name_regex"); ok {
if r, err := regexp.Compile(v.(string)); err == nil {
nameRegex = r
}

action := "DescribeSecurityGroups"
conn, err := client.NewEcsClient()
if err != nil {
return WrapError(err)
}
if v, ok := d.GetOk("tags"); ok {
var tags []ecs.DescribeSecurityGroupsTag
request := make(map[string]interface{})

for key, value := range v.(map[string]interface{}) {
tags = append(tags, ecs.DescribeSecurityGroupsTag{
Key: key,
Value: value.(string),
})
if v, ok := d.GetOk("page_number"); ok && v.(int) > 0 {
request["PageNumber"] = v.(int)
} else {
request["PageNumber"] = 1
}
if v, ok := d.GetOk("page_size"); ok && v.(int) > 0 {
request["PageSize"] = v.(int)
} else {
request["PageSize"] = PageSizeLarge
}

var objects []interface{}
var securityGroupNameRegex *regexp.Regexp
if v, ok := d.GetOk("name_regex"); ok {
r, err := regexp.Compile(v.(string))
if err != nil {
return WrapError(err)
}
request.Tag = &tags
securityGroupNameRegex = r
}

// ids
idsMap := make(map[string]string)
if v, ok := d.GetOk("ids"); ok {
for _, vv := range v.([]interface{}) {
if vv == nil {
continue
}
idsMap[Trim(vv.(string))] = Trim(vv.(string))
idsMap[vv.(string)] = vv.(string)
}
}

if v, ok := d.GetOk("tags"); ok {
tags := make([]map[string]interface{}, 0)
for key, value := range v.(map[string]interface{}) {
tags = append(tags, map[string]interface{}{
"Key": key,
"Value": value.(string),
})
}
request["Tag"] = tags
}

request["RegionId"] = client.RegionId
if v, ok := d.GetOk("vpc_id"); ok {
request["VpcId"] = v
}
if v, ok := d.GetOk("resource_group_id"); ok {
request["ResourceGroupId"] = v
}
if v, ok := d.GetOk("security_group_name"); ok {
request["SecurityGroupName"] = v
}

var response map[string]interface{}
for {
raw, err := client.WithEcsClient(func(ecsClient *ecs.Client) (interface{}, error) {
return ecsClient.DescribeSecurityGroups(request)
runtime := util.RuntimeOptions{}
runtime.SetAutoretry(true)
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2014-05-26"), StringPointer("AK"), nil, request, &runtime)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
addDebug(action, response, request)
resp, err := jsonpath.Get("$.SecurityGroups.SecurityGroup", response)
if err != nil {
return WrapErrorf(err, DataDefaultErrorMsg, "security_groups", request.GetActionName(), AlibabaCloudSdkGoERROR)
return WrapErrorf(err, FailedGetAttributeMsg, action, "$.SecurityGroups.SecurityGroup", response)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ecs.DescribeSecurityGroupsResponse)
if len(response.SecurityGroups.SecurityGroup) < 1 {
result, _ := resp.([]interface{})
if isPagingRequest(d) {
objects = result
break
}

for _, item := range response.SecurityGroups.SecurityGroup {
if nameRegex != nil {
if !nameRegex.MatchString(item.SecurityGroupName) {
for _, v := range result {
item := v.(map[string]interface{})
if securityGroupNameRegex != nil {
if !securityGroupNameRegex.MatchString(fmt.Sprint(item["SecurityGroupName"])) {
continue
}
}

if len(idsMap) > 0 {
if _, ok := idsMap[item.SecurityGroupId]; !ok {
if _, ok := idsMap[fmt.Sprint(item["SecurityGroupId"])]; !ok {
continue
}
}

attr, err := ecsService.DescribeSecurityGroup(item.SecurityGroupId)
if err != nil {
return WrapError(err)
}

sg = append(sg,
SecurityGroup{
Attributes: attr,
CreationTime: item.CreationTime,
SecurityGroupType: item.SecurityGroupType,
ResourceGroupId: item.ResourceGroupId,
Tags: item.Tags,
},
)
objects = append(objects, item)
}

if len(response.SecurityGroups.SecurityGroup) < PageSizeLarge {
if len(result) < request["PageSize"].(int) {
break
}

if page, err := getNextpageNumber(request.PageNumber); err != nil {
return WrapError(err)
} else {
request.PageNumber = page
}
request["PageNumber"] = request["PageNumber"].(int) + 1
}
return securityGroupsDescription(d, sg, meta)
}

func securityGroupsDescription(d *schema.ResourceData, sg []SecurityGroup, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ecsService := EcsService{client}
var ids []string
var names []string
var s []map[string]interface{}

for _, item := range sg {
ids := make([]string, 0)
names := make([]interface{}, 0)
s := make([]map[string]interface{}, 0)
for _, v := range objects {
object := v.(map[string]interface{})
mapping := map[string]interface{}{
"id": item.Attributes.SecurityGroupId,
"name": item.Attributes.SecurityGroupName,
"description": item.Attributes.Description,
"vpc_id": item.Attributes.VpcId,
"resource_group_id": item.ResourceGroupId,
"security_group_type": item.SecurityGroupType,
"inner_access": item.Attributes.InnerAccessPolicy == string(GroupInnerAccept),
"creation_time": item.CreationTime,
"tags": ecsService.tagsToMap(item.Tags.Tag),
"id": object["SecurityGroupId"],
"name": object["SecurityGroupName"],
"description": object["Description"],
"vpc_id": object["VpcId"],
"resource_group_id": object["ResourceGroupId"],
"security_group_type": object["SecurityGroupType"],
"creation_time": object["CreationTime"],
}

ids = append(ids, string(item.Attributes.SecurityGroupId))
names = append(names, item.Attributes.SecurityGroupName)
tags := make(map[string]interface{})
t, _ := jsonpath.Get("$.Tags.Tag", object)
if t != nil {
for _, t := range t.([]interface{}) {
key := t.(map[string]interface{})["TagKey"].(string)
value := t.(map[string]interface{})["TagValue"].(string)
if !ignoredTags(key, value) {
tags[key] = value
}
}
}
mapping["tags"] = tags

if d.Get("enable_details").(bool) {
ecsService := EcsService{client}
id := fmt.Sprint(object["SecurityGroupId"])
getResp, err := ecsService.DescribeSecurityGroupAttribute(id)
if err != nil {
return WrapError(err)
}
mapping["inner_access"] = getResp["InnerAccessPolicy"] == string(GroupInnerAccept)
}
ids = append(ids, fmt.Sprint(object["SecurityGroupId"]))
names = append(names, object["SecurityGroupName"])
s = append(s, mapping)
}

d.SetId(dataResourceIdHash(ids))
if err := d.Set("groups", s); err != nil {
if err := d.Set("ids", ids); err != nil {
return WrapError(err)
}

if err := d.Set("names", names); err != nil {
return WrapError(err)
}
if err := d.Set("ids", ids); err != nil {

if err := d.Set("groups", s); err != nil {
return WrapError(err)
}
if err := d.Set("total_count", formatInt(response["TotalCount"])); err != nil {
return WrapError(err)
}
// create a json file in current directory and write data source to it
if output, ok := d.GetOk("output_file"); ok && output.(string) != "" {
writeToFile(output.(string), s)
}
Expand Down
1 change: 1 addition & 0 deletions alicloud/data_source_alicloud_security_groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ var existSecurityGroupsMapFunc = func(rand int) map[string]string {
"ids.#": "1",
"names.#": "1",
"groups.#": "1",
"total_count": CHECKSET,
"groups.0.vpc_id": CHECKSET,
"groups.0.resource_group_id": os.Getenv("ALICLOUD_RESOURCE_GROUP_ID"),
"groups.0.security_group_type": "normal",
Expand Down
44 changes: 44 additions & 0 deletions alicloud/service_alicloud_ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,50 @@ func (s *EcsService) DescribeSecurityGroup(id string) (group ecs.DescribeSecurit
return *response, nil
}

func (s *EcsService) DescribeSecurityGroupAttribute(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
conn, err := s.client.NewEcsClient()
if err != nil {
return nil, WrapError(err)
}
action := "DescribeSecurityGroupAttribute"
request := map[string]interface{}{
"RegionId": s.client.RegionId,
"SecurityGroupId": id,
}
runtime := util.RuntimeOptions{}
runtime.SetAutoretry(true)
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2014-05-26"), StringPointer("AK"), nil, request, &runtime)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
addDebug(action, response, request)
return nil
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidSecurityGroupId.NotFound"}) {
return object, WrapErrorf(Error(GetNotFoundMessage("ECS:SecurityGroup", id)), NotFoundMsg, ProviderERROR, fmt.Sprint(response["RequestId"]))
}
return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR)
}
v, err := jsonpath.Get("$", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$", response)
}
if v.(map[string]interface{})["SecurityGroupId"] != id {
err = WrapErrorf(Error(GetNotFoundMessage("Security Group", id)), NotFoundMsg, ProviderERROR, fmt.Sprint(response["RequestId"]))
return
}
object = v.(map[string]interface{})
return object, nil
}

func (s *EcsService) DescribeSecurityGroupRule(id string) (rule ecs.Permission, err error) {
parts, err := ParseResourceId(id, 8)
if err != nil {
Expand Down

0 comments on commit e9e4bbb

Please sign in to comment.