Skip to content

Commit 30f9713

Browse files
authored
add sweeper resources scan (#2490)
* add sweeper resources scan * update file common function * add log * update log print * update file generate path * update sweeper resource scan dir * generate csv file add Classification * delete cloud_common file * optimization add scanning resources * add scanning some resources * fix DescribeTargetGroups request Filters param * optimize Filters logic * update add scanning resources logic * csv file add CreationDuration * added handling of non-keep resources * add e2e scanning resources * update csv file title * update NonKeepResourceScanHeader * add err log print
1 parent 126bedc commit 30f9713

32 files changed

+732
-8
lines changed

tencentcloud/common/file_common.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package common
2+
3+
import (
4+
"encoding/csv"
5+
"log"
6+
"os"
7+
"path/filepath"
8+
"time"
9+
)
10+
11+
const (
12+
SweeperResourceScanDir = "../../../tmp/resource_scan/"
13+
SweeperNonKeepResourceScanDir = "../../../tmp/non_keep_resource_scan/"
14+
)
15+
16+
var ResourceScanHeader = []string{"资源类型", "资源名称", "实例ID", "实例名称", "分类", "创建时长(天)"}
17+
var NonKeepResourceScanHeader = []string{"ResourceType", "ResourceName", "InstanceId", "InstanceName"}
18+
19+
// WriteCsvFileData write data to csv file
20+
func WriteCsvFileData(dirPath string, header []string, data [][]string) error {
21+
log.Printf("[INFO] write csv file data[%v] to path[%v] start", len(data), dirPath)
22+
23+
count := 0
24+
defer func() {
25+
log.Printf("[INFO] write csv file data to path[%v] success count[%v]", dirPath, count)
26+
}()
27+
28+
if len(data) == 0 {
29+
return nil
30+
}
31+
32+
err := os.MkdirAll(dirPath, 0755)
33+
if err != nil {
34+
log.Printf("[CRITAL] create directory %s error: %v", dirPath, err.Error())
35+
return err
36+
}
37+
38+
currentDate := time.Now().Format("20060102")
39+
filePath := filepath.Join(dirPath, currentDate+".csv")
40+
41+
_, err = os.Stat(filePath)
42+
if os.IsNotExist(err) {
43+
err = GenerateCsvFile(filePath, header)
44+
if err != nil {
45+
log.Printf("[CRITAL] generate csv file error: %v", err.Error())
46+
return err
47+
}
48+
}
49+
50+
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0644)
51+
if err != nil {
52+
log.Printf("[CRITAL] open csv file error: %v", err.Error())
53+
return err
54+
}
55+
defer file.Close()
56+
57+
writer := csv.NewWriter(file)
58+
59+
for _, row := range data {
60+
err = writer.Write(row)
61+
if err != nil {
62+
log.Printf("[CRITAL] write data[%v] to csv file error: %v", row, err.Error())
63+
return err
64+
}
65+
count++
66+
}
67+
writer.Flush()
68+
69+
return nil
70+
}
71+
72+
// GenerateCsvFile generate when csv file does not exist
73+
func GenerateCsvFile(filePath string, header []string) error {
74+
file, err := os.Create(filePath)
75+
if err != nil {
76+
log.Printf("[CRITAL] create csv file error: %v", err.Error())
77+
return err
78+
}
79+
defer file.Close()
80+
81+
writer := csv.NewWriter(file)
82+
err = writer.Write(header)
83+
if err != nil {
84+
log.Printf("[CRITAL] write header to csv file error: %v", err.Error())
85+
return err
86+
}
87+
writer.Flush()
88+
89+
return nil
90+
}

tencentcloud/common/resource_scan.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package common
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"regexp"
7+
"strconv"
8+
"time"
9+
)
10+
11+
const (
12+
KeepResource = "keep"
13+
NonKeepResource = "non-keep"
14+
)
15+
16+
// TimeFormats add all possible time formats
17+
var TimeFormats = []string{
18+
time.RFC3339, //ISO8601 UTC time
19+
"2006-01-02 15:04:05",
20+
// add other time formats here
21+
}
22+
23+
type ResourceInstance struct {
24+
Id string
25+
Name string
26+
CreatTime string
27+
DefaultKeep bool
28+
}
29+
30+
func ProcessScanCloudResources(resources, nonKeepResources []*ResourceInstance, resourceType, resourceName string) {
31+
ProcessResources(resources, resourceType, resourceName)
32+
33+
ProcessNonKeepResources(nonKeepResources, resourceType, resourceName)
34+
}
35+
36+
// ProcessResources Process all scanned cloud resources
37+
func ProcessResources(resources []*ResourceInstance, resourceType, resourceName string) {
38+
data := make([][]string, len(resources))
39+
for i, r := range resources {
40+
isResourceKeep := CheckResourceNameKeep(r.Name)
41+
// some resources default to keep
42+
if r.DefaultKeep {
43+
isResourceKeep = KeepResource
44+
}
45+
46+
creationDuration, err := DaysSinceCreation(r.CreatTime)
47+
if err != nil {
48+
log.Printf("[CRITAL] compute resource creation duration error: %v", err.Error())
49+
}
50+
51+
data[i] = []string{
52+
resourceType,
53+
resourceName,
54+
r.Id,
55+
r.Name,
56+
isResourceKeep,
57+
creationDuration,
58+
}
59+
}
60+
err := WriteCsvFileData(SweeperResourceScanDir, ResourceScanHeader, data)
61+
if err != nil {
62+
log.Printf("[CRITAL] write csv file data error: %v", err.Error())
63+
}
64+
}
65+
66+
// ProcessNonKeepResources Processing scanned non-keep cloud resources
67+
func ProcessNonKeepResources(nonKeepResources []*ResourceInstance, resourceType, resourceName string) {
68+
data := make([][]string, len(nonKeepResources))
69+
for i, r := range nonKeepResources {
70+
data[i] = []string{
71+
resourceType,
72+
resourceName,
73+
r.Id,
74+
r.Name,
75+
}
76+
}
77+
err := WriteCsvFileData(SweeperNonKeepResourceScanDir, NonKeepResourceScanHeader, data)
78+
if err != nil {
79+
log.Printf("[CRITAL] write csv file data error: %v", err.Error())
80+
}
81+
}
82+
83+
// CheckResourceNameKeep check whether to keep resource name
84+
func CheckResourceNameKeep(name string) string {
85+
flag := CheckResourcePersist(name, "")
86+
if flag {
87+
return KeepResource
88+
}
89+
return NonKeepResource
90+
}
91+
92+
// CheckResourcePersist check whether to persist resource
93+
func CheckResourcePersist(name, createTime string) bool {
94+
if name == "" && createTime == "" {
95+
return false
96+
}
97+
parsedTime, _ := ParsedTime(createTime)
98+
99+
createdWithin30Minutes := false
100+
if parsedTime != nil {
101+
createdWithin30Minutes = parsedTime.Add(time.Minute * 30).After(time.Now())
102+
}
103+
104+
flag := regexp.MustCompile("^(keep|Default)").MatchString(name)
105+
return flag || createdWithin30Minutes
106+
}
107+
108+
// DaysSinceCreation compute resource creation duration
109+
func DaysSinceCreation(createTime string) (string, error) {
110+
parsedTime, err := ParsedTime(createTime)
111+
if err != nil {
112+
return "", err
113+
}
114+
115+
duration := time.Since(*parsedTime)
116+
days := duration.Hours() / 24
117+
118+
return fmt.Sprintf("%.2f", days), nil
119+
}
120+
121+
// ParsedTime parse time
122+
func ParsedTime(createTime string) (*time.Time, error) {
123+
if createTime == "" {
124+
return nil, nil
125+
}
126+
127+
var parsedTime time.Time
128+
var err error
129+
130+
timestamp, err := strconv.ParseInt(createTime, 10, 64)
131+
if err == nil {
132+
parsedTime = time.Unix(timestamp, 0)
133+
} else {
134+
// try parsing input strings using different time formats
135+
for _, format := range TimeFormats {
136+
parsedTime, err = time.Parse(format, createTime)
137+
if err == nil {
138+
break
139+
}
140+
}
141+
}
142+
143+
if err != nil {
144+
log.Printf("[CRITAL] unable to parse create time[%s]", createTime)
145+
return nil, fmt.Errorf("unable to parse create time: %v", err.Error())
146+
}
147+
return &parsedTime, nil
148+
}

tencentcloud/services/as/resource_tc_as_attachment_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,23 @@ func testSweepAsAttachment(r string) error {
3535
return fmt.Errorf("list scaling group error: %s", err.Error())
3636
}
3737

38+
// add scanning resources
39+
var resources, nonKeepResources []*tccommon.ResourceInstance
40+
for _, v := range scalingGroups {
41+
if !tccommon.CheckResourcePersist(*v.AutoScalingGroupName, *v.CreatedTime) {
42+
nonKeepResources = append(nonKeepResources, &tccommon.ResourceInstance{
43+
Id: *v.AutoScalingGroupId,
44+
Name: *v.AutoScalingGroupName,
45+
})
46+
}
47+
resources = append(resources, &tccommon.ResourceInstance{
48+
Id: *v.AutoScalingGroupId,
49+
Name: *v.AutoScalingGroupName,
50+
CreatTime: *v.CreatedTime,
51+
})
52+
}
53+
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "as", "attachment")
54+
3855
for _, v := range scalingGroups {
3956
scalingGroupId := *v.AutoScalingGroupId
4057
scalingGroupName := *v.AutoScalingGroupName

tencentcloud/services/cam/resource_tc_cam_group_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"log"
7+
"strconv"
78
"testing"
89

910
tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest"
@@ -33,6 +34,24 @@ func init() {
3334
if err != nil {
3435
return err
3536
}
37+
38+
// add scanning resources
39+
var resources, nonKeepResources []*tccommon.ResourceInstance
40+
for _, v := range groups {
41+
if !tccommon.CheckResourcePersist(*v.GroupName, *v.CreateTime) {
42+
nonKeepResources = append(nonKeepResources, &tccommon.ResourceInstance{
43+
Id: strconv.FormatUint(*v.GroupId, 10),
44+
Name: *v.GroupName,
45+
})
46+
}
47+
resources = append(resources, &tccommon.ResourceInstance{
48+
Id: strconv.FormatUint(*v.GroupId, 10),
49+
Name: *v.GroupName,
50+
CreatTime: *v.CreateTime,
51+
})
52+
}
53+
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "cam", "group")
54+
3655
for _, v := range groups {
3756
name := *v.GroupName
3857

tencentcloud/services/cbs/resource_tc_cbs_storage_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,27 @@ func init() {
2727
service := localcbs.NewCbsService(client)
2828

2929
disks, err := service.DescribeDisksByFilter(ctx, nil)
30-
3130
if err != nil {
3231
return err
3332
}
3433

34+
// add scanning resources
35+
var resources, nonKeepResources []*tccommon.ResourceInstance
36+
for _, v := range disks {
37+
if !tccommon.CheckResourcePersist(*v.DiskName, *v.CreateTime) {
38+
nonKeepResources = append(nonKeepResources, &tccommon.ResourceInstance{
39+
Id: *v.DiskId,
40+
Name: *v.DiskName,
41+
})
42+
}
43+
resources = append(resources, &tccommon.ResourceInstance{
44+
Id: *v.DiskId,
45+
Name: *v.DiskName,
46+
CreatTime: *v.CreateTime,
47+
})
48+
}
49+
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "cbs", "storage")
50+
3551
for i := range disks {
3652
disk := disks[i]
3753
id := *disk.DiskId

tencentcloud/services/ccn/resource_tc_ccn_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ func testSweepCcnInstance(region string) error {
4141
return fmt.Errorf("get instance list error: %s", err.Error())
4242
}
4343

44+
// add scanning resources
45+
var resources, nonKeepResources []*tccommon.ResourceInstance
46+
for _, v := range instances {
47+
if !tccommon.CheckResourcePersist(v.Name(), v.CreateTime()) {
48+
nonKeepResources = append(nonKeepResources, &tccommon.ResourceInstance{
49+
Id: v.CcnId(),
50+
Name: v.Name(),
51+
})
52+
}
53+
resources = append(resources, &tccommon.ResourceInstance{
54+
Id: v.CcnId(),
55+
Name: v.Name(),
56+
CreatTime: v.CreateTime(),
57+
})
58+
}
59+
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "ccn", "")
60+
4461
for _, v := range instances {
4562
instanceId := v.CcnId()
4663
instanceName := v.Name()

tencentcloud/services/cdb/resource_tc_mysql_instance_test.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,30 @@ func testSweepMySQLInstance(region string) error {
4747
if err != nil {
4848
return err
4949
}
50+
items := response.Response.Items
5051

51-
if len(response.Response.Items) == 0 {
52+
if len(items) == 0 {
5253
return nil
5354
}
5455

55-
for _, v := range response.Response.Items {
56+
// add scanning resources
57+
var resources, nonKeepResources []*tccommon.ResourceInstance
58+
for _, v := range items {
59+
if !tccommon.CheckResourcePersist(*v.InstanceId, *v.CreateTime) {
60+
nonKeepResources = append(nonKeepResources, &tccommon.ResourceInstance{
61+
Id: *v.InstanceId,
62+
Name: *v.InstanceName,
63+
})
64+
}
65+
resources = append(resources, &tccommon.ResourceInstance{
66+
Id: *v.InstanceId,
67+
Name: *v.InstanceName,
68+
CreatTime: *v.CreateTime,
69+
})
70+
}
71+
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "msql", "instance")
72+
73+
for _, v := range items {
5674
id := *v.InstanceId
5775
name := *v.InstanceName
5876
if tcacctest.IsResourcePersist(name, nil) {

0 commit comments

Comments
 (0)