Skip to content

Commit 1d8821a

Browse files
gitmknanonymous
andauthored
feat: support security group (#1914)
* feat: support security group * feat: add changelog --------- Co-authored-by: anonymous <anonymous@mail.org>
1 parent 1e00f1c commit 1d8821a

File tree

7 files changed

+392
-0
lines changed

7 files changed

+392
-0
lines changed

.changelog/1914.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:new-resource
2+
tencentcloud_redis_security_group_attachment
3+
```

tencentcloud/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ TencentDB for Redis(crs)
735735
tencentcloud_redis_switch_master
736736
tencentcloud_redis_replicate_attachment
737737
tencentcloud_redis_backup_operation
738+
tencentcloud_redis_security_group_attachment
738739
739740
Serverless Cloud Function(SCF)
740741
Data Source
@@ -2326,6 +2327,7 @@ func Provider() *schema.Provider {
23262327
"tencentcloud_redis_switch_master": resourceTencentCloudRedisSwitchMaster(),
23272328
"tencentcloud_redis_replicate_attachment": resourceTencentCloudRedisReplicateAttachment(),
23282329
"tencentcloud_redis_backup_operation": resourceTencentCloudRedisBackupOperation(),
2330+
"tencentcloud_redis_security_group_attachment": resourceTencentCloudRedisSecurityGroupAttachment(),
23292331
"tencentcloud_as_load_balancer": resourceTencentCloudAsLoadBalancer(),
23302332
"tencentcloud_as_scaling_config": resourceTencentCloudAsScalingConfig(),
23312333
"tencentcloud_as_scaling_group": resourceTencentCloudAsScalingGroup(),
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
Provides a resource to create a redis security_group_attachment
3+
4+
Example Usage
5+
6+
```hcl
7+
resource "tencentcloud_redis_security_group_attachment" "security_group_attachment" {
8+
instance_id = "crs-jf4ico4v"
9+
security_group_id = "sg-edmur627"
10+
}
11+
```
12+
13+
Import
14+
15+
redis security_group_attachment can be imported using the id, e.g.
16+
17+
```
18+
terraform import tencentcloud_redis_security_group_attachment.security_group_attachment instance_id#security_group_id
19+
```
20+
*/
21+
package tencentcloud
22+
23+
import (
24+
"context"
25+
"fmt"
26+
"log"
27+
"strings"
28+
29+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
30+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
31+
redis "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/redis/v20180412"
32+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
33+
)
34+
35+
const PRODUCT string = "redis"
36+
37+
func resourceTencentCloudRedisSecurityGroupAttachment() *schema.Resource {
38+
return &schema.Resource{
39+
Create: resourceTencentCloudRedisSecurityGroupAttachmentCreate,
40+
Read: resourceTencentCloudRedisSecurityGroupAttachmentRead,
41+
Delete: resourceTencentCloudRedisSecurityGroupAttachmentDelete,
42+
Importer: &schema.ResourceImporter{
43+
State: schema.ImportStatePassthrough,
44+
},
45+
Schema: map[string]*schema.Schema{
46+
"instance_id": {
47+
Required: true,
48+
ForceNew: true,
49+
Type: schema.TypeString,
50+
Description: "Instance ID.",
51+
},
52+
53+
"security_group_id": {
54+
Required: true,
55+
ForceNew: true,
56+
Type: schema.TypeString,
57+
Description: "Security group ID.",
58+
},
59+
},
60+
}
61+
}
62+
63+
func resourceTencentCloudRedisSecurityGroupAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
64+
defer logElapsed("resource.tencentcloud_redis_security_group_attachment.create")()
65+
defer inconsistentCheck(d, meta)()
66+
67+
logId := getLogId(contextNil)
68+
69+
var (
70+
request = redis.NewAssociateSecurityGroupsRequest()
71+
securityGroupId string
72+
instanceId string
73+
)
74+
request.Product = helper.String(PRODUCT)
75+
76+
if v, ok := d.GetOk("instance_id"); ok {
77+
instanceId = v.(string)
78+
request.InstanceIds = append(request.InstanceIds, &instanceId)
79+
}
80+
81+
if v, ok := d.GetOk("security_group_id"); ok {
82+
securityGroupId = v.(string)
83+
request.SecurityGroupId = helper.String(v.(string))
84+
}
85+
86+
err := resource.Retry(writeRetryTimeout, func() *resource.RetryError {
87+
result, e := meta.(*TencentCloudClient).apiV3Conn.UseRedisClient().AssociateSecurityGroups(request)
88+
if e != nil {
89+
return retryError(e)
90+
} else {
91+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString())
92+
}
93+
return nil
94+
})
95+
if err != nil {
96+
log.Printf("[CRITAL]%s create redis securityGroupAttachment failed, reason:%+v", logId, err)
97+
return err
98+
}
99+
100+
d.SetId(instanceId + FILED_SP + securityGroupId)
101+
102+
return resourceTencentCloudRedisSecurityGroupAttachmentRead(d, meta)
103+
}
104+
105+
func resourceTencentCloudRedisSecurityGroupAttachmentRead(d *schema.ResourceData, meta interface{}) error {
106+
defer logElapsed("resource.tencentcloud_redis_security_group_attachment.read")()
107+
defer inconsistentCheck(d, meta)()
108+
109+
logId := getLogId(contextNil)
110+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
111+
112+
service := RedisService{client: meta.(*TencentCloudClient).apiV3Conn}
113+
114+
idSplit := strings.Split(d.Id(), FILED_SP)
115+
if len(idSplit) != 2 {
116+
return fmt.Errorf("id is broken,%s", d.Id())
117+
}
118+
instanceId := idSplit[0]
119+
securityGroupId := idSplit[1]
120+
121+
securityGroupAttachment, err := service.DescribeRedisSecurityGroupAttachmentById(ctx, PRODUCT, instanceId, securityGroupId)
122+
if err != nil {
123+
return err
124+
}
125+
126+
if securityGroupAttachment == nil {
127+
d.SetId("")
128+
log.Printf("[WARN]%s resource `RedisSecurityGroupAttachment` [%s] not found, please check if it has been deleted.\n", logId, d.Id())
129+
return nil
130+
}
131+
132+
_ = d.Set("instance_id", instanceId)
133+
134+
if securityGroupAttachment.SecurityGroupId != nil {
135+
_ = d.Set("security_group_id", securityGroupAttachment.SecurityGroupId)
136+
}
137+
138+
return nil
139+
}
140+
141+
func resourceTencentCloudRedisSecurityGroupAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
142+
defer logElapsed("resource.tencentcloud_redis_security_group_attachment.delete")()
143+
defer inconsistentCheck(d, meta)()
144+
145+
logId := getLogId(contextNil)
146+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
147+
148+
service := RedisService{client: meta.(*TencentCloudClient).apiV3Conn}
149+
idSplit := strings.Split(d.Id(), FILED_SP)
150+
if len(idSplit) != 2 {
151+
return fmt.Errorf("id is broken,%s", d.Id())
152+
}
153+
instanceId := idSplit[0]
154+
securityGroupId := idSplit[1]
155+
156+
if err := service.DeleteRedisSecurityGroupAttachmentById(ctx, PRODUCT, instanceId, securityGroupId); err != nil {
157+
return err
158+
}
159+
160+
return nil
161+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package tencentcloud
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
"testing"
8+
"time"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
12+
)
13+
14+
// go test -i; go test -test.run TestAccTencentCloudRedisSecurityGroupAttachmentResource_basic -v
15+
func TestAccTencentCloudRedisSecurityGroupAttachmentResource_basic(t *testing.T) {
16+
t.Parallel()
17+
resource.Test(t, resource.TestCase{
18+
PreCheck: func() { testAccPreCheck(t) },
19+
Providers: testAccProviders,
20+
CheckDestroy: testAccTencentCloudRedisSecurityGroupDestroy,
21+
Steps: []resource.TestStep{
22+
{
23+
Config: testAccRedisSecurityGroupAttachment,
24+
Check: resource.ComposeTestCheckFunc(
25+
testAccTencentCloudRedisSecurityGroupExists("tencentcloud_redis_security_group_attachment.security_group_attachment"),
26+
resource.TestCheckResourceAttrSet("tencentcloud_redis_security_group_attachment.security_group_attachment", "id"),
27+
resource.TestCheckResourceAttr("tencentcloud_redis_security_group_attachment.security_group_attachment", "instance_id", defaultCrsInstanceId),
28+
resource.TestCheckResourceAttr("tencentcloud_redis_security_group_attachment.security_group_attachment", "security_group_id", defaultCrsSecurityGroups),
29+
),
30+
},
31+
{
32+
ResourceName: "tencentcloud_redis_security_group_attachment.security_group_attachment",
33+
ImportState: true,
34+
ImportStateVerify: true,
35+
},
36+
},
37+
})
38+
}
39+
40+
func testAccTencentCloudRedisSecurityGroupExists(r string) resource.TestCheckFunc {
41+
return func(s *terraform.State) error {
42+
43+
logId := getLogId(contextNil)
44+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
45+
46+
rs, ok := s.RootModule().Resources[r]
47+
if !ok {
48+
return fmt.Errorf("resource %s is not found", r)
49+
}
50+
51+
items := strings.Split(rs.Primary.ID, FILED_SP)
52+
if len(items) != 2 {
53+
return fmt.Errorf("invalid ID %s", rs.Primary.ID)
54+
}
55+
instanceId := items[0]
56+
securityGroupId := items[1]
57+
58+
service := RedisService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn}
59+
securityGroup, err := service.DescribeRedisSecurityGroupAttachmentById(ctx, PRODUCT, instanceId, securityGroupId)
60+
if err != nil {
61+
return err
62+
}
63+
if securityGroup == nil {
64+
return fmt.Errorf("redis securityGroup %s is not found", rs.Primary.ID)
65+
}
66+
67+
return nil
68+
}
69+
}
70+
71+
func testAccTencentCloudRedisSecurityGroupDestroy(s *terraform.State) error {
72+
logId := getLogId(contextNil)
73+
ctx := context.WithValue(context.TODO(), logIdKey, logId)
74+
75+
service := RedisService{client: testAccProvider.Meta().(*TencentCloudClient).apiV3Conn}
76+
for _, rs := range s.RootModule().Resources {
77+
if rs.Type != "tencentcloud_redis_security_group_attachment" {
78+
continue
79+
}
80+
time.Sleep(5 * time.Second)
81+
82+
items := strings.Split(rs.Primary.ID, FILED_SP)
83+
if len(items) != 2 {
84+
return fmt.Errorf("invalid ID %s", rs.Primary.ID)
85+
}
86+
instanceId := items[0]
87+
securityGroupId := items[1]
88+
89+
securityGroup, err := service.DescribeRedisSecurityGroupAttachmentById(ctx, PRODUCT, instanceId, securityGroupId)
90+
if err != nil {
91+
return err
92+
}
93+
if securityGroup != nil {
94+
return fmt.Errorf("redis securityGroup %s still exists", rs.Primary.ID)
95+
}
96+
}
97+
return nil
98+
}
99+
100+
const testAccRedisSecurityGroupVar = `
101+
variable "instance_id" {
102+
default = "` + defaultCrsInstanceId + `"
103+
}
104+
variable "security_group_id" {
105+
default = "` + defaultCrsSecurityGroups + `"
106+
}
107+
`
108+
109+
const testAccRedisSecurityGroupAttachment = testAccRedisSecurityGroupVar + `
110+
111+
resource "tencentcloud_redis_security_group_attachment" "security_group_attachment" {
112+
instance_id = var.instance_id
113+
security_group_id = var.security_group_id
114+
}
115+
116+
`

tencentcloud/service_tencentcloud_redis.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,3 +1862,65 @@ func (me *RedisService) DeleteRedisReplicateAttachmentById(ctx context.Context,
18621862

18631863
return
18641864
}
1865+
1866+
func (me *RedisService) DescribeRedisSecurityGroupAttachmentById(ctx context.Context, product string, instanceId string, securityGroupId string) (securityGroupAttachment *redis.SecurityGroup, errRet error) {
1867+
logId := getLogId(ctx)
1868+
1869+
request := redis.NewDescribeDBSecurityGroupsRequest()
1870+
request.Product = &product
1871+
request.InstanceId = &instanceId
1872+
1873+
defer func() {
1874+
if errRet != nil {
1875+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error())
1876+
}
1877+
}()
1878+
1879+
ratelimit.Check(request.GetAction())
1880+
1881+
response, err := me.client.UseRedisClient().DescribeDBSecurityGroups(request)
1882+
if err != nil {
1883+
errRet = err
1884+
return
1885+
}
1886+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString())
1887+
1888+
if len(response.Response.Groups) < 1 {
1889+
return
1890+
}
1891+
1892+
for _, v := range response.Response.Groups {
1893+
if *v.SecurityGroupId == securityGroupId {
1894+
securityGroupAttachment = v
1895+
return
1896+
}
1897+
}
1898+
1899+
return
1900+
}
1901+
1902+
func (me *RedisService) DeleteRedisSecurityGroupAttachmentById(ctx context.Context, product string, instanceId string, securityGroupId string) (errRet error) {
1903+
logId := getLogId(ctx)
1904+
1905+
request := redis.NewDisassociateSecurityGroupsRequest()
1906+
request.Product = &product
1907+
request.SecurityGroupId = &securityGroupId
1908+
request.InstanceIds = []*string{&instanceId}
1909+
1910+
defer func() {
1911+
if errRet != nil {
1912+
log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error())
1913+
}
1914+
}()
1915+
1916+
ratelimit.Check(request.GetAction())
1917+
1918+
response, err := me.client.UseRedisClient().DisassociateSecurityGroups(request)
1919+
if err != nil {
1920+
errRet = err
1921+
return
1922+
}
1923+
log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString())
1924+
1925+
return
1926+
}

0 commit comments

Comments
 (0)