Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions collector/hws/collector/vpc/securitygroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import (
"github.com/core-sdk/constant"
"github.com/core-sdk/log"
"github.com/core-sdk/schema"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v3/model"
vpc "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v3"
vpcModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v3/model"
"go.uber.org/zap"
)

Expand All @@ -42,13 +43,16 @@ func GetSecurityGroupResource() schema.Resource {
}

type SecurityGroupDetail struct {
SecurityGroup model.SecurityGroup
Region string
SecurityGroup vpcModel.SecurityGroup
SecurityGroupDetail *vpcModel.SecurityGroupInfo
}

func GetSecurityGroupDetail(ctx context.Context, service schema.ServiceInterface, res chan<- any) error {
cli := service.(*collector.Services).VPC
services := service.(*collector.Services)
cli := services.VPC

request := &model.ListSecurityGroupsRequest{}
request := &vpcModel.ListSecurityGroupsRequest{}
for {
response, err := cli.ListSecurityGroups(request)
if err != nil {
Expand All @@ -58,7 +62,9 @@ func GetSecurityGroupDetail(ctx context.Context, service schema.ServiceInterface

for _, securityGroup := range *response.SecurityGroups {
res <- &SecurityGroupDetail{
Region: services.Region,
SecurityGroup: securityGroup,
SecurityGroupDetail: getSecurityGroupRules(ctx, securityGroup, cli),
}
}
Comment on lines 63 to 69
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation fetches security group details sequentially for each security group within this loop. This will result in poor performance, especially when dealing with a large number of security groups (a classic N+1 query problem). To improve efficiency, these API calls should be performed concurrently.

I suggest using goroutines to parallelize the fetching of security group details. To prevent overwhelming the API endpoint, it's also a good practice to use a semaphore to limit the number of concurrent requests.

Note: You will need to add import "sync" to the file for this suggestion to work.

        var wg sync.WaitGroup
		// Using a semaphore to limit concurrency to avoid overwhelming the API endpoint.
		// The limit of 10 is an example and might need tuning based on API rate limits.
		sem := make(chan struct{}, 10)

		for _, securityGroup := range *response.SecurityGroups {
			wg.Add(1)
			go func(sg vpcModel.SecurityGroup) {
				defer wg.Done()
				sem <- struct{}{}        // Acquire a token
				defer func() { <-sem }() // Release the token

				res <- &SecurityGroupDetail{
					Region:              services.Region,
					SecurityGroup:       sg,
					SecurityGroupDetail: getSecurityGroupRules(ctx, sg, cli),
				}
			}(securityGroup)
		}
		wg.Wait()


Expand All @@ -72,3 +78,14 @@ func GetSecurityGroupDetail(ctx context.Context, service schema.ServiceInterface
}
return nil
}

func getSecurityGroupRules(ctx context.Context, securityGroup vpcModel.SecurityGroup, client *vpc.VpcClient) *vpcModel.SecurityGroupInfo {
request := &vpcModel.ShowSecurityGroupRequest{}
request.SecurityGroupId = securityGroup.Id
response, err := client.ShowSecurityGroup(request)
if err != nil {
log.CtxLogger(ctx).Warn("get SecurityGroup error", zap.Error(err))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The log message "get SecurityGroup error" is a bit generic. For better traceability and debugging, it would be helpful to include the ID of the security group for which the operation failed.

        log.CtxLogger(ctx).Warn("failed to get details for security group", zap.String("security_group_id", securityGroup.Id), zap.Error(err))

return nil
}
return response.SecurityGroup
}
Loading