Skip to content

Commit 36097b8

Browse files
tongyimingmikatong
andauthored
fix(es): [125657314]fix node_info_list update (#3442)
* es update * update * add changelog * change list to set --------- Co-authored-by: mikatong <[email protected]>
1 parent 87bf673 commit 36097b8

File tree

4 files changed

+291
-34
lines changed

4 files changed

+291
-34
lines changed

.changelog/3442.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/tencentcloud_elasticsearch_instance: fix node_info_list update
3+
```

tencentcloud/services/es/resource_tc_elasticsearch_instance.go

Lines changed: 190 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func ResourceTencentCloudElasticsearchInstance() *schema.Resource {
178178
Description: "License type. Valid values are `oss`, `basic` and `platinum`. The default value is `platinum`.",
179179
},
180180
"node_info_list": {
181-
Type: schema.TypeList,
181+
Type: schema.TypeSet,
182182
Required: true,
183183
MinItems: 1,
184184
Description: "Node information list, which is used to describe the specification information of various types of nodes in the cluster, such as node type, node quantity, node specification, disk type, and disk size.",
@@ -346,6 +346,19 @@ func ResourceTencentCloudElasticsearchInstance() *schema.Resource {
346346
Description: "Instance creation time.",
347347
},
348348
},
349+
CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error {
350+
nodeInfos := d.Get("node_info_list").(*schema.Set).List()
351+
typeMap := map[string]bool{}
352+
for _, v := range nodeInfos {
353+
m := v.(map[string]interface{})
354+
t := m["type"].(string)
355+
if typeMap[t] {
356+
return fmt.Errorf("duplicate node type '%s' is not allowed in node_info_list", t)
357+
}
358+
typeMap[t] = true
359+
}
360+
return nil
361+
},
349362
}
350363
}
351364

@@ -428,7 +441,7 @@ func resourceTencentCloudElasticsearchInstanceCreate(d *schema.ResourceData, met
428441
}
429442

430443
if v, ok := d.GetOk("node_info_list"); ok {
431-
infos := v.([]interface{})
444+
infos := v.(*schema.Set).List()
432445
request.NodeInfoList = make([]*es.NodeInfo, 0, len(infos))
433446
for _, item := range infos {
434447
value := item.(map[string]interface{})
@@ -995,39 +1008,155 @@ func resourceTencentCloudElasticsearchInstanceUpdate(d *schema.ResourceData, met
9951008
}
9961009

9971010
if d.HasChange("node_info_list") {
998-
nodeInfos := d.Get("node_info_list").([]interface{})
999-
nodeInfoList := make([]*es.NodeInfo, 0, len(nodeInfos))
1000-
for _, d := range nodeInfos {
1001-
value := d.(map[string]interface{})
1002-
nodeType := value["node_type"].(string)
1003-
diskSize := uint64(value["disk_size"].(int))
1004-
nodeNum := uint64(value["node_num"].(int))
1005-
types := value["type"].(string)
1006-
diskType := value["disk_type"].(string)
1007-
encrypt := value["encrypt"].(bool)
1008-
dataDisk := es.NodeInfo{
1009-
NodeType: &nodeType,
1010-
DiskSize: &diskSize,
1011-
NodeNum: &nodeNum,
1012-
Type: &types,
1013-
DiskType: &diskType,
1014-
DiskEncrypt: helper.BoolToInt64Pointer(encrypt),
1011+
o, n := d.GetChange("node_info_list")
1012+
oldNodeMap := make(map[string]map[string]interface{})
1013+
newNodesMap := make(map[string]map[string]interface{})
1014+
for _, node := range o.(*schema.Set).List() {
1015+
nodeMap := node.(map[string]interface{})
1016+
oldNodeMap[nodeMap["type"].(string)] = nodeMap
1017+
}
1018+
for _, node := range n.(*schema.Set).List() {
1019+
nodeMap := node.(map[string]interface{})
1020+
newNodesMap[nodeMap["type"].(string)] = nodeMap
1021+
}
1022+
1023+
typeList := []string{"hotData", "warmData", "dedicatedMaster"}
1024+
for _, t := range typeList {
1025+
old := oldNodeMap[t]
1026+
new := newNodesMap[t]
1027+
baseNodeList := make([]interface{}, 0)
1028+
for k, v := range oldNodeMap {
1029+
if k == t {
1030+
continue
1031+
}
1032+
baseNodeList = append(baseNodeList, v)
10151033
}
1016-
nodeInfoList = append(nodeInfoList, &dataDisk)
1017-
}
1018-
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1019-
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, nodeInfoList, nil, nil, nil, nil)
1020-
if errRet != nil {
1021-
return tccommon.RetryError(errRet)
1034+
1035+
if old == nil && new == nil {
1036+
// 没有该类型节点配置
1037+
continue
1038+
} else if old == nil {
1039+
// 新增
1040+
baseNodeList = append(baseNodeList, new)
1041+
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1042+
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, convertToNodeInfos(baseNodeList), nil, nil, nil, nil)
1043+
if errRet != nil {
1044+
return tccommon.RetryError(errRet)
1045+
}
1046+
return nil
1047+
})
1048+
if err != nil {
1049+
return err
1050+
}
1051+
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1052+
if err != nil {
1053+
return err
1054+
}
1055+
} else if new == nil {
1056+
// 删除
1057+
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1058+
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, convertToNodeInfos(baseNodeList), nil, nil, nil, nil)
1059+
if errRet != nil {
1060+
return tccommon.RetryError(errRet)
1061+
}
1062+
return nil
1063+
})
1064+
if err != nil {
1065+
return err
1066+
}
1067+
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1068+
if err != nil {
1069+
return err
1070+
}
1071+
} else {
1072+
// 磁盘类型不支持修改
1073+
fields := []string{"disk_type", "encrypt", "type"}
1074+
for _, field := range fields {
1075+
if old[field] != new[field] {
1076+
return fmt.Errorf("%s not support change", field)
1077+
}
1078+
}
1079+
// 修改一种节点的个数
1080+
var isUpdateNodeNum bool
1081+
if old["node_num"].(int) != new["node_num"].(int) {
1082+
changeESNodes := convertToNodeInfos(baseNodeList)
1083+
thisNode := convertToNodeInfo(old)
1084+
thisNode.NodeNum = helper.IntUint64(new["node_num"].(int))
1085+
changeESNodes = append(changeESNodes, thisNode)
1086+
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1087+
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, changeESNodes, nil, nil, nil, nil)
1088+
if errRet != nil {
1089+
return tccommon.RetryError(errRet)
1090+
}
1091+
return nil
1092+
})
1093+
if err != nil {
1094+
return err
1095+
}
1096+
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1097+
if err != nil {
1098+
return err
1099+
}
1100+
isUpdateNodeNum = true
1101+
}
1102+
1103+
var isUpdateNodeType bool
1104+
// 修改一种节点的节点规格
1105+
if old["node_type"].(string) != new["node_type"].(string) {
1106+
changeESNodes := convertToNodeInfos(baseNodeList)
1107+
thisNode := convertToNodeInfo(old)
1108+
thisNode.NodeType = helper.String(new["node_type"].(string))
1109+
if isUpdateNodeNum {
1110+
thisNode.NodeNum = helper.IntUint64(new["node_num"].(int))
1111+
}
1112+
changeESNodes = append(changeESNodes, thisNode)
1113+
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1114+
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, changeESNodes, nil, nil, nil, nil)
1115+
if errRet != nil {
1116+
return tccommon.RetryError(errRet)
1117+
}
1118+
return nil
1119+
})
1120+
if err != nil {
1121+
return err
1122+
}
1123+
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1124+
if err != nil {
1125+
return err
1126+
}
1127+
isUpdateNodeType = true
1128+
}
1129+
// 修改一种节点的磁盘大小
1130+
if old["disk_size"].(int) != new["disk_size"].(int) {
1131+
changeESNodes := convertToNodeInfos(baseNodeList)
1132+
thisNode := convertToNodeInfo(old)
1133+
thisNode.NodeType = helper.String(new["node_type"].(string))
1134+
thisNode.DiskSize = helper.IntUint64(new["disk_size"].(int))
1135+
if isUpdateNodeNum {
1136+
thisNode.NodeNum = helper.IntUint64(new["node_num"].(int))
1137+
}
1138+
if isUpdateNodeType {
1139+
thisNode.NodeType = helper.String(new["node_type"].(string))
1140+
}
1141+
changeESNodes = append(changeESNodes, thisNode)
1142+
err := resource.Retry(tccommon.WriteRetryTimeout*2, func() *resource.RetryError {
1143+
errRet := elasticsearchService.UpdateInstance(ctx, instanceId, "", "", "", "", "", 0, changeESNodes, nil, nil, nil, nil)
1144+
if errRet != nil {
1145+
return tccommon.RetryError(errRet)
1146+
}
1147+
return nil
1148+
})
1149+
if err != nil {
1150+
return err
1151+
}
1152+
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1153+
if err != nil {
1154+
return err
1155+
}
1156+
}
10221157
}
1023-
return nil
1024-
})
1025-
if err != nil {
1026-
return err
1027-
}
1028-
err = tencentCloudElasticsearchInstanceUpgradeWaiting(ctx, &elasticsearchService, instanceId)
1029-
if err != nil {
1030-
return err
1158+
// 更新oldNodeMap中的值
1159+
oldNodeMap[t] = new
10311160
}
10321161
}
10331162

@@ -1251,3 +1380,31 @@ func tencentCloudElasticsearchInstanceUpgradeWaiting(ctx context.Context, servic
12511380
return nil
12521381
})
12531382
}
1383+
1384+
func convertToNodeInfo(n interface{}) *es.NodeInfo {
1385+
value := n.(map[string]interface{})
1386+
nodeType := value["node_type"].(string)
1387+
diskSize := uint64(value["disk_size"].(int))
1388+
nodeNum := uint64(value["node_num"].(int))
1389+
types := value["type"].(string)
1390+
diskType := value["disk_type"].(string)
1391+
encrypt := value["encrypt"].(bool)
1392+
nodeInfo := &es.NodeInfo{
1393+
NodeType: &nodeType,
1394+
DiskSize: &diskSize,
1395+
NodeNum: &nodeNum,
1396+
Type: &types,
1397+
DiskType: &diskType,
1398+
DiskEncrypt: helper.BoolToInt64Pointer(encrypt),
1399+
}
1400+
return nodeInfo
1401+
}
1402+
1403+
func convertToNodeInfos(nodeInfos []interface{}) []*es.NodeInfo {
1404+
nodeInfoList := make([]*es.NodeInfo, 0, len(nodeInfos))
1405+
for _, n := range nodeInfos {
1406+
nodeInfo := convertToNodeInfo(n)
1407+
nodeInfoList = append(nodeInfoList, nodeInfo)
1408+
}
1409+
return nodeInfoList
1410+
}

tencentcloud/services/es/resource_tc_elasticsearch_instance_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,30 @@ func TestAccTencentCloudElasticsearchInstanceResource_https(t *testing.T) {
250250
})
251251
}
252252

253+
func TestAccTencentCloudElasticsearchInstanceResource_nodeInfoList(t *testing.T) {
254+
resource.Test(t, resource.TestCase{
255+
PreCheck: func() { tcacctest.AccPreCheck(t) },
256+
Providers: tcacctest.AccProviders,
257+
CheckDestroy: testAccCheckElasticsearchInstanceDestroy,
258+
Steps: []resource.TestStep{
259+
{
260+
Config: testAccElasticsearchInstanceNodeInfoList,
261+
Check: resource.ComposeTestCheckFunc(
262+
testAccCheckElasticsearchInstanceExists("tencentcloud_elasticsearch_instance.es_node_info_list"),
263+
resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_node_info_list", "node_info_list.#", "1"),
264+
),
265+
},
266+
{
267+
Config: testAccElasticsearchInstanceNodeInfoListUpdate,
268+
Check: resource.ComposeTestCheckFunc(
269+
testAccCheckElasticsearchInstanceExists("tencentcloud_elasticsearch_instance.es_node_info_list"),
270+
resource.TestCheckResourceAttr("tencentcloud_elasticsearch_instance.es_node_info_list", "node_info_list.#", "2"),
271+
),
272+
},
273+
},
274+
})
275+
}
276+
253277
func testAccCheckElasticsearchInstanceDestroy(s *terraform.State) error {
254278
logId := tccommon.GetLogId(tccommon.ContextNil)
255279
ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId)
@@ -573,3 +597,76 @@ resource "tencentcloud_elasticsearch_instance" "es_kibana" {
573597
}
574598
}
575599
`
600+
601+
const testAccElasticsearchInstanceNodeInfoList = tcacctest.DefaultEsVariables + `
602+
resource "tencentcloud_elasticsearch_instance" "es_node_info_list" {
603+
instance_name = "tf-ci-test-node"
604+
availability_zone = var.availability_zone
605+
version = "7.10.1"
606+
vpc_id = var.vpc_id
607+
subnet_id = var.subnet_id
608+
password = "Test1234"
609+
license_type = "basic"
610+
basic_security_type = 2
611+
public_access = "OPEN"
612+
protocol = "https"
613+
es_acl {
614+
white_list = [
615+
"127.0.0.2"
616+
]
617+
}
618+
es_public_acl {
619+
white_ip_list = [
620+
"127.0.0.2"
621+
]
622+
}
623+
624+
node_info_list {
625+
node_num = 2
626+
node_type = "ES.S1.MEDIUM4"
627+
disk_size = 50
628+
type = "hotData"
629+
disk_type = "CLOUD_SSD"
630+
}
631+
}
632+
`
633+
634+
const testAccElasticsearchInstanceNodeInfoListUpdate = tcacctest.DefaultEsVariables + `
635+
resource "tencentcloud_elasticsearch_instance" "es_node_info_list" {
636+
instance_name = "tf-ci-test-node"
637+
availability_zone = var.availability_zone
638+
version = "7.10.1"
639+
vpc_id = var.vpc_id
640+
subnet_id = var.subnet_id
641+
password = "Test1234"
642+
license_type = "basic"
643+
basic_security_type = 2
644+
public_access = "OPEN"
645+
protocol = "https"
646+
es_acl {
647+
white_list = [
648+
"127.0.0.2"
649+
]
650+
}
651+
es_public_acl {
652+
white_ip_list = [
653+
"127.0.0.2"
654+
]
655+
}
656+
657+
node_info_list {
658+
node_num = 3
659+
node_type = "ES.S1.MEDIUM8"
660+
disk_size = 100
661+
type = "hotData"
662+
disk_type = "CLOUD_SSD"
663+
}
664+
node_info_list {
665+
node_num = 3
666+
node_type = "ES.S1.MEDIUM8"
667+
disk_type = "CLOUD_SSD"
668+
type = "dedicatedMaster"
669+
disk_size = 50
670+
}
671+
}
672+
`

website/docs/r/elasticsearch_instance.html.markdown

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ resource "tencentcloud_elasticsearch_instance" "example_multi_zone" {
160160

161161
The following arguments are supported:
162162

163-
* `node_info_list` - (Required, List) Node information list, which is used to describe the specification information of various types of nodes in the cluster, such as node type, node quantity, node specification, disk type, and disk size.
163+
* `node_info_list` - (Required, Set) Node information list, which is used to describe the specification information of various types of nodes in the cluster, such as node type, node quantity, node specification, disk type, and disk size.
164164
* `password` - (Required, String) Password to an instance, the password needs to be 8 to 16 characters, including at least two items ([a-z,A-Z], [0-9] and [-!@#$%&^*+=_:;,.?] special symbols.
165165
* `version` - (Required, String) Version of the instance. Valid values are `5.6.4`, `6.4.3`, `6.8.2`, `7.5.1` and `7.10.1`.
166166
* `vpc_id` - (Required, String, ForceNew) The ID of a VPC network.

0 commit comments

Comments
 (0)