From dbd42ad9efec111ba9c46e0d57340b4d5f88caa1 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Fri, 4 Nov 2022 02:14:46 +0800 Subject: [PATCH 01/58] feat: update Vke-v2.6.0 and fix the bug of KubernetesConfig --- common/common_volcengine_convert.go | 19 +++++ ...source_volcengine_vke_default_node_pool.go | 6 ++ ...ervice_volcengine_vke_default_node_pool.go | 6 ++ .../data_source_volcengine_vke_node_pools.go | 5 ++ .../resource_volcengine_vke_node_pool.go | 11 ++- .../service_volcengine_vke_node_pool.go | 85 ++++++++----------- 6 files changed, 77 insertions(+), 55 deletions(-) diff --git a/common/common_volcengine_convert.go b/common/common_volcengine_convert.go index adc0eb9a..49ac03fb 100644 --- a/common/common_volcengine_convert.go +++ b/common/common_volcengine_convert.go @@ -577,3 +577,22 @@ func GetFinalKey(t RequestConvert, k string, isRoot bool) string { } } } + +func DefaultMapValue(source *map[string]interface{}, key string, defaultStruct map[string]interface{}) { + if def, ok := (*source)[key]; !ok { + (*source)[key] = defaultStruct + } else { + if ele, ok1 := def.(map[string]interface{}); ok1 { + for k, v := range defaultStruct { + if v1, ok3 := v.(map[string]interface{}); ok3 { + next := (*source)[key].(map[string]interface{}) + DefaultMapValue(&next, k, v1) + } + + if _, ok2 := ele[k]; !ok2 { + (*source)[key].(map[string]interface{})[k] = v + } + } + } + } +} diff --git a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go index a66ab128..c4ba8fb6 100644 --- a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go @@ -203,6 +203,12 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { Optional: true, Description: "The initializeScript of NodeConfig.", }, + "name_prefix": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The NamePrefix of NodeConfig.", + }, }, }, Description: "The Config of NodePool.", diff --git a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go index 53a6ad27..5e00ce3a 100644 --- a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go @@ -223,6 +223,9 @@ func (s *VolcengineDefaultNodePoolService) CreateResource(resourceData *schema.R }, }, }, + "name_prefix": { + ConvertType: ve.ConvertJsonObject, + }, }, }, }, @@ -292,6 +295,9 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R "initialize_script": { ConvertType: ve.ConvertJsonObject, }, + "name_prefix": { + ConvertType: ve.ConvertJsonObject, + }, }, }, "kubernetes_config": { diff --git a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go index a5c9d3fb..74fa6666 100644 --- a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go +++ b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go @@ -398,6 +398,11 @@ func DataSourceVolcengineNodePools() *schema.Resource { Computed: true, Description: "The AutoRenewPeriod of the PrePaid instance of NodeConfig.", }, + "name_prefix": { + Type: schema.TypeString, + Computed: true, + Description: "The NamePrefix of NodeConfig.", + }, }, }, }, diff --git a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go index 9f294271..1e63840b 100644 --- a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go @@ -105,7 +105,6 @@ func ResourceVolcengineNodePool() *schema.Resource { "subnet_ids": { Type: schema.TypeList, Required: true, - ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -244,7 +243,6 @@ func ResourceVolcengineNodePool() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - ForceNew: true, ValidateFunc: validation.IntInSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36}), DiffSuppressFunc: prePaidDiffSuppressFunc, Description: "The Period of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36. Unit: month. when InstanceChargeType is PrePaid, default value is 12.", @@ -253,7 +251,6 @@ func ResourceVolcengineNodePool() *schema.Resource { Type: schema.TypeBool, Optional: true, Computed: true, - ForceNew: true, DiffSuppressFunc: prePaidDiffSuppressFunc, Description: "Is AutoRenew of PrePaid instance of NodeConfig. Valid values: true, false. when InstanceChargeType is PrePaid, default value is true.", }, @@ -261,11 +258,16 @@ func ResourceVolcengineNodePool() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - ForceNew: true, ValidateFunc: validation.IntInSlice([]int{1, 2, 3, 6, 12}), DiffSuppressFunc: prePaidAndAutoNewDiffSuppressFunc, Description: "The AutoRenewPeriod of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 6, 12. Unit: month. when InstanceChargeType is PrePaid and AutoRenew enable, default value is 1.", }, + "name_prefix": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The NamePrefix of NodeConfig.", + }, }, }, Description: "The Config of NodePool.", @@ -314,6 +316,7 @@ func ResourceVolcengineNodePool() *schema.Resource { "effect": { Type: schema.TypeString, Optional: true, + Default: "NoSchedule", Description: "The Effect of Taints, the value can be `NoSchedule` or `NoExecute` or `PreferNoSchedule`.", }, }, diff --git a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go index ac68c158..ef80d241 100644 --- a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go @@ -350,6 +350,9 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource "auto_renew_period": { ConvertType: ve.ConvertJsonObject, }, + "name_prefix": { + ConvertType: ve.ConvertJsonObject, + }, }, }, "kubernetes_config": { @@ -456,6 +459,22 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource "initialize_script": { ConvertType: ve.ConvertJsonObject, }, + "subnet_ids": { + ConvertType: ve.ConvertJsonArray, + }, + "period": { + ConvertType: ve.ConvertJsonObject, + }, + "auto_renew": { + ForceGet: true, + TargetField: "AutoRenew", + }, + "auto_renew_period": { + ConvertType: ve.ConvertJsonObject, + }, + "name_prefix": { + ConvertType: ve.ConvertJsonObject, + }, }, }, "kubernetes_config": { @@ -463,9 +482,11 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource NextLevelConvert: map[string]ve.RequestConvert{ "labels": { ConvertType: ve.ConvertJsonObjectArray, + ForceGet: true, }, "taints": { ConvertType: ve.ConvertJsonObjectArray, + ForceGet: true, }, "cordon": { ConvertType: ve.ConvertJsonObject, @@ -516,61 +537,20 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource } } - if d.HasChange("kubernetes_config") { - if _, ok := (*call.SdkParam)["KubernetesConfig"]; !ok { // 列表被删除 - (*call.SdkParam)["KubernetesConfig"] = map[string]interface{}{ - "Labels": []interface{}{}, - "Taints": []interface{}{}, + instanceChargeType := d.Get("node_config").([]interface{})[0].(map[string]interface{})["instance_charge_type"].(string) + if instanceChargeType != "PrePaid" { + if nodeCfg, ok := (*call.SdkParam)["NodeConfig"]; ok { + if _, ok := nodeCfg.(map[string]interface{})["AutoRenew"]; ok { + delete((*call.SdkParam)["NodeConfig"].(map[string]interface{}), "AutoRenew") } } } - labelsChange := false - taintsChange := false - if d.HasChange("kubernetes_config.0.taints") { - taintsChange = true - } - if d.HasChange("kubernetes_config.0.labels") { - labelsChange = true - } - if labelsChange || taintsChange { - if _, ok := (*call.SdkParam)["KubernetesConfig"]; !ok { - (*call.SdkParam)["KubernetesConfig"] = map[string]interface{}{} - } - } - if labelsChange { - if _, ok := (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Labels"]; !ok { // 被清空了 - (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Labels"] = []interface{}{} - } - } - if taintsChange { - if _, ok := (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Taints"]; !ok { - (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Taints"] = []interface{}{} - } - } - - if labelsChange && (!taintsChange) { - var taints []interface{} - for _, taint := range d.Get("kubernetes_config.0.taints").([]interface{}) { - t := taint.(map[string]interface{}) - taints = append(taints, map[string]interface{}{ - "Key": t["key"], - "Value": t["value"], - "Effect": t["effect"], - }) - } - (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Taints"] = taints - } else if taintsChange && (!labelsChange) { - var labels []interface{} - for _, label := range d.Get("kubernetes_config.0.labels").(*schema.Set).List() { // for set - t := label.(map[string]interface{}) - labels = append(labels, map[string]interface{}{ - "Key": t["key"], - "Value": t["value"], - }) - } - (*call.SdkParam)["KubernetesConfig"].(map[string]interface{})["Labels"] = labels - } + // 当列表被删除时,入参添加空列表来置空 + ve.DefaultMapValue(call.SdkParam, "KubernetesConfig", map[string]interface{}{ + "Labels": []interface{}{}, + "Taints": []interface{}{}, + }) logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) @@ -816,6 +796,9 @@ func (s *VolcengineNodePoolService) DatasourceResources(*schema.ResourceData, *s "NodeConfig.AutoRenewPeriod": { TargetField: "auto_renew_period", }, + "NodeConfig.NamePrefix": { + TargetField: "name_prefix", + }, "NodeStatistics": { TargetField: "node_statistics", Convert: func(i interface{}) interface{} { From cd69e400b47e6429007fe0389b594c823fd5589a Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Tue, 8 Nov 2022 16:30:37 +0800 Subject: [PATCH 02/58] feat: support Tags --- common/common_volcengine_convert.go | 9 ++ common/common_volcengine_hashcodes.go | 16 +++ common/common_volcengine_tags.go | 81 ++++++++++++ example/vkeCluster/main.tf | 3 + example/vkeDefaultNodePool/main.tf | 6 + example/vkeNodePool/main.tf | 6 + .../data_source_volcengine_vke_clusters.go | 26 ++++ .../resource_volcengine_vke_cluster.go | 1 + .../cluster/service_volcengine_vke_cluster.go | 98 +++++++++++++- ...source_volcengine_vke_default_node_pool.go | 3 + ...ervice_volcengine_vke_default_node_pool.go | 105 +++++++++++++++ .../data_source_volcengine_vke_node_pools.go | 27 ++++ .../resource_volcengine_vke_node_pool.go | 4 +- .../service_volcengine_vke_node_pool.go | 125 +++++++++++++++++- 14 files changed, 505 insertions(+), 5 deletions(-) create mode 100644 common/common_volcengine_tags.go diff --git a/common/common_volcengine_convert.go b/common/common_volcengine_convert.go index 49ac03fb..2f998f34 100644 --- a/common/common_volcengine_convert.go +++ b/common/common_volcengine_convert.go @@ -450,6 +450,15 @@ func RequestConvertListN(v interface{}, k string, t RequestConvert, req *map[str break } break + case reflect.Map: + // 暂定Map类型必须通过Convert函数转换成[]map[string]interface{} + if t.NextLevelConvert[k2].Convert != nil { + err = Convert(d, k2, t.NextLevelConvert[k2].Convert(d, v2), t.NextLevelConvert[k2], 0, req, k3, t.NextLevelConvert[k2].ForceGet, contentType, k4, nil) + } + if err != nil { + return err + } + break default: k3 = k3 + GetFinalKey(t, k2, false) (*req)[k3] = v2 diff --git a/common/common_volcengine_hashcodes.go b/common/common_volcengine_hashcodes.go index 73d36e3a..78683cf0 100644 --- a/common/common_volcengine_hashcodes.go +++ b/common/common_volcengine_hashcodes.go @@ -22,3 +22,19 @@ func ClbAclEntryHash(v interface{}) int { buf := clbAclEntryHashBase(m) return hashcode.String(buf.String()) } + +func vkeTagsResponseHashBase(m map[string]interface{}) (buf bytes.Buffer) { + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["key"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["value"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["type"].(string)))) + return buf +} + +var VkeTagsResponseHash = func(v interface{}) int { + if v == nil { + return hashcode.String("") + } + m := v.(map[string]interface{}) + buf := vkeTagsResponseHashBase(m) + return hashcode.String(buf.String()) +} diff --git a/common/common_volcengine_tags.go b/common/common_volcengine_tags.go new file mode 100644 index 00000000..e5e47de6 --- /dev/null +++ b/common/common_volcengine_tags.go @@ -0,0 +1,81 @@ +package common + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "reflect" +) + +func TagsSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Description: "Tags.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + } +} + +func TagsSchemaComputed() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Description: "Tags.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + } +} + +func TagsMapToList(in interface{}) []map[string]interface{} { + result := make([]map[string]interface{}, 0) + if tags, ok := in.(map[string]interface{}); ok { + for k, v := range tags { + m := map[string]interface{}{ + "key": k, + "value": v.(string), + } + result = append(result, m) + } + } + return result +} + +func TagsListToMap(in interface{}) map[string]interface{} { + result := make(map[string]interface{}) + if tags, ok := in.([]interface{}); ok { + for _, tag := range tags { + result[tag.(map[string]interface{})["Key"].(string)] = tag.(map[string]interface{})["Value"].(string) + } + } + return result +} + +func GetTagsDifference(key string, d *schema.ResourceData) (addedTags map[string]interface{}, removedTags map[string]interface{}) { + if d.HasChange(key) { + oldRaw, newRaw := d.GetChange(key) + if oldRaw == nil { + oldRaw = make(map[string]interface{}) + } + if newRaw == nil { + newRaw = make(map[string]interface{}) + } + oldTags := oldRaw.(map[string]interface{}) + newTags := newRaw.(map[string]interface{}) + + addedTags = getDifference(newTags, oldTags) + removedTags = getDifference(oldTags, newTags) + return addedTags, removedTags + } + return addedTags, removedTags +} + +func getDifference(m, other map[string]interface{}) map[string]interface{} { + result := make(map[string]interface{}) + for k, v := range m { + if otherValue, ok := other[k]; !ok || !reflect.DeepEqual(v, otherValue) { + result[k] = v + } + } + return result +} diff --git a/example/vkeCluster/main.tf b/example/vkeCluster/main.tf index 7051e184..c41500cc 100644 --- a/example/vkeCluster/main.tf +++ b/example/vkeCluster/main.tf @@ -26,4 +26,7 @@ resource "volcengine_vke_cluster" "foo" { services_config { service_cidrsv4 = ["192.168.0.0/16"] } + tags = { + type = "Cluster" + } } \ No newline at end of file diff --git a/example/vkeDefaultNodePool/main.tf b/example/vkeDefaultNodePool/main.tf index 910f3e50..c635ad94 100644 --- a/example/vkeDefaultNodePool/main.tf +++ b/example/vkeDefaultNodePool/main.tf @@ -9,6 +9,9 @@ resource "volcengine_vke_default_node_pool" "default" { security_strategies = ["Hids"] } initialize_script = "ISMvYmluL2Jhc2gKZWNobyAx" + node_config_tags = { + type = "ecs" + } } kubernetes_config { labels { @@ -42,4 +45,7 @@ resource "volcengine_vke_default_node_pool" "default" { additional_container_storage_enabled = true container_storage_path = "/" } + tags = { + type = "DefaultNodePool" + } } \ No newline at end of file diff --git a/example/vkeNodePool/main.tf b/example/vkeNodePool/main.tf index 543173a2..406fa8ec 100644 --- a/example/vkeNodePool/main.tf +++ b/example/vkeNodePool/main.tf @@ -17,6 +17,9 @@ resource "volcengine_vke_node_pool" "vke_test" { } instance_charge_type = "PrePaid" period = 1 + node_config_tags = { + type = "ecs" + } } kubernetes_config { labels { @@ -28,4 +31,7 @@ resource "volcengine_vke_node_pool" "vke_test" { value = "dddd" } } + tags = { + type = "NodePool" + } } \ No newline at end of file diff --git a/volcengine/vke/cluster/data_source_volcengine_vke_clusters.go b/volcengine/vke/cluster/data_source_volcengine_vke_clusters.go index cd46bff5..502efc7a 100644 --- a/volcengine/vke/cluster/data_source_volcengine_vke_clusters.go +++ b/volcengine/vke/cluster/data_source_volcengine_vke_clusters.go @@ -93,6 +93,7 @@ func DataSourceVolcengineVkeVkeClusters() *schema.Resource { Optional: true, Description: "The ClientToken when the last cluster update succeeded. ClientToken is a string that guarantees the idempotency of the request. This string is passed in by the caller.", }, + "tags": ve.TagsSchema(), "clusters": { Description: "The collection of VkeCluster query.", Type: schema.TypeList, @@ -442,6 +443,31 @@ func DataSourceVolcengineVkeVkeClusters() *schema.Resource { Computed: true, Description: "Eip allocation Id.", }, + "tags": { + Type: schema.TypeSet, + Computed: true, + Description: "Tags.", + Set: ve.VkeTagsResponseHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: "The Value of Tags.", + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: "The Type of Tags.", + }, + }, + }, + }, }, }, }, diff --git a/volcengine/vke/cluster/resource_volcengine_vke_cluster.go b/volcengine/vke/cluster/resource_volcengine_vke_cluster.go index 779259e2..90ca06ee 100644 --- a/volcengine/vke/cluster/resource_volcengine_vke_cluster.go +++ b/volcengine/vke/cluster/resource_volcengine_vke_cluster.go @@ -55,6 +55,7 @@ func ResourceVolcengineVkeCluster() *schema.Resource { ForceNew: true, Description: "The version of Kubernetes specified when creating a VKE cluster (specified to patch version), if not specified, the latest Kubernetes version supported by VKE is used by default, which is a 3-segment version format starting with a lowercase v, that is, KubernetesVersion with IsLatestVersion=True in the return value of ListSupportedVersions.", }, + "tags": ve.TagsSchema(), "cluster_config": { Type: schema.TypeList, MaxItems: 1, diff --git a/volcengine/vke/cluster/service_volcengine_vke_cluster.go b/volcengine/vke/cluster/service_volcengine_vke_cluster.go index c2facc6e..0abb8247 100644 --- a/volcengine/vke/cluster/service_volcengine_vke_cluster.go +++ b/volcengine/vke/cluster/service_volcengine_vke_cluster.go @@ -208,6 +208,14 @@ func (s *VolcengineVkeClusterService) ReadResource(resourceData *schema.Resource if len(data) == 0 { return data, fmt.Errorf("Vke Cluster %s not exist ", clusterId) } + + logger.Debug(logger.RespFormat, "data of ReadResource ", data) + if tagsResponse, ok := data["Tags"]; ok { + tagsResponseMap := ve.TagsListToMap(tagsResponse) + data["Tags"] = tagsResponseMap + } + logger.Debug(logger.RespFormat, "data of ReadResource ", data) + return data, err } @@ -342,6 +350,13 @@ func (s *VolcengineVkeClusterService) CreateResource(resourceData *schema.Resour }, }, }, + "tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { if billingType, ok := (*call.SdkParam)["ClusterConfig.ApiServerPublicAccessConfig.PublicAccessNetworkConfig.BillingType"]; ok { @@ -372,6 +387,8 @@ func (s *VolcengineVkeClusterService) CreateResource(resourceData *schema.Resour } func (s *VolcengineVkeClusterService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "UpdateClusterConfig", @@ -428,8 +445,12 @@ func (s *VolcengineVkeClusterService) ModifyResource(resourceData *schema.Resour realBillingType := billingTypeRequestConvert(d, billingType) (*call.SdkParam)["ClusterConfig.ApiServerPublicAccessConfig.PublicAccessNetworkConfig.BillingType"] = realBillingType } - (*call.SdkParam)["Id"] = d.Id() + + // 删除UpdateClusterConfig中的Tags字段 + if _, exist := (*call.SdkParam)["Tags"]; exist { + delete(*call.SdkParam, "Tags") + } return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -443,6 +464,7 @@ func (s *VolcengineVkeClusterService) ModifyResource(resourceData *schema.Resour }, }, } + callbacks = append(callbacks, callback) if resourceData.HasChange("cluster_config.0.api_server_public_access_config.0.public_access_network_config.0.bandwidth") && !resourceData.HasChange("cluster_config.0.api_server_public_access_enabled") { @@ -471,10 +493,13 @@ func (s *VolcengineVkeClusterService) ModifyResource(resourceData *schema.Resour }, }, } - return []ve.Callback{modifyEipCallback, callback} + callbacks = append(callbacks, modifyEipCallback) } - return []ve.Callback{callback} + // 更新Tags + callbacks = s.setResourceTags(resourceData, "Cluster", callbacks) + + return callbacks } func (s *VolcengineVkeClusterService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -558,6 +583,13 @@ func (s *VolcengineVkeClusterService) DatasourceResources(*schema.ResourceData, "update_client_token": { TargetField: "Filter.UpdateClientToken", }, + "tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, ContentType: ve.ContentTypeJson, NameField: "Name", @@ -594,6 +626,66 @@ func (s *VolcengineVkeClusterService) ReadResourceId(id string) string { return id } +func (s *VolcengineVkeClusterService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { + addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UntagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if removedTags != nil && len(removedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["TagKeys"] = make([]string, 0) + for key, _ := range removedTags { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + //假如需要异步状态 这里需要等一下 + time.Sleep(time.Duration(5) * time.Second) + return nil + }, + }, + } + callbacks = append(callbacks, removeCallback) + + addCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "TagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if addedTags != nil && len(addedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) + addedTagsList := ve.TagsMapToList(addedTags) + for _, tag := range addedTagsList { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, addCallback) + + return callbacks +} + func getUniversalInfo(actionName string) ve.UniversalInfo { return ve.UniversalInfo{ ServiceName: "vke", diff --git a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go index c4ba8fb6..348dc875 100644 --- a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go @@ -33,6 +33,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { ForceNew: true, Description: "The ClusterId of NodePool.", }, + "tags": ve.TagsSchema(), "instances": { Type: schema.TypeSet, Optional: true, @@ -129,6 +130,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { "effect": { Type: schema.TypeString, Optional: true, + Default: "NoSchedule", Description: "The Effect of Taints.", }, }, @@ -209,6 +211,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { Computed: true, Description: "The NamePrefix of NodeConfig.", }, + "node_config_tags": ve.TagsSchema(), }, }, Description: "The Config of NodePool.", diff --git a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go index 5e00ce3a..572e1c2d 100644 --- a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go @@ -226,6 +226,20 @@ func (s *VolcengineDefaultNodePoolService) CreateResource(resourceData *schema.R "name_prefix": { ConvertType: ve.ConvertJsonObject, }, + "node_config_tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, + }, + }, + "tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags }, }, }, @@ -298,6 +312,13 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R "name_prefix": { ConvertType: ve.ConvertJsonObject, }, + "node_config_tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, }, "kubernetes_config": { @@ -305,9 +326,11 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R NextLevelConvert: map[string]ve.RequestConvert{ "labels": { ConvertType: ve.ConvertJsonArray, + ForceGet: true, }, "taints": { ConvertType: ve.ConvertJsonArray, + ForceGet: true, }, "cordon": { ConvertType: ve.ConvertJsonObject, @@ -321,6 +344,11 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R } (*call.SdkParam)["Id"] = d.Id() (*call.SdkParam)["ClusterId"] = d.Get("cluster_id") + + // 删除UpdateClusterConfig中的Tags字段 + if _, exist := (*call.SdkParam)["Tags"]; exist { + delete(*call.SdkParam, "Tags") + } return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -335,6 +363,19 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R } } } + + // 当列表被删除时,入参添加空列表来置空 + ve.DefaultMapValue(call.SdkParam, "KubernetesConfig", map[string]interface{}{ + "Labels": []interface{}{}, + "Taints": []interface{}{}, + }) + + if d.HasChange("node_config.0.node_config_tags") { + ve.DefaultMapValue(call.SdkParam, "NodeConfig", map[string]interface{}{ + "Tags": []interface{}{}, + }) + } + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) logger.Debug(logger.RespFormat, call.Action, resp, err) @@ -346,6 +387,10 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R }, }, }) + + // 更新Tags + calls = s.setResourceTags(resourceData, "NodePool", calls) + //修改实例 if resourceData.HasChange("instances") { calls = s.processNodeInstances(resourceData, calls) @@ -539,3 +584,63 @@ func (s *VolcengineDefaultNodePoolService) processNodeInstances(resourceData *sc } return calls } + +func (s *VolcengineDefaultNodePoolService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { + addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UntagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if removedTags != nil && len(removedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["TagKeys"] = make([]string, 0) + for key, _ := range removedTags { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + //假如需要异步状态 这里需要等一下 + time.Sleep(time.Duration(5) * time.Second) + return nil + }, + }, + } + callbacks = append(callbacks, removeCallback) + + addCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "TagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if addedTags != nil && len(addedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) + addedTagsList := ve.TagsMapToList(addedTags) + for _, tag := range addedTagsList { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, addCallback) + + return callbacks +} diff --git a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go index 74fa6666..fd2a784e 100644 --- a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go +++ b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go @@ -88,6 +88,7 @@ func DataSourceVolcengineNodePools() *schema.Resource { Optional: true, Description: "Is enabled of AutoScaling.", }, + "tags": ve.TagsSchema(), "node_pools": { Description: "The collection of NodePools query.", Type: schema.TypeList, @@ -403,6 +404,32 @@ func DataSourceVolcengineNodePools() *schema.Resource { Computed: true, Description: "The NamePrefix of NodeConfig.", }, + "node_config_tags": ve.TagsSchemaComputed(), + "tags": { + Type: schema.TypeSet, + Computed: true, + Description: "Tags.", + Set: ve.VkeTagsResponseHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: "The Value of Tags.", + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: "The Type of Tags.", + }, + }, + }, + }, }, }, }, diff --git a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go index 1e63840b..8d578c0b 100644 --- a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go @@ -13,7 +13,7 @@ import ( Import NodePool can be imported using the id, e.g. ``` -$ terraform import volcengine_node_pools.default pcabe57vqtofgrbln3dp0 +$ terraform import volcengine_vke_node_pool.default pcabe57vqtofgrbln3dp0 ``` */ @@ -44,6 +44,7 @@ func ResourceVolcengineNodePool() *schema.Resource { Optional: true, Description: "The ClientToken of NodePool.", }, + "tags": ve.TagsSchema(), "auto_scaling": { Type: schema.TypeList, MaxItems: 1, @@ -268,6 +269,7 @@ func ResourceVolcengineNodePool() *schema.Resource { Computed: true, Description: "The NamePrefix of NodeConfig.", }, + "node_config_tags": ve.TagsSchema(), }, }, Description: "The Config of NodePool.", diff --git a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go index ef80d241..4062fc93 100644 --- a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go @@ -200,6 +200,16 @@ func (s *VolcengineNodePoolService) ReadResource(resourceData *schema.ResourceDa logger.Debug(logger.RespFormat, "filteredSecurityGroupIds", tmpSecurityGroupIds, filteredSecurityGroupIds) } + if tags, ok := result["NodeConfig"].(map[string]interface{})["Tags"]; ok { + tagsMap := ve.TagsListToMap(tags) + result["NodeConfig"].(map[string]interface{})["NodeConfigTags"] = tagsMap + delete(result["NodeConfig"].(map[string]interface{}), "Tags") + } + if tagsResponse, ok := result["Tags"]; ok { + tagsResponseMap := ve.TagsListToMap(tagsResponse) + result["Tags"] = tagsResponseMap + } + logger.Debug(logger.RespFormat, "result of ReadResource ", result) return result, err } @@ -353,6 +363,13 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource "name_prefix": { ConvertType: ve.ConvertJsonObject, }, + "node_config_tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, }, "kubernetes_config": { @@ -394,6 +411,13 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource }, }, }, + "tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.RespFormat, call.Action, call.SdkParam) @@ -416,6 +440,8 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource } func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "UpdateNodePoolConfig", @@ -475,6 +501,13 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource "name_prefix": { ConvertType: ve.ConvertJsonObject, }, + "node_config_tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, }, "kubernetes_config": { @@ -522,6 +555,11 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["Id"] = d.Id() (*call.SdkParam)["ClusterId"] = d.Get("cluster_id") + + // 删除UpdateClusterConfig中的Tags字段 + if _, exist := (*call.SdkParam)["Tags"]; exist { + delete(*call.SdkParam, "Tags") + } return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -552,6 +590,12 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource "Taints": []interface{}{}, }) + if d.HasChange("node_config.0.node_config_tags") { + ve.DefaultMapValue(call.SdkParam, "NodeConfig", map[string]interface{}{ + "Tags": []interface{}{}, + }) + } + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) logger.Debug(logger.RespFormat, call.Action, resp, err) @@ -563,7 +607,12 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + callbacks = s.setResourceTags(resourceData, "NodePool", callbacks) + + return callbacks } func (s *VolcengineNodePoolService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -624,6 +673,13 @@ func (s *VolcengineNodePoolService) DatasourceResources(*schema.ResourceData, *s "update_client_token": { TargetField: "Filter.UpdateClientToken", }, + "tags": { + TargetField: "Tags", + Convert: func(data *schema.ResourceData, i interface{}) interface{} { + tags := ve.TagsMapToList(i) + return tags + }, + }, }, NameField: "Name", IdField: "Id", @@ -799,6 +855,13 @@ func (s *VolcengineNodePoolService) DatasourceResources(*schema.ResourceData, *s "NodeConfig.NamePrefix": { TargetField: "name_prefix", }, + "NodeConfig.Tags": { + TargetField: "node_config_tags", + Convert: func(i interface{}) interface{} { + tags := ve.TagsListToMap(i) + return tags + }, + }, "NodeStatistics": { TargetField: "node_statistics", Convert: func(i interface{}) interface{} { @@ -823,6 +886,66 @@ func (s *VolcengineNodePoolService) ReadResourceId(id string) string { return id } +func (s *VolcengineNodePoolService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { + addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UntagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if removedTags != nil && len(removedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["TagKeys"] = make([]string, 0) + for key, _ := range removedTags { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + //假如需要异步状态 这里需要等一下 + time.Sleep(time.Duration(5) * time.Second) + return nil + }, + }, + } + callbacks = append(callbacks, removeCallback) + + addCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "TagResources", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if addedTags != nil && len(addedTags) > 0 { + (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["ResourceType"] = resourceType + (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) + addedTagsList := ve.TagsMapToList(addedTags) + for _, tag := range addedTagsList { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, addCallback) + + return callbacks +} + func getUniversalInfo(actionName string) ve.UniversalInfo { return ve.UniversalInfo{ ServiceName: "vke", From 5439636cbe22d0d810e58141df5575804d6a023c Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Thu, 10 Nov 2022 11:06:08 +0800 Subject: [PATCH 03/58] fix: fix the bug of Cordon and NamePrefix --- .../resource_volcengine_vke_default_node_pool.go | 9 +++------ .../service_volcengine_vke_default_node_pool.go | 7 ++----- .../vke/node_pool/resource_volcengine_vke_node_pool.go | 9 ++++----- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go index fd880a88..df46f170 100644 --- a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go @@ -21,7 +21,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { return &schema.Resource{ Create: resourceVolcengineDefaultNodePoolCreate, Update: resourceVolcengineDefaultNodePoolUpdate, - Read: resourceVolcengineDefaultNodePoolUpdate, + Read: resourceVolcengineDefaultNodePoolRead, Delete: resourceVolcengineNodePoolDelete, Importer: &schema.ResourceImporter{ State: defaultNodePoolImporter, @@ -88,8 +88,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { "kubernetes_config": { Type: schema.TypeList, MaxItems: 1, - Optional: true, - Computed: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "labels": { @@ -139,8 +138,7 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { }, "cordon": { Type: schema.TypeBool, - Optional: true, - Computed: true, + Required: true, Description: "The Cordon of KubernetesConfig.", }, }, @@ -208,7 +206,6 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { "name_prefix": { Type: schema.TypeString, Optional: true, - Computed: true, Description: "The NamePrefix of NodeConfig.", }, "ecs_tags": { diff --git a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go index 9913f2f6..cbcf1624 100644 --- a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go @@ -325,11 +325,11 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R ConvertType: ve.ConvertJsonObject, NextLevelConvert: map[string]ve.RequestConvert{ "labels": { - ConvertType: ve.ConvertJsonArray, + ConvertType: ve.ConvertJsonObjectArray, ForceGet: true, }, "taints": { - ConvertType: ve.ConvertJsonArray, + ConvertType: ve.ConvertJsonObjectArray, ForceGet: true, }, "cordon": { @@ -339,9 +339,6 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(*call.SdkParam) < 1 { - return false, nil - } (*call.SdkParam)["Id"] = d.Id() (*call.SdkParam)["ClusterId"] = d.Get("cluster_id") diff --git a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go index 510206f3..6451e89d 100644 --- a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go @@ -61,7 +61,7 @@ func ResourceVolcengineNodePool() *schema.Resource { "max_replicas": { Type: schema.TypeInt, Optional: true, - Computed: true, + Default: 10, ValidateFunc: validation.IntBetween(0, 1000), Description: "The MaxReplicas of AutoScaling, default 10, range in 1~1000.", }, @@ -75,7 +75,7 @@ func ResourceVolcengineNodePool() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - Description: "The DesiredReplicas of AutoScaling, default 0.", + Description: "The DesiredReplicas of AutoScaling, default 0,range in min_replicas to max_replicas.", }, "priority": { Type: schema.TypeInt, @@ -266,7 +266,6 @@ func ResourceVolcengineNodePool() *schema.Resource { "name_prefix": { Type: schema.TypeString, Optional: true, - Computed: true, Description: "The NamePrefix of NodeConfig.", }, "ecs_tags": { @@ -284,7 +283,7 @@ func ResourceVolcengineNodePool() *schema.Resource { "kubernetes_config": { Type: schema.TypeList, MaxItems: 1, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "labels": { @@ -334,7 +333,7 @@ func ResourceVolcengineNodePool() *schema.Resource { }, "cordon": { Type: schema.TypeBool, - Optional: true, + Required: true, Description: "The Cordon of KubernetesConfig.", }, }, From 420b1c904a78a336065957e4ac31458deb04bedb Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Mon, 21 Nov 2022 19:10:04 +0800 Subject: [PATCH 04/58] feat: use TypeSet to support Tags --- common/common_volcengine_convert.go | 3 - common/common_volcengine_hashcodes.go | 16 --- common/common_volcengine_tags.go | 109 +++++++++--------- common/common_volcengine_version.go | 2 +- example/vkeCluster/main.tf | 5 +- example/vkeDefaultNodePool/main.tf | 10 +- example/vkeNodePool/main.tf | 11 +- .../cluster/service_volcengine_vke_cluster.go | 32 ++--- ...source_volcengine_vke_default_node_pool.go | 18 ++- ...ervice_volcengine_vke_default_node_pool.go | 30 ++--- .../data_source_volcengine_vke_node_pools.go | 18 ++- .../resource_volcengine_vke_node_pool.go | 20 +++- .../service_volcengine_vke_node_pool.go | 56 ++++----- website/docs/d/vke_clusters.html.markdown | 10 ++ website/docs/d/vke_node_pools.html.markdown | 14 +++ website/docs/r/vke_cluster.html.markdown | 10 ++ .../r/vke_default_node_pool.html.markdown | 25 +++- ...fault_node_pool_batch_attach.html.markdown | 7 ++ website/docs/r/vke_node_pool.html.markdown | 38 ++++-- 19 files changed, 254 insertions(+), 180 deletions(-) diff --git a/common/common_volcengine_convert.go b/common/common_volcengine_convert.go index 742d5670..49ac03fb 100644 --- a/common/common_volcengine_convert.go +++ b/common/common_volcengine_convert.go @@ -451,9 +451,6 @@ func RequestConvertListN(v interface{}, k string, t RequestConvert, req *map[str } break default: - if t.NextLevelConvert[k2].Convert != nil { - v2 = t.NextLevelConvert[k2].Convert(d, v2) - } k3 = k3 + GetFinalKey(t, k2, false) (*req)[k3] = v2 break diff --git a/common/common_volcengine_hashcodes.go b/common/common_volcengine_hashcodes.go index 78683cf0..73d36e3a 100644 --- a/common/common_volcengine_hashcodes.go +++ b/common/common_volcengine_hashcodes.go @@ -22,19 +22,3 @@ func ClbAclEntryHash(v interface{}) int { buf := clbAclEntryHashBase(m) return hashcode.String(buf.String()) } - -func vkeTagsResponseHashBase(m map[string]interface{}) (buf bytes.Buffer) { - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["key"].(string)))) - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["value"].(string)))) - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["type"].(string)))) - return buf -} - -var VkeTagsResponseHash = func(v interface{}) int { - if v == nil { - return hashcode.String("") - } - m := v.(map[string]interface{}) - buf := vkeTagsResponseHashBase(m) - return hashcode.String(buf.String()) -} diff --git a/common/common_volcengine_tags.go b/common/common_volcengine_tags.go index e5e47de6..343b531c 100644 --- a/common/common_volcengine_tags.go +++ b/common/common_volcengine_tags.go @@ -1,81 +1,82 @@ package common import ( + "bytes" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "reflect" ) func TagsSchema() *schema.Schema { return &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeSet, Optional: true, Description: "Tags.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Set: TagsHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: "The Value of Tags.", + }, + }, }, } } func TagsSchemaComputed() *schema.Schema { return &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeSet, Computed: true, Description: "Tags.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Set: TagsHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: "The Value of Tags.", + }, + }, }, } } -func TagsMapToList(in interface{}) []map[string]interface{} { - result := make([]map[string]interface{}, 0) - if tags, ok := in.(map[string]interface{}); ok { - for k, v := range tags { - m := map[string]interface{}{ - "key": k, - "value": v.(string), - } - result = append(result, m) - } - } - return result -} - -func TagsListToMap(in interface{}) map[string]interface{} { - result := make(map[string]interface{}) - if tags, ok := in.([]interface{}); ok { - for _, tag := range tags { - result[tag.(map[string]interface{})["Key"].(string)] = tag.(map[string]interface{})["Value"].(string) - } - } - return result -} - -func GetTagsDifference(key string, d *schema.ResourceData) (addedTags map[string]interface{}, removedTags map[string]interface{}) { - if d.HasChange(key) { - oldRaw, newRaw := d.GetChange(key) - if oldRaw == nil { - oldRaw = make(map[string]interface{}) - } - if newRaw == nil { - newRaw = make(map[string]interface{}) - } - oldTags := oldRaw.(map[string]interface{}) - newTags := newRaw.(map[string]interface{}) - - addedTags = getDifference(newTags, oldTags) - removedTags = getDifference(oldTags, newTags) - return addedTags, removedTags +var TagsHash = func(v interface{}) int { + if v == nil { + return hashcode.String("") } - return addedTags, removedTags + m := v.(map[string]interface{}) + var ( + buf bytes.Buffer + ) + buf.WriteString(fmt.Sprintf("%v#%v", m["key"], m["value"])) + return hashcode.String(buf.String()) } -func getDifference(m, other map[string]interface{}) map[string]interface{} { - result := make(map[string]interface{}) - for k, v := range m { - if otherValue, ok := other[k]; !ok || !reflect.DeepEqual(v, otherValue) { - result[k] = v - } +var VkeTagsResponseHash = func(v interface{}) int { + if v == nil { + return hashcode.String("") } - return result + m := v.(map[string]interface{}) + var ( + buf bytes.Buffer + ) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["key"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["value"].(string)))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["type"].(string)))) + return hashcode.String(buf.String()) } diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index e89ad947..4866d800 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.34" + TerraformProviderVersion = "0.0.35" ) diff --git a/example/vkeCluster/main.tf b/example/vkeCluster/main.tf index c41500cc..d6e76f66 100644 --- a/example/vkeCluster/main.tf +++ b/example/vkeCluster/main.tf @@ -26,7 +26,8 @@ resource "volcengine_vke_cluster" "foo" { services_config { service_cidrsv4 = ["192.168.0.0/16"] } - tags = { - type = "Cluster" + tags { + key = "k1" + value = "v1" } } \ No newline at end of file diff --git a/example/vkeDefaultNodePool/main.tf b/example/vkeDefaultNodePool/main.tf index 5ed6b595..5a1d3add 100644 --- a/example/vkeDefaultNodePool/main.tf +++ b/example/vkeDefaultNodePool/main.tf @@ -9,8 +9,9 @@ resource "volcengine_vke_default_node_pool" "default" { security_strategies = ["Hids"] } initialize_script = "ISMvYmluL2Jhc2gKZWNobyAx" - ecs_tags = { - type = "ecs" + ecs_tags { + key = "ecs_k1" + value = "ecs_v1" } } kubernetes_config { @@ -45,7 +46,8 @@ resource "volcengine_vke_default_node_pool" "default" { additional_container_storage_enabled = true container_storage_path = "/" } - tags = { - type = "DefaultNodePool" + tags { + key = "k1" + value = "v1" } } \ No newline at end of file diff --git a/example/vkeNodePool/main.tf b/example/vkeNodePool/main.tf index 3f05634a..a6657085 100644 --- a/example/vkeNodePool/main.tf +++ b/example/vkeNodePool/main.tf @@ -17,8 +17,9 @@ resource "volcengine_vke_node_pool" "vke_test" { } instance_charge_type = "PrePaid" period = 1 - ecs_tags = { - type = "ecs" + ecs_tags { + key = "ecs_k1" + value = "ecs_v1" } } kubernetes_config { @@ -30,8 +31,10 @@ resource "volcengine_vke_node_pool" "vke_test" { key = "cccc" value = "dddd" } + cordon = false } - tags = { - type = "NodePool" + tags { + key = "k1" + value = "v1" } } \ No newline at end of file diff --git a/volcengine/vke/cluster/service_volcengine_vke_cluster.go b/volcengine/vke/cluster/service_volcengine_vke_cluster.go index da8d85fd..8bf56ecb 100644 --- a/volcengine/vke/cluster/service_volcengine_vke_cluster.go +++ b/volcengine/vke/cluster/service_volcengine_vke_cluster.go @@ -209,13 +209,6 @@ func (s *VolcengineVkeClusterService) ReadResource(resourceData *schema.Resource return data, fmt.Errorf("Vke Cluster %s not exist ", clusterId) } - logger.Debug(logger.RespFormat, "data of ReadResource ", data) - if tagsResponse, ok := data["Tags"]; ok { - tagsResponseMap := ve.TagsListToMap(tagsResponse) - data["Tags"] = tagsResponseMap - } - logger.Debug(logger.RespFormat, "data of ReadResource ", data) - return data, err } @@ -352,10 +345,7 @@ func (s *VolcengineVkeClusterService) CreateResource(resourceData *schema.Resour }, "tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { @@ -583,10 +573,7 @@ func (s *VolcengineVkeClusterService) DatasourceResources(*schema.ResourceData, }, "tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, ContentType: ve.ContentTypeJson, @@ -625,19 +612,19 @@ func (s *VolcengineVkeClusterService) ReadResourceId(id string) string { } func (s *VolcengineVkeClusterService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { - addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + addedTags, removedTags, _, _ := ve.GetSetDifference("tags", resourceData, ve.TagsHash, false) removeCallback := ve.Callback{ Call: ve.SdkCall{ Action: "UntagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(removedTags) > 0 { + if removedTags != nil && len(removedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["TagKeys"] = make([]string, 0) - for key, _ := range removedTags { - (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + for _, tag := range removedTags.List() { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), tag.(map[string]interface{})["key"].(string)) } return true, nil } @@ -656,13 +643,12 @@ func (s *VolcengineVkeClusterService) setResourceTags(resourceData *schema.Resou Action: "TagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(addedTags) > 0 { + if addedTags != nil && len(addedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) - addedTagsList := ve.TagsMapToList(addedTags) - for _, tag := range addedTagsList { - (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + for _, tag := range addedTags.List() { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag.(map[string]interface{})) } return true, nil } diff --git a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go index 871de754..35782da7 100644 --- a/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/resource_volcengine_vke_default_node_pool.go @@ -215,11 +215,23 @@ func ResourceVolcengineDefaultNodePool() *schema.Resource { Description: "The NamePrefix of NodeConfig.", }, "ecs_tags": { - Type: schema.TypeMap, + Type: schema.TypeSet, Optional: true, Description: "Tags for Ecs.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Set: ve.TagsHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: "The Value of Tags.", + }, + }, }, }, }, diff --git a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go index 671c48c9..f35353dd 100644 --- a/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go +++ b/volcengine/vke/default_node_pool/service_volcengine_vke_default_node_pool.go @@ -228,19 +228,13 @@ func (s *VolcengineDefaultNodePoolService) CreateResource(resourceData *schema.R }, "ecs_tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, }, "tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { @@ -314,10 +308,7 @@ func (s *VolcengineDefaultNodePoolService) ModifyResource(resourceData *schema.R }, "ecs_tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, }, @@ -581,19 +572,19 @@ func (s *VolcengineDefaultNodePoolService) ProcessNodeInstances(resourceData *sc } func (s *VolcengineDefaultNodePoolService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { - addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + addedTags, removedTags, _, _ := ve.GetSetDifference("tags", resourceData, ve.TagsHash, false) removeCallback := ve.Callback{ Call: ve.SdkCall{ Action: "UntagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(removedTags) > 0 { + if removedTags != nil && len(removedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["TagKeys"] = make([]string, 0) - for key, _ := range removedTags { - (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + for _, tag := range removedTags.List() { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), tag.(map[string]interface{})["key"].(string)) } return true, nil } @@ -612,13 +603,12 @@ func (s *VolcengineDefaultNodePoolService) setResourceTags(resourceData *schema. Action: "TagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(addedTags) > 0 { + if addedTags != nil && len(addedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) - addedTagsList := ve.TagsMapToList(addedTags) - for _, tag := range addedTagsList { - (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + for _, tag := range addedTags.List() { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag.(map[string]interface{})) } return true, nil } diff --git a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go index 77bf04f1..a964340a 100644 --- a/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go +++ b/volcengine/vke/node_pool/data_source_volcengine_vke_node_pools.go @@ -405,11 +405,23 @@ func DataSourceVolcengineNodePools() *schema.Resource { Description: "The NamePrefix of NodeConfig.", }, "ecs_tags": { - Type: schema.TypeMap, + Type: schema.TypeSet, Computed: true, Description: "Tags for Ecs.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Set: ve.TagsHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: "The Value of Tags.", + }, + }, }, }, "tags": { diff --git a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go index 746eeec6..2e8b30cc 100644 --- a/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/resource_volcengine_vke_node_pool.go @@ -81,7 +81,7 @@ func ResourceVolcengineNodePool() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - Description: "The DesiredReplicas of AutoScaling, default 0,range in min_replicas to max_replicas.", + Description: "The DesiredReplicas of AutoScaling, default 0, range in min_replicas to max_replicas.", }, "priority": { Type: schema.TypeInt, @@ -275,11 +275,23 @@ func ResourceVolcengineNodePool() *schema.Resource { Description: "The NamePrefix of NodeConfig.", }, "ecs_tags": { - Type: schema.TypeMap, + Type: schema.TypeSet, Optional: true, Description: "Tags for Ecs.", - Elem: &schema.Schema{ - Type: schema.TypeString, + Set: ve.TagsHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: "The Key of Tags.", + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: "The Value of Tags.", + }, + }, }, }, }, diff --git a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go index 9f764d52..dc6abc2f 100644 --- a/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go +++ b/volcengine/vke/node_pool/service_volcengine_vke_node_pool.go @@ -200,15 +200,10 @@ func (s *VolcengineNodePoolService) ReadResource(resourceData *schema.ResourceDa logger.Debug(logger.RespFormat, "filteredSecurityGroupIds", tmpSecurityGroupIds, filteredSecurityGroupIds) } - if tags, ok := result["NodeConfig"].(map[string]interface{})["Tags"]; ok { - tagsMap := ve.TagsListToMap(tags) - result["NodeConfig"].(map[string]interface{})["EcsTags"] = tagsMap + if ecsTags, ok := result["NodeConfig"].(map[string]interface{})["Tags"]; ok { + result["NodeConfig"].(map[string]interface{})["EcsTags"] = ecsTags delete(result["NodeConfig"].(map[string]interface{}), "Tags") } - if tagsResponse, ok := result["Tags"]; ok { - tagsResponseMap := ve.TagsListToMap(tagsResponse) - result["Tags"] = tagsResponseMap - } logger.Debug(logger.RespFormat, "result of ReadResource ", result) return result, err @@ -365,10 +360,7 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource }, "ecs_tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, }, @@ -413,10 +405,7 @@ func (s *VolcengineNodePoolService) CreateResource(resourceData *schema.Resource }, "tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -503,10 +492,7 @@ func (s *VolcengineNodePoolService) ModifyResource(resourceData *schema.Resource }, "ecs_tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, }, @@ -673,10 +659,7 @@ func (s *VolcengineNodePoolService) DatasourceResources(*schema.ResourceData, *s }, "tags": { TargetField: "Tags", - Convert: func(data *schema.ResourceData, i interface{}) interface{} { - tags := ve.TagsMapToList(i) - return tags - }, + ConvertType: ve.ConvertJsonObjectArray, }, }, NameField: "Name", @@ -856,8 +839,16 @@ func (s *VolcengineNodePoolService) DatasourceResources(*schema.ResourceData, *s "NodeConfig.Tags": { TargetField: "ecs_tags", Convert: func(i interface{}) interface{} { - tags := ve.TagsListToMap(i) - return tags + var results []interface{} + if dd, ok := i.([]interface{}); ok { + for _, data := range dd { + tag := make(map[string]interface{}, 0) + tag["key"] = data.(map[string]interface{})["Key"].(string) + tag["value"] = data.(map[string]interface{})["Value"].(string) + results = append(results, tag) + } + } + return results }, }, "NodeStatistics": { @@ -885,19 +876,19 @@ func (s *VolcengineNodePoolService) ReadResourceId(id string) string { } func (s *VolcengineNodePoolService) setResourceTags(resourceData *schema.ResourceData, resourceType string, callbacks []ve.Callback) []ve.Callback { - addedTags, removedTags := ve.GetTagsDifference("tags", resourceData) + addedTags, removedTags, _, _ := ve.GetSetDifference("tags", resourceData, ve.TagsHash, false) removeCallback := ve.Callback{ Call: ve.SdkCall{ Action: "UntagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(removedTags) > 0 { + if removedTags != nil && len(removedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["TagKeys"] = make([]string, 0) - for key, _ := range removedTags { - (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), key) + for _, tag := range removedTags.List() { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), tag.(map[string]interface{})["key"].(string)) } return true, nil } @@ -916,13 +907,12 @@ func (s *VolcengineNodePoolService) setResourceTags(resourceData *schema.Resourc Action: "TagResources", ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { - if len(addedTags) > 0 { + if addedTags != nil && len(addedTags.List()) > 0 { (*call.SdkParam)["ResourceIds"] = []string{resourceData.Id()} (*call.SdkParam)["ResourceType"] = resourceType (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) - addedTagsList := ve.TagsMapToList(addedTags) - for _, tag := range addedTagsList { - (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag) + for _, tag := range addedTags.List() { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag.(map[string]interface{})) } return true, nil } diff --git a/website/docs/d/vke_clusters.html.markdown b/website/docs/d/vke_clusters.html.markdown index 4ed653a9..5313f03a 100644 --- a/website/docs/d/vke_clusters.html.markdown +++ b/website/docs/d/vke_clusters.html.markdown @@ -30,6 +30,7 @@ The following arguments are supported: * `page_size` - (Optional) The page size of clusters query. * `pods_config_pod_network_mode` - (Optional) The container network model of the cluster, the value is `Flannel` or `VpcCniShared`. Flannel: Flannel network model, an independent Underlay container network solution, combined with the global routing capability of VPC, to achieve a high-performance network experience for the cluster. VpcCniShared: VPC-CNI network model, an Underlay container network solution based on the ENI of the private network elastic network card, with high network communication performance. * `statuses` - (Optional) Array of cluster states to filter. (The elements of the array are logically ORed. A maximum of 15 state array elements can be filled at a time). +* `tags` - (Optional) Tags. * `update_client_token` - (Optional) The ClientToken when the last cluster update succeeded. ClientToken is a string that guarantees the idempotency of the request. This string is passed in by the caller. The `statuses` object supports the following: @@ -37,6 +38,11 @@ The `statuses` object supports the following: * `conditions_type` - (Optional) The state condition in the current main state of the cluster, that is, the reason for entering the main state, there can be multiple reasons, the value contains `Progressing`, `Ok`, `Degraded`, `SetByProvider`, `Balance`, `Security`, `CreateError`, `ResourceCleanupFailed`, `LimitedByQuota`, `StockOut`,`Unknown`. * `phase` - (Optional) The status of cluster. the value contains `Creating`, `Running`, `Updating`, `Deleting`, `Stopped`, `Failed`. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `clusters` - The collection of VkeCluster query. @@ -88,6 +94,10 @@ In addition to all arguments above, the following attributes are exported: * `conditions` - The state condition in the current primary state of the cluster, that is, the reason for entering the primary state. * `type` - The state condition in the current main state of the cluster, that is, the reason for entering the main state, there can be multiple reasons, the value contains `Progressing`, `Ok`, `Balance`, `CreateError`, `ResourceCleanupFailed`, `Unknown`. * `phase` - The status of cluster. the value contains `Creating`, `Running`, `Updating`, `Deleting`, `Stopped`, `Failed`. + * `tags` - Tags of the Cluster. + * `key` - The Key of Tags. + * `type` - The Type of Tags. + * `value` - The Value of Tags. * `update_time` - The last time a request was accepted by the cluster and executed or completed. UTC+0 time in standard RFC3339 format. * `total_count` - The total count of Cluster query. diff --git a/website/docs/d/vke_node_pools.html.markdown b/website/docs/d/vke_node_pools.html.markdown index c0e27969..04de2d39 100644 --- a/website/docs/d/vke_node_pools.html.markdown +++ b/website/docs/d/vke_node_pools.html.markdown @@ -26,6 +26,7 @@ The following arguments are supported: * `name` - (Optional) The Name of NodePool. * `output_file` - (Optional) File name where to save data source results. * `statuses` - (Optional) The Status of NodePool. +* `tags` - (Optional) Tags. * `update_client_token` - (Optional) The ClientToken when last update was successful. The `statuses` object supports the following: @@ -33,6 +34,11 @@ The `statuses` object supports the following: * `conditions_type` - (Optional) Indicates the status condition of the node pool in the active state. The value can be `Progressing` or `Ok` or `VersionPartlyUpgraded` or `StockOut` or `LimitedByQuota` or `Balance` or `Degraded` or `ClusterVersionUpgrading` or `Cluster` or `ResourceCleanupFailed` or `Unknown` or `ClusterNotRunning` or `SetByProvider`. * `phase` - (Optional) The Phase of Status. The value can be `Creating` or `Running` or `Updating` or `Deleting` or `Failed` or `Scaling`. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `node_pools` - The collection of NodePools query. @@ -49,6 +55,9 @@ In addition to all arguments above, the following attributes are exported: * `size` - The Size of DataVolume. * `type` - The Type of DataVolume. * `desired_replicas` - The DesiredReplicas of AutoScaling. + * `ecs_tags` - Tags for Ecs. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `enabled` - Is Enabled of AutoScaling. * `id` - The Id of NodePool. * `image_id` - The ImageId of NodeConfig. @@ -62,6 +71,7 @@ In addition to all arguments above, the following attributes are exported: * `login_type` - The login type of NodeConfig. * `max_replicas` - The MaxReplicas of AutoScaling. * `min_replicas` - The MinReplicas of AutoScaling. + * `name_prefix` - The NamePrefix of NodeConfig. * `name` - The Name of NodePool. * `node_statistics` - The NodeStatistics of NodeConfig. * `creating_count` - The CreatingCount of Node. @@ -83,6 +93,10 @@ In addition to all arguments above, the following attributes are exported: * `system_volume` - The SystemVolume of NodeConfig. * `size` - The Size of SystemVolume. * `type` - The Type of SystemVolume. + * `tags` - Tags of the NodePool. + * `key` - The Key of Tags. + * `type` - The Type of Tags. + * `value` - The Value of Tags. * `taint_content` - The TaintContent of NodeConfig. * `effect` - The Effect of Taint. * `key` - The Key of Taint. diff --git a/website/docs/r/vke_cluster.html.markdown b/website/docs/r/vke_cluster.html.markdown index 48a08709..d2d64f36 100644 --- a/website/docs/r/vke_cluster.html.markdown +++ b/website/docs/r/vke_cluster.html.markdown @@ -38,6 +38,10 @@ resource "volcengine_vke_cluster" "foo" { services_config { service_cidrsv4 = ["192.168.0.0/16"] } + tags { + key = "k1" + value = "v1" + } } ``` ## Argument Reference @@ -50,6 +54,7 @@ The following arguments are supported: * `delete_protection_enabled` - (Optional) The delete protection of the cluster, the value is `true` or `false`. * `description` - (Optional) The description of the cluster. * `kubernetes_version` - (Optional, ForceNew) The version of Kubernetes specified when creating a VKE cluster (specified to patch version), if not specified, the latest Kubernetes version supported by VKE is used by default, which is a 3-segment version format starting with a lowercase v, that is, KubernetesVersion with IsLatestVersion=True in the return value of ListSupportedVersions. +* `tags` - (Optional) Tags. The `api_server_public_access_config` object supports the following: @@ -82,6 +87,11 @@ The `services_config` object supports the following: * `service_cidrsv4` - (Required, ForceNew) The IPv4 private network address exposed by the service. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + The `vpc_cni_config` object supports the following: * `subnet_ids` - (Optional, ForceNew) A list of Pod subnet IDs for the VPC-CNI container network. diff --git a/website/docs/r/vke_default_node_pool.html.markdown b/website/docs/r/vke_default_node_pool.html.markdown index ad41e9da..20b161a5 100644 --- a/website/docs/r/vke_default_node_pool.html.markdown +++ b/website/docs/r/vke_default_node_pool.html.markdown @@ -21,6 +21,10 @@ resource "volcengine_vke_default_node_pool" "default" { security_strategies = ["Hids"] } initialize_script = "ISMvYmluL2Jhc2gKZWNobyAx" + ecs_tags { + key = "ecs_k1" + value = "ecs_v1" + } } kubernetes_config { labels { @@ -54,14 +58,24 @@ resource "volcengine_vke_default_node_pool" "default" { additional_container_storage_enabled = true container_storage_path = "/" } + tags { + key = "k1" + value = "v1" + } } ``` ## Argument Reference The following arguments are supported: * `cluster_id` - (Required, ForceNew) The ClusterId of NodePool. +* `kubernetes_config` - (Required) The KubernetesConfig of NodeConfig. * `node_config` - (Required) The Config of NodePool. * `instances` - (Optional) The ECS InstanceIds add to NodePool. -* `kubernetes_config` - (Optional) The KubernetesConfig of NodeConfig. +* `tags` - (Optional) Tags. + +The `ecs_tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. The `instances` object supports the following: @@ -73,7 +87,7 @@ The `instances` object supports the following: The `kubernetes_config` object supports the following: -* `cordon` - (Optional) The Cordon of KubernetesConfig. +* `cordon` - (Required) The Cordon of KubernetesConfig. * `labels` - (Optional) The Labels of KubernetesConfig. * `taints` - (Optional) The Taints of KubernetesConfig. @@ -90,7 +104,9 @@ The `login` object supports the following: The `node_config` object supports the following: * `security` - (Required) The Security of NodeConfig. +* `ecs_tags` - (Optional) Tags for Ecs. * `initialize_script` - (Optional) The initializeScript of NodeConfig. +* `name_prefix` - (Optional) The NamePrefix of NodeConfig. The `security` object supports the following: @@ -98,6 +114,11 @@ The `security` object supports the following: * `security_group_ids` - (Optional) The SecurityGroupIds of Security. * `security_strategies` - (Optional) The SecurityStrategies of Security. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + The `taints` object supports the following: * `effect` - (Optional) The Effect of Taints. diff --git a/website/docs/r/vke_default_node_pool_batch_attach.html.markdown b/website/docs/r/vke_default_node_pool_batch_attach.html.markdown index c040409c..a92b5930 100644 --- a/website/docs/r/vke_default_node_pool_batch_attach.html.markdown +++ b/website/docs/r/vke_default_node_pool_batch_attach.html.markdown @@ -54,12 +54,19 @@ In addition to all arguments above, the following attributes are exported: * `key` - The Key of Taints. * `value` - The Value of Taints. * `node_config` - The Config of NodePool. + * `ecs_tags` - Tags for Ecs. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `initialize_script` - The initializeScript of NodeConfig. + * `name_prefix` - The NamePrefix of NodeConfig. * `security` - The Security of NodeConfig. * `login` - The Login of Security. * `password` - The Password of Security. * `ssh_key_pair_name` - The SshKeyPairName of Security. * `security_group_ids` - The SecurityGroupIds of Security. * `security_strategies` - The SecurityStrategies of Security. +* `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. diff --git a/website/docs/r/vke_node_pool.html.markdown b/website/docs/r/vke_node_pool.html.markdown index 137e91c5..417d9061 100644 --- a/website/docs/r/vke_node_pool.html.markdown +++ b/website/docs/r/vke_node_pool.html.markdown @@ -29,6 +29,10 @@ resource "volcengine_vke_node_pool" "vke_test" { } instance_charge_type = "PrePaid" period = 1 + ecs_tags { + key = "ecs_k1" + value = "ecs_v1" + } } kubernetes_config { labels { @@ -39,21 +43,27 @@ resource "volcengine_vke_node_pool" "vke_test" { key = "cccc" value = "dddd" } + cordon = false + } + tags { + key = "k1" + value = "v1" } } ``` ## Argument Reference The following arguments are supported: +* `kubernetes_config` - (Required) The KubernetesConfig of NodeConfig. * `node_config` - (Required) The Config of NodePool. * `auto_scaling` - (Optional) The node pool elastic scaling configuration information. * `client_token` - (Optional) The ClientToken of NodePool. * `cluster_id` - (Optional, ForceNew) The ClusterId of NodePool. -* `kubernetes_config` - (Optional) The KubernetesConfig of NodeConfig. * `name` - (Optional) The Name of NodePool. +* `tags` - (Optional) Tags. The `auto_scaling` object supports the following: -* `desired_replicas` - (Optional) The DesiredReplicas of AutoScaling, default 0. +* `desired_replicas` - (Optional) The DesiredReplicas of AutoScaling, default 0, range in min_replicas to max_replicas. * `enabled` - (Optional) Is Enabled of AutoScaling. * `max_replicas` - (Optional) The MaxReplicas of AutoScaling, default 10, range in 1~1000. * `min_replicas` - (Optional) The MinReplicas of AutoScaling, default 0. @@ -65,9 +75,14 @@ The `data_volumes` object supports the following: * `size` - (Optional, ForceNew) The Size of DataVolumes, the value range in 20~32768. * `type` - (Optional, ForceNew) The Type of DataVolumes, the value can be `PTSSD` or `ESSD_PL0` or `ESSD_FlexPL`. +The `ecs_tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + The `kubernetes_config` object supports the following: -* `cordon` - (Optional) The Cordon of KubernetesConfig. +* `cordon` - (Required) The Cordon of KubernetesConfig. * `labels` - (Optional) The Labels of KubernetesConfig. * `taints` - (Optional) The Taints of KubernetesConfig. @@ -85,15 +100,17 @@ The `node_config` object supports the following: * `instance_type_ids` - (Required, ForceNew) The InstanceTypeIds of NodeConfig. * `security` - (Required) The Security of NodeConfig. -* `subnet_ids` - (Required, ForceNew) The SubnetIds of NodeConfig. +* `subnet_ids` - (Required) The SubnetIds of NodeConfig. * `additional_container_storage_enabled` - (Optional, ForceNew) The AdditionalContainerStorageEnabled of NodeConfig. -* `auto_renew_period` - (Optional, ForceNew) The AutoRenewPeriod of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 6, 12. Unit: month. when InstanceChargeType is PrePaid and AutoRenew enable, default value is 1. -* `auto_renew` - (Optional, ForceNew) Is AutoRenew of PrePaid instance of NodeConfig. Valid values: true, false. when InstanceChargeType is PrePaid, default value is true. +* `auto_renew_period` - (Optional) The AutoRenewPeriod of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 6, 12. Unit: month. when InstanceChargeType is PrePaid and AutoRenew enable, default value is 1. +* `auto_renew` - (Optional) Is AutoRenew of PrePaid instance of NodeConfig. Valid values: true, false. when InstanceChargeType is PrePaid, default value is true. * `data_volumes` - (Optional, ForceNew) The DataVolumes of NodeConfig. +* `ecs_tags` - (Optional) Tags for Ecs. * `image_id` - (Optional, ForceNew) The ImageId of NodeConfig. * `initialize_script` - (Optional) The initializeScript of NodeConfig. * `instance_charge_type` - (Optional, ForceNew) The InstanceChargeType of PrePaid instance of NodeConfig. Valid values: PostPaid, PrePaid. Default value: PostPaid. -* `period` - (Optional, ForceNew) The Period of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36. Unit: month. when InstanceChargeType is PrePaid, default value is 12. +* `name_prefix` - (Optional) The NamePrefix of NodeConfig. +* `period` - (Optional) The Period of PrePaid instance of NodeConfig. Valid values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36. Unit: month. when InstanceChargeType is PrePaid, default value is 12. * `system_volume` - (Optional, ForceNew) The SystemVolume of NodeConfig. The `security` object supports the following: @@ -107,6 +124,11 @@ The `system_volume` object supports the following: * `size` - (Optional, ForceNew) The Size of SystemVolume, the value range in 20~2048. * `type` - (Optional, ForceNew) The Type of SystemVolume, the value can be `PTSSD` or `ESSD_PL0` or `ESSD_FlexPL`. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + The `taints` object supports the following: * `effect` - (Optional) The Effect of Taints, the value can be `NoSchedule` or `NoExecute` or `PreferNoSchedule`. @@ -122,6 +144,6 @@ In addition to all arguments above, the following attributes are exported: ## Import NodePool can be imported using the id, e.g. ``` -$ terraform import volcengine_node_pools.default pcabe57vqtofgrbln3dp0 +$ terraform import volcengine_vke_node_pool.default pcabe57vqtofgrbln3dp0 ``` From 1316abc32db67b458fe572c07b00c8815806c65f Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Thu, 24 Nov 2022 19:52:24 +0800 Subject: [PATCH 05/58] =?UTF-8?q?feat:=20support=20Tags=20and=20ProjectNam?= =?UTF-8?q?e=20for=20vpc=E3=80=81eip=E3=80=81clb=20and=20ecs=20instance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common_volcengine_tags.go | 59 +++++++++++++++++++ common/common_volcengine_version.go | 2 +- .../clb/acl/data_source_volcengine_acls.go | 10 ++++ volcengine/clb/acl/resource_volcengine_acl.go | 6 ++ .../data_source_volcengine_certificates.go | 10 ++++ .../resource_volcengine_certificate.go | 6 ++ .../clb/clb/data_source_volcengine_clbs.go | 12 ++++ volcengine/clb/clb/resource_volcengine_clb.go | 7 +++ volcengine/clb/clb/service_volcengine_clb.go | 34 ++++++++++- .../data_source_volcengine_ecs_instances.go | 12 ++++ .../resource_volcengine_ecs_instance.go | 7 +++ .../service_volcengine_ecs_instance.go | 18 ++++++ .../data_source_volcengine_eip_addresses.go | 12 ++++ .../resource_volcengine_eip_address.go | 7 +++ .../service_volcengine_eip_address.go | 19 ++++++ ...ta_source_volcengine_network_interfaces.go | 12 ++++ .../resource_volcengine_network_interface.go | 7 +++ .../service_volcengine_network_interface.go | 34 ++++++++++- .../data_source_volcengine_route_tables.go | 10 ++++ .../resource_volcengine_route_table.go | 5 ++ .../data_source_volcengine_security_groups.go | 12 ++++ .../resource_volcengine_security_group.go | 7 +++ .../service_volcengine_security_group.go | 36 ++++++++++- .../vpc/vpc/data_source_volcengine_vpcs.go | 12 ++++ volcengine/vpc/vpc/resource_volcengine_vpc.go | 7 +++ volcengine/vpc/vpc/service_volcengine_vpc.go | 34 ++++++++++- website/docs/d/acls.html.markdown | 2 + website/docs/d/certificates.html.markdown | 2 + website/docs/d/clbs.html.markdown | 11 ++++ website/docs/d/ecs_instances.html.markdown | 11 ++++ website/docs/d/eip_addresses.html.markdown | 11 ++++ .../docs/d/network_interfaces.html.markdown | 11 ++++ website/docs/d/route_tables.html.markdown | 2 + website/docs/d/security_groups.html.markdown | 11 ++++ website/docs/d/vpcs.html.markdown | 11 ++++ website/docs/r/acl.html.markdown | 1 + website/docs/r/certificate.html.markdown | 1 + website/docs/r/clb.html.markdown | 7 +++ website/docs/r/ecs_instance.html.markdown | 7 +++ website/docs/r/eip_address.html.markdown | 7 +++ .../docs/r/network_interface.html.markdown | 7 +++ website/docs/r/route_table.html.markdown | 1 + website/docs/r/security_group.html.markdown | 7 +++ website/docs/r/vpc.html.markdown | 7 +++ 44 files changed, 509 insertions(+), 5 deletions(-) diff --git a/common/common_volcengine_tags.go b/common/common_volcengine_tags.go index 343b531c..366c857d 100644 --- a/common/common_volcengine_tags.go +++ b/common/common_volcengine_tags.go @@ -3,6 +3,8 @@ package common import ( "bytes" "fmt" + "github.com/volcengine/terraform-provider-volcengine/logger" + "strconv" "strings" "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" @@ -80,3 +82,60 @@ var VkeTagsResponseHash = func(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["type"].(string)))) return hashcode.String(buf.String()) } + +type GetUniversalInfo func(actionName string) UniversalInfo + +func SetResourceTags(serviceClient *SdkClient, addAction, RemoveAction, resourceType string, + resourceData *schema.ResourceData, getUniversalInfo GetUniversalInfo) []Callback { + var callbacks []Callback + addedTags, removedTags, _, _ := GetSetDifference("tags", resourceData, TagsHash, false) + + removeCallback := Callback{ + Call: SdkCall{ + Action: RemoveAction, + ConvertMode: RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *SdkClient, call SdkCall) (bool, error) { + if removedTags != nil && len(removedTags.List()) > 0 { + (*call.SdkParam)["ResourceIds.1"] = resourceData.Id() + (*call.SdkParam)["ResourceType"] = resourceType + for index, tag := range removedTags.List() { + (*call.SdkParam)["TagKeys."+strconv.Itoa(index+1)] = tag.(map[string]interface{})["key"].(string) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *SdkClient, call SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return serviceClient.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + addCallback := Callback{ + Call: SdkCall{ + Action: addAction, + ConvertMode: RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *SdkClient, call SdkCall) (bool, error) { + if addedTags != nil && len(addedTags.List()) > 0 { + (*call.SdkParam)["ResourceIds.1"] = resourceData.Id() + (*call.SdkParam)["ResourceType"] = resourceType + for index, tag := range addedTags.List() { + (*call.SdkParam)["Tags."+strconv.Itoa(index+1)+".Key"] = tag.(map[string]interface{})["key"].(string) + (*call.SdkParam)["Tags."+strconv.Itoa(index+1)+".Value"] = tag.(map[string]interface{})["value"].(string) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *SdkClient, call SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return serviceClient.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, addCallback) + + return callbacks +} diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index 2a7322be..5c0f3a8b 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.42" + TerraformProviderVersion = "0.0.43" ) diff --git a/volcengine/clb/acl/data_source_volcengine_acls.go b/volcengine/clb/acl/data_source_volcengine_acls.go index 21d776ac..8bffd7c4 100644 --- a/volcengine/clb/acl/data_source_volcengine_acls.go +++ b/volcengine/clb/acl/data_source_volcengine_acls.go @@ -25,6 +25,11 @@ func DataSourceVolcengineAcls() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "A Name Regex of Acl.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of Acl.", + }, "output_file": { Type: schema.TypeString, Optional: true, @@ -90,6 +95,11 @@ func DataSourceVolcengineAcls() *schema.Resource { }, Set: schema.HashString, }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of Acl.", + }, }, }, }, diff --git a/volcengine/clb/acl/resource_volcengine_acl.go b/volcengine/clb/acl/resource_volcengine_acl.go index c47afab2..cf3989d5 100644 --- a/volcengine/clb/acl/resource_volcengine_acl.go +++ b/volcengine/clb/acl/resource_volcengine_acl.go @@ -64,6 +64,12 @@ func ResourceVolcengineAcl() *schema.Resource { }, }, }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the Acl.", + }, "create_time": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/clb/certificate/data_source_volcengine_certificates.go b/volcengine/clb/certificate/data_source_volcengine_certificates.go index e221085f..30e0fe6c 100644 --- a/volcengine/clb/certificate/data_source_volcengine_certificates.go +++ b/volcengine/clb/certificate/data_source_volcengine_certificates.go @@ -25,6 +25,11 @@ func DataSourceVolcengineCertificates() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "The Name Regex of Certificate.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of Certificate.", + }, "output_file": { Type: schema.TypeString, @@ -83,6 +88,11 @@ func DataSourceVolcengineCertificates() *schema.Resource { Computed: true, Description: "The domain name of the Certificate.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the Certificate.", + }, "listeners": { Type: schema.TypeSet, Elem: &schema.Schema{ diff --git a/volcengine/clb/certificate/resource_volcengine_certificate.go b/volcengine/clb/certificate/resource_volcengine_certificate.go index 59b80035..a67384a5 100644 --- a/volcengine/clb/certificate/resource_volcengine_certificate.go +++ b/volcengine/clb/certificate/resource_volcengine_certificate.go @@ -55,6 +55,12 @@ func ResourceVolcengineCertificate() *schema.Resource { ForceNew: true, Description: "The description of the Certificate.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the Certificate.", + }, }, } } diff --git a/volcengine/clb/clb/data_source_volcengine_clbs.go b/volcengine/clb/clb/data_source_volcengine_clbs.go index 4fc14804..e34dddca 100644 --- a/volcengine/clb/clb/data_source_volcengine_clbs.go +++ b/volcengine/clb/clb/data_source_volcengine_clbs.go @@ -25,6 +25,12 @@ func DataSourceVolcengineClbs() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "A Name Regex of Clb.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of Clb.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -168,6 +174,12 @@ func DataSourceVolcengineClbs() *schema.Resource { Computed: true, Description: "The billing type of the Clb.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the Clb.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/clb/clb/resource_volcengine_clb.go b/volcengine/clb/clb/resource_volcengine_clb.go index b22cbaf3..d0049a6c 100644 --- a/volcengine/clb/clb/resource_volcengine_clb.go +++ b/volcengine/clb/clb/resource_volcengine_clb.go @@ -103,6 +103,13 @@ func ResourceVolcengineClb() *schema.Resource { Description: "The billing type of the CLB, the value can be `PostPaid`.", ValidateFunc: validation.StringInSlice([]string{"PostPaid"}, false), }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the CLB.", + }, + "tags": ve.TagsSchema(), //"period_unit": { // Type: schema.TypeString, // Optional: true, diff --git a/volcengine/clb/clb/service_volcengine_clb.go b/volcengine/clb/clb/service_volcengine_clb.go index 0c315419..9c7b01dc 100644 --- a/volcengine/clb/clb/service_volcengine_clb.go +++ b/volcengine/clb/clb/service_volcengine_clb.go @@ -173,6 +173,10 @@ func (s *VolcengineClbService) CreateResource(resourceData *schema.ResourceData, return i }, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { if regionId, ok := (*call.SdkParam)["RegionId"]; !ok { @@ -204,6 +208,8 @@ func (s *VolcengineClbService) CreateResource(resourceData *schema.ResourceData, } func (s *VolcengineClbService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyLoadBalancerAttributes", @@ -228,6 +234,7 @@ func (s *VolcengineClbService) ModifyResource(resourceData *schema.ResourceData, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["LoadBalancerId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -241,7 +248,13 @@ func (s *VolcengineClbService) ModifyResource(resourceData *schema.ResourceData, }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "CLB", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + + return callbacks } func (s *VolcengineClbService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -287,6 +300,15 @@ func (s *VolcengineClbService) DatasourceResources(*schema.ResourceData, *schema TargetField: "LoadBalancerIds", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "LoadBalancerName", IdField: "LoadBalancerId", @@ -325,3 +347,13 @@ func (s *VolcengineClbService) DatasourceResources(*schema.ResourceData, *schema func (s *VolcengineClbService) ReadResourceId(id string) string { return id } + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "clb", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go b/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go index 3c0c25de..6128cd29 100644 --- a/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go +++ b/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go @@ -60,6 +60,12 @@ func DataSourceVolcengineEcsInstances() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "A Name Regex of ECS instance.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of ECS instance.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -284,6 +290,12 @@ func DataSourceVolcengineEcsInstances() *schema.Resource { }, }, }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of ECS instance.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go b/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go index 57c9ae4e..848a5167 100644 --- a/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go +++ b/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go @@ -282,6 +282,13 @@ func ResourceVolcengineEcsInstance() *schema.Resource { }, }, }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the VPC.", + }, + "tags": ve.TagsSchema(), }, } dataSource := DataSourceVolcengineEcsInstances().Schema["instances"].Elem.(*schema.Resource).Schema diff --git a/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go b/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go index acb1ea25..f44b03e4 100644 --- a/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go +++ b/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go @@ -393,6 +393,10 @@ func (s *VolcengineEcsService) CreateResource(resourceData *schema.ResourceData, } }, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["ClientToken"] = uuid.New().String() @@ -481,6 +485,7 @@ func (s *VolcengineEcsService) ModifyResource(resourceData *schema.ResourceData, delete(*call.SdkParam, "Password") } if len(*call.SdkParam) > 1 { + delete(*call.SdkParam, "Tags") return true, nil } return false, nil @@ -799,6 +804,10 @@ func (s *VolcengineEcsService) ModifyResource(resourceData *schema.ResourceData, startInstance := s.StartOrStopInstanceCallback(resourceData, false, &flag) callbacks = append(callbacks, startInstance) + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "CreateTags", "DeleteTags", "instance", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + return callbacks } @@ -849,6 +858,15 @@ func (s *VolcengineEcsService) DatasourceResources(data *schema.ResourceData, re TargetField: "InstanceIds", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "InstanceName", IdField: "InstanceId", diff --git a/volcengine/eip/eip_address/data_source_volcengine_eip_addresses.go b/volcengine/eip/eip_address/data_source_volcengine_eip_addresses.go index 0212de1b..b2f04c23 100644 --- a/volcengine/eip/eip_address/data_source_volcengine_eip_addresses.go +++ b/volcengine/eip/eip_address/data_source_volcengine_eip_addresses.go @@ -56,6 +56,12 @@ func DataSourceVolcengineEipAddresses() *schema.Resource { Optional: true, Description: "An id of associated instance.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of EIP.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -163,6 +169,12 @@ func DataSourceVolcengineEipAddresses() *schema.Resource { Computed: true, Description: "The expired time of the EIP.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the EIP.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/eip/eip_address/resource_volcengine_eip_address.go b/volcengine/eip/eip_address/resource_volcengine_eip_address.go index f9bc8499..df6b2c55 100644 --- a/volcengine/eip/eip_address/resource_volcengine_eip_address.go +++ b/volcengine/eip/eip_address/resource_volcengine_eip_address.go @@ -65,6 +65,13 @@ func ResourceVolcengineEipAddress() *schema.Resource { Optional: true, Description: "The description of the EIP.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the EIP.", + }, + "tags": ve.TagsSchema(), "status": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/eip/eip_address/service_volcengine_eip_address.go b/volcengine/eip/eip_address/service_volcengine_eip_address.go index 3ca03f33..19dd8e2e 100644 --- a/volcengine/eip/eip_address/service_volcengine_eip_address.go +++ b/volcengine/eip/eip_address/service_volcengine_eip_address.go @@ -167,6 +167,10 @@ func (s *VolcengineEipAddressService) CreateResource(resourceData *schema.Resour "isp": { TargetField: "ISP", }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, }, } @@ -183,6 +187,7 @@ func (s *VolcengineEipAddressService) ModifyResource(resourceData *schema.Resour BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { if len(*call.SdkParam) > 0 { (*call.SdkParam)["AllocationId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil } return false, nil @@ -237,6 +242,11 @@ func (s *VolcengineEipAddressService) ModifyResource(resourceData *schema.Resour } callbacks = append(callbacks, chargeTypeCall) } + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "eip", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + return callbacks } @@ -292,6 +302,15 @@ func (s *VolcengineEipAddressService) DatasourceResources(*schema.ResourceData, "isp": { TargetField: "ISP", }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "Name", IdField: "AllocationId", diff --git a/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go b/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go index 9be14e2f..5a28f16d 100644 --- a/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go +++ b/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go @@ -64,6 +64,12 @@ func DataSourceVolcengineNetworkInterfaces() *schema.Resource { Optional: true, Description: "A name of ENI.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of the ENI.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -184,6 +190,12 @@ func DataSourceVolcengineNetworkInterfaces() *schema.Resource { Computed: true, Description: "The IP address of the EIP to which the ENI associates.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the ENI.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/vpc/network_interface/resource_volcengine_network_interface.go b/volcengine/vpc/network_interface/resource_volcengine_network_interface.go index fa95cb23..ee1726f2 100644 --- a/volcengine/vpc/network_interface/resource_volcengine_network_interface.go +++ b/volcengine/vpc/network_interface/resource_volcengine_network_interface.go @@ -73,6 +73,13 @@ func ResourceVolcengineNetworkInterface() *schema.Resource { Computed: true, Description: "Set port security enable or disable.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the ENI.", + }, + "tags": ve.TagsSchema(), "status": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/vpc/network_interface/service_volcengine_network_interface.go b/volcengine/vpc/network_interface/service_volcengine_network_interface.go index 8af70ae2..d721e1fe 100644 --- a/volcengine/vpc/network_interface/service_volcengine_network_interface.go +++ b/volcengine/vpc/network_interface/service_volcengine_network_interface.go @@ -153,6 +153,10 @@ func (s *VolcengineNetworkInterfaceService) CreateResource(resourceData *schema. TargetField: "SecurityGroupIds", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, }, } @@ -160,12 +164,15 @@ func (s *VolcengineNetworkInterfaceService) CreateResource(resourceData *schema. } func (s *VolcengineNetworkInterfaceService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyNetworkInterfaceAttributes", ConvertMode: ve.RequestConvertAll, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["NetworkInterfaceId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -180,7 +187,13 @@ func (s *VolcengineNetworkInterfaceService) ModifyResource(resourceData *schema. }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "eni", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + + return callbacks } func (s *VolcengineNetworkInterfaceService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -232,6 +245,15 @@ func (s *VolcengineNetworkInterfaceService) DatasourceResources(*schema.Resource TargetField: "PrimaryIpAddresses", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "NetworkInterfaceName", IdField: "NetworkInterfaceId", @@ -254,3 +276,13 @@ func (s *VolcengineNetworkInterfaceService) DatasourceResources(*schema.Resource func (s *VolcengineNetworkInterfaceService) ReadResourceId(id string) string { return id } + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/vpc/route_table/data_source_volcengine_route_tables.go b/volcengine/vpc/route_table/data_source_volcengine_route_tables.go index 594fd89e..ba343a85 100644 --- a/volcengine/vpc/route_table/data_source_volcengine_route_tables.go +++ b/volcengine/vpc/route_table/data_source_volcengine_route_tables.go @@ -27,6 +27,11 @@ func DataSourceVolcengineRouteTables() *schema.Resource { Optional: true, Description: "A name of route table.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of the route table.", + }, "output_file": { Type: schema.TypeString, @@ -102,6 +107,11 @@ func DataSourceVolcengineRouteTables() *schema.Resource { Computed: true, Description: "The description of the route table.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the route table.", + }, }, }, }, diff --git a/volcengine/vpc/route_table/resource_volcengine_route_table.go b/volcengine/vpc/route_table/resource_volcengine_route_table.go index c6d51815..c3c012cd 100644 --- a/volcengine/vpc/route_table/resource_volcengine_route_table.go +++ b/volcengine/vpc/route_table/resource_volcengine_route_table.go @@ -50,6 +50,11 @@ func ResourceVolcengineRouteTable() *schema.Resource { Optional: true, Description: "The description of the route table.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of the route table.", + }, }, } } diff --git a/volcengine/vpc/security_group/data_source_volcengine_security_groups.go b/volcengine/vpc/security_group/data_source_volcengine_security_groups.go index 983b725f..a559ec36 100644 --- a/volcengine/vpc/security_group/data_source_volcengine_security_groups.go +++ b/volcengine/vpc/security_group/data_source_volcengine_security_groups.go @@ -25,6 +25,12 @@ func DataSourceVolcengineSecurityGroups() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "A Name Regex of SecurityGroup.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of SecurityGroup.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, Optional: true, @@ -81,6 +87,12 @@ func DataSourceVolcengineSecurityGroups() *schema.Resource { Computed: true, Description: "A Name Regex of SecurityGroup.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of SecurityGroup.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/vpc/security_group/resource_volcengine_security_group.go b/volcengine/vpc/security_group/resource_volcengine_security_group.go index d9dd2e79..a1acfe4f 100644 --- a/volcengine/vpc/security_group/resource_volcengine_security_group.go +++ b/volcengine/vpc/security_group/resource_volcengine_security_group.go @@ -60,6 +60,13 @@ func ResourceVolcengineSecurityGroup() *schema.Resource { Computed: true, Description: "Name of SecurityGroup.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of SecurityGroup.", + }, + "tags": ve.TagsSchema(), }, } } diff --git a/volcengine/vpc/security_group/service_volcengine_security_group.go b/volcengine/vpc/security_group/service_volcengine_security_group.go index c07381c3..086d9e60 100644 --- a/volcengine/vpc/security_group/service_volcengine_security_group.go +++ b/volcengine/vpc/security_group/service_volcengine_security_group.go @@ -140,6 +140,12 @@ func (s *VolcengineSecurityGroupService) CreateResource(resourceData *schema.Res Call: ve.SdkCall{ Action: "CreateSecurityGroup", ConvertMode: ve.RequestConvertAll, + Convert: map[string]ve.RequestConvert{ + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, + }, LockId: func(d *schema.ResourceData) string { return d.Get("vpc_id").(string) }, @@ -171,6 +177,8 @@ func (s *VolcengineSecurityGroupService) CreateResource(resourceData *schema.Res } func (s *VolcengineSecurityGroupService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifySecurityGroupAttributes", @@ -180,6 +188,7 @@ func (s *VolcengineSecurityGroupService) ModifyResource(resourceData *schema.Res }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["SecurityGroupId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -199,7 +208,13 @@ func (s *VolcengineSecurityGroupService) ModifyResource(resourceData *schema.Res }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "securitygroup", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + + return callbacks } func (s *VolcengineSecurityGroupService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -251,6 +266,15 @@ func (s *VolcengineSecurityGroupService) DatasourceResources(*schema.ResourceDat TargetField: "SecurityGroupNames", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "SecurityGroupName", IdField: "SecurityGroupId", @@ -267,3 +291,13 @@ func (s *VolcengineSecurityGroupService) DatasourceResources(*schema.ResourceDat func (s *VolcengineSecurityGroupService) ReadResourceId(id string) string { return id } + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go index 0ae4a50a..3c19bdb6 100644 --- a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go +++ b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go @@ -25,6 +25,12 @@ func DataSourceVolcengineVpcs() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "A Name Regex of Vpc.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The ProjectName of the VPC.", + }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -164,6 +170,12 @@ func DataSourceVolcengineVpcs() *schema.Resource { Set: schema.HashString, Description: "The auxiliary cidr block list of VPC.", }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The ProjectName of the VPC.", + }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/vpc/vpc/resource_volcengine_vpc.go b/volcengine/vpc/vpc/resource_volcengine_vpc.go index 9ae34180..37da5869 100644 --- a/volcengine/vpc/vpc/resource_volcengine_vpc.go +++ b/volcengine/vpc/vpc/resource_volcengine_vpc.go @@ -62,6 +62,13 @@ func ResourceVolcengineVpc() *schema.Resource { Set: schema.HashString, Description: "The DNS server list of the VPC. And you can specify 0 to 5 servers to this list.", }, + "project_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The ProjectName of the VPC.", + }, + "tags": ve.TagsSchema(), "status": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/vpc/vpc/service_volcengine_vpc.go b/volcengine/vpc/vpc/service_volcengine_vpc.go index d203ae52..d2c85a94 100644 --- a/volcengine/vpc/vpc/service_volcengine_vpc.go +++ b/volcengine/vpc/vpc/service_volcengine_vpc.go @@ -146,6 +146,10 @@ func (s *VolcengineVpcService) CreateResource(resourceData *schema.ResourceData, TargetField: "DnsServers", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.RespFormat, call.Action, call.SdkParam) @@ -169,6 +173,8 @@ func (s *VolcengineVpcService) CreateResource(resourceData *schema.ResourceData, } func (s *VolcengineVpcService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyVpcAttributes", @@ -181,6 +187,7 @@ func (s *VolcengineVpcService) ModifyResource(resourceData *schema.ResourceData, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["VpcId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -194,7 +201,13 @@ func (s *VolcengineVpcService) ModifyResource(resourceData *schema.ResourceData, }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "vpc", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + + return callbacks } func (s *VolcengineVpcService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -240,6 +253,15 @@ func (s *VolcengineVpcService) DatasourceResources(*schema.ResourceData, *schema TargetField: "VpcIds", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "VpcName", IdField: "VpcId", @@ -256,3 +278,13 @@ func (s *VolcengineVpcService) DatasourceResources(*schema.ResourceData, *schema func (s *VolcengineVpcService) ReadResourceId(id string) string { return id } + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/website/docs/d/acls.html.markdown b/website/docs/d/acls.html.markdown index f23c4958..30329ca2 100644 --- a/website/docs/d/acls.html.markdown +++ b/website/docs/d/acls.html.markdown @@ -20,6 +20,7 @@ The following arguments are supported: * `ids` - (Optional) A list of Acl IDs. * `name_regex` - (Optional) A Name Regex of Acl. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of Acl. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -31,6 +32,7 @@ In addition to all arguments above, the following attributes are exported: * `description` - The description of Acl. * `id` - The ID of Acl. * `listeners` - The listeners of Acl. + * `project_name` - The ProjectName of Acl. * `update_time` - Update time of Acl. * `total_count` - The total count of Acl query. diff --git a/website/docs/d/certificates.html.markdown b/website/docs/d/certificates.html.markdown index ac986893..e73793dc 100644 --- a/website/docs/d/certificates.html.markdown +++ b/website/docs/d/certificates.html.markdown @@ -20,6 +20,7 @@ The following arguments are supported: * `ids` - (Optional) The list of Certificate IDs. * `name_regex` - (Optional) The Name Regex of Certificate. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of Certificate. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -32,6 +33,7 @@ In addition to all arguments above, the following attributes are exported: * `expired_at` - The expire time of the Certificate. * `id` - The ID of the Certificate. * `listeners` - The ID list of the Listener. + * `project_name` - The ProjectName of the Certificate. * `total_count` - The total count of Certificate query. diff --git a/website/docs/d/clbs.html.markdown b/website/docs/d/clbs.html.markdown index cef891d4..967ec9d5 100644 --- a/website/docs/d/clbs.html.markdown +++ b/website/docs/d/clbs.html.markdown @@ -21,8 +21,15 @@ The following arguments are supported: * `load_balancer_name` - (Optional) The name of the Clb. * `name_regex` - (Optional) A Name Regex of Clb. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of Clb. +* `tags` - (Optional) Tags. * `vpc_id` - (Optional) The id of the VPC. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `clbs` - The collection of Clb query. @@ -43,8 +50,12 @@ In addition to all arguments above, the following attributes are exported: * `modification_protection_reason` - The modification protection reason of the Clb. * `modification_protection_status` - The modification protection status of the Clb. * `overdue_time` - The overdue time of the Clb. + * `project_name` - The ProjectName of the Clb. * `status` - The status of the Clb. * `subnet_id` - The subnet ID of the Clb. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `type` - The type of the Clb. * `update_time` - The update time of the Clb. * `vpc_id` - The vpc ID of the Clb. diff --git a/website/docs/d/ecs_instances.html.markdown b/website/docs/d/ecs_instances.html.markdown index a7d85bdc..de1ec6ef 100644 --- a/website/docs/d/ecs_instances.html.markdown +++ b/website/docs/d/ecs_instances.html.markdown @@ -23,10 +23,17 @@ The following arguments are supported: * `name_regex` - (Optional) A Name Regex of ECS instance. * `output_file` - (Optional) File name where to save data source results. * `primary_ip_address` - (Optional) The primary ip address of ECS instance. +* `project_name` - (Optional) The ProjectName of ECS instance. * `status` - (Optional) The status of ECS instance. +* `tags` - (Optional) Tags. * `vpc_id` - (Optional) The VPC ID of ECS instance. * `zone_id` - (Optional) The available zone ID of ECS instance. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `instances` - The collection of ECS instance query. @@ -57,8 +64,12 @@ In addition to all arguments above, the following attributes are exported: * `vpc_id` - The ID of networkInterface. * `os_name` - The os name of ECS instance. * `os_type` - The os type of ECS instance. + * `project_name` - The ProjectName of ECS instance. * `status` - The status of ECS instance. * `stopped_mode` - The stop mode of ECS instance. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `updated_at` - The update time of ECS instance. * `volumes` - The volume detail collection of volume. * `delete_with_instance` - The delete with instance flag of volume. diff --git a/website/docs/d/eip_addresses.html.markdown b/website/docs/d/eip_addresses.html.markdown index 50cf3b37..456d08da 100644 --- a/website/docs/d/eip_addresses.html.markdown +++ b/website/docs/d/eip_addresses.html.markdown @@ -23,7 +23,14 @@ The following arguments are supported: * `isp` - (Optional) An ISP of EIP Address, the value can be `BGP` or `ChinaMobile` or `ChinaUnicom` or `ChinaTelecom`. * `name` - (Optional) A name of EIP. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of EIP. * `status` - (Optional) A status of EIP, the value can be `Attaching` or `Detaching` or `Attached` or `Available`. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -44,7 +51,11 @@ In addition to all arguments above, the following attributes are exported: * `lock_reason` - The lock reason of the EIP. * `name` - The name of the EIP. * `overdue_time` - The overdue time of the EIP. + * `project_name` - The ProjectName of the EIP. * `status` - The status of the EIP. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `updated_at` - The last update time of the EIP. * `total_count` - The total count of EIP addresses query. diff --git a/website/docs/d/network_interfaces.html.markdown b/website/docs/d/network_interfaces.html.markdown index 774f0103..87cbb2c6 100644 --- a/website/docs/d/network_interfaces.html.markdown +++ b/website/docs/d/network_interfaces.html.markdown @@ -21,12 +21,19 @@ The following arguments are supported: * `network_interface_name` - (Optional) A name of ENI. * `output_file` - (Optional) File name where to save data source results. * `primary_ip_addresses` - (Optional) A list of primary IP address of ENI. +* `project_name` - (Optional) The ProjectName of the ENI. * `security_group_id` - (Optional) An id of the security group to which the secondary ENI belongs. * `status` - (Optional) A status of ENI, Optional choice contains `Creating`, `Available`, `Attaching`, `InUse`, `Detaching`, `Deleting`. * `subnet_id` - (Optional) An id of the subnet to which the ENI is connected. +* `tags` - (Optional) Tags. * `type` - (Optional) A type of ENI, Optional choice contains `primary`, `secondary`. * `vpc_id` - (Optional) An id of the virtual private cloud (VPC) to which the ENI belongs. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `network_interfaces` - The collection of ENI. @@ -42,9 +49,13 @@ In addition to all arguments above, the following attributes are exported: * `network_interface_name` - The name of the ENI. * `port_security_enabled` - The enable of port security. * `primary_ip_address` - The primary IP address of the ENI. + * `project_name` - The ProjectName of the ENI. * `security_group_ids` - The list of the security group id to which the secondary ENI belongs. * `status` - The status of the ENI. * `subnet_id` - The id of the subnet to which the ENI is connected. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `type` - The type of the ENI. * `updated_at` - The last update time of the ENI. * `vpc_id` - The id of the virtual private cloud (VPC) to which the ENI belongs. diff --git a/website/docs/d/route_tables.html.markdown b/website/docs/d/route_tables.html.markdown index 4552abc2..ea51ee4a 100644 --- a/website/docs/d/route_tables.html.markdown +++ b/website/docs/d/route_tables.html.markdown @@ -19,6 +19,7 @@ data "volcengine_route_tables" "default" { The following arguments are supported: * `ids` - (Optional) A list of route table ids. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of the route table. * `route_table_name` - (Optional) A name of route table. * `vpc_id` - (Optional) An id of VPC. @@ -29,6 +30,7 @@ In addition to all arguments above, the following attributes are exported: * `creation_time` - The create time of the route table. * `description` - The description of the route table. * `id` - The id of the route table. + * `project_name` - The ProjectName of the route table. * `route_table_id` - The id of the route table. * `route_table_name` - The name of the route table. * `route_table_type` - The type of the route table. diff --git a/website/docs/d/security_groups.html.markdown b/website/docs/d/security_groups.html.markdown index bc9ee671..7454738a 100644 --- a/website/docs/d/security_groups.html.markdown +++ b/website/docs/d/security_groups.html.markdown @@ -19,6 +19,13 @@ The following arguments are supported: * `ids` - (Optional) A list of SecurityGroup IDs. * `name_regex` - (Optional) A Name Regex of SecurityGroup. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of SecurityGroup. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -26,9 +33,13 @@ In addition to all arguments above, the following attributes are exported: * `creation_time` - The creation time of SecurityGroup. * `description` - The description of SecurityGroup. * `id` - The ID of SecurityGroup. + * `project_name` - The ProjectName of SecurityGroup. * `security_group_id` - The ID of SecurityGroup. * `security_group_name` - The Name of SecurityGroup. * `status` - The Status of SecurityGroup. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `type` - A Name Regex of SecurityGroup. * `vpc_id` - The ID of Vpc. * `total_count` - The total count of SecurityGroup query. diff --git a/website/docs/d/vpcs.html.markdown b/website/docs/d/vpcs.html.markdown index e3acaa59..07d6bed5 100644 --- a/website/docs/d/vpcs.html.markdown +++ b/website/docs/d/vpcs.html.markdown @@ -19,6 +19,13 @@ The following arguments are supported: * `ids` - (Optional) A list of VPC IDs. * `name_regex` - (Optional) A Name Regex of Vpc. * `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The ProjectName of the VPC. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -35,10 +42,14 @@ In addition to all arguments above, the following attributes are exported: * `description` - The description of VPC. * `dns_servers` - The dns server list of VPC. * `nat_gateway_ids` - The nat gateway ID list of VPC. + * `project_name` - The ProjectName of the VPC. * `route_table_ids` - The route table ID list of VPC. * `security_group_ids` - The security group ID list of VPC. * `status` - The status of VPC. * `subnet_ids` - The subnet ID list of VPC. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `update_time` - The update time of VPC. * `vpc_id` - The ID of VPC. * `vpc_name` - The name of VPC. diff --git a/website/docs/r/acl.html.markdown b/website/docs/r/acl.html.markdown index 33a5dc73..5e9fadce 100644 --- a/website/docs/r/acl.html.markdown +++ b/website/docs/r/acl.html.markdown @@ -28,6 +28,7 @@ The following arguments are supported: * `acl_entries` - (Optional) The acl entry set of the Acl. * `acl_name` - (Optional) The name of Acl. * `description` - (Optional) The description of the Acl. +* `project_name` - (Optional, ForceNew) The ProjectName of the Acl. The `acl_entries` object supports the following: diff --git a/website/docs/r/certificate.html.markdown b/website/docs/r/certificate.html.markdown index 55276eea..976f5bdf 100644 --- a/website/docs/r/certificate.html.markdown +++ b/website/docs/r/certificate.html.markdown @@ -23,6 +23,7 @@ The following arguments are supported: * `public_key` - (Required, ForceNew) The public key of the Certificate. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. * `certificate_name` - (Optional, ForceNew) The name of the Certificate. * `description` - (Optional, ForceNew) The description of the Certificate. +* `project_name` - (Optional, ForceNew) The ProjectName of the Certificate. ## Attributes Reference In addition to all arguments above, the following attributes are exported: diff --git a/website/docs/r/clb.html.markdown b/website/docs/r/clb.html.markdown index 66459941..b41173f7 100644 --- a/website/docs/r/clb.html.markdown +++ b/website/docs/r/clb.html.markdown @@ -29,9 +29,16 @@ The following arguments are supported: * `load_balancer_name` - (Optional) The name of the CLB. * `modification_protection_reason` - (Optional) The reason of the console modification protection. * `modification_protection_status` - (Optional) The status of the console modification protection, the value can be `NonProtection` or `ConsoleProtection`. +* `project_name` - (Optional, ForceNew) The ProjectName of the CLB. * `region_id` - (Optional, ForceNew) The region of the request. +* `tags` - (Optional) Tags. * `vpc_id` - (Optional, ForceNew) The id of the VPC. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. diff --git a/website/docs/r/ecs_instance.html.markdown b/website/docs/r/ecs_instance.html.markdown index 6512d88d..d51a8971 100644 --- a/website/docs/r/ecs_instance.html.markdown +++ b/website/docs/r/ecs_instance.html.markdown @@ -71,8 +71,10 @@ The following arguments are supported: * `key_pair_name` - (Optional, ForceNew) The ssh key name of ECS instance. * `password` - (Optional) The password of ECS instance. * `period` - (Optional) The period of ECS instance.Only effective when instance_charge_type is PrePaid. Default is 12. Unit is Month. +* `project_name` - (Optional, ForceNew) The ProjectName of the VPC. * `secondary_network_interfaces` - (Optional) The secondary networkInterface detail collection of ECS instance. * `security_enhancement_strategy` - (Optional, ForceNew) The security enhancement strategy of ECS instance. The value can be Active or InActive. Default is Active.When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. +* `tags` - (Optional) Tags. * `user_data` - (Optional) The user data of ECS instance, this field must be encrypted with base64. * `zone_id` - (Optional, ForceNew) The available zone ID of ECS instance. @@ -87,6 +89,11 @@ The `secondary_network_interfaces` object supports the following: * `security_group_ids` - (Required, ForceNew) The security group ID set of secondary networkInterface. * `subnet_id` - (Required, ForceNew) The subnet ID of secondary networkInterface. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. diff --git a/website/docs/r/eip_address.html.markdown b/website/docs/r/eip_address.html.markdown index 51dc1ac3..ad5b687b 100644 --- a/website/docs/r/eip_address.html.markdown +++ b/website/docs/r/eip_address.html.markdown @@ -25,6 +25,13 @@ The following arguments are supported: * `description` - (Optional) The description of the EIP. * `isp` - (Optional, ForceNew) The ISP of the EIP, the value can be `BGP` or `ChinaMobile` or `ChinaUnicom` or `ChinaTelecom`. * `name` - (Optional) The name of the EIP Address. +* `project_name` - (Optional, ForceNew) The ProjectName of the EIP. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: diff --git a/website/docs/r/network_interface.html.markdown b/website/docs/r/network_interface.html.markdown index aaa9fd9f..61ca84ca 100644 --- a/website/docs/r/network_interface.html.markdown +++ b/website/docs/r/network_interface.html.markdown @@ -27,6 +27,13 @@ The following arguments are supported: * `network_interface_name` - (Optional) The name of the ENI. * `port_security_enabled` - (Optional) Set port security enable or disable. * `primary_ip_address` - (Optional, ForceNew) The primary IP address of the ENI. +* `project_name` - (Optional, ForceNew) The ProjectName of the ENI. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: diff --git a/website/docs/r/route_table.html.markdown b/website/docs/r/route_table.html.markdown index dab8ea5a..ed73a01f 100644 --- a/website/docs/r/route_table.html.markdown +++ b/website/docs/r/route_table.html.markdown @@ -20,6 +20,7 @@ resource "volcengine_route_table" "foo" { The following arguments are supported: * `vpc_id` - (Required, ForceNew) The id of the VPC. * `description` - (Optional) The description of the route table. +* `project_name` - (Optional) The ProjectName of the route table. * `route_table_name` - (Optional) The name of the route table. ## Attributes Reference diff --git a/website/docs/r/security_group.html.markdown b/website/docs/r/security_group.html.markdown index 824550af..eb4958e1 100644 --- a/website/docs/r/security_group.html.markdown +++ b/website/docs/r/security_group.html.markdown @@ -18,7 +18,14 @@ resource "volcengine_security_group" "g1test1" { The following arguments are supported: * `vpc_id` - (Required, ForceNew) Id of the VPC. * `description` - (Optional) Description of SecurityGroup. +* `project_name` - (Optional, ForceNew) The ProjectName of SecurityGroup. * `security_group_name` - (Optional) Name of SecurityGroup. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: diff --git a/website/docs/r/vpc.html.markdown b/website/docs/r/vpc.html.markdown index 3e1cc474..3a6b4697 100644 --- a/website/docs/r/vpc.html.markdown +++ b/website/docs/r/vpc.html.markdown @@ -21,8 +21,15 @@ The following arguments are supported: * `cidr_block` - (Required, ForceNew) A network address block which should be a subnet of the three internal network segments (10.0.0.0/16, 172.16.0.0/12 and 192.168.0.0/16). * `description` - (Optional) The description of the VPC. * `dns_servers` - (Optional) The DNS server list of the VPC. And you can specify 0 to 5 servers to this list. +* `project_name` - (Optional, ForceNew) The ProjectName of the VPC. +* `tags` - (Optional) Tags. * `vpc_name` - (Optional) The name of the VPC. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `id` - ID of the resource. From 9b87900e016fae7e208ddf113ced80b6dd2ea8a4 Mon Sep 17 00:00:00 2001 From: xuyaming Date: Tue, 20 Dec 2022 15:10:05 +0800 Subject: [PATCH 06/58] feat: support AfterLocked and AfterRefresh --- common/common_volcengine_callback.go | 13 +++- .../listener/service_volcengine_listener.go | 62 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/common/common_volcengine_callback.go b/common/common_volcengine_callback.go index 1826e94f..97852ffa 100644 --- a/common/common_volcengine_callback.go +++ b/common/common_volcengine_callback.go @@ -28,8 +28,10 @@ type SdkCall struct { RequestIdField string Refresh *StateRefresh ExtraRefresh map[ResourceService]*StateRefresh + AfterRefresh CallFunc ContentType RequestContentType LockId LockId + AfterLocked CallFunc ServiceCategory ServiceCategory } @@ -44,6 +46,7 @@ type ExecuteCallFunc func(d *schema.ResourceData, client *SdkClient, call SdkCal type AfterCallFunc func(d *schema.ResourceData, client *SdkClient, resp *map[string]interface{}, call SdkCall) error type BeforeCallFunc func(d *schema.ResourceData, client *SdkClient, call SdkCall) (bool, error) type ReadResourceFunc func(d *schema.ResourceData, resourceId string) (map[string]interface{}, error) +type CallFunc func(d *schema.ResourceData, client *SdkClient, call SdkCall) error type LockId func(d *schema.ResourceData) string @@ -194,7 +197,12 @@ func CallProcess(calls []SdkCall, d *schema.ResourceData, client *SdkClient, ser TryLock(key) } } - resp, err = fn.ExecuteCall(d, client, fn) + if fn.AfterLocked != nil { + err = fn.AfterLocked(d, client, fn) + } + if err == nil { + resp, err = fn.ExecuteCall(d, client, fn) + } } if err != nil { if fn.CallError != nil { @@ -220,6 +228,9 @@ func CallProcess(calls []SdkCall, d *schema.ResourceData, client *SdkClient, ser } } } + if doExecute && fn.AfterRefresh != nil && err == nil { + err = fn.AfterRefresh(d, client, fn) + } if doExecute && fn.LockId != nil { key := fn.LockId(d) diff --git a/volcengine/clb/listener/service_volcengine_listener.go b/volcengine/clb/listener/service_volcengine_listener.go index 666818b7..c536ae61 100644 --- a/volcengine/clb/listener/service_volcengine_listener.go +++ b/volcengine/clb/listener/service_volcengine_listener.go @@ -3,6 +3,7 @@ package listener import ( "errors" "fmt" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -10,6 +11,8 @@ import ( ve "github.com/volcengine/terraform-provider-volcengine/common" "github.com/volcengine/terraform-provider-volcengine/logger" "github.com/volcengine/terraform-provider-volcengine/volcengine/clb/clb" + clbSDK "github.com/volcengine/volcengine-go-sdk/service/clb" + "github.com/volcengine/volcengine-go-sdk/volcengine" ) type VolcengineListenerService struct { @@ -163,6 +166,61 @@ func (*VolcengineListenerService) WithResourceResponseHandlers(listener map[stri } +func (s *VolcengineListenerService) refreshAclStatus() ve.CallFunc { + return func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) error { + var aclIds []string + for k, v := range *call.SdkParam { + if strings.HasPrefix(k, "AclIds.") { + aclIds = append(aclIds, v.(string)) + } + } + if len(aclIds) > 0 { + if err := s.checkAcl(aclIds); err != nil { + return err + } + } + return nil + } +} + +func (s *VolcengineListenerService) checkAcl(aclIds []string) error { + return resource.Retry(20*time.Minute, func() *resource.RetryError { + logger.Debug(logger.ReqFormat, "DescribeAcls", aclIds) + // create 的时候上限为5个,无需翻页 + resp, err := s.Client.ClbClient.DescribeAcls(&clbSDK.DescribeAclsInput{ + AclIds: volcengine.StringSlice(aclIds), + PageNumber: volcengine.Int64(1), + PageSize: volcengine.Int64(100), + }) + if err != nil { + return resource.NonRetryableError(err) + } + logger.Debug(logger.RespFormat, "DescribeAcls", aclIds, *resp) + + statusOK := true + aclIdMap := make(map[string]bool) + for _, element := range resp.Acls { + aclIdMap[*element.AclId] = true + if *element.Status == "Deleting" { + return resource.NonRetryableError(fmt.Errorf("acl is in deleting status")) + } else if *element.Status != "Active" { // Creating / Configuring + statusOK = false + break + } + } + if !statusOK { + return resource.RetryableError(fmt.Errorf("acl still in waiting status")) + } + + for _, aclId := range aclIds { + if _, exist := aclIdMap[aclId]; !exist { + return resource.NonRetryableError(errors.New(fmt.Sprintf("cannot find acl: %s", aclId))) + } + } + return nil + }) +} + func (s *VolcengineListenerService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { callback := ve.Callback{ Call: ve.SdkCall{ @@ -193,6 +251,7 @@ func (s *VolcengineListenerService) CreateResource(resourceData *schema.Resource return true, nil }, + AfterLocked: s.refreshAclStatus(), ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.RespFormat, call.Action, call.SdkParam) //创建listener @@ -215,6 +274,7 @@ func (s *VolcengineListenerService) CreateResource(resourceData *schema.Resource ResourceId: resourceData.Get("load_balancer_id").(string), }, }, + AfterRefresh: s.refreshAclStatus(), LockId: func(d *schema.ResourceData) string { return resourceData.Get("load_balancer_id").(string) }, @@ -276,6 +336,7 @@ func (s *VolcengineListenerService) ModifyResource(resourceData *schema.Resource } return true, nil }, + AfterLocked: s.refreshAclStatus(), ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.RespFormat, call.Action, call.SdkParam) //修改 listener 属性 @@ -292,6 +353,7 @@ func (s *VolcengineListenerService) ModifyResource(resourceData *schema.Resource ResourceId: clbId, }, }, + AfterRefresh: s.refreshAclStatus(), LockId: func(d *schema.ResourceData) string { return clbId }, From cf3b3ddcc5483ea1a9ec354afd9765827702b9bc Mon Sep 17 00:00:00 2001 From: zhangpeihua Date: Tue, 3 Jan 2023 18:18:48 +0800 Subject: [PATCH 07/58] feat: update cr --- common/common_volcengine_version.go | 2 +- .../resource_volcengine_cr_endpoint.go | 7 +- .../service_volcengine_cr_endpoint.go | 65 +++++++++++++++++-- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index d9096d50..f8e22bf2 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.45" + TerraformProviderVersion = "0.0.46" ) diff --git a/volcengine/cr/cr_endpoint/resource_volcengine_cr_endpoint.go b/volcengine/cr/cr_endpoint/resource_volcengine_cr_endpoint.go index 68843917..f36b1a18 100644 --- a/volcengine/cr/cr_endpoint/resource_volcengine_cr_endpoint.go +++ b/volcengine/cr/cr_endpoint/resource_volcengine_cr_endpoint.go @@ -2,10 +2,11 @@ package cr_endpoint import ( "fmt" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - ve "github.com/volcengine/terraform-provider-volcengine/common" "strings" "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" ) /* @@ -32,12 +33,14 @@ func crEndpointImporter(d *schema.ResourceData, m interface{}) ([]*schema.Resour func ResourceVolcengineCrEndpoint() *schema.Resource { resource := &schema.Resource{ Read: resourceVolcengineCrEndpointRead, + Create: resourceVolcengineCrEndpointCreate, Update: resourceVolcengineCrEndpointUpdate, Delete: resourceVolcengineCrEndpointDelete, Importer: &schema.ResourceImporter{ State: crEndpointImporter, }, Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), Update: schema.DefaultTimeout(30 * time.Minute), Delete: schema.DefaultTimeout(30 * time.Minute), }, diff --git a/volcengine/cr/cr_endpoint/service_volcengine_cr_endpoint.go b/volcengine/cr/cr_endpoint/service_volcengine_cr_endpoint.go index 550179ef..8845d227 100644 --- a/volcengine/cr/cr_endpoint/service_volcengine_cr_endpoint.go +++ b/volcengine/cr/cr_endpoint/service_volcengine_cr_endpoint.go @@ -150,17 +150,54 @@ func (VolcengineCrEndpointService) WithResourceResponseHandlers(instance map[str } func (s *VolcengineCrEndpointService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { - return []ve.Callback{} + target := "Disabled" + enabled := resourceData.Get("enabled").(bool) + if enabled { + target = "Enabled" + } + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UpdatePublicEndpoint", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["Registry"] = d.Get("registry") + (*call.SdkParam)["Enabled"] = d.Get("enabled") + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + registry := d.Get("registry").(string) + id := "endpoint:" + registry + d.SetId(id) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{target}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + return []ve.Callback{callback} } func (s *VolcengineCrEndpointService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + target := "Disabled" + enabled := resourceData.Get("enabled").(bool) + if enabled { + target = "Enabled" + } callback := ve.Callback{ Call: ve.SdkCall{ Action: "UpdatePublicEndpoint", ContentType: ve.ContentTypeJson, - ConvertMode: ve.RequestConvertAll, + ConvertMode: ve.RequestConvertIgnore, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["Registry"] = d.Get("registry") + (*call.SdkParam)["Enabled"] = d.Get("enabled") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -168,7 +205,7 @@ func (s *VolcengineCrEndpointService) ModifyResource(resourceData *schema.Resour return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) }, Refresh: &ve.StateRefresh{ - Target: []string{"Enabled", "Disabled"}, + Target: []string{target}, Timeout: resourceData.Timeout(schema.TimeoutUpdate), }, }, @@ -177,7 +214,27 @@ func (s *VolcengineCrEndpointService) ModifyResource(resourceData *schema.Resour } func (s *VolcengineCrEndpointService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { - return []ve.Callback{} + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UpdatePublicEndpoint", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["Registry"] = d.Get("registry") + (*call.SdkParam)["Enabled"] = false + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Disabled"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + return []ve.Callback{callback} } func (s *VolcengineCrEndpointService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { From 9c13606b3b23175f58589b55a56a75aae7196c1f Mon Sep 17 00:00:00 2001 From: zhangpeihua Date: Wed, 4 Jan 2023 18:14:54 +0800 Subject: [PATCH 08/58] feat: support vpn --- .../data_source_volcengine_vpn_connections.go | 5 +++++ .../vpn_connection/resource_volcengine_vpn_connection.go | 6 ++++++ website/docs/d/vpn_connections.html.markdown | 1 + website/docs/r/vpn_connection.html.markdown | 1 + 4 files changed, 13 insertions(+) diff --git a/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go b/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go index 855b4003..947a03a9 100644 --- a/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go +++ b/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go @@ -212,6 +212,11 @@ func DataSourceVolcengineVpnConnections() *schema.Resource { Computed: true, Description: "The lifetime of the ike config of the VPN connection.", }, + "negotiate_instantly": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether to initiate negotiation mode immediately.", + }, }, }, }, diff --git a/volcengine/vpn/vpn_connection/resource_volcengine_vpn_connection.go b/volcengine/vpn/vpn_connection/resource_volcengine_vpn_connection.go index 4723f763..8dfc3c00 100644 --- a/volcengine/vpn/vpn_connection/resource_volcengine_vpn_connection.go +++ b/volcengine/vpn/vpn_connection/resource_volcengine_vpn_connection.go @@ -186,6 +186,12 @@ func ResourceVolcengineVpnConnection() *schema.Resource { ValidateFunc: validation.IntBetween(0, 86400), Description: "The ipsec config of the ike config of the VPN connection.", }, + "negotiate_instantly": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: "Whether to initiate negotiation mode immediately.", + }, }, } dataSource := DataSourceVolcengineVpnConnections().Schema["vpn_connections"].Elem.(*schema.Resource).Schema diff --git a/website/docs/d/vpn_connections.html.markdown b/website/docs/d/vpn_connections.html.markdown index c92e5644..977d40d3 100644 --- a/website/docs/d/vpn_connections.html.markdown +++ b/website/docs/d/vpn_connections.html.markdown @@ -49,6 +49,7 @@ In addition to all arguments above, the following attributes are exported: * `ipsec_config_lifetime` - The lifetime of the ike config of the VPN connection. * `local_subnet` - The local subnet of the VPN connection. * `nat_traversal` - The nat traversal of the VPN connection. + * `negotiate_instantly` - Whether to initiate negotiation mode immediately. * `remote_subnet` - The remote subnet of the VPN connection. * `status` - The status of the VPN connection. * `update_time` - The update time of VPN connection. diff --git a/website/docs/r/vpn_connection.html.markdown b/website/docs/r/vpn_connection.html.markdown index 0a4531ac..b68f33d9 100644 --- a/website/docs/r/vpn_connection.html.markdown +++ b/website/docs/r/vpn_connection.html.markdown @@ -56,6 +56,7 @@ The following arguments are supported: * `ipsec_config_enc_alg` - (Optional) The enc alg of the ipsec config of the VPN connection. * `ipsec_config_lifetime` - (Optional) The ipsec config of the ike config of the VPN connection. * `nat_traversal` - (Optional) The nat traversal of the VPN connection. +* `negotiate_instantly` - (Optional) Whether to initiate negotiation mode immediately. * `vpn_connection_name` - (Optional) The name of the VPN connection. ## Attributes Reference From 63f52fe30a923ef881512ebe20dface1b5d77571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 31 Jan 2023 17:47:35 +0800 Subject: [PATCH 09/58] feat: update cen and clb --- .../cen/cen/data_source_volcengine_cens.go | 2 ++ volcengine/cen/cen/resource_volcengine_cen.go | 1 + volcengine/cen/cen/service_volcengine_cen.go | 22 ++++++++++++++++++- ...ource_volcengine_cen_bandwidth_packages.go | 2 ++ ...source_volcengine_cen_bandwidth_package.go | 1 + ...ervice_volcengine_cen_bandwidth_package.go | 18 +++++++++++++++ .../clb/clb/data_source_volcengine_clbs.go | 15 +++++++++++++ volcengine/clb/clb/resource_volcengine_clb.go | 10 +++++++++ .../data_source_volcengine_listeners.go | 10 +++++++++ 9 files changed, 80 insertions(+), 1 deletion(-) diff --git a/volcengine/cen/cen/data_source_volcengine_cens.go b/volcengine/cen/cen/data_source_volcengine_cens.go index 8e7655ca..d32413d0 100644 --- a/volcengine/cen/cen/data_source_volcengine_cens.go +++ b/volcengine/cen/cen/data_source_volcengine_cens.go @@ -45,6 +45,7 @@ func DataSourceVolcengineCens() *schema.Resource { Computed: true, Description: "The total count of cen query.", }, + "tags": ve.TagsSchema(), "cens": { Description: "The collection of cen query.", Type: schema.TypeList, @@ -99,6 +100,7 @@ func DataSourceVolcengineCens() *schema.Resource { }, Description: "A list of bandwidth package IDs of the cen.", }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/cen/cen/resource_volcengine_cen.go b/volcengine/cen/cen/resource_volcengine_cen.go index e1b15301..f60fd691 100644 --- a/volcengine/cen/cen/resource_volcengine_cen.go +++ b/volcengine/cen/cen/resource_volcengine_cen.go @@ -45,6 +45,7 @@ func ResourceVolcengineCen() *schema.Resource { Computed: true, Description: "The description of the cen.", }, + "tags": ve.TagsSchema(), }, } s := DataSourceVolcengineCens().Schema["cens"].Elem.(*schema.Resource).Schema diff --git a/volcengine/cen/cen/service_volcengine_cen.go b/volcengine/cen/cen/service_volcengine_cen.go index d9d40d3e..f34e0223 100644 --- a/volcengine/cen/cen/service_volcengine_cen.go +++ b/volcengine/cen/cen/service_volcengine_cen.go @@ -181,6 +181,12 @@ func (s *VolcengineCenService) CreateResource(resourceData *schema.ResourceData, Target: []string{"Available"}, Timeout: resourceData.Timeout(schema.TimeoutCreate), }, + Convert: map[string]ve.RequestConvert{ + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, + }, }, } return []ve.Callback{callback} @@ -188,12 +194,14 @@ func (s *VolcengineCenService) CreateResource(resourceData *schema.ResourceData, } func (s *VolcengineCenService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyCenAttributes", ConvertMode: ve.RequestConvertAll, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["CenId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -202,7 +210,10 @@ func (s *VolcengineCenService) ModifyResource(resourceData *schema.ResourceData, }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + tagCallback := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "cen", resourceData, getUniversalInfo) + callbacks = append(callbacks, tagCallback...) + return callbacks } func (s *VolcengineCenService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -251,6 +262,15 @@ func (s *VolcengineCenService) DatasourceResources(*schema.ResourceData, *schema TargetField: "CenNames", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "CenName", IdField: "CenId", diff --git a/volcengine/cen/cen_bandwidth_package/data_source_volcengine_cen_bandwidth_packages.go b/volcengine/cen/cen_bandwidth_package/data_source_volcengine_cen_bandwidth_packages.go index ee1c2e84..fe83c670 100644 --- a/volcengine/cen/cen_bandwidth_package/data_source_volcengine_cen_bandwidth_packages.go +++ b/volcengine/cen/cen_bandwidth_package/data_source_volcengine_cen_bandwidth_packages.go @@ -60,6 +60,7 @@ func DataSourceVolcengineCenBandwidthPackages() *schema.Resource { Computed: true, Description: "The total count of cen bandwidth package query.", }, + "tags": ve.TagsSchema(), "bandwidth_packages": { Description: "The collection of cen bandwidth package query.", Type: schema.TypeList, @@ -154,6 +155,7 @@ func DataSourceVolcengineCenBandwidthPackages() *schema.Resource { Computed: true, Description: "The deleted time of the cen bandwidth package.", }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/cen/cen_bandwidth_package/resource_volcengine_cen_bandwidth_package.go b/volcengine/cen/cen_bandwidth_package/resource_volcengine_cen_bandwidth_package.go index acb19edc..31fa0221 100644 --- a/volcengine/cen/cen_bandwidth_package/resource_volcengine_cen_bandwidth_package.go +++ b/volcengine/cen/cen_bandwidth_package/resource_volcengine_cen_bandwidth_package.go @@ -92,6 +92,7 @@ func ResourceVolcengineCenBandwidthPackage() *schema.Resource { DiffSuppressFunc: periodDiffSuppress, Description: "The period of the cen bandwidth package.", }, + "tags": ve.TagsSchema(), }, } s := DataSourceVolcengineCenBandwidthPackages().Schema["bandwidth_packages"].Elem.(*schema.Resource).Schema diff --git a/volcengine/cen/cen_bandwidth_package/service_volcengine_cen_bandwidth_package.go b/volcengine/cen/cen_bandwidth_package/service_volcengine_cen_bandwidth_package.go index d2b56ee2..1661b88c 100644 --- a/volcengine/cen/cen_bandwidth_package/service_volcengine_cen_bandwidth_package.go +++ b/volcengine/cen/cen_bandwidth_package/service_volcengine_cen_bandwidth_package.go @@ -185,6 +185,10 @@ func (s *VolcengineCenBandwidthPackageService) CreateResource(resourceData *sche TargetField: "BillingType", Convert: billingTypeRequestConvert, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["ClientToken"] = uuid.New().String() @@ -211,6 +215,7 @@ func (s *VolcengineCenBandwidthPackageService) CreateResource(resourceData *sche } func (s *VolcengineCenBandwidthPackageService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyCenBandwidthPackageAttributes", @@ -231,6 +236,7 @@ func (s *VolcengineCenBandwidthPackageService) ModifyResource(resourceData *sche return false, nil } (*call.SdkParam)["CenBandwidthPackageId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -239,6 +245,9 @@ func (s *VolcengineCenBandwidthPackageService) ModifyResource(resourceData *sche }, }, } + callbacks = append(callbacks, callback) + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "cenbandwidthpackage", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) return []ve.Callback{callback} } @@ -292,6 +301,15 @@ func (s *VolcengineCenBandwidthPackageService) DatasourceResources(*schema.Resou TargetField: "CenBandwidthPackageNames", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "CenBandwidthPackageName", IdField: "CenBandwidthPackageId", diff --git a/volcengine/clb/clb/data_source_volcengine_clbs.go b/volcengine/clb/clb/data_source_volcengine_clbs.go index e34dddca..677ee10d 100644 --- a/volcengine/clb/clb/data_source_volcengine_clbs.go +++ b/volcengine/clb/clb/data_source_volcengine_clbs.go @@ -180,6 +180,21 @@ func DataSourceVolcengineClbs() *schema.Resource { Description: "The ProjectName of the Clb.", }, "tags": ve.TagsSchemaComputed(), + "master_zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The master zone ID of the CLB.", + }, + "slave_zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The slave zone ID of the CLB.", + }, + "logic_topic_id": { + Type: schema.TypeString, + Computed: true, + Description: "The topic ID of the CLB.", + }, }, }, }, diff --git a/volcengine/clb/clb/resource_volcengine_clb.go b/volcengine/clb/clb/resource_volcengine_clb.go index d0049a6c..0d2f979e 100644 --- a/volcengine/clb/clb/resource_volcengine_clb.go +++ b/volcengine/clb/clb/resource_volcengine_clb.go @@ -110,6 +110,16 @@ func ResourceVolcengineClb() *schema.Resource { Description: "The ProjectName of the CLB.", }, "tags": ve.TagsSchema(), + "master_zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The master zone ID of the CLB.", + }, + "slave_zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The slave zone ID of the CLB.", + }, //"period_unit": { // Type: schema.TypeString, // Optional: true, diff --git a/volcengine/clb/listener/data_source_volcengine_listeners.go b/volcengine/clb/listener/data_source_volcengine_listeners.go index 04b8659c..d32d43f2 100644 --- a/volcengine/clb/listener/data_source_volcengine_listeners.go +++ b/volcengine/clb/listener/data_source_volcengine_listeners.go @@ -172,6 +172,16 @@ func DataSourceVolcengineListeners() *schema.Resource { Computed: true, Description: "The normal http status code of health check.", }, + "health_check_udp_request": { + Type: schema.TypeString, + Computed: true, + Description: "A request string to perform a health check.", + }, + "health_check_udp_expect": { + Type: schema.TypeString, + Computed: true, + Description: "The expected response string for the health check.", + }, }, }, }, From e985c4ebc05a9b3e8ef5afb6b2adcad01b3d36d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Wed, 1 Feb 2023 14:51:16 +0800 Subject: [PATCH 10/58] feat: update cen and clb --- example/dataClbZones/main.tf | 2 + .../clb/clb/data_source_volcengine_clbs.go | 5 - .../zone/data_source_volcengine_clb_zones.go | 57 +++++++++ .../clb/zone/service_volcengine_clb_zone.go | 114 ++++++++++++++++++ volcengine/provider.go | 2 + 5 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 example/dataClbZones/main.tf create mode 100644 volcengine/clb/zone/data_source_volcengine_clb_zones.go create mode 100644 volcengine/clb/zone/service_volcengine_clb_zone.go diff --git a/example/dataClbZones/main.tf b/example/dataClbZones/main.tf new file mode 100644 index 00000000..5ef8220a --- /dev/null +++ b/example/dataClbZones/main.tf @@ -0,0 +1,2 @@ +data "volcengine_clb_zones" "default" { +} \ No newline at end of file diff --git a/volcengine/clb/clb/data_source_volcengine_clbs.go b/volcengine/clb/clb/data_source_volcengine_clbs.go index 677ee10d..5cbeaea7 100644 --- a/volcengine/clb/clb/data_source_volcengine_clbs.go +++ b/volcengine/clb/clb/data_source_volcengine_clbs.go @@ -190,11 +190,6 @@ func DataSourceVolcengineClbs() *schema.Resource { Computed: true, Description: "The slave zone ID of the CLB.", }, - "logic_topic_id": { - Type: schema.TypeString, - Computed: true, - Description: "The topic ID of the CLB.", - }, }, }, }, diff --git a/volcengine/clb/zone/data_source_volcengine_clb_zones.go b/volcengine/clb/zone/data_source_volcengine_clb_zones.go new file mode 100644 index 00000000..db7d097d --- /dev/null +++ b/volcengine/clb/zone/data_source_volcengine_clb_zones.go @@ -0,0 +1,57 @@ +package zone + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineClbZones() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineClbZonesRead, + Schema: map[string]*schema.Schema{ + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of zone query.", + }, + "master_zones": { + Description: "The master zones list.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The master zone id.", + }, + "slave_zones": { + Type: schema.TypeList, + Computed: true, + Description: "The slave zones list.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The slave zone id.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineClbZonesRead(d *schema.ResourceData, meta interface{}) error { + service := NewClbZoneService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineClbZones()) +} diff --git a/volcengine/clb/zone/service_volcengine_clb_zone.go b/volcengine/clb/zone/service_volcengine_clb_zone.go new file mode 100644 index 00000000..7d31350a --- /dev/null +++ b/volcengine/clb/zone/service_volcengine_clb_zone.go @@ -0,0 +1,114 @@ +package zone + +import ( + "errors" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineClbZoneService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func (s *VolcengineClbZoneService) ReadResources(condition map[string]interface{}) ([]interface{}, error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + err error + data []interface{} + ) + action := "DescribeZones" + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + } + if err != nil { + return nil, err + } + logger.Debug(logger.RespFormat, action, condition, *resp) + results, err = ve.ObtainSdkValue("Result.MasterZones", *resp) + if err != nil { + return nil, err + } + if results == nil { + results = make([]interface{}, 0) + } + if data, ok = results.([]interface{}); !ok { + return nil, errors.New("Result.MasterZones is not Slice") + } + return data, nil +} + +func (s *VolcengineClbZoneService) ReadResource(data *schema.ResourceData, s2 string) (map[string]interface{}, error) { + return nil, nil +} + +func (s *VolcengineClbZoneService) RefreshResourceState(data *schema.ResourceData, target []string, timeout time.Duration, s2 string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 5 * time.Second, + MinTimeout: 5 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + return nil, "", err + }, + } +} + +func (s *VolcengineClbZoneService) WithResourceResponseHandlers(m map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return m, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineClbZoneService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{} +} + +func (s *VolcengineClbZoneService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{} +} + +func (s *VolcengineClbZoneService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{} +} + +func (s *VolcengineClbZoneService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + CollectField: "master_zones", + } +} + +func (s *VolcengineClbZoneService) ReadResourceId(id string) string { + return id +} + +func NewClbZoneService(c *ve.SdkClient) *VolcengineClbZoneService { + return &VolcengineClbZoneService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineClbZoneService) GetClient() *ve.SdkClient { + return s.Client +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "clb", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/provider.go b/volcengine/provider.go index cf396c9b..0c2535a6 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -32,6 +32,7 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/clb/rule" "github.com/volcengine/terraform-provider-volcengine/volcengine/clb/server_group" "github.com/volcengine/terraform-provider-volcengine/volcengine/clb/server_group_server" + clbZone "github.com/volcengine/terraform-provider-volcengine/volcengine/clb/zone" "github.com/volcengine/terraform-provider-volcengine/volcengine/cr/cr_authorization_token" "github.com/volcengine/terraform-provider-volcengine/volcengine/cr/cr_endpoint" "github.com/volcengine/terraform-provider-volcengine/volcengine/cr/cr_namespace" @@ -178,6 +179,7 @@ func Provider() terraform.ResourceProvider { "volcengine_certificates": certificate.DataSourceVolcengineCertificates(), "volcengine_clb_rules": rule.DataSourceVolcengineRules(), "volcengine_server_group_servers": server_group_server.DataSourceVolcengineServerGroupServers(), + "volcengine_clb_zones": clbZone.DataSourceVolcengineClbZones(), // ================ EBS ================ "volcengine_volumes": volume.DataSourceVolcengineVolumes(), From 73d06831937b2416fb6360dfba70eb7f712ba2da Mon Sep 17 00:00:00 2001 From: lixiang Date: Thu, 2 Feb 2023 16:28:05 +0800 Subject: [PATCH 11/58] update vpc/vpn parameters. --- ...ta_source_volcengine_network_interfaces.go | 74 +++++++++++++++++++ .../resource_volcengine_network_interface.go | 13 ++++ .../service_volcengine_network_interface.go | 12 +++ .../data_source_volcengine_security_groups.go | 13 ++++ ..._source_volcengine_security_group_rules.go | 10 +++ .../subnet/data_source_volcengine_subnets.go | 50 +++++++++++++ .../vpc/vpc/data_source_volcengine_vpcs.go | 5 ++ .../data_source_volcengine_vpn_connections.go | 10 +++ .../data_source_volcengine_vpn_gateways.go | 2 + .../resource_volcengine_vpn_gateway.go | 1 + .../service_volcengine_vpn_gateway.go | 13 ++++ 11 files changed, 203 insertions(+) diff --git a/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go b/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go index 5a28f16d..d0fd17af 100644 --- a/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go +++ b/volcengine/vpc/network_interface/data_source_volcengine_network_interfaces.go @@ -59,11 +59,32 @@ func DataSourceVolcengineNetworkInterfaces() *schema.Resource { Optional: true, Description: "An id of the security group to which the secondary ENI belongs.", }, + "network_interface_ids": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Description: "A list of network interface ids.", + }, "network_interface_name": { Type: schema.TypeString, Optional: true, Description: "A name of ENI.", }, + "private_ip_addresses": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Description: "A list of private IP addresses.", + }, + "zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The zone ID.", + }, "project_name": { Type: schema.TypeString, Optional: true, @@ -190,6 +211,59 @@ func DataSourceVolcengineNetworkInterfaces() *schema.Resource { Computed: true, Description: "The IP address of the EIP to which the ENI associates.", }, + "service_managed": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether the network card has been authorized to be used by other account services.", + }, + "private_ip_sets": { + Type: schema.TypeSet, + Computed: true, + Description: "The IP address of secondary private network interface.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "private_ip_address": { + Type: schema.TypeString, + Computed: true, + Description: "The secondary private network IP address of the network interface card.", + }, + "associated_elastic_ip": { + Type: schema.TypeSet, + Computed: true, + Description: "The public IP that secondary private network IP associated with.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allocation_id": { + Type: schema.TypeString, + Computed: true, + Description: "The public IP ID.", + }, + "eip_address": { + Type: schema.TypeString, + Computed: true, + Description: "The public IP address.", + }, + }, + }, + }, + "primary": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether the network interface is primary IP address.", + }, + }, + }, + }, + //"associated_elastic_ip_id": { + // Type: schema.TypeString, + // Computed: true, + // Description: "The allocation id of the EIP to which the ENI associates.", + //}, + //"associated_elastic_ip_address": { + // Type: schema.TypeString, + // Computed: true, + // Description: "The IP address of the EIP to which the ENI associates.", + //}, "project_name": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/vpc/network_interface/resource_volcengine_network_interface.go b/volcengine/vpc/network_interface/resource_volcengine_network_interface.go index ee1726f2..c812da6d 100644 --- a/volcengine/vpc/network_interface/resource_volcengine_network_interface.go +++ b/volcengine/vpc/network_interface/resource_volcengine_network_interface.go @@ -73,6 +73,19 @@ func ResourceVolcengineNetworkInterface() *schema.Resource { Computed: true, Description: "Set port security enable or disable.", }, + "secondary_private_ip_address_count": { + Type: schema.TypeInt, + Optional: true, + Description: "The count of secondary private ip address.", + }, + "private_ip_address": { + Type: schema.TypeSet, + Optional: true, + Description: "The list of private ip address.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "project_name": { Type: schema.TypeString, Optional: true, diff --git a/volcengine/vpc/network_interface/service_volcengine_network_interface.go b/volcengine/vpc/network_interface/service_volcengine_network_interface.go index d721e1fe..57bafb7a 100644 --- a/volcengine/vpc/network_interface/service_volcengine_network_interface.go +++ b/volcengine/vpc/network_interface/service_volcengine_network_interface.go @@ -153,6 +153,10 @@ func (s *VolcengineNetworkInterfaceService) CreateResource(resourceData *schema. TargetField: "SecurityGroupIds", ConvertType: ve.ConvertWithN, }, + "private_ip_address": { + TargetField: "PrivateIpAddress", + ConvertType: ve.ConvertWithN, + }, "tags": { TargetField: "Tags", ConvertType: ve.ConvertListN, @@ -245,6 +249,14 @@ func (s *VolcengineNetworkInterfaceService) DatasourceResources(*schema.Resource TargetField: "PrimaryIpAddresses", ConvertType: ve.ConvertWithN, }, + "private_ip_addresses": { + TargetField: "PrivateIpAddresses", + ConvertType: ve.ConvertWithN, + }, + "network_interface_ids": { + TargetField: "NetworkInterfaceIds", + ConvertType: ve.ConvertWithN, + }, "tags": { TargetField: "TagFilters", ConvertType: ve.ConvertListN, diff --git a/volcengine/vpc/security_group/data_source_volcengine_security_groups.go b/volcengine/vpc/security_group/data_source_volcengine_security_groups.go index a559ec36..c4018a83 100644 --- a/volcengine/vpc/security_group/data_source_volcengine_security_groups.go +++ b/volcengine/vpc/security_group/data_source_volcengine_security_groups.go @@ -19,6 +19,19 @@ func DataSourceVolcengineSecurityGroups() *schema.Resource { Set: schema.HashString, Description: "A list of SecurityGroup IDs.", }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of vpc where security group is located.", + }, + "security_group_names": { + Type: schema.TypeSet, + Optional: true, + Description: "The list of security group name to query.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "name_regex": { Type: schema.TypeString, Optional: true, diff --git a/volcengine/vpc/security_group_rule/data_source_volcengine_security_group_rules.go b/volcengine/vpc/security_group_rule/data_source_volcengine_security_group_rules.go index c45d332a..00434f5e 100644 --- a/volcengine/vpc/security_group_rule/data_source_volcengine_security_group_rules.go +++ b/volcengine/vpc/security_group_rule/data_source_volcengine_security_group_rules.go @@ -106,6 +106,16 @@ func DataSourceVolcengineSecurityGroupRules() *schema.Resource { Computed: true, Description: "description of a group rule.", }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + Description: "The creation time of security group rule.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "The update time of security group rule.", + }, }, }, }, diff --git a/volcengine/vpc/subnet/data_source_volcengine_subnets.go b/volcengine/vpc/subnet/data_source_volcengine_subnets.go index a87b6aa1..3cb459e5 100644 --- a/volcengine/vpc/subnet/data_source_volcengine_subnets.go +++ b/volcengine/vpc/subnet/data_source_volcengine_subnets.go @@ -35,6 +35,26 @@ func DataSourceVolcengineSubnets() *schema.Resource { Computed: true, Description: "The total count of Subnet query.", }, + "zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of zone which subnet belongs to.", + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of VPC which subnet belongs to.", + }, + "subnet_name": { + Type: schema.TypeString, + Optional: true, + Description: "The subnet name to query.", + }, + "route_table_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of route table which subnet associated with.", + }, "subnets": { Description: "The collection of Subnet query.", Type: schema.TypeList, @@ -46,6 +66,11 @@ func DataSourceVolcengineSubnets() *schema.Resource { Computed: true, Description: "The ID of Subnet.", }, + "account_id": { + Type: schema.TypeString, + Computed: true, + Description: "The account ID which the subnet belongs to.", + }, "subnet_name": { Type: schema.TypeString, Computed: true, @@ -106,6 +131,31 @@ func DataSourceVolcengineSubnets() *schema.Resource { Computed: true, Description: "The type of route table.", }, + "network_acl_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of network acl which this subnet associate with.", + }, + "route_table": { + Type: schema.TypeSet, + MaxItems: 1, + Computed: true, + Description: "The route table information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_table_id": { + Type: schema.TypeString, + Computed: true, + Description: "The route table ID.", + }, + "route_table_type": { + Type: schema.TypeString, + Computed: true, + Description: "The route table type.", + }, + }, + }, + }, }, }, }, diff --git a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go index 3c19bdb6..7af7362f 100644 --- a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go +++ b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go @@ -30,6 +30,11 @@ func DataSourceVolcengineVpcs() *schema.Resource { Optional: true, Description: "The ProjectName of the VPC.", }, + "vpc_name": { + Type: schema.TypeString, + Optional: true, + Description: "The vpc name to query.", + }, "tags": ve.TagsSchema(), "output_file": { diff --git a/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go b/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go index 947a03a9..a5ba46ae 100644 --- a/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go +++ b/volcengine/vpn/vpn_connection/data_source_volcengine_vpn_connections.go @@ -217,6 +217,16 @@ func DataSourceVolcengineVpnConnections() *schema.Resource { Computed: true, Description: "Whether to initiate negotiation mode immediately.", }, + "attach_status": { + Type: schema.TypeString, + Computed: true, + Description: "The IPsec attach status.", + }, + "attach_type": { + Type: schema.TypeString, + Computed: true, + Description: "The IPsec attach type.", + }, }, }, }, diff --git a/volcengine/vpn/vpn_gateway/data_source_volcengine_vpn_gateways.go b/volcengine/vpn/vpn_gateway/data_source_volcengine_vpn_gateways.go index 4046e650..2a584c63 100644 --- a/volcengine/vpn/vpn_gateway/data_source_volcengine_vpn_gateways.go +++ b/volcengine/vpn/vpn_gateway/data_source_volcengine_vpn_gateways.go @@ -44,6 +44,7 @@ func DataSourceVolcengineVpnGateways() *schema.Resource { ValidateFunc: validation.IsIPAddress, Description: "A IP address of the VPN gateway.", }, + "tags": ve.TagsSchema(), "name_regex": { Type: schema.TypeString, Optional: true, @@ -163,6 +164,7 @@ func DataSourceVolcengineVpnGateways() *schema.Resource { Computed: true, Description: "The deleted time of the VPN gateway.", }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/vpn/vpn_gateway/resource_volcengine_vpn_gateway.go b/volcengine/vpn/vpn_gateway/resource_volcengine_vpn_gateway.go index b9e4875d..3bbbb92c 100644 --- a/volcengine/vpn/vpn_gateway/resource_volcengine_vpn_gateway.go +++ b/volcengine/vpn/vpn_gateway/resource_volcengine_vpn_gateway.go @@ -94,6 +94,7 @@ func ResourceVolcengineVpnGateway() *schema.Resource { Computed: true, Description: "The renew type of the VPN gateway.", }, + "tags": ve.TagsSchema(), }, } dataSource := DataSourceVolcengineVpnGateways().Schema["vpn_gateways"].Elem.(*schema.Resource).Schema diff --git a/volcengine/vpn/vpn_gateway/service_volcengine_vpn_gateway.go b/volcengine/vpn/vpn_gateway/service_volcengine_vpn_gateway.go index 5f92e8e6..fbefa65f 100644 --- a/volcengine/vpn/vpn_gateway/service_volcengine_vpn_gateway.go +++ b/volcengine/vpn/vpn_gateway/service_volcengine_vpn_gateway.go @@ -235,6 +235,10 @@ func (s *VolcengineVpnGatewayService) CreateResource(resourceData *schema.Resour TargetField: "BillingType", Convert: billingTypeRequestConvert, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { if len(*call.SdkParam) < 1 { @@ -391,6 +395,15 @@ func (s *VolcengineVpnGatewayService) DatasourceResources(*schema.ResourceData, TargetField: "VpnGatewayNames", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "VpnGatewayName", IdField: "VpnGatewayId", From 780bda107d53d63e4cb9a4a69290d3a3043b539c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Mon, 6 Feb 2023 14:56:51 +0800 Subject: [PATCH 12/58] fix: add miss parameters --- volcengine/clb/listener/service_volcengine_listener.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/volcengine/clb/listener/service_volcengine_listener.go b/volcengine/clb/listener/service_volcengine_listener.go index c536ae61..dd183fee 100644 --- a/volcengine/clb/listener/service_volcengine_listener.go +++ b/volcengine/clb/listener/service_volcengine_listener.go @@ -458,6 +458,12 @@ func (s *VolcengineListenerService) DatasourceResources(*schema.ResourceData, *s "HealthCheck.HttpCode": { TargetField: "health_check_http_code", }, + "HealthCheck.UdpRequest": { + TargetField: "health_check_udp_request", + }, + "HealthCheck.UdpExpect": { + TargetField: "health_check_udp_expect", + }, }, } } From 9b6bb05c45dafbc61ef23f5a1a3137e0efcfbc7c Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Tue, 7 Feb 2023 16:53:35 +0800 Subject: [PATCH 13/58] feat: update ecs_instance and nat_gateway --- common/common_volcengine_version.go | 2 +- .../data_source_volcengine_ecs_instances.go | 14 ++++++ .../service_volcengine_ecs_instance.go | 4 ++ .../data_source_volcengine_nat_gateways.go | 2 + .../resource_volcengine_nat_gateway.go | 1 + .../service_volcengine_nat_gateway.go | 50 +++++++++++++++++-- .../data_source_volcengine_snat_entries.go | 10 ++++ .../resource_volcengine_snat_entry.go | 16 ++++-- website/docs/d/ecs_instances.html.markdown | 2 + website/docs/d/nat_gateways.html.markdown | 9 ++++ website/docs/d/snat_entries.html.markdown | 2 + website/docs/r/nat_gateway.html.markdown | 6 +++ website/docs/r/snat_entry.html.markdown | 3 +- 13 files changed, 112 insertions(+), 9 deletions(-) diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index fea90fb2..1129782a 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.47" + TerraformProviderVersion = "0.0.48" ) diff --git a/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go b/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go index 7c793dc1..cd550436 100644 --- a/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go +++ b/volcengine/ecs/ecs_instance/data_source_volcengine_ecs_instances.go @@ -66,6 +66,15 @@ func DataSourceVolcengineEcsInstances() *schema.Resource { Description: "The ProjectName of ECS instance.", }, "tags": ve.TagsSchema(), + "deployment_set_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "A list of DeploymentSet IDs.", + }, "output_file": { Type: schema.TypeString, @@ -301,6 +310,11 @@ func DataSourceVolcengineEcsInstances() *schema.Resource { Description: "The ProjectName of ECS instance.", }, "tags": ve.TagsSchemaComputed(), + "deployment_set_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of DeploymentSet.", + }, }, }, }, diff --git a/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go b/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go index f44b03e4..ba7593c4 100644 --- a/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go +++ b/volcengine/ecs/ecs_instance/service_volcengine_ecs_instance.go @@ -867,6 +867,10 @@ func (s *VolcengineEcsService) DatasourceResources(data *schema.ResourceData, re }, }, }, + "deployment_set_ids": { + TargetField: "DeploymentSetIds", + ConvertType: ve.ConvertWithN, + }, }, NameField: "InstanceName", IdField: "InstanceId", diff --git a/volcengine/nat/nat_gateway/data_source_volcengine_nat_gateways.go b/volcengine/nat/nat_gateway/data_source_volcengine_nat_gateways.go index 36a04664..402c6d4d 100644 --- a/volcengine/nat/nat_gateway/data_source_volcengine_nat_gateways.go +++ b/volcengine/nat/nat_gateway/data_source_volcengine_nat_gateways.go @@ -25,6 +25,7 @@ func DataSourceVolcengineNatGateways() *schema.Resource { ValidateFunc: validation.StringIsValidRegExp, Description: "The Name Regex of NatGateway.", }, + "tags": ve.TagsSchema(), "output_file": { Type: schema.TypeString, @@ -172,6 +173,7 @@ func DataSourceVolcengineNatGateways() *schema.Resource { Computed: true, Description: "The update time of the NatGateway.", }, + "tags": ve.TagsSchemaComputed(), }, }, }, diff --git a/volcengine/nat/nat_gateway/resource_volcengine_nat_gateway.go b/volcengine/nat/nat_gateway/resource_volcengine_nat_gateway.go index ac1620d7..8266b981 100644 --- a/volcengine/nat/nat_gateway/resource_volcengine_nat_gateway.go +++ b/volcengine/nat/nat_gateway/resource_volcengine_nat_gateway.go @@ -69,6 +69,7 @@ func ResourceVolcengineNatGateway() *schema.Resource { Description: "The billing type of the NatGateway, the value is `PostPaid`.", ValidateFunc: validation.StringInSlice([]string{"PostPaid"}, false), }, + "tags": ve.TagsSchema(), //"period_unit": { // Type: schema.TypeString, // Optional: true, diff --git a/volcengine/nat/nat_gateway/service_volcengine_nat_gateway.go b/volcengine/nat/nat_gateway/service_volcengine_nat_gateway.go index 52f4231d..1df3e2b1 100644 --- a/volcengine/nat/nat_gateway/service_volcengine_nat_gateway.go +++ b/volcengine/nat/nat_gateway/service_volcengine_nat_gateway.go @@ -48,6 +48,7 @@ func (s *VolcengineNatGatewayService) ReadResources(condition map[string]interfa return data, err } } + logger.Debug(logger.RespFormat, "testDescribeNatGateways", condition, *resp) results, err = ve.ObtainSdkValue("Result.NatGateways", *resp) if err != nil { @@ -117,10 +118,21 @@ func (s *VolcengineNatGatewayService) RefreshResourceState(resourceData *schema. demo map[string]interface{} status interface{} ) - demo, err = s.ReadResource(resourceData, id) - if err != nil { + + if err = resource.Retry(20*time.Minute, func() *resource.RetryError { + demo, err = s.ReadResource(resourceData, id) + if err != nil { + if ve.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(err) + } + } + return nil + }); err != nil { return nil, "", err } + status, err = ve.ObtainSdkValue("Status", demo) if err != nil { return nil, "", err @@ -180,6 +192,10 @@ func (s *VolcengineNatGatewayService) CreateResource(resourceData *schema.Resour return i }, }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertListN, + }, }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.RespFormat, call.Action, call.SdkParam) @@ -203,6 +219,8 @@ func (s *VolcengineNatGatewayService) CreateResource(resourceData *schema.Resour } func (s *VolcengineNatGatewayService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ Call: ve.SdkCall{ Action: "ModifyNatGatewayAttributes", @@ -227,6 +245,7 @@ func (s *VolcengineNatGatewayService) ModifyResource(resourceData *schema.Resour }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { (*call.SdkParam)["NatGatewayId"] = d.Id() + delete(*call.SdkParam, "Tags") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -240,7 +259,13 @@ func (s *VolcengineNatGatewayService) ModifyResource(resourceData *schema.Resour }, }, } - return []ve.Callback{callback} + callbacks = append(callbacks, callback) + + // 更新Tags + setResourceTagsCallbacks := ve.SetResourceTags(s.Client, "TagResources", "UntagResources", "ngw", resourceData, getUniversalInfo) + callbacks = append(callbacks, setResourceTagsCallbacks...) + + return callbacks } func (s *VolcengineNatGatewayService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { @@ -303,6 +328,15 @@ func (s *VolcengineNatGatewayService) DatasourceResources(*schema.ResourceData, TargetField: "NatGatewayIds", ConvertType: ve.ConvertWithN, }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertListN, + NextLevelConvert: map[string]ve.RequestConvert{ + "value": { + TargetField: "Values.1", + }, + }, + }, }, NameField: "NatGatewayName", IdField: "NatGatewayId", @@ -335,3 +369,13 @@ func (s *VolcengineNatGatewayService) DatasourceResources(*schema.ResourceData, func (s *VolcengineNatGatewayService) ReadResourceId(id string) string { return id } + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/nat/snat_entry/data_source_volcengine_snat_entries.go b/volcengine/nat/snat_entry/data_source_volcengine_snat_entries.go index 530bb86f..36d5a58d 100644 --- a/volcengine/nat/snat_entry/data_source_volcengine_snat_entries.go +++ b/volcengine/nat/snat_entry/data_source_volcengine_snat_entries.go @@ -33,6 +33,11 @@ func DataSourceVolcengineSnatEntries() *schema.Resource { Optional: true, Description: "An id of the subnet that is required to access the Internet.", }, + "source_cidr": { + Type: schema.TypeString, + Optional: true, + Description: "The SourceCidr of SNAT entry.", + }, "eip_id": { Type: schema.TypeString, Optional: true, @@ -80,6 +85,11 @@ func DataSourceVolcengineSnatEntries() *schema.Resource { Computed: true, Description: "The id of the subnet that is required to access the internet.", }, + "source_cidr": { + Type: schema.TypeString, + Computed: true, + Description: "The SourceCidr of the SNAT entry.", + }, "eip_id": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/nat/snat_entry/resource_volcengine_snat_entry.go b/volcengine/nat/snat_entry/resource_volcengine_snat_entry.go index bedf3b4e..78277284 100644 --- a/volcengine/nat/snat_entry/resource_volcengine_snat_entry.go +++ b/volcengine/nat/snat_entry/resource_volcengine_snat_entry.go @@ -40,10 +40,11 @@ func ResourceVolcengineSnatEntry() *schema.Resource { Description: "The id of the nat gateway to which the entry belongs.", }, "subnet_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "The id of the subnet that is required to access the internet.", + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ExactlyOneOf: []string{"subnet_id", "source_cidr"}, + Description: "The id of the subnet that is required to access the internet. Only one of `subnet_id,source_cidr` can be specified.", }, "eip_id": { Type: schema.TypeString, @@ -61,6 +62,13 @@ func ResourceVolcengineSnatEntry() *schema.Resource { Computed: true, Description: "The status of the SNAT entry.", }, + "source_cidr": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ExactlyOneOf: []string{"subnet_id", "source_cidr"}, + Description: "The SourceCidr of the SNAT entry. Only one of `subnet_id,source_cidr` can be specified.", + }, }, } } diff --git a/website/docs/d/ecs_instances.html.markdown b/website/docs/d/ecs_instances.html.markdown index e2719fa9..8b0b0da9 100644 --- a/website/docs/d/ecs_instances.html.markdown +++ b/website/docs/d/ecs_instances.html.markdown @@ -16,6 +16,7 @@ data "volcengine_ecs_instances" "foo" { ``` ## Argument Reference The following arguments are supported: +* `deployment_set_ids` - (Optional) A list of DeploymentSet IDs. * `hpc_cluster_id` - (Optional) The hpc cluster ID of ECS instance. * `ids` - (Optional) A list of ECS instance IDs. * `instance_charge_type` - (Optional) The charge type of ECS instance. @@ -39,6 +40,7 @@ In addition to all arguments above, the following attributes are exported: * `instances` - The collection of ECS instance query. * `cpus` - The number of ECS instance CPU cores. * `created_at` - The create time of ECS instance. + * `deployment_set_id` - The ID of DeploymentSet. * `description` - The description of ECS instance. * `gpu_devices` - The GPU device info of Instance. * `count` - The Count of GPU device. diff --git a/website/docs/d/nat_gateways.html.markdown b/website/docs/d/nat_gateways.html.markdown index 299d32b9..9c0edb6c 100644 --- a/website/docs/d/nat_gateways.html.markdown +++ b/website/docs/d/nat_gateways.html.markdown @@ -23,8 +23,14 @@ The following arguments are supported: * `output_file` - (Optional) File name where to save data source results. * `spec` - (Optional) The specification of the NatGateway. * `subnet_id` - (Optional) The id of the Subnet. +* `tags` - (Optional) Tags. * `vpc_id` - (Optional) The id of the VPC. +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + ## Attributes Reference In addition to all arguments above, the following attributes are exported: * `nat_gateways` - The collection of NatGateway query. @@ -46,6 +52,9 @@ In addition to all arguments above, the following attributes are exported: * `spec` - The specification of the NatGateway. * `status` - The status of the NatGateway. * `subnet_id` - The ID of the Subnet. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. * `updated_at` - The update time of the NatGateway. * `vpc_id` - The ID of the VPC. * `total_count` - The total count of NatGateway query. diff --git a/website/docs/d/snat_entries.html.markdown b/website/docs/d/snat_entries.html.markdown index ebfd1d9a..6f21c941 100644 --- a/website/docs/d/snat_entries.html.markdown +++ b/website/docs/d/snat_entries.html.markdown @@ -21,6 +21,7 @@ The following arguments are supported: * `nat_gateway_id` - (Optional) An id of the nat gateway to which the entry belongs. * `output_file` - (Optional) File name where to save data source results. * `snat_entry_name` - (Optional) A name of SNAT entry. +* `source_cidr` - (Optional) The SourceCidr of SNAT entry. * `subnet_id` - (Optional) An id of the subnet that is required to access the Internet. ## Attributes Reference @@ -32,6 +33,7 @@ In addition to all arguments above, the following attributes are exported: * `nat_gateway_id` - The id of the nat gateway to which the entry belongs. * `snat_entry_id` - The id of the SNAT entry. * `snat_entry_name` - The name of the SNAT entry. + * `source_cidr` - The SourceCidr of the SNAT entry. * `status` - The status of the SNAT entry. * `subnet_id` - The id of the subnet that is required to access the internet. * `total_count` - The total count of snat entries query. diff --git a/website/docs/r/nat_gateway.html.markdown b/website/docs/r/nat_gateway.html.markdown index 3c36241f..8ac2aa14 100644 --- a/website/docs/r/nat_gateway.html.markdown +++ b/website/docs/r/nat_gateway.html.markdown @@ -26,6 +26,12 @@ The following arguments are supported: * `description` - (Optional) The description of the NatGateway. * `nat_gateway_name` - (Optional) The name of the NatGateway. * `spec` - (Optional) The specification of the NatGateway. Optional choice contains `Small`(default), `Medium`, `Large`. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. ## Attributes Reference In addition to all arguments above, the following attributes are exported: diff --git a/website/docs/r/snat_entry.html.markdown b/website/docs/r/snat_entry.html.markdown index 211407c8..136e916d 100644 --- a/website/docs/r/snat_entry.html.markdown +++ b/website/docs/r/snat_entry.html.markdown @@ -21,8 +21,9 @@ resource "volcengine_snat_entry" "foo" { The following arguments are supported: * `eip_id` - (Required) The id of the public ip address used by the SNAT entry. * `nat_gateway_id` - (Required, ForceNew) The id of the nat gateway to which the entry belongs. -* `subnet_id` - (Required, ForceNew) The id of the subnet that is required to access the internet. * `snat_entry_name` - (Optional) The name of the SNAT entry. +* `source_cidr` - (Optional, ForceNew) The SourceCidr of the SNAT entry. Only one of `subnet_id,source_cidr` can be specified. +* `subnet_id` - (Optional, ForceNew) The id of the subnet that is required to access the internet. Only one of `subnet_id,source_cidr` can be specified. ## Attributes Reference In addition to all arguments above, the following attributes are exported: From e408e31aa67f941a019ca519ac481061cd30cc5b Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Tue, 7 Feb 2023 16:47:05 +0800 Subject: [PATCH 14/58] feat: support network acl --- common/common_volcengine_version.go | 2 +- example/dataNetworkAcls/main.tf | 6 + example/networkAcl/main.tf | 16 + example/networkAclAssociate/main.tf | 9 + volcengine/provider.go | 5 + .../data_source_volcengine_network_acls.go | 231 ++++++++++ .../resource_volcengine_network_acl.go | 206 +++++++++ .../service_volcengine_network_acl.go | 406 ++++++++++++++++++ ...common_volcengine_network_acl_associate.go | 21 + ...source_volcengine_network_acl_associate.go | 74 ++++ ...ervice_volcengine_network_acl_associate.go | 229 ++++++++++ website/docs/d/network_acls.html.markdown | 64 +++ website/docs/r/network_acl.html.markdown | 67 +++ .../r/network_acl_associate.html.markdown | 39 ++ website/volcengine.erb | 9 + 15 files changed, 1383 insertions(+), 1 deletion(-) create mode 100644 example/dataNetworkAcls/main.tf create mode 100644 example/networkAcl/main.tf create mode 100644 example/networkAclAssociate/main.tf create mode 100644 volcengine/vpc/network_acl/data_source_volcengine_network_acls.go create mode 100644 volcengine/vpc/network_acl/resource_volcengine_network_acl.go create mode 100644 volcengine/vpc/network_acl/service_volcengine_network_acl.go create mode 100644 volcengine/vpc/network_acl_associate/common_volcengine_network_acl_associate.go create mode 100644 volcengine/vpc/network_acl_associate/resource_volcengine_network_acl_associate.go create mode 100644 volcengine/vpc/network_acl_associate/service_volcengine_network_acl_associate.go create mode 100644 website/docs/d/network_acls.html.markdown create mode 100644 website/docs/r/network_acl.html.markdown create mode 100644 website/docs/r/network_acl_associate.html.markdown diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index fea90fb2..1129782a 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.47" + TerraformProviderVersion = "0.0.48" ) diff --git a/example/dataNetworkAcls/main.tf b/example/dataNetworkAcls/main.tf new file mode 100644 index 00000000..2779147a --- /dev/null +++ b/example/dataNetworkAcls/main.tf @@ -0,0 +1,6 @@ +data "volcengine_network_acls" "default"{ +# ids = ["nacl-172leak37mi9s4d1w33pswqkh"] +# vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" +# subnet_id = "subnet-637jxq81u5mon3gd6ivc7rj" + network_acl_name = "ms-tf-acl" +} \ No newline at end of file diff --git a/example/networkAcl/main.tf b/example/networkAcl/main.tf new file mode 100644 index 00000000..02434a0f --- /dev/null +++ b/example/networkAcl/main.tf @@ -0,0 +1,16 @@ +resource "volcengine_network_acl" "foo" { + vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" + network_acl_name = "tf-test-acl" + ingress_acl_entries { + network_acl_entry_name = "ingress1" + policy = "accept" + protocol = "all" + source_cidr_ip = "192.168.0.0/24" + } + egress_acl_entries { + network_acl_entry_name = "egress2" + policy = "accept" + protocol = "all" + destination_cidr_ip = "192.168.0.0/16" + } +} diff --git a/example/networkAclAssociate/main.tf b/example/networkAclAssociate/main.tf new file mode 100644 index 00000000..7bd152c8 --- /dev/null +++ b/example/networkAclAssociate/main.tf @@ -0,0 +1,9 @@ +resource "volcengine_network_acl" "foo" { + vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" + network_acl_name = "tf-test-acl" +} + +resource "volcengine_network_acl_associate" "foo1" { + network_acl_id = volcengine_network_acl.foo.id + resource_id = "subnet-637jxq81u5mon3gd6ivc7rj" +} diff --git a/volcengine/provider.go b/volcengine/provider.go index 0c2535a6..07cbc6e2 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -86,6 +86,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/node" "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/node_pool" "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/support_addon" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_acl" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_acl_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_interface" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_interface_attach" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/route_entry" @@ -167,6 +169,7 @@ func Provider() terraform.ResourceProvider { "volcengine_security_groups": security_group.DataSourceVolcengineSecurityGroups(), "volcengine_security_group_rules": security_group_rule.DataSourceVolcengineSecurityGroupRules(), "volcengine_network_interfaces": network_interface.DataSourceVolcengineNetworkInterfaces(), + "volcengine_network_acls": network_acl.DataSourceVolcengineNetworkAcls(), // ================ EIP ================ "volcengine_eip_addresses": eip_address.DataSourceVolcengineEipAddresses(), @@ -275,6 +278,8 @@ func Provider() terraform.ResourceProvider { "volcengine_network_interface": network_interface.ResourceVolcengineNetworkInterface(), "volcengine_network_interface_attach": network_interface_attach.ResourceVolcengineNetworkInterfaceAttach(), "volcengine_security_group_rule": security_group_rule.ResourceVolcengineSecurityGroupRule(), + "volcengine_network_acl": network_acl.ResourceVolcengineNetworkAcl(), + "volcengine_network_acl_associate": network_acl_associate.ResourceVolcengineNetworkAclAssociate(), // ================ EIP ================ "volcengine_eip_address": eip_address.ResourceVolcengineEipAddress(), diff --git a/volcengine/vpc/network_acl/data_source_volcengine_network_acls.go b/volcengine/vpc/network_acl/data_source_volcengine_network_acls.go new file mode 100644 index 00000000..5833696e --- /dev/null +++ b/volcengine/vpc/network_acl/data_source_volcengine_network_acls.go @@ -0,0 +1,231 @@ +package network_acl + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineNetworkAcls() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineNetworkAclsRead, + Schema: map[string]*schema.Schema{ + "ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "A list of Network Acl IDs.", + }, + "network_acl_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of Network Acl.", + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Description: "The vpc id of Network Acl.", + }, + "subnet_id": { + Type: schema.TypeString, + Optional: true, + Description: "The subnet id of Network Acl.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of Network Acl.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of Network Acl query.", + }, + "network_acls": { + Description: "The collection of Network Acl query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of Network Acl.", + }, + "network_acl_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of Network Acl.", + }, + "network_acl_name": { + Type: schema.TypeString, + Computed: true, + Description: "The Name of Network Acl.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of Network Acl.", + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + Description: "The vpc id of Network Acl.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The Status of Network Acl.", + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + Description: "Creation time of Network Acl.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "Update time of Network Acl.", + }, + "acl_entry_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The count of Network acl entry.", + }, + "ingress_acl_entries": { + Type: schema.TypeList, + Computed: true, + Description: "The ingress entries info of Network Acl.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_acl_entry_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of entry.", + }, + "network_acl_entry_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of entry.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of entry.", + }, + "policy": { + Type: schema.TypeString, + Computed: true, + Description: "The policy of entry.", + }, + "source_cidr_ip": { + Type: schema.TypeString, + Computed: true, + Description: "The SourceCidrIp of entry.", + }, + "protocol": { + Type: schema.TypeString, + Computed: true, + Description: "The protocol of entry.", + }, + "priority": { + Type: schema.TypeInt, + Computed: true, + Description: "The priority of entry.", + }, + "port": { + Type: schema.TypeString, + Computed: true, + Description: "The port of entry.", + }, + }, + }, + }, + "egress_acl_entries": { + Type: schema.TypeList, + Computed: true, + Description: "The egress entries info of Network Acl.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_acl_entry_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of entry.", + }, + "network_acl_entry_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of entry.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of entry.", + }, + "policy": { + Type: schema.TypeString, + Computed: true, + Description: "The policy of entry.", + }, + "destination_cidr_ip": { + Type: schema.TypeString, + Computed: true, + Description: "The DestinationCidrIp of entry.", + }, + "protocol": { + Type: schema.TypeString, + Computed: true, + Description: "The protocol of entry.", + }, + "priority": { + Type: schema.TypeInt, + Computed: true, + Description: "The priority of entry.", + }, + "port": { + Type: schema.TypeString, + Computed: true, + Description: "The port of entry.", + }, + }, + }, + }, + "resources": { + Type: schema.TypeList, + Computed: true, + Description: "The resources info of Network Acl.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_id": { + Type: schema.TypeString, + Computed: true, + Description: "The resource id of Network Acl.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The resource status of Network Acl.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineNetworkAclsRead(d *schema.ResourceData, meta interface{}) error { + aclService := NewNetworkAclService(meta.(*ve.SdkClient)) + return aclService.Dispatcher.Data(aclService, d, DataSourceVolcengineNetworkAcls()) +} diff --git a/volcengine/vpc/network_acl/resource_volcengine_network_acl.go b/volcengine/vpc/network_acl/resource_volcengine_network_acl.go new file mode 100644 index 00000000..d7403c89 --- /dev/null +++ b/volcengine/vpc/network_acl/resource_volcengine_network_acl.go @@ -0,0 +1,206 @@ +package network_acl + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "time" +) + +/* + +Import +Network Acl can be imported using the id, e.g. +``` +$ terraform import volcengine_network_acl.default nacl-172leak37mi9s4d1w33pswqkh +``` + +*/ + +func ResourceVolcengineNetworkAcl() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineNetworkAclCreate, + Read: resourceVolcengineNetworkAclRead, + Update: resourceVolcengineNetworkAclUpdate, + Delete: resourceVolcengineNetworkAclDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "vpc_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The vpc id of Network Acl.", + }, + "network_acl_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name of Network Acl.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the Network Acl.", + }, + "ingress_acl_entries": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "The ingress entries of Network Acl.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_acl_entry_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of entry.", + }, + "network_acl_entry_name": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Description: "The name of entry.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Description: "The description of entry.", + }, + "policy": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "accept", + Description: "The policy of entry.", + }, + "source_cidr_ip": { + Type: schema.TypeString, + Optional: true, + Description: "The SourceCidrIp of entry.", + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "all", + Description: "The protocol of entry.", + }, + "priority": { + Type: schema.TypeInt, + Computed: true, + Description: "The priority of entry.", + }, + "port": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "-1/-1", + Description: "The port of entry.", + }, + }, + }, + }, + "egress_acl_entries": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: "The egress entries of Network Acl.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_acl_entry_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of entry.", + }, + "network_acl_entry_name": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Description: "The name of entry.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Description: "The description of entry.", + }, + "policy": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "accept", + Description: "The policy of entry.", + }, + "destination_cidr_ip": { + Type: schema.TypeString, + Optional: true, + Description: "The DestinationCidrIp of entry.", + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "all", + Description: "The protocol of entry.", + }, + "priority": { + Type: schema.TypeInt, + Computed: true, + Description: "The priority of entry.", + }, + "port": { + Type: schema.TypeString, + Optional: true, + //Computed: true, + Default: "-1/-1", + Description: "The port of entry.", + }, + }, + }, + }, + }, + } +} + +func resourceVolcengineNetworkAclCreate(d *schema.ResourceData, meta interface{}) (err error) { + aclService := NewNetworkAclService(meta.(*ve.SdkClient)) + err = aclService.Dispatcher.Create(aclService, d, ResourceVolcengineNetworkAcl()) + if err != nil { + return fmt.Errorf("error on creating network acl %q, %w", d.Id(), err) + } + return resourceVolcengineNetworkAclRead(d, meta) +} + +func resourceVolcengineNetworkAclRead(d *schema.ResourceData, meta interface{}) (err error) { + aclService := NewNetworkAclService(meta.(*ve.SdkClient)) + err = aclService.Dispatcher.Read(aclService, d, ResourceVolcengineNetworkAcl()) + if err != nil { + return fmt.Errorf("error on reading network acl %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineNetworkAclUpdate(d *schema.ResourceData, meta interface{}) (err error) { + aclService := NewNetworkAclService(meta.(*ve.SdkClient)) + err = aclService.Dispatcher.Update(aclService, d, ResourceVolcengineNetworkAcl()) + if err != nil { + return fmt.Errorf("error on updating network acl %q, %w", d.Id(), err) + } + return resourceVolcengineNetworkAclRead(d, meta) +} + +func resourceVolcengineNetworkAclDelete(d *schema.ResourceData, meta interface{}) (err error) { + aclService := NewNetworkAclService(meta.(*ve.SdkClient)) + err = aclService.Dispatcher.Delete(aclService, d, ResourceVolcengineNetworkAcl()) + if err != nil { + return fmt.Errorf("error on deleting network acl %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/vpc/network_acl/service_volcengine_network_acl.go b/volcengine/vpc/network_acl/service_volcengine_network_acl.go new file mode 100644 index 00000000..591fb643 --- /dev/null +++ b/volcengine/vpc/network_acl/service_volcengine_network_acl.go @@ -0,0 +1,406 @@ +package network_acl + +import ( + "errors" + "fmt" + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "strconv" + "time" +) + +type VolcengineNetworkAclService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewNetworkAclService(c *ve.SdkClient) *VolcengineNetworkAclService { + return &VolcengineNetworkAclService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineNetworkAclService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineNetworkAclService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(condition, "PageSize", "PageNumber", 20, 1, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeNetworkAcls" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + logger.Debug(logger.RespFormat, action, condition, *resp) + + results, err = ve.ObtainSdkValue("Result.NetworkAcls", *resp) + if err != nil { + return data, err + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.NetworkAcls is not Slice") + } + + return data, err + }) +} + +func (s *VolcengineNetworkAclService) ReadResource(resourceData *schema.ResourceData, networkAclId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if networkAclId == "" { + networkAclId = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "NetworkAclIds.1": networkAclId, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("network acl %s is not exist ", networkAclId) + } + + // 删除默认创建的拒绝规则 + if ingressAclEntries, ok := data["IngressAclEntries"]; ok { + for index, entry := range ingressAclEntries.([]interface{}) { + if priority, ok := entry.(map[string]interface{})["Priority"]; ok && priority.(float64) > 100 { + ingressAclEntries = append(ingressAclEntries.([]interface{})[:index], ingressAclEntries.([]interface{})[index+1:]...) + data["IngressAclEntries"] = ingressAclEntries + } + } + } + if egressAclEntries, ok := data["EgressAclEntries"]; ok { + for index, entry := range egressAclEntries.([]interface{}) { + if priority, ok := entry.(map[string]interface{})["Priority"]; ok && priority.(float64) > 100 { + egressAclEntries = append(egressAclEntries.([]interface{})[:index], egressAclEntries.([]interface{})[index+1:]...) + data["EgressAclEntries"] = egressAclEntries + } + } + } + + return data, err +} + +func (s *VolcengineNetworkAclService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + demo map[string]interface{} + status interface{} + ) + //no failed status. + demo, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", demo) + if err != nil { + return nil, "", err + } + return demo, status.(string), err + }, + } +} + +func (VolcengineNetworkAclService) WithResourceResponseHandlers(acl map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return acl, nil, nil + } + return []ve.ResourceResponseHandler{handler} + +} + +func (s *VolcengineNetworkAclService) CreateResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateNetworkAcl", + ConvertMode: ve.RequestConvertAll, + Convert: map[string]ve.RequestConvert{ + "ingress_acl_entries": { + Ignore: true, + }, + "egress_acl_entries": { + Ignore: true, + }, + "resources": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["ClientToken"] = uuid.New().String() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.NetworkAclId", *resp) + d.SetId(id.(string)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + // 规则创建 + entryCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UpdateNetworkAclEntries", + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "ingress_acl_entries": { + ConvertType: ve.ConvertListN, + }, + "egress_acl_entries": { + ConvertType: ve.ConvertListN, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["NetworkAclId"] = d.Id() + (*call.SdkParam)["ClientToken"] = uuid.New().String() + if _, ok := d.GetOk("ingress_acl_entries"); ok { + (*call.SdkParam)["UpdateIngressAclEntries"] = true + } + if _, ok := d.GetOk("egress_acl_entries"); ok { + (*call.SdkParam)["UpdateEgressAclEntries"] = true + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, entryCallback) + + return callbacks +} + +func (s *VolcengineNetworkAclService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyNetworkAclAttributes", + ConvertMode: ve.RequestConvertAll, + Convert: map[string]ve.RequestConvert{ + "ingress_acl_entries": { + Ignore: true, + }, + "egress_acl_entries": { + Ignore: true, + }, + "resources": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["NetworkAclId"] = d.Id() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + // 规则修改 + if resourceData.HasChange("ingress_acl_entries") { + ingressUpdateCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UpdateNetworkAclEntries", + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "ingress_acl_entries": { + ConvertType: ve.ConvertListN, + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["NetworkAclId"] = d.Id() + (*call.SdkParam)["ClientToken"] = uuid.New().String() + (*call.SdkParam)["UpdateIngressAclEntries"] = true + for index, entry := range d.Get("ingress_acl_entries").([]interface{}) { + (*call.SdkParam)["IngressAclEntries."+strconv.Itoa(index+1)+".NetworkAclEntryId"] = entry.(map[string]interface{})["network_acl_entry_id"].(string) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, ingressUpdateCallback) + } + if resourceData.HasChange("egress_acl_entries") { + ingressUpdateCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "UpdateNetworkAclEntries", + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "egress_acl_entries": { + ConvertType: ve.ConvertListN, + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["NetworkAclId"] = d.Id() + (*call.SdkParam)["ClientToken"] = uuid.New().String() + (*call.SdkParam)["UpdateEgressAclEntries"] = true + for index, entry := range d.Get("egress_acl_entries").([]interface{}) { + (*call.SdkParam)["EgressAclEntries."+strconv.Itoa(index+1)+".NetworkAclEntryId"] = entry.(map[string]interface{})["network_acl_entry_id"].(string) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, ingressUpdateCallback) + } + + return callbacks +} + +func (s *VolcengineNetworkAclService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteNetworkAcl", + ConvertMode: ve.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "NetworkAclId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading network acl on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + return callbacks +} + +func (s *VolcengineNetworkAclService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{ + "ids": { + TargetField: "NetworkAclIds", + ConvertType: ve.ConvertWithN, + }, + }, + NameField: "NetworkAclName", + IdField: "NetworkAclId", + CollectField: "network_acls", + ResponseConverts: map[string]ve.ResponseConvert{ + "NetworkAclId": { + TargetField: "id", + KeepDefault: true, + }, + }, + } +} + +func (s *VolcengineNetworkAclService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/vpc/network_acl_associate/common_volcengine_network_acl_associate.go b/volcengine/vpc/network_acl_associate/common_volcengine_network_acl_associate.go new file mode 100644 index 00000000..ad74343a --- /dev/null +++ b/volcengine/vpc/network_acl_associate/common_volcengine_network_acl_associate.go @@ -0,0 +1,21 @@ +package network_acl_associate + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "strings" +) + +var aclAssociateImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("network_acl_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("resource_id", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/vpc/network_acl_associate/resource_volcengine_network_acl_associate.go b/volcengine/vpc/network_acl_associate/resource_volcengine_network_acl_associate.go new file mode 100644 index 00000000..c1b0a36e --- /dev/null +++ b/volcengine/vpc/network_acl_associate/resource_volcengine_network_acl_associate.go @@ -0,0 +1,74 @@ +package network_acl_associate + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "time" +) + +/* + +Import +NetworkAcl associate can be imported using the network_acl_id:resource_id, e.g. +``` +$ terraform import volcengine_network_acl_associate.default nacl-172leak37mi9s4d1w33pswqkh:subnet-637jxq81u5mon3gd6ivc7rj +``` + +*/ + +func ResourceVolcengineNetworkAclAssociate() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineAclAssociateCreate, + Read: resourceVolcengineAclAssociateRead, + Delete: resourceVolcengineAclAssociateDelete, + Importer: &schema.ResourceImporter{ + State: aclAssociateImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "network_acl_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of Network Acl.", + }, + "resource_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The resource id of Network Acl.", + }, + }, + } +} + +func resourceVolcengineAclAssociateCreate(d *schema.ResourceData, meta interface{}) (err error) { + aclAssociateService := NewNetworkAclAssociateService(meta.(*ve.SdkClient)) + err = aclAssociateService.Dispatcher.Create(aclAssociateService, d, ResourceVolcengineNetworkAclAssociate()) + if err != nil { + return fmt.Errorf("error on creating acl Associate %q, %w", d.Id(), err) + } + return resourceVolcengineAclAssociateRead(d, meta) +} + +func resourceVolcengineAclAssociateRead(d *schema.ResourceData, meta interface{}) (err error) { + aclAssociateService := NewNetworkAclAssociateService(meta.(*ve.SdkClient)) + err = aclAssociateService.Dispatcher.Read(aclAssociateService, d, ResourceVolcengineNetworkAclAssociate()) + if err != nil { + return fmt.Errorf("error on reading acl Associate %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineAclAssociateDelete(d *schema.ResourceData, meta interface{}) (err error) { + aclAssociateService := NewNetworkAclAssociateService(meta.(*ve.SdkClient)) + err = aclAssociateService.Dispatcher.Delete(aclAssociateService, d, ResourceVolcengineNetworkAclAssociate()) + if err != nil { + return fmt.Errorf("error on deleting acl Associate %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/vpc/network_acl_associate/service_volcengine_network_acl_associate.go b/volcengine/vpc/network_acl_associate/service_volcengine_network_acl_associate.go new file mode 100644 index 00000000..4a7c647f --- /dev/null +++ b/volcengine/vpc/network_acl_associate/service_volcengine_network_acl_associate.go @@ -0,0 +1,229 @@ +package network_acl_associate + +import ( + "errors" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_acl" + "strings" + "time" +) + +type VolcengineNetworkAclAssociateService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewNetworkAclAssociateService(c *ve.SdkClient) *VolcengineNetworkAclAssociateService { + return &VolcengineNetworkAclAssociateService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineNetworkAclAssociateService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineNetworkAclAssociateService) ReadResources(condition map[string]interface{}) ([]interface{}, error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + err error + ) + + return ve.WithSimpleQuery(condition, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeNetworkAcls" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return []interface{}{}, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return []interface{}{}, err + } + } + logger.Debug(logger.RespFormat, action, condition, *resp) + + results, err = ve.ObtainSdkValue("Result.NetworkAcls", *resp) + if err != nil { + return []interface{}{}, err + } + if _, ok = results.([]interface{}); !ok { + return []interface{}{}, errors.New("Result.NetworkAcls is not Slice") + } + return results.([]interface{}), err + }) +} + +func (s *VolcengineNetworkAclAssociateService) ReadResource(resourceData *schema.ResourceData, associateId string) (data map[string]interface{}, err error) { + if associateId == "" { + associateId = resourceData.Id() + } + + ids := strings.Split(associateId, ":") + if len(ids) != 2 { + return map[string]interface{}{}, fmt.Errorf("invalid acl associateId: %s", associateId) + } + + networkAclId := ids[0] + resourceId := ids[1] + req := map[string]interface{}{ + "NetworkAclIds.1": networkAclId, + } + + networkAcls, err := s.ReadResources(req) + if err != nil { + return nil, err + } + if len(networkAcls) == 0 { + return map[string]interface{}{}, fmt.Errorf("network acl %s not exist ", networkAclId) + } + for _, v := range networkAcls { + if _, ok := v.(map[string]interface{}); !ok { + return map[string]interface{}{}, errors.New("Value is not map ") + } + } + + aclResources := networkAcls[0].(map[string]interface{})["Resources"] + if len(aclResources.([]interface{})) == 0 { + return map[string]interface{}{}, fmt.Errorf("network acl resource %s:%s not exist ", networkAclId, resourceId) + } + for _, v := range aclResources.([]interface{}) { + if _, ok := v.(map[string]interface{}); !ok { + return map[string]interface{}{}, errors.New("Value is not map ") + } + if v.(map[string]interface{})["ResourceId"] == resourceId { + data = v.(map[string]interface{}) + } + } + + return data, err +} + +func (s *VolcengineNetworkAclAssociateService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return nil +} + +func (VolcengineNetworkAclAssociateService) WithResourceResponseHandlers(aclEntry map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return aclEntry, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineNetworkAclAssociateService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AssociateNetworkAcl", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["NetworkAclId"] = d.Get("network_acl_id") + (*call.SdkParam)["Resource.1.ResourceId"] = d.Get("resource_id") + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + // ResourceData中,network_acl_associate的Id形式为'network_acl_id:resource_id' + id := fmt.Sprintf("%s:%s", d.Get("network_acl_id"), d.Get("resource_id")) + d.SetId(id) + return nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("network_acl_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + network_acl.NewNetworkAclService(s.Client): { + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("network_acl_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineNetworkAclAssociateService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{} +} + +func (s *VolcengineNetworkAclAssociateService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DisassociateNetworkAcl", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + aclAssociateId := d.Id() + ids := strings.Split(aclAssociateId, ":") + if len(ids) != 2 { + return false, fmt.Errorf("error network acl associate id: %s", aclAssociateId) + } + (*call.SdkParam)["NetworkAclId"] = ids[0] + (*call.SdkParam)["Resource.1.ResourceId"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading acl entry on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("network_acl_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + network_acl.NewNetworkAclService(s.Client): { + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("network_acl_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineNetworkAclAssociateService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{} +} + +func (s *VolcengineNetworkAclAssociateService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/website/docs/d/network_acls.html.markdown b/website/docs/d/network_acls.html.markdown new file mode 100644 index 00000000..895c278c --- /dev/null +++ b/website/docs/d/network_acls.html.markdown @@ -0,0 +1,64 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_network_acls" +sidebar_current: "docs-volcengine-datasource-network_acls" +description: |- + Use this data source to query detailed information of network acls +--- +# volcengine_network_acls +Use this data source to query detailed information of network acls +## Example Usage +```hcl +data "volcengine_network_acls" "default" { + # ids = ["nacl-172leak37mi9s4d1w33pswqkh"] + # vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" + # subnet_id = "subnet-637jxq81u5mon3gd6ivc7rj" + network_acl_name = "ms-tf-acl" +} +``` +## Argument Reference +The following arguments are supported: +* `ids` - (Optional) A list of Network Acl IDs. +* `name_regex` - (Optional) A Name Regex of Network Acl. +* `network_acl_name` - (Optional) The name of Network Acl. +* `output_file` - (Optional) File name where to save data source results. +* `subnet_id` - (Optional) The subnet id of Network Acl. +* `vpc_id` - (Optional) The vpc id of Network Acl. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `network_acls` - The collection of Network Acl query. + * `acl_entry_count` - The count of Network acl entry. + * `creation_time` - Creation time of Network Acl. + * `description` - The description of Network Acl. + * `egress_acl_entries` - The egress entries info of Network Acl. + * `description` - The description of entry. + * `destination_cidr_ip` - The DestinationCidrIp of entry. + * `network_acl_entry_id` - The id of entry. + * `network_acl_entry_name` - The name of entry. + * `policy` - The policy of entry. + * `port` - The port of entry. + * `priority` - The priority of entry. + * `protocol` - The protocol of entry. + * `id` - The ID of Network Acl. + * `ingress_acl_entries` - The ingress entries info of Network Acl. + * `description` - The description of entry. + * `network_acl_entry_id` - The id of entry. + * `network_acl_entry_name` - The name of entry. + * `policy` - The policy of entry. + * `port` - The port of entry. + * `priority` - The priority of entry. + * `protocol` - The protocol of entry. + * `source_cidr_ip` - The SourceCidrIp of entry. + * `network_acl_id` - The ID of Network Acl. + * `network_acl_name` - The Name of Network Acl. + * `resources` - The resources info of Network Acl. + * `resource_id` - The resource id of Network Acl. + * `status` - The resource status of Network Acl. + * `status` - The Status of Network Acl. + * `update_time` - Update time of Network Acl. + * `vpc_id` - The vpc id of Network Acl. +* `total_count` - The total count of Network Acl query. + + diff --git a/website/docs/r/network_acl.html.markdown b/website/docs/r/network_acl.html.markdown new file mode 100644 index 00000000..a4da2b4f --- /dev/null +++ b/website/docs/r/network_acl.html.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_network_acl" +sidebar_current: "docs-volcengine-resource-network_acl" +description: |- + Provides a resource to manage network acl +--- +# volcengine_network_acl +Provides a resource to manage network acl +## Example Usage +```hcl +resource "volcengine_network_acl" "foo" { + vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" + network_acl_name = "tf-test-acl" + ingress_acl_entries { + network_acl_entry_name = "ingress1" + policy = "accept" + protocol = "all" + source_cidr_ip = "192.168.0.0/24" + } + egress_acl_entries { + network_acl_entry_name = "egress2" + policy = "accept" + protocol = "all" + destination_cidr_ip = "192.168.0.0/16" + } +} +``` +## Argument Reference +The following arguments are supported: +* `vpc_id` - (Required, ForceNew) The vpc id of Network Acl. +* `description` - (Optional) The description of the Network Acl. +* `egress_acl_entries` - (Optional) The egress entries of Network Acl. +* `ingress_acl_entries` - (Optional) The ingress entries of Network Acl. +* `network_acl_name` - (Optional) The name of Network Acl. + +The `egress_acl_entries` object supports the following: + +* `description` - (Optional) The description of entry. +* `destination_cidr_ip` - (Optional) The DestinationCidrIp of entry. +* `network_acl_entry_name` - (Optional) The name of entry. +* `policy` - (Optional) The policy of entry. +* `port` - (Optional) The port of entry. +* `protocol` - (Optional) The protocol of entry. + +The `ingress_acl_entries` object supports the following: + +* `description` - (Optional) The description of entry. +* `network_acl_entry_name` - (Optional) The name of entry. +* `policy` - (Optional) The policy of entry. +* `port` - (Optional) The port of entry. +* `protocol` - (Optional) The protocol of entry. +* `source_cidr_ip` - (Optional) The SourceCidrIp of entry. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +Network Acl can be imported using the id, e.g. +``` +$ terraform import volcengine_network_acl.default nacl-172leak37mi9s4d1w33pswqkh +``` + diff --git a/website/docs/r/network_acl_associate.html.markdown b/website/docs/r/network_acl_associate.html.markdown new file mode 100644 index 00000000..038b73cd --- /dev/null +++ b/website/docs/r/network_acl_associate.html.markdown @@ -0,0 +1,39 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_network_acl_associate" +sidebar_current: "docs-volcengine-resource-network_acl_associate" +description: |- + Provides a resource to manage network acl associate +--- +# volcengine_network_acl_associate +Provides a resource to manage network acl associate +## Example Usage +```hcl +resource "volcengine_network_acl" "foo" { + vpc_id = "vpc-ru0wv9alfoxsu3nuld85rpp" + network_acl_name = "tf-test-acl" +} + +resource "volcengine_network_acl_associate" "foo1" { + network_acl_id = volcengine_network_acl.foo.id + resource_id = "subnet-637jxq81u5mon3gd6ivc7rj" +} +``` +## Argument Reference +The following arguments are supported: +* `network_acl_id` - (Required, ForceNew) The id of Network Acl. +* `resource_id` - (Required, ForceNew) The resource id of Network Acl. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +NetworkAcl associate can be imported using the network_acl_id:resource_id, e.g. +``` +$ terraform import volcengine_network_acl_associate.default nacl-172leak37mi9s4d1w33pswqkh:subnet-637jxq81u5mon3gd6ivc7rj +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index 63d33e9b..e789d57e 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -601,6 +601,9 @@
  • Data Sources
  • @@ -252,6 +255,9 @@
  • cr_tag
  • +
  • + cr_vpc_endpoint +
  • From f317f4985c1ca5939d08a4b69967ca178a0fc670 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Thu, 6 Apr 2023 19:42:58 +0800 Subject: [PATCH 25/58] feat: opt ESCloud instance --- example/esCloudInstance/main.tf | 7 +- .../common_volcengine_escloud_instance.go | 48 +++++ .../resource_volcengine_escloud_instance.go | 33 ++-- .../service_volcengine_escloud_instance.go | 175 ++++++++++++++++-- website/docs/r/escloud_instance.html.markdown | 18 +- 5 files changed, 241 insertions(+), 40 deletions(-) create mode 100644 volcengine/escloud/instance/common_volcengine_escloud_instance.go diff --git a/example/esCloudInstance/main.tf b/example/esCloudInstance/main.tf index 36200008..acd06e33 100644 --- a/example/esCloudInstance/main.tf +++ b/example/esCloudInstance/main.tf @@ -1,4 +1,3 @@ - resource "volcengine_escloud_instance" "foo" { instance_configuration { version = "V7_10" @@ -28,9 +27,9 @@ resource "volcengine_escloud_instance" "foo" { type = "Kibana" number = 1 resource_spec_name = "kibana.x2.small" - storage_spec_name = "es.volume.essd.pl0" - storage_size = 0 } subnet_id = "subnet-2bz9vxrixqigw2dx0eextz50p" + project_name = "default" + force_restart_after_scale = false } -} +} \ No newline at end of file diff --git a/volcengine/escloud/instance/common_volcengine_escloud_instance.go b/volcengine/escloud/instance/common_volcengine_escloud_instance.go new file mode 100644 index 00000000..a98e5b0a --- /dev/null +++ b/volcengine/escloud/instance/common_volcengine_escloud_instance.go @@ -0,0 +1,48 @@ +package instance + +import ( + "reflect" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var nodeSpecsAssignsDiffSuppressFunc = func(k, old, new string, d *schema.ResourceData) bool { + return !diffNodeSpecsAssigns(d) +} + +var forceRestartAfterScaleDiffSuppressFunc = func(k, old, new string, d *schema.ResourceData) bool { + // 创建时不存在这个参数,修改 node_specs_assigns 时存在这个参数 + return !(d.Id() != "" && diffNodeSpecsAssigns(d)) +} + +func diffNodeSpecsAssigns(d *schema.ResourceData) bool { + oldVal, newVal := d.GetChange("instance_configuration.0.node_specs_assigns") + oldNodeConfigs := transListToMap(oldVal.([]interface{})) + newNodeConfigs := transListToMap(newVal.([]interface{})) + + if !reflect.DeepEqual(oldNodeConfigs["Master"], newNodeConfigs["Master"]) { + return true + } + if !reflect.DeepEqual(oldNodeConfigs["Hot"], newNodeConfigs["Hot"]) { + return true + } + if !reflect.DeepEqual(oldNodeConfigs["Kibana"], newNodeConfigs["Kibana"]) { + return true + } + + return false +} + +func transListToMap(nodeList []interface{}) map[string]map[string]interface{} { + nodeMap := map[string]map[string]interface{}{} + for _, value := range nodeList { + nodeType := value.(map[string]interface{})["type"] + nodeMap[nodeType.(string)] = map[string]interface{}{ + "StorageSpecName": value.(map[string]interface{})["storage_spec_name"], + "StorageSize": value.(map[string]interface{})["storage_size"], + "ResourceSpecName": value.(map[string]interface{})["resource_spec_name"], + "Number": value.(map[string]interface{})["number"], + } + } + return nodeMap +} diff --git a/volcengine/escloud/instance/resource_volcengine_escloud_instance.go b/volcengine/escloud/instance/resource_volcengine_escloud_instance.go index dd1c8032..b82e46c8 100644 --- a/volcengine/escloud/instance/resource_volcengine_escloud_instance.go +++ b/volcengine/escloud/instance/resource_volcengine_escloud_instance.go @@ -90,7 +90,7 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { Type: schema.TypeString, Required: true, Sensitive: true, - Description: "The password of administrator account.", + Description: "The password of administrator account. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", }, "charge_type": { Type: schema.TypeString, @@ -105,6 +105,7 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { "configuration_code": { Type: schema.TypeString, Required: true, + ForceNew: true, Description: "Configuration code used for billing.", }, "enable_pure_master": { @@ -114,9 +115,10 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { Description: "Whether the Master node is independent.", }, "node_specs_assigns": { - Type: schema.TypeList, - Required: true, - Description: "The number and configuration of various ESCloud instance node.", + Type: schema.TypeList, + Required: true, + Description: "The number and configuration of various ESCloud instance node. Kibana NodeSpecsAssign should not be modified.", + DiffSuppressFunc: nodeSpecsAssignsDiffSuppressFunc, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "type": { @@ -137,13 +139,13 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { }, "storage_spec_name": { Type: schema.TypeString, - Required: true, - Description: "The name of storage spec.", + Optional: true, + Description: "The name of storage spec. Kibana NodeSpecsAssign should not specify this field.", }, "storage_size": { Type: schema.TypeInt, - Required: true, - Description: "The size of storage.", + Optional: true, + Description: "The size of storage. Kibana NodeSpecsAssign should not specify this field.", }, }, }, @@ -175,9 +177,10 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { }, }, "maintenance_day": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, Computed: true, + Set: schema.HashString, Description: "The maintainable date for the instance. Works only on modified scenes.", DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { // 创建时不存在这个参数,修改时存在这个参数 @@ -188,13 +191,11 @@ func ResourceVolcengineESCloudInstance() *schema.Resource { }, }, "force_restart_after_scale": { - Type: schema.TypeBool, - Optional: true, - Default: false, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return d.Id() == "" - }, - Description: "Whether to force restart when changes are made. If true, it means that the cluster will be forced to restart without paying attention to instance availability.", + Type: schema.TypeBool, + Optional: true, + DiffSuppressFunc: forceRestartAfterScaleDiffSuppressFunc, + Description: "Whether to force restart when changes are made. " + + "If true, it means that the cluster will be forced to restart without paying attention to instance availability. Works only on modified the node_specs_assigns field.", }, }, }, diff --git a/volcengine/escloud/instance/service_volcengine_escloud_instance.go b/volcengine/escloud/instance/service_volcengine_escloud_instance.go index b8947ecc..bed17b48 100644 --- a/volcengine/escloud/instance/service_volcengine_escloud_instance.go +++ b/volcengine/escloud/instance/service_volcengine_escloud_instance.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "reflect" "strconv" "strings" "time" @@ -155,16 +156,48 @@ func (s *VolcengineESCloudInstanceService) ReadResource(resourceData *schema.Res if val := resourceData.Get("instance_configuration.0.admin_password"); val != "" { data["InstanceConfiguration"].(map[string]interface{})["AdminPassword"] = val } - if val := resourceData.Get("instance_configuration.0.configuration_code"); val != "" { - data["InstanceConfiguration"].(map[string]interface{})["ConfigurationCode"] = val + if val, ok := resourceData.GetOkExists("instance_configuration.0.force_restart_after_scale"); ok { + data["InstanceConfiguration"].(map[string]interface{})["ForceRestartAfterScale"] = val } + if subnet, ok := data["InstanceConfiguration"].(map[string]interface{})["Subnet"]; ok { + data["InstanceConfiguration"].(map[string]interface{})["SubnetId"] = subnet.(map[string]interface{})["SubnetId"] + } + + if nodeAssigns, ok := data["InstanceConfiguration"].(map[string]interface{})["NodeSpecsAssigns"]; ok { + finalAssigns := make([]interface{}, 0) + for _, nodeAssign := range nodeAssigns.([]interface{}) { + if nodeType := nodeAssign.(map[string]interface{})["Type"]; nodeType == "Master" || nodeType == "Hot" || nodeType == "Kibana" { + finalAssigns = append(finalAssigns, nodeAssign) + } + } + data["InstanceConfiguration"].(map[string]interface{})["NodeSpecsAssigns"] = finalAssigns + } + + // 查询 configuration_code + action := "DescribeNodeAvailableSpecs" + con := &map[string]interface{}{ + "InstanceId": id, + } + logger.Debug(logger.ReqFormat, action, con) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), con) + if err != nil { + return data, err + } + logger.Debug(logger.RespFormat, action, resp) + configurationCode, err := ve.ObtainSdkValue("Result.ConfigurationCode", *resp) + if err != nil { + return data, err + } + if configurationCode == nil { + configurationCode = "" + } + data["InstanceConfiguration"].(map[string]interface{})["ConfigurationCode"] = configurationCode + + // 确保查询后 state 文件里的顺序和用户填写的顺序一致 assigns := resourceData.Get("instance_configuration.0.node_specs_assigns") if assigns != nil && len(assigns.([]interface{})) > 0 { data["InstanceConfiguration"].(map[string]interface{})["NodeSpecsAssigns"] = assigns } - if subnet, ok := data["InstanceConfiguration"].(map[string]interface{})["Subnet"]; ok { - data["InstanceConfiguration"].(map[string]interface{})["SubnetId"] = subnet.(map[string]interface{})["SubnetId"] - } return data, err } @@ -298,11 +331,22 @@ func preCheckNodeSpec(call ve.SdkCall) error { return nil } +func diffCheckNodeSpec(d *schema.ResourceData) error { + oldVal, newVal := d.GetChange("instance_configuration.0.node_specs_assigns") + oldNodeConfigs := transListToMap(oldVal.([]interface{})) + newNodeConfigs := transListToMap(newVal.([]interface{})) + if !reflect.DeepEqual(oldNodeConfigs["Kibana"], newNodeConfigs["Kibana"]) { + return fmt.Errorf(" Kibana NodeSpecsAssign should not be modified.") + } + return nil +} + func (s *VolcengineESCloudInstanceService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { callback := ve.Callback{ Call: ve.SdkCall{ Action: "CreateInstance", ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertAll, Convert: map[string]ve.RequestConvert{ "instance_configuration": { ConvertType: ve.ConvertJsonObject, @@ -419,6 +463,7 @@ func (s *VolcengineESCloudInstanceService) CreateResource(resourceData *schema.R } (*call.SdkParam)["InstanceConfiguration.RegionId"] = regionId (*call.SdkParam)["InstanceConfiguration.ZoneId"] = zoneId + (*call.SdkParam)["ClientToken"] = uuid.New().String() logger.DebugInfo("sdk param:%v", *call.SdkParam) return true, nil @@ -473,7 +518,7 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R if resourceData.HasChange("instance_configuration.0.maintenance_day") || resourceData.HasChange("instance_configuration.0.maintenance_time") { id := resourceData.Id() maintenanceTime := resourceData.Get("instance_configuration.0.maintenance_time") - maintenanceDay := resourceData.Get("instance_configuration.0.maintenance_day") + maintenanceDay := resourceData.Get("instance_configuration.0.maintenance_day").(*schema.Set).List() logger.DebugInfo("maintenance changed:%v", maintenanceTime) logger.DebugInfo("maintenance changed:%v", maintenanceDay) @@ -501,7 +546,7 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R if resourceData.HasChange("instance_configuration.0.admin_password") { id := resourceData.Id() password := resourceData.Get("instance_configuration.0.admin_password") - userName := resourceData.Get("instance_configuration.0.instance_name") + userName := resourceData.Get("instance_configuration.0.admin_user_name") logger.DebugInfo("Modify admin password of instance %s.", id) @@ -523,7 +568,7 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R }, Refresh: &ve.StateRefresh{ Target: []string{"Running"}, - Timeout: resourceData.Timeout(schema.TimeoutCreate), + Timeout: resourceData.Timeout(schema.TimeoutUpdate), }, }, } @@ -544,6 +589,9 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R "node_specs_assigns": { ConvertType: ve.ConvertJsonObjectArray, }, + "force_restart_after_scale": { + Ignore: true, + }, }, }, }, @@ -551,6 +599,11 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R totalNodeNumber := 0 var nodeSpecsAssigns []map[string]interface{} nodeSpecs := d.Get("instance_configuration.0.node_specs_assigns").([]interface{}) + // 不允许修改 Kibana,如果修改了 Kibana 就给用户报错 + err := diffCheckNodeSpec(d) + if err != nil { + return false, err + } for i, node := range nodeSpecs { if node.(map[string]interface{})["type"].(string) == "Master" { if d.HasChange("instance_configuration.0.node_specs_assigns." + strconv.Itoa(i) + ".number") { @@ -561,6 +614,10 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R nodeNumber := d.Get("instance_configuration.0.node_specs_assigns." + strconv.Itoa(i) + ".number") totalNodeNumber += nodeNumber.(int) } + // 不能传递 Kibana 的信息 + if node.(map[string]interface{})["type"].(string) == "Kibana" { + continue + } nodeSpecsAssigns = append(nodeSpecsAssigns, map[string]interface{}{ "Type": node.(map[string]interface{})["type"], "Number": node.(map[string]interface{})["number"], @@ -574,7 +631,7 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R } // check node specs (*call.SdkParam)["InstanceConfiguration.EnablePureMaster"] = d.Get("instance_configuration.0.enable_pure_master") - err := preCheckNodeSpec(call) + err = preCheckNodeSpec(call) if err != nil { return false, err } @@ -587,22 +644,27 @@ func (s *VolcengineESCloudInstanceService) ModifyResource(resourceData *schema.R (*call.SdkParam)["InstanceId"] = d.Id() (*call.SdkParam)["NodeSpecsAssigns"] = nodeSpecsAssigns (*call.SdkParam)["ConfigurationCode"] = d.Get("instance_configuration.0.configuration_code") - (*call.SdkParam)["Force"] = false + (*call.SdkParam)["Force"] = d.Get("instance_configuration.0.force_restart_after_scale") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + delete(*call.SdkParam, "InstanceConfiguration") logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) }, Refresh: &ve.StateRefresh{ Target: []string{"Running"}, - Timeout: resourceData.Timeout(schema.TimeoutCreate), + Timeout: resourceData.Timeout(schema.TimeoutUpdate), }, }, } callbacks = append(callbacks, scaleCallback) } + if resourceData.HasChange("instance_configuration.0.project_name") { + callbacks = s.modifyProject(resourceData, callbacks) + } + return callbacks } @@ -620,6 +682,24 @@ func (s *VolcengineESCloudInstanceService) RemoveResource(resourceData *schema.R logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) return s.Client.UniversalClient.DoCall(getUniversalInfo("ReleaseInstance"), call.SdkParam) }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading ESCloud instance on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, }, } return []ve.Callback{callback} @@ -696,6 +776,70 @@ func (s *VolcengineESCloudInstanceService) ReadResourceId(id string) string { return id } +func (s *VolcengineESCloudInstanceService) modifyProject(resourceData *schema.ResourceData, callbacks []ve.Callback) []ve.Callback { + modifyProjectCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "MoveProjectResource", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["TargetProjectName"] = d.Get("instance_configuration.0.project_name") + if (*call.SdkParam)["TargetProjectName"] == nil || (*call.SdkParam)["TargetProjectName"] == "" { + return false, fmt.Errorf("Could set ProjectName to empty ") + } + //获取用户ID + input := map[string]interface{}{ + "ProjectName": (*call.SdkParam)["TargetProjectName"], + } + logger.Debug(logger.ReqFormat, "GetProject", input) + out, err := s.Client.UniversalClient.DoCall(getIamUniversalInfo("GetProject"), &input) + if err != nil { + return false, err + } + accountId, err := ve.ObtainSdkValue("Result.AccountID", *out) + if err != nil { + return false, err + } + trnStr := fmt.Sprintf("trn:ESCloud:%s:%d:instance/%s", s.Client.Region, int(accountId.(float64)), resourceData.Id()) + (*call.SdkParam)["ResourceTrn.1"] = trnStr + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getIamUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + var ( + instance = make(map[string]interface{}) + err error + ) + // 通过 retry 确保 project_name 已成功修改 + resource.Retry(15*time.Minute, func() *resource.RetryError { + instance, err = s.ReadResource(d, d.Id()) + if err != nil { + if ve.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading ESCloud instance %q", d.Id())) + } + } + projectName, err := ve.ObtainSdkValue("InstanceConfiguration.ProjectName", instance) + if err != nil { + return resource.RetryableError(err) + } + if projectName.(string) != d.Get("instance_configuration.0.project_name").(string) { + return resource.RetryableError(fmt.Errorf("ESCloud instance is still in updating project name")) + } + return nil + }) + return nil + }, + }, + } + callbacks = append(callbacks, modifyProjectCallback) + + return callbacks +} + func getUniversalInfo(actionName string) ve.UniversalInfo { return ve.UniversalInfo{ ServiceName: "ESCloud", @@ -705,3 +849,12 @@ func getUniversalInfo(actionName string) ve.UniversalInfo { Action: actionName, } } + +func getIamUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "iam", + Version: "2021-08-01", + HttpMethod: ve.GET, + Action: actionName, + } +} diff --git a/website/docs/r/escloud_instance.html.markdown b/website/docs/r/escloud_instance.html.markdown index 8eadead0..83e23a41 100644 --- a/website/docs/r/escloud_instance.html.markdown +++ b/website/docs/r/escloud_instance.html.markdown @@ -39,10 +39,10 @@ resource "volcengine_escloud_instance" "foo" { type = "Kibana" number = 1 resource_spec_name = "kibana.x2.small" - storage_spec_name = "es.volume.essd.pl0" - storage_size = 0 } - subnet_id = "subnet-2bz9vxrixqigw2dx0eextz50p" + subnet_id = "subnet-2bz9vxrixqigw2dx0eextz50p" + project_name = "default" + force_restart_after_scale = false } } ``` @@ -52,17 +52,17 @@ The following arguments are supported: The `instance_configuration` object supports the following: -* `admin_password` - (Required) The password of administrator account. +* `admin_password` - (Required) The password of administrator account. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. * `admin_user_name` - (Required, ForceNew) The name of administrator account(should be admin). * `charge_type` - (Required, ForceNew) The charge type of ESCloud instance, the value can be PostPaid or PrePaid. -* `configuration_code` - (Required) Configuration code used for billing. +* `configuration_code` - (Required, ForceNew) Configuration code used for billing. * `enable_https` - (Required, ForceNew) Whether Https access is enabled. * `enable_pure_master` - (Required, ForceNew) Whether the Master node is independent. -* `node_specs_assigns` - (Required) The number and configuration of various ESCloud instance node. +* `node_specs_assigns` - (Required) The number and configuration of various ESCloud instance node. Kibana NodeSpecsAssign should not be modified. * `subnet_id` - (Required, ForceNew) The ID of subnet, the subnet must belong to the AZ selected. * `version` - (Required, ForceNew) The version of ESCloud instance, the value is V6_7 or V7_10. * `zone_number` - (Required, ForceNew) The zone count of the ESCloud instance used. -* `force_restart_after_scale` - (Optional) Whether to force restart when changes are made. If true, it means that the cluster will be forced to restart without paying attention to instance availability. +* `force_restart_after_scale` - (Optional) Whether to force restart when changes are made. If true, it means that the cluster will be forced to restart without paying attention to instance availability. Works only on modified the node_specs_assigns field. * `instance_name` - (Optional) The name of ESCloud instance. * `maintenance_day` - (Optional) The maintainable date for the instance. Works only on modified scenes. * `maintenance_time` - (Optional) The maintainable time period for the instance. Works only on modified scenes. @@ -74,9 +74,9 @@ The `node_specs_assigns` object supports the following: * `number` - (Required) The number of node. * `resource_spec_name` - (Required) The name of compute resource spec, the value is `kibana.x2.small` or `es.x4.medium` or `es.x4.large` or `es.x4.xlarge` or `es.x2.2xlarge` or `es.x4.2xlarge` or `es.x2.3xlarge`. -* `storage_size` - (Required) The size of storage. -* `storage_spec_name` - (Required) The name of storage spec. * `type` - (Required) The type of node, the value is `Master` or `Hot` or `Kibana`. +* `storage_size` - (Optional) The size of storage. Kibana NodeSpecsAssign should not specify this field. +* `storage_spec_name` - (Optional) The name of storage spec. Kibana NodeSpecsAssign should not specify this field. ## Attributes Reference In addition to all arguments above, the following attributes are exported: From f1cdf80332a3d461d6f2837c4bd504c4be2ce44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 15:15:42 +0800 Subject: [PATCH 26/58] feat: add rds mysql allowlist and allowlist_associate --- example/dataRdsMysqlAllowlists/main.tf | 3 + example/rdsMysqlAllowlist/main.tf | 5 + example/rdsMysqlAllowlistAssociate/main.tf | 4 + ..._source_volcengine_rds_mysql_allowlists.go | 78 ++++++++ ...resource_volcengine_rds_mysql_allowlist.go | 116 +++++++++++ .../service_volcengine_rds_mysql_allowlist.go | 187 ++++++++++++++++++ ...olcengine_rds_mysql_allowlist_associate.go | 93 +++++++++ ...olcengine_rds_mysql_allowlist_associate.go | 112 +++++++++++ volcengine/provider.go | 9 + 9 files changed, 607 insertions(+) create mode 100644 example/dataRdsMysqlAllowlists/main.tf create mode 100644 example/rdsMysqlAllowlist/main.tf create mode 100644 example/rdsMysqlAllowlistAssociate/main.tf create mode 100644 volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go create mode 100644 volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go create mode 100644 volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go create mode 100644 volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go create mode 100644 volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go diff --git a/example/dataRdsMysqlAllowlists/main.tf b/example/dataRdsMysqlAllowlists/main.tf new file mode 100644 index 00000000..c8e8a3ca --- /dev/null +++ b/example/dataRdsMysqlAllowlists/main.tf @@ -0,0 +1,3 @@ +data "volcengine_rds_mysql_allowlists" "default" { + region_id = "cn-guilin-boe" +} \ No newline at end of file diff --git a/example/rdsMysqlAllowlist/main.tf b/example/rdsMysqlAllowlist/main.tf new file mode 100644 index 00000000..78bea068 --- /dev/null +++ b/example/rdsMysqlAllowlist/main.tf @@ -0,0 +1,5 @@ +resource "volcengine_rds_mysql_allowlist" "foo" { + allow_list_name = "tf-test" + allow_list_desc = "terraform test zzm" + allow_list = "127.0.0.1" +} \ No newline at end of file diff --git a/example/rdsMysqlAllowlistAssociate/main.tf b/example/rdsMysqlAllowlistAssociate/main.tf new file mode 100644 index 00000000..2e1e287e --- /dev/null +++ b/example/rdsMysqlAllowlistAssociate/main.tf @@ -0,0 +1,4 @@ +resource "volcengine_rds_mysql_allowlist_associate" "foo" { + instance_id = "mysql-1b2c7b2d7583" + allow_list_id = "acl-15451212dcfa473baeda24be4baa02fe" +} \ No newline at end of file diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go new file mode 100644 index 00000000..82c6b197 --- /dev/null +++ b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go @@ -0,0 +1,78 @@ +package allowlist + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineRdsMysqlAllowLists() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineRdsMysqlAllowListsRead, + Schema: map[string]*schema.Schema{ + "region_id": { + Required: true, + Type: schema.TypeString, + Description: "The region of the allow lists.", + }, + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of Scaling Activity query.", + }, + "allow_lists": { + Description: "The list of allowed list.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_list_desc": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the allow list.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + "allow_list_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the allow list.", + }, + "allow_list_ip_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of IP addresses (or address ranges) in the whitelist.", + }, + "allow_list_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the allow list.", + }, + "associated_instance_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of instances bound under the whitelist.", + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineRdsMysqlAllowListsRead(d *schema.ResourceData, meta interface{}) error { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineRdsMysqlAllowLists()) +} diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go new file mode 100644 index 00000000..8faeddcc --- /dev/null +++ b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go @@ -0,0 +1,116 @@ +package allowlist + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +RDS AllowList can be imported using the id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist.default acl-d1fd76693bd54e658912e7337d5b**** +``` + +*/ + +func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlAllowlistCreate, + Read: resourceVolcengineRdsMysqlAllowlistRead, + Update: resourceVolcengineRdsMysqlAllowlistUpdate, + Delete: resourceVolcengineRdsMysqlAllowlistDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "allow_list_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of the allow list.", + }, + "allow_list_desc": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the allow list.", + }, + "allow_list_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", + }, + "allow_list": { + Type: schema.TypeString, + Required: true, + Description: "Enter an IP address or a range of IP addresses in CIDR format.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + "modify_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Cover", + "Append", + "Delete", + }, false), + Description: "The modify mode.", + }, + "apply_instance_number": { + Type: schema.TypeInt, + Optional: true, + Description: "The number of instances bound to the current whitelist.", + }, + }, + } +} + +func resourceVolcengineRdsMysqlAllowlistCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error creating RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error reading RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlAllowlistUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error updating RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error deleting RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go new file mode 100644 index 00000000..825c1914 --- /dev/null +++ b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -0,0 +1,187 @@ +package allowlist + +import ( + "errors" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlAllowListService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func (s *VolcengineRdsMysqlAllowListService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return volc.WithSimpleQuery(condition, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeAllowLists" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + results, err = volc.ObtainSdkValue("Result.AllowLists", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.AllowLists is not slice ") + } + return data, err + }) +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "AllowListId": id, + } + action := "DescribeAllowListDetail" + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + return data, err + } + results, err = volc.ObtainSdkValue("Result", *resp) + if err != nil { + return data, err + } + if data, ok = results.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + if len(data) == 0 { + return data, fmt.Errorf("Rds instance %s not exist ", id) + } + return data, err +} + +func (s *VolcengineRdsMysqlAllowListService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{} +} + +func (s *VolcengineRdsMysqlAllowListService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return m, map[string]volc.ResponseConvert{}, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "CreateAllowList", + ConvertMode: volc.RequestConvertAll, + ContentType: volc.ContentTypeJson, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + id, _ := volc.ObtainSdkValue("Result.AllowListId", *resp) + d.SetId(id.(string)) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "ModifyAllowList", + ConvertMode: volc.RequestConvertInConvert, + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "AllowListId": data.Id(), + "AllowListName": data.Get("allow_list_name").(string), + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DeleteAllowList", + ConvertMode: volc.RequestConvertIgnore, + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "AllowListId": data.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{ + ContentType: volc.ContentTypeJson, + NameField: "AllowListName", + IdField: "AllowListId", + CollectField: "allow_lists", + ResponseConverts: map[string]volc.ResponseConvert{ + "AllowListIPNum": { + TargetField: "allow_list_ip_num", + }, + }, + } +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResourceId(id string) string { + return id +} + +func NewRdsMysqlAllowListService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListService { + return &VolcengineRdsMysqlAllowListService{ + Client: client, + Dispatcher: &volc.Dispatcher{}, + } +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go new file mode 100644 index 00000000..eaf178e0 --- /dev/null +++ b/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go @@ -0,0 +1,93 @@ +package allowlist_associate + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +RDS AllowList Associate can be imported using the instance id and allow list id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist_associate.default rds-mysql-h441603c68aaa:acl-d1fd76693bd54e658912e7337d5b**** +``` + +*/ + +func ResourceVolcengineRdsMysqlAllowlistAssociate() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlAllowlistAssociateCreate, + Read: resourceVolcengineRdsMysqlAllowlistAssociateRead, + Delete: resourceVolcengineRdsMysqlAllowlistAssociateDelete, + Importer: &schema.ResourceImporter{ + State: importAllowListAssociate, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the mysql instance.", + }, + "allow_list_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the allow list.", + }, + }, + } +} + +func resourceVolcengineRdsMysqlAllowlistAssociateCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error creating RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistAssociateRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistAssociateRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error reading RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlAllowlistAssociateDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error deleting RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return err +} + +func importAllowListAssociate(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + var err error + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must be of the form InstanceId:AllowListId") + } + err = data.Set("instance_id", items[0]) + if err != nil { + return []*schema.ResourceData{data}, err + } + err = data.Set("allow_list_id", items[1]) + if err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go new file mode 100644 index 00000000..763a62ec --- /dev/null +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -0,0 +1,112 @@ +package allowlist_associate + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlAllowListAssociateService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + return nil, nil +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + return nil, nil +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return m, map[string]volc.ResponseConvert{}, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + instanceId := data.Get("instance_id").(string) + allowListId := data.Get("allow_list_id").(string) + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "AssociateAllowList", + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + d.SetId(fmt.Sprint(instanceId, ":", allowListId)) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + return []volc.Callback{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + instanceId := data.Get("instance_id").(string) + allowListId := data.Get("allow_list_id").(string) + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DisassociateAllowList", + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResourceId(id string) string { + return id +} + +func NewRdsMysqlAllowListAssociateService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListAssociateService { + return &VolcengineRdsMysqlAllowListAssociateService{ + Client: client, + Dispatcher: &volc.Dispatcher{}, + } +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/provider.go b/volcengine/provider.go index ccc6b88c..7e293d07 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -79,6 +79,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/instance_parameter_log" mongodbRegion "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/region" mongodbZone "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/zone" + "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist" + "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/dnat_entry" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/nat_gateway" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/snat_entry" @@ -261,6 +263,9 @@ func Provider() terraform.ResourceProvider { // ================ RDS V2 ============== "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), + // ================ RDS MySQL ============= + "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), + // ================ ESCloud ============= "volcengine_escloud_instances": instance.DataSourceVolcengineESCloudInstances(), "volcengine_escloud_regions": region.DataSourceVolcengineESCloudRegions(), @@ -400,6 +405,10 @@ func Provider() terraform.ResourceProvider { // ================ RDS V2 ============== "volcengine_rds_instance_v2": rds_instance_v2.ResourceVolcengineRdsInstance(), + // ================ RDS MySQL ============= + "volcengine_rds_mysql_allowlist": allowlist.ResourceVolcengineRdsMysqlAllowlist(), + "volcengine_rds_mysql_allowlist_associate": allowlist_associate.ResourceVolcengineRdsMysqlAllowlistAssociate(), + // ================ ESCloud ================ "volcengine_escloud_instance": instance.ResourceVolcengineESCloudInstance(), From 812592e2a54adf9da5837b71602a33e32cb54b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 15:53:06 +0800 Subject: [PATCH 27/58] feat: opt allowlist_associate read func --- ...olcengine_rds_mysql_allowlist_associate.go | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go index 763a62ec..91aa32a9 100644 --- a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -1,7 +1,9 @@ package allowlist_associate import ( + "errors" "fmt" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -24,7 +26,53 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResources(m map[string } func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { - return nil, nil + var ( + results interface{} + resultsMap = make(map[string]interface{}) + instanceMap = make(map[string]interface{}) + instances = make([]interface{}, 0) + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 2 { + return data, err + } + req := map[string]interface{}{ + "AllowListId": ids[1], + } + action := "DescribeAllowListDetail" + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + return data, err + } + results, err = volc.ObtainSdkValue("Result", *resp) + if err != nil { + return data, err + } + if resultsMap, ok = results.(map[string]interface{}); !ok { + return resultsMap, errors.New("Value is not map ") + } + if len(resultsMap) == 0 { + return resultsMap, fmt.Errorf("Rds instance %s not exist ", id) + } + logger.Debug(logger.ReqFormat, action, resultsMap) + instances = resultsMap["AssociatedInstances"].([]interface{}) + logger.Debug(logger.ReqFormat, action, instances) + for _, instance := range instances { + if instanceMap, ok = instance.(map[string]interface{}); !ok { + return data, errors.New("instance is not map ") + } + if len(instanceMap) == 0 { + continue + } + if instanceMap["InstanceId"].(string) == ids[0] { + data = resultsMap + } + } + return data, err } func (s *VolcengineRdsMysqlAllowListAssociateService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { From 14a6ffd1d9402efe81f0b961a4fee1559b5a1e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 17:49:51 +0800 Subject: [PATCH 28/58] fix: fix allowlist err --- example/rdsMysqlAllowlist/main.tf | 6 +- ..._source_volcengine_rds_mysql_allowlists.go | 24 +++++ ...resource_volcengine_rds_mysql_allowlist.go | 18 +--- .../service_volcengine_rds_mysql_allowlist.go | 96 ++++++++++++++++--- ...olcengine_rds_mysql_allowlist_associate.go | 5 +- 5 files changed, 122 insertions(+), 27 deletions(-) diff --git a/example/rdsMysqlAllowlist/main.tf b/example/rdsMysqlAllowlist/main.tf index 78bea068..6b0b0b1b 100644 --- a/example/rdsMysqlAllowlist/main.tf +++ b/example/rdsMysqlAllowlist/main.tf @@ -1,5 +1,7 @@ resource "volcengine_rds_mysql_allowlist" "foo" { - allow_list_name = "tf-test" + allow_list_name = "tf-test-opt" allow_list_desc = "terraform test zzm" - allow_list = "127.0.0.1" + allow_list = [ + "127.0.0.1" + ] } \ No newline at end of file diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go index 82c6b197..274794b0 100644 --- a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go +++ b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go @@ -65,6 +65,30 @@ func DataSourceVolcengineRdsMysqlAllowLists() *schema.Resource { Computed: true, Description: "The total number of instances bound under the whitelist.", }, + "associated_instances": { + Type: schema.TypeList, + Computed: true, + Description: "The list of instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the instance.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the instance.", + }, + "vpc": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the vpc.", + }, + }, + }, + }, }, }, }, diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go index 8faeddcc..dd360058 100644 --- a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go +++ b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go @@ -5,7 +5,6 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" volc "github.com/volcengine/terraform-provider-volcengine/common" ) @@ -51,8 +50,11 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", }, "allow_list": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, Description: "Enter an IP address or a range of IP addresses in CIDR format.", }, "allow_list_id": { @@ -60,16 +62,6 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Computed: true, Description: "The id of the allow list.", }, - "modify_mode": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - "Cover", - "Append", - "Delete", - }, false), - Description: "The modify mode.", - }, "apply_instance_number": { Type: schema.TypeInt, Optional: true, diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go index 825c1914..74ee3aae 100644 --- a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go +++ b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -50,32 +50,50 @@ func (s *VolcengineRdsMysqlAllowListService) ReadResources(condition map[string] if data, ok = results.([]interface{}); !ok { return data, errors.New("Result.AllowLists is not slice ") } + for index, ele := range data { + allowList := ele.(map[string]interface{}) + query := map[string]interface{}{ + "AllowListId": allowList["AllowListId"], + } + action = "DescribeAllowListDetail" + logger.Debug(logger.ReqFormat, action, query) + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &query) + if err != nil { + return data, err + } + logger.Debug(logger.RespFormat, action, query, *resp) + instances, err := volc.ObtainSdkValue("Result.AssociatedInstances", *resp) + if err != nil { + return data, err + } + data[index].(map[string]interface{})["AssociatedInstances"] = instances + } return data, err }) } func (s *VolcengineRdsMysqlAllowListService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { var ( - results interface{} - ok bool + results []interface{} ) if id == "" { id = s.ReadResourceId(resourceData.Id()) } req := map[string]interface{}{ - "AllowListId": id, + "RegionId": s.Client.Region, } - action := "DescribeAllowListDetail" - resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + results, err = s.ReadResources(req) if err != nil { return data, err } - results, err = volc.ObtainSdkValue("Result", *resp) - if err != nil { - return data, err - } - if data, ok = results.(map[string]interface{}); !ok { - return data, errors.New("Value is not map ") + for _, v := range results { + result, ok := v.(map[string]interface{}) + if !ok { + return data, errors.New("Value is not map ") + } + if result["AllowListId"].(string) == id { + data = result + } } if len(data) == 0 { return data, fmt.Errorf("Rds instance %s not exist ", id) @@ -100,6 +118,26 @@ func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.Resourc Action: "CreateAllowList", ConvertMode: volc.RequestConvertAll, ContentType: volc.ContentTypeJson, + Convert: map[string]volc.RequestConvert{ + "allow_list": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + allowLists := d.Get("allow_list").([]interface{}) + if len(allowLists) == 1 { + (*call.SdkParam)["AllowList"] = allowLists[0] + return true, nil + } + lists := "" + for _, list := range allowLists { + lists += list.(string) + lists += "," + } + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + return true, nil + }, ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) @@ -120,6 +158,39 @@ func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.Resourc Action: "ModifyAllowList", ConvertMode: volc.RequestConvertInConvert, ContentType: volc.ContentTypeJson, + Convert: map[string]volc.RequestConvert{ + "allow_list": { + Ignore: true, + }, + "apply_instance_num": { + Ignore: true, + }, + "allow_list_desc": { + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + // 修改allowList必须传ApplyInstanceNum + resp, err := s.ReadResource(d, d.Id()) + if err != nil { + return false, err + } + num := resp["AssociatedInstanceNum"].(float64) + (*call.SdkParam)["ApplyInstanceNum"] = int(num) + allowLists := d.Get("allow_list").([]interface{}) + if len(allowLists) == 1 { + (*call.SdkParam)["AllowList"] = allowLists[0] + return true, nil + } + lists := "" + for _, list := range allowLists { + lists += list.(string) + lists += "," + } + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + return true, nil + }, SdkParam: &map[string]interface{}{ "AllowListId": data.Id(), "AllowListName": data.Get("allow_list_name").(string), @@ -161,6 +232,9 @@ func (s *VolcengineRdsMysqlAllowListService) DatasourceResources(data *schema.Re "AllowListIPNum": { TargetField: "allow_list_ip_num", }, + "VPC": { + TargetField: "vpc", + }, }, } } diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go index 91aa32a9..c1376404 100644 --- a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -56,7 +56,7 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData return resultsMap, errors.New("Value is not map ") } if len(resultsMap) == 0 { - return resultsMap, fmt.Errorf("Rds instance %s not exist ", id) + return resultsMap, fmt.Errorf("Rds allowlist %s not exist ", ids[1]) } logger.Debug(logger.ReqFormat, action, resultsMap) instances = resultsMap["AssociatedInstances"].([]interface{}) @@ -72,6 +72,9 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData data = resultsMap } } + if len(data) == 0 { + return data, fmt.Errorf("Rds allowlist associate %s not exist ", id) + } return data, err } From 4212b8214e28ae4fe99c1ebb15ddc8d42658bbcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Wed, 22 Feb 2023 14:54:04 +0800 Subject: [PATCH 29/58] feat: rename(mysql_rds to rds_mysql) and opt param --- volcengine/provider.go | 4 ++-- .../data_source_volcengine_rds_mysql_allowlists.go | 0 .../allowlist/resource_volcengine_rds_mysql_allowlist.go | 8 ++------ .../allowlist/service_volcengine_rds_mysql_allowlist.go | 6 ++++-- .../resource_volcengine_rds_mysql_allowlist_associate.go | 0 .../service_volcengine_rds_mysql_allowlist_associate.go | 0 6 files changed, 8 insertions(+), 10 deletions(-) rename volcengine/{mysql_rds => rds_mysql}/allowlist/data_source_volcengine_rds_mysql_allowlists.go (100%) rename volcengine/{mysql_rds => rds_mysql}/allowlist/resource_volcengine_rds_mysql_allowlist.go (94%) rename volcengine/{mysql_rds => rds_mysql}/allowlist/service_volcengine_rds_mysql_allowlist.go (97%) rename volcengine/{mysql_rds => rds_mysql}/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go (100%) rename volcengine/{mysql_rds => rds_mysql}/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go (100%) diff --git a/volcengine/provider.go b/volcengine/provider.go index 7e293d07..c13c466b 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -79,8 +79,6 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/instance_parameter_log" mongodbRegion "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/region" mongodbZone "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/zone" - "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist" - "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/dnat_entry" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/nat_gateway" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/snat_entry" @@ -90,6 +88,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/rds/rds_instance" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds/rds_ip_list" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds/rds_parameter_template" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/allowlist" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/allowlist_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_v2/rds_instance_v2" "github.com/volcengine/terraform-provider-volcengine/volcengine/tos/bucket" "github.com/volcengine/terraform-provider-volcengine/volcengine/tos/object" diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/rds_mysql/allowlist/data_source_volcengine_rds_mysql_allowlists.go similarity index 100% rename from volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go rename to volcengine/rds_mysql/allowlist/data_source_volcengine_rds_mysql_allowlists.go diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/rds_mysql/allowlist/resource_volcengine_rds_mysql_allowlist.go similarity index 94% rename from volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go rename to volcengine/rds_mysql/allowlist/resource_volcengine_rds_mysql_allowlist.go index dd360058..4bc96642 100644 --- a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go +++ b/volcengine/rds_mysql/allowlist/resource_volcengine_rds_mysql_allowlist.go @@ -50,11 +50,12 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", }, "allow_list": { - Type: schema.TypeList, + Type: schema.TypeSet, Required: true, Elem: &schema.Schema{ Type: schema.TypeString, }, + Set: schema.HashString, Description: "Enter an IP address or a range of IP addresses in CIDR format.", }, "allow_list_id": { @@ -62,11 +63,6 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Computed: true, Description: "The id of the allow list.", }, - "apply_instance_number": { - Type: schema.TypeInt, - Optional: true, - Description: "The number of instances bound to the current whitelist.", - }, }, } } diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go similarity index 97% rename from volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go rename to volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go index 74ee3aae..daf859b8 100644 --- a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go +++ b/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -124,7 +124,8 @@ func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.Resourc }, }, BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - allowLists := d.Get("allow_list").([]interface{}) + allowListsSet := d.Get("allow_list").(*schema.Set) + allowLists := allowListsSet.List() if len(allowLists) == 1 { (*call.SdkParam)["AllowList"] = allowLists[0] return true, nil @@ -177,7 +178,8 @@ func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.Resourc } num := resp["AssociatedInstanceNum"].(float64) (*call.SdkParam)["ApplyInstanceNum"] = int(num) - allowLists := d.Get("allow_list").([]interface{}) + allowListsSet := d.Get("allow_list").(*schema.Set) + allowLists := allowListsSet.List() if len(allowLists) == 1 { (*call.SdkParam)["AllowList"] = allowLists[0] return true, nil diff --git a/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go b/volcengine/rds_mysql/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go similarity index 100% rename from volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go rename to volcengine/rds_mysql/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/rds_mysql/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go similarity index 100% rename from volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go rename to volcengine/rds_mysql/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go From 769988162cf4fa1addbaad760383d8a3ea1ab1ed Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 17 Feb 2023 16:43:55 +0800 Subject: [PATCH 30/58] feat:support rds mysql account and database. --- example/dataRdsMysqlAccounts/main.tf | 4 + example/dataRdsMysqlDatabases/main.tf | 4 + example/rdsMysqlAccount/main.tf | 16 + example/rdsMysqlDatabase/main.tf | 5 + volcengine/provider.go | 10 + .../common_volcengine_rds_mysql_account.go | 72 ++++ ...ta_source_volcengine_rds_mysql_accounts.go | 100 +++++ .../resource_volcengine_rds_mysql_account.go | 124 ++++++ .../service_volcengine_rds_mysql_account.go | 352 ++++++++++++++++++ .../common_volcengine_rds_database.go | 70 ++++ .../data_source_volcengine_rds_databases.go | 96 +++++ .../resource_volcengine_rds_database.go | 116 ++++++ .../service_volcengine_rds_database.go | 334 +++++++++++++++++ 13 files changed, 1303 insertions(+) create mode 100644 example/dataRdsMysqlAccounts/main.tf create mode 100644 example/dataRdsMysqlDatabases/main.tf create mode 100644 example/rdsMysqlAccount/main.tf create mode 100644 example/rdsMysqlDatabase/main.tf create mode 100644 volcengine/rds_mysql/rds_mysql_account/common_volcengine_rds_mysql_account.go create mode 100644 volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go create mode 100644 volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go create mode 100644 volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go create mode 100644 volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go create mode 100644 volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go create mode 100644 volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go create mode 100644 volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go diff --git a/example/dataRdsMysqlAccounts/main.tf b/example/dataRdsMysqlAccounts/main.tf new file mode 100644 index 00000000..533d3496 --- /dev/null +++ b/example/dataRdsMysqlAccounts/main.tf @@ -0,0 +1,4 @@ +data "volcengine_rds_mysql_accounts" "default"{ + instance_id="" + account_name="" +} \ No newline at end of file diff --git a/example/dataRdsMysqlDatabases/main.tf b/example/dataRdsMysqlDatabases/main.tf new file mode 100644 index 00000000..c4d4c026 --- /dev/null +++ b/example/dataRdsMysqlDatabases/main.tf @@ -0,0 +1,4 @@ +data "volcengine_rds_mysql_databases" "default"{ + instance_id="" + db_name="" +} \ No newline at end of file diff --git a/example/rdsMysqlAccount/main.tf b/example/rdsMysqlAccount/main.tf new file mode 100644 index 00000000..667b665c --- /dev/null +++ b/example/rdsMysqlAccount/main.tf @@ -0,0 +1,16 @@ +resource "volcengine_rds_mysql_account" "default"{ + instance_id="mysql-xxx" + account_name="xxx" + account_password="xxx" + account_type="Normal" + account_privileges{ + db_name="xxx" + account_privilege="Custom" + account_privilege_detail="SELECT,UPDATE,INSERT" + } + account_privileges{ + db_name="xx" + account_privilege="Custom" + account_privilege_detail="SELECT,UPDATE,INSERT" + } +} \ No newline at end of file diff --git a/example/rdsMysqlDatabase/main.tf b/example/rdsMysqlDatabase/main.tf new file mode 100644 index 00000000..7d10d6ab --- /dev/null +++ b/example/rdsMysqlDatabase/main.tf @@ -0,0 +1,5 @@ +resource "volcengine_rds_mysql_database" "default"{ + instance_id="mysql-xxx" + db_name="xxx" + character_set_name="utf8" +} diff --git a/volcengine/provider.go b/volcengine/provider.go index c13c466b..88c9891f 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -7,6 +7,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/spec" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_account" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_database" "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/kubeconfig" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -306,6 +308,10 @@ func Provider() terraform.ResourceProvider { // ================ Bioos ================== "volcengine_bioos_clusters": bioosCluster.DataSourceVolcengineBioosClusters(), "volcengine_bioos_workspaces": workspace.DataSourceVolcengineBioosWorkspaces(), + + // ================ RdsMysql ================ + "volcengine_rds_mysql_accounts": rds_mysql_account.DataSourceVolcengineRdsMysqlAccounts(), + "volcengine_rds_mysql_databases": rds_mysql_database.DataSourceVolcengineRdsMysqlDatabases(), }, ResourcesMap: map[string]*schema.Resource{ "volcengine_vpc": vpc.ResourceVolcengineVpc(), @@ -442,6 +448,10 @@ func Provider() terraform.ResourceProvider { "volcengine_bioos_cluster": bioosCluster.ResourceVolcengineBioosCluster(), "volcengine_bioos_workspace": workspace.ResourceVolcengineBioosWorkspace(), "volcengine_bioos_cluster_bind": cluster_bind.ResourceVolcengineBioosClusterBind(), + + // ================ RdsMysql ================ + "volcengine_rds_mysql_account": rds_mysql_account.ResourceVolcengineRdsMysqlAccount(), + "volcengine_rds_mysql_database": rds_mysql_database.ResourceVolcengineRdsMysqlDatabase(), }, ConfigureFunc: ProviderConfigure, } diff --git a/volcengine/rds_mysql/rds_mysql_account/common_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/common_volcengine_rds_mysql_account.go new file mode 100644 index 00000000..4e6e676f --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_account/common_volcengine_rds_mysql_account.go @@ -0,0 +1,72 @@ +package rds_mysql_account + +import ( + "bytes" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "sort" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +var rdsMysqlAccountImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("account_name", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} + +var rdsMysqlAccountPrivilegeStrMapping = map[string]string{ + "create tmp table": "create temporary tables", + "CREATE TMP TABLE": "CREATE TEMPORARY TABLES", +} + +func mappingAccountPrivilegeStr(accountPrivilegeStr string) []string { + privileges := strings.Split(accountPrivilegeStr, ",") + mappingPrivileges := make([]string, 0) + for _, privilege := range privileges { + if mappedPrivilege, ok := rdsMysqlAccountPrivilegeStrMapping[privilege]; ok { + mappingPrivileges = append(mappingPrivileges, mappedPrivilege) + } else { + mappingPrivileges = append(mappingPrivileges, privilege) + } + } + return mappingPrivileges +} + +// mappingAndSortAccountPrivilegeStr RDS account privilege string mapping +func mappingAndSortAccountPrivilegeStr(accountPrivilegeStr string) string { + mappingPrivileges := mappingAccountPrivilegeStr(accountPrivilegeStr) + sort.Strings(mappingPrivileges) + return strings.Join(mappingPrivileges, ",") +} + +func rdsMysqlAccountPrivilegeHashBase(m map[string]interface{}) (buf bytes.Buffer) { + dbName := strings.ToLower(m["db_name"].(string)) + accountPrivilege := strings.ToLower(m["account_privilege"].(string)) + buf.WriteString(fmt.Sprintf("%s-", dbName)) + buf.WriteString(fmt.Sprintf("%s-", accountPrivilege)) + if accountPrivilege == "custom" { + buf.WriteString(fmt.Sprintf("%s-", mappingAndSortAccountPrivilegeStr(strings.ToLower(m["account_privilege_detail"].(string))))) + } + return buf +} + +func RdsMysqlAccountPrivilegeHash(v interface{}) int { + if v == nil { + return hashcode.String("") + } + m := v.(map[string]interface{}) + buf := rdsMysqlAccountPrivilegeHashBase(m) + logger.DebugInfo("RdsMysqlAccountPrivilegeHash %s", buf.String()) + return hashcode.String(buf.String()) +} diff --git a/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go b/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go new file mode 100644 index 00000000..66c35e13 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go @@ -0,0 +1,100 @@ +package rds_mysql_account + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineRdsMysqlAccounts() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineRdsMysqlAccountsRead, + Schema: map[string]*schema.Schema{ + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of database account.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of database account query.", + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The id of the RDS instance.", + }, + "account_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the database account.", + }, + "accounts": { + Description: "The collection of RDS instance account query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, // tf中不支持写值 + Description: "The ID of the RDS instance account.", + }, + "account_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the database account.", + }, + "account_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the database account.", + }, + "account_status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the database account.", + }, + "account_privileges": { + Type: schema.TypeList, + Computed: true, + Description: "The privilege detail list of RDS mysql instance account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of database.", + }, + "account_privilege": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege type of the account.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege detail of the account.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineRdsMysqlAccountsRead(d *schema.ResourceData, meta interface{}) error { + service := NewRdsMysqlAccountService(meta.(*volc.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineRdsMysqlAccounts()) +} diff --git a/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go new file mode 100644 index 00000000..e49969f2 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go @@ -0,0 +1,124 @@ +package rds_mysql_account + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +RDS mysql account can be imported using the instance_id:account_name, e.g. +``` +$ terraform import volcengine_rds_account.default mysql-42b38c769c4b:test +``` + +*/ + +func ResourceVolcengineRdsMysqlAccount() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlAccountCreate, + Read: resourceVolcengineRdsMysqlAccountRead, + Update: resourceVolcengineRdsMysqlAccountUpdate, + Delete: resourceVolcengineRdsMysqlAccountDelete, + Importer: &schema.ResourceImporter{ + State: rdsMysqlAccountImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The ID of the RDS instance.", + }, + "account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database account name. The rules are as follows:\nUnique name.\nStart with a letter and end with a letter or number.\nConsists of lowercase letters, numbers, or underscores (_).\nThe length is 2~32 characters.\nThe [keyword list](https://www.volcengine.com/docs/6313/66162) is disabled for database accounts, and certain reserved words, including root, admin, etc., cannot be used.", + }, + "account_password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + Description: "The password of the database account.\nillustrate\nCannot start with `!` or `@`.\nThe length is 8~32 characters.\nIt consists of any three of uppercase letters, lowercase letters, numbers, and special characters.\nThe special characters are `!@#$%^*()_+-=`. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", + }, + "account_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database account type, value:\nSuper: A high-privilege account. Only one database account can be created for an instance.\nNormal: An account with ordinary privileges.", + ValidateFunc: validation.StringInSlice([]string{"Super", "Normal"}, false), + }, + "account_privileges": { + Type: schema.TypeSet, + Optional: true, + Set: RdsMysqlAccountPrivilegeHash, + Description: "The privilege information of account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of database.", + }, + "account_privilege": { + Type: schema.TypeString, + Required: true, + Description: "The privilege type of the account.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Optional: true, + Description: "The privilege detail of the account.", + }, + }, + }, + }, + }, + } +} + +func resourceVolcengineRdsMysqlAccountCreate(d *schema.ResourceData, meta interface{}) (err error) { + rdsAccountService := NewRdsMysqlAccountService(meta.(*volc.SdkClient)) + err = rdsAccountService.Dispatcher.Create(rdsAccountService, d, ResourceVolcengineRdsMysqlAccount()) + if err != nil { + return fmt.Errorf("error on creating rds mysql account %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAccountRead(d, meta) +} + +func resourceVolcengineRdsMysqlAccountRead(d *schema.ResourceData, meta interface{}) (err error) { + rdsAccountService := NewRdsMysqlAccountService(meta.(*volc.SdkClient)) + err = rdsAccountService.Dispatcher.Read(rdsAccountService, d, ResourceVolcengineRdsMysqlAccount()) + if err != nil { + return fmt.Errorf("error on reading rds mysql account %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlAccountUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAccountService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlAccount()) + if err != nil { + return fmt.Errorf("error on updating rds mysql account %q, %s", d.Id(), err) + } + return resourceVolcengineRdsMysqlAccountRead(d, meta) +} + +func resourceVolcengineRdsMysqlAccountDelete(d *schema.ResourceData, meta interface{}) (err error) { + rdsAccountService := NewRdsMysqlAccountService(meta.(*volc.SdkClient)) + err = rdsAccountService.Dispatcher.Delete(rdsAccountService, d, ResourceVolcengineRdsMysqlAccount()) + if err != nil { + return fmt.Errorf("error on deleting rds mysql account %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go new file mode 100644 index 00000000..801b212a --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -0,0 +1,352 @@ +package rds_mysql_account + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/volcengine/terraform-provider-volcengine/common" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlAccountService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func NewRdsMysqlAccountService(c *volc.SdkClient) *VolcengineRdsMysqlAccountService { + return &VolcengineRdsMysqlAccountService{ + Client: c, + Dispatcher: &volc.Dispatcher{}, + } +} + +func (s *VolcengineRdsMysqlAccountService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlAccountService) ReadResources(m map[string]interface{}) ([]interface{}, error) { + list, err := volc.WithPageOffsetQuery(m, "PageSize", "PageNumber", 20, 0, func(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + universalClient := s.Client.UniversalClient + action := "DescribeDBAccounts" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = universalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = universalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + results, err = volc.ObtainSdkValue("Result.Accounts", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Accounts is not Slice") + } + return data, err + }) + if err != nil { + return list, err + } + + accountName := m["AccountName"] + res := make([]interface{}, 0) + for _, a := range list { + account, ok := a.(map[string]interface{}) + if !ok { + continue + } + // accountName是模糊搜索,需要过滤一下 + if accountName != "" && accountName != account["AccountName"].(string) { + continue + } + // 拼接id + account["Id"] = fmt.Sprintf("%s:%s", m["InstanceId"], account["AccountName"]) + res = append(res, account) + } + return res, nil +} + +func (s *VolcengineRdsMysqlAccountService) ReadResource(resourceData *schema.ResourceData, RdsMysqlAccountId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if RdsMysqlAccountId == "" { + RdsMysqlAccountId = s.ReadResourceId(resourceData.Id()) + } + + ids := strings.Split(RdsMysqlAccountId, ":") + if len(ids) != 2 { + return map[string]interface{}{}, fmt.Errorf("invalid rds mysql account id") + } + + instanceId := ids[0] + accountName := ids[1] + + req := map[string]interface{}{ + "InstanceId": instanceId, + "AccountName": accountName, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("RDS account %s not exist ", RdsMysqlAccountId) + } + + return data, err +} + +func (s *VolcengineRdsMysqlAccountService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return nil +} + +func (VolcengineRdsMysqlAccountService) WithResourceResponseHandlers(rdsAccount map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return rdsAccount, map[string]volc.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlAccountService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "CreateDBAccount", + ConvertMode: volc.RequestConvertAll, + Convert: map[string]volc.RequestConvert{ + "account_privileges": { + TargetField: "AccountPrivileges", + ConvertType: volc.ConvertJsonObjectArray, + }, + }, + ContentType: volc.ContentTypeJson, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //创建RdsMysqlAccount + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), d.Get("account_name")) + d.SetId(id) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func hasDbNameInSet(dbName string, set *schema.Set) bool { + for _, item := range set.List() { + if m, ok := item.(map[string]interface{}); ok { + if v, ok := m["db_name"]; ok && v.(string) == dbName { + return true + } + } + } + return false +} + +func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callbacks := []volc.Callback{} + if resourceData.HasChange("account_password") { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "ResetDBAccount", + ConvertMode: volc.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "InstanceId": resourceData.Get("instance_id"), + "AccountName": resourceData.Get("account_name"), + "AccountPassword": resourceData.Get("account_password"), + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, callback) + } + if resourceData.HasChange("account_privileges") { + addPrivis, removePrivs, _, _ := common.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) + logger.DebugInfo("account_privileges %v", resourceData.Get("account_privileges")) + logger.DebugInfo("addPrivis %v len %d", addPrivis, addPrivis.Len()) + logger.DebugInfo("removePrivs %v len %d", removePrivs, addPrivis.Len()) + + if addPrivis != nil && addPrivis.Len() != 0 { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "GrantDBAccountPrivilege", + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["AccountName"] = d.Get("account_name") + accountPrivileges := make([]map[string]interface{}, 0) + for _, item := range addPrivis.List() { + m, _ := item.(map[string]interface{}) + privi := make(map[string]interface{}) + if v, ok := m["db_name"]; ok { + privi["DBName"] = v + } + if v, ok := m["account_privilege"]; ok { + privi["AccountPrivilege"] = v + } + if v, ok := m["account_privilege_detail"]; ok { + privi["AccountPrivilegeDetail"] = v + } + accountPrivileges = append(accountPrivileges, privi) + } + (*call.SdkParam)["AccountPrivileges"] = accountPrivileges + logger.DebugInfo("accountPrivileges %v", accountPrivileges) + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + + callbacks = append(callbacks, callback) + + } + if removePrivs != nil && removePrivs.Len() != 0 { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "RevokeDBAccountPrivilege", + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["AccountName"] = d.Get("account_name") + dbNames := make([]string, 0) + for _, item := range addPrivis.List() { + m, ok := item.(map[string]interface{}) + if !ok { + continue + } + dbName := m["db_name"].(string) + // 过滤掉有Grant操作的db_name,Grant权限方式为覆盖,先取消原有权限,再赋新权限,此处无需再取消一次。 + if addPrivis != nil && addPrivis.Len() != 0 && hasDbNameInSet(dbName, addPrivis) { + continue + } + dbNames = append(dbNames, dbName) + } + if len(dbNames) == 0 { + return false, nil + } + (*call.SdkParam)["DBNames"] = dbNames + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, callback) + } + } + + return callbacks +} + +func (s *VolcengineRdsMysqlAccountService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DeleteDBAccount", + ContentType: volc.ContentTypeJson, + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + rdsAccountId := d.Id() + ids := strings.Split(rdsAccountId, ":") + if len(ids) != 2 { + return false, fmt.Errorf("invalid rds account id") + } + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["AccountName"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //删除RdsMysqlAccount + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if volc.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading RDS account on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAccountService) DatasourceResources(*schema.ResourceData, *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{ + ContentType: volc.ContentTypeJson, + NameField: "AccountName", + CollectField: "accounts", + ResponseConverts: map[string]volc.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, + } +} + +func (s *VolcengineRdsMysqlAccountService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go new file mode 100644 index 00000000..004ba9f3 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go @@ -0,0 +1,70 @@ +package rds_mysql_database + +import ( + "bytes" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "sort" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var databaseImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("db_name", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} + +var rdsMysqlDatabasePrivilegeStrMapping = map[string]string{ + "create tmp table": "create temporary tables", + "CREATE TMP TABLE": "CREATE TEMPORARY TABLES", +} + +func mappingAccountPrivilegeStr(accountPrivilegeStr string) []string { + privileges := strings.Split(accountPrivilegeStr, ",") + mappingPrivileges := make([]string, 0) + for _, privilege := range privileges { + if mappedPrivilege, ok := rdsMysqlDatabasePrivilegeStrMapping[privilege]; ok { + mappingPrivileges = append(mappingPrivileges, mappedPrivilege) + } else { + mappingPrivileges = append(mappingPrivileges, privilege) + } + } + return mappingPrivileges +} + +// mappingAndSortAccountPrivilegeStr RDS account privilege string mapping +func mappingAndSortAccountPrivilegeStr(accountPrivilegeStr string) string { + mappingPrivileges := mappingAccountPrivilegeStr(accountPrivilegeStr) + sort.Strings(mappingPrivileges) + return strings.Join(mappingPrivileges, ",") +} + +func rdsMysqlDatabasePrivilegeHashBase(m map[string]interface{}) (buf bytes.Buffer) { + dbName := strings.ToLower(m["account_name"].(string)) + accountPrivilege := strings.ToLower(m["account_privilege"].(string)) + buf.WriteString(fmt.Sprintf("%s-", dbName)) + buf.WriteString(fmt.Sprintf("%s-", accountPrivilege)) + if accountPrivilege == "custom" { + buf.WriteString(fmt.Sprintf("%s-", mappingAndSortAccountPrivilegeStr(strings.ToLower(m["account_privilege_detail"].(string))))) + } + return buf +} + +func RdsMysqlDatabasePrivilegeHash(v interface{}) int { + if v == nil { + return hashcode.String("") + } + m := v.(map[string]interface{}) + buf := rdsMysqlDatabasePrivilegeHashBase(m) + return hashcode.String(buf.String()) +} diff --git a/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go b/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go new file mode 100644 index 00000000..6921f459 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go @@ -0,0 +1,96 @@ +package rds_mysql_database + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineRdsMysqlDatabases() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineRdsMysqlDatabasesRead, + Schema: map[string]*schema.Schema{ + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of RDS database.", + }, + + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of RDS database query.", + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The id of the RDS instance.", + }, + "db_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the RDS database.", + }, + "databases": { + Description: "The collection of RDS instance account query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, // tf中不支持写值 + Description: "The ID of the RDS database.", + }, + "db_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the RDS database.", + }, + "character_set_name": { + Type: schema.TypeString, + Computed: true, + Description: "The character set of the RDS database.", + }, + "database_privileges": { + Type: schema.TypeList, + Computed: true, + Description: "The privilege detail list of RDS mysql instance database.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of account.", + }, + "account_privilege": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege type of the account.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege detail of the account.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineRdsMysqlDatabasesRead(d *schema.ResourceData, meta interface{}) error { + databaseService := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) + return databaseService.Dispatcher.Data(databaseService, d, DataSourceVolcengineRdsMysqlDatabases()) +} diff --git a/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go new file mode 100644 index 00000000..80ed7d31 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go @@ -0,0 +1,116 @@ +package rds_mysql_database + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Database can be imported using the instanceId:dbName, e.g. +``` +$ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname +``` + +*/ + +func ResourceVolcengineRdsMysqlDatabase() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlDatabaseCreate, + Read: resourceVolcengineRdsMysqlDatabaseRead, + Update: resourceVolcengineRdsMysqlDatabaseUpdate, + Delete: resourceVolcengineRdsMysqlDatabaseDelete, + Importer: &schema.ResourceImporter{ + State: databaseImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The ID of the RDS instance.", + }, + "db_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Name database.\nillustrate:\nUnique name.\nThe length is 2~64 characters.\nStart with a letter and end with a letter or number.\nConsists of lowercase letters, numbers, and underscores (_) or dashes (-).\nDatabase names are disabled [keywords](https://www.volcengine.com/docs/6313/66162).", + }, + "character_set_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database character set. Currently supported character sets include: utf8, utf8mb4, latin1, ascii.", + }, + "database_privileges": { + Type: schema.TypeSet, + Optional: true, + Set: RdsMysqlDatabasePrivilegeHash, + Description: "The privilege detail list of RDS mysql instance database.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of account.", + }, + "account_privilege": { + Type: schema.TypeString, + Required: true, + Description: "The privilege type of the account.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Optional: true, + Description: "The privilege detail of the account.", + }, + }, + }, + }, + }, + } +} + +func resourceVolcengineRdsMysqlDatabaseCreate(d *schema.ResourceData, meta interface{}) (err error) { + databaseService := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) + err = databaseService.Dispatcher.Create(databaseService, d, ResourceVolcengineRdsMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on creating database %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlDatabaseRead(d, meta) +} + +func resourceVolcengineRdsMysqlDatabaseRead(d *schema.ResourceData, meta interface{}) (err error) { + databaseService := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) + err = databaseService.Dispatcher.Read(databaseService, d, ResourceVolcengineRdsMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on reading database %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlDatabaseUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on updating rds mysql database %q, %s", d.Id(), err) + } + return resourceVolcengineRdsMysqlDatabaseRead(d, meta) +} + +func resourceVolcengineRdsMysqlDatabaseDelete(d *schema.ResourceData, meta interface{}) (err error) { + databaseService := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) + err = databaseService.Dispatcher.Delete(databaseService, d, ResourceVolcengineRdsMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on deleting database %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go new file mode 100644 index 00000000..56f4a0ba --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go @@ -0,0 +1,334 @@ +package rds_mysql_database + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/volcengine/terraform-provider-volcengine/common" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlDatabaseService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func NewRdsMysqlDatabaseService(c *volc.SdkClient) *VolcengineRdsMysqlDatabaseService { + return &VolcengineRdsMysqlDatabaseService{ + Client: c, + Dispatcher: &volc.Dispatcher{}, + } +} + +func (s *VolcengineRdsMysqlDatabaseService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlDatabaseService) ReadResources(m map[string]interface{}) ([]interface{}, error) { + list, err := volc.WithPageOffsetQuery(m, "PageSize", "PageNumber", 20, 0, func(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + action := "DescribeDatabases" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + + results, err = volc.ObtainSdkValue("Result.Databases", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Databases is not Slice") + } + return data, err + }) + if err != nil { + return list, err + } + + dbName := m["DBName"] + res := make([]interface{}, 0) + for _, d := range list { + db, ok := d.(map[string]interface{}) + if !ok { + continue + } + // DBName是模糊搜索,需要过滤一下 + if dbName != "" && dbName != db["DBName"].(string) { + continue + } + // 拼接id + db["Id"] = fmt.Sprintf("%s:%s", m["InstanceId"], db["DBName"]) + res = append(res, db) + } + return res, nil +} + +func (s *VolcengineRdsMysqlDatabaseService) ReadResource(resourceData *schema.ResourceData, rdsDatabaseId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if rdsDatabaseId == "" { + rdsDatabaseId = s.ReadResourceId(resourceData.Id()) + } + + ids := strings.Split(rdsDatabaseId, ":") + if len(ids) != 2 { + return map[string]interface{}{}, fmt.Errorf("invalid database id") + } + + instanceId := ids[0] + dbName := ids[1] + + req := map[string]interface{}{ + "InstanceId": instanceId, + "DBName": dbName, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("RDS database %s not exist ", rdsDatabaseId) + } + + return data, err +} + +func (s *VolcengineRdsMysqlDatabaseService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{} +} + +func (s *VolcengineRdsMysqlDatabaseService) WithResourceResponseHandlers(database map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return database, map[string]volc.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlDatabaseService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "CreateDatabase", + ContentType: volc.ContentTypeJson, + ConvertMode: volc.RequestConvertAll, + Convert: map[string]volc.RequestConvert{ + "database_privileges": { + TargetField: "DatabasePrivileges", + ConvertType: volc.ConvertJsonObjectArray, + }, + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //创建Database + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), d.Get("db_name")) + d.SetId(id) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func hasAccountNameInSet(account string, set *schema.Set) bool { + for _, item := range set.List() { + if m, ok := item.(map[string]interface{}); ok { + if v, ok := m["account_name"]; ok && v.(string) == account { + return true + } + } + } + return false +} + +func (s *VolcengineRdsMysqlDatabaseService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callbacks := make([]volc.Callback, 0) + if resourceData.HasChange("database_privileges") { + addPrivis, removePrivs, _, _ := common.GetSetDifference("database_privileges", resourceData, RdsMysqlDatabasePrivilegeHash, false) + if addPrivis.Len() != 0 { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "GrantDatabasePrivilege", + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["DBName"] = d.Get("db_name") + dbPrivileges := make([]map[string]interface{}, 0) + for _, item := range addPrivis.List() { + m, _ := item.(map[string]interface{}) + privi := make(map[string]interface{}) + if v, ok := m["account_name"]; ok { + privi["AccountName"] = v + } + if v, ok := m["account_privilege"]; ok { + privi["AccountPrivilege"] = v + } + if v, ok := m["account_privilege_detail"]; ok { + privi["AccountPrivilegeDetail"] = v + } + dbPrivileges = append(dbPrivileges, privi) + } + (*call.SdkParam)["DatabasePrivileges"] = dbPrivileges + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + + callbacks = append(callbacks, callback) + + } + if removePrivs.Len() != 0 { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "RevokeDatabasePrivilege", + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["DBName"] = d.Get("db_name") + accountNames := make([]string, 0) + for _, item := range addPrivis.List() { + m, ok := item.(map[string]interface{}) + if !ok { + continue + } + account := m["account_name"].(string) + // 过滤掉有Grant操作的account,Grant权限方式为覆盖,先取消原有权限,再赋新权限,此处无需再取消一次。 + if addPrivis != nil && addPrivis.Len() != 0 && hasAccountNameInSet(account, addPrivis) { + continue + } + accountNames = append(accountNames, account) + } + (*call.SdkParam)["AccountNames"] = accountNames + if len(accountNames) == 0 { + return false, nil + } + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, callback) + } + } + + return callbacks +} + +func (s *VolcengineRdsMysqlDatabaseService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DeleteDatabase", + ContentType: volc.ContentTypeJson, + ConvertMode: volc.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + databaseId := d.Id() + ids := strings.Split(databaseId, ":") + if len(ids) != 2 { + return false, fmt.Errorf("invalid rds database id") + } + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["DBName"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //删除Database + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if volc.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading RDS database on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlDatabaseService) DatasourceResources(*schema.ResourceData, *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{ + ContentType: volc.ContentTypeJson, + RequestConverts: map[string]volc.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, + NameField: "DBName", + CollectField: "databases", + ResponseConverts: map[string]volc.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, + } +} + +func (s *VolcengineRdsMysqlDatabaseService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} From 7e108356129cad8e6bc3e4a542682019beaebc9b Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 24 Feb 2023 10:51:42 +0800 Subject: [PATCH 31/58] fix:add update timeout for rds mysql account&database. --- .../rds_mysql_account/resource_volcengine_rds_mysql_account.go | 1 + .../rds_mysql_account/service_volcengine_rds_mysql_account.go | 3 --- .../rds_mysql_database/resource_volcengine_rds_database.go | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go index e49969f2..f1de8acc 100644 --- a/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go @@ -30,6 +30,7 @@ func ResourceVolcengineRdsMysqlAccount() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), Delete: schema.DefaultTimeout(30 * time.Minute), }, Schema: map[string]*schema.Schema{ diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index 801b212a..b86ac610 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -199,9 +199,6 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R } if resourceData.HasChange("account_privileges") { addPrivis, removePrivs, _, _ := common.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) - logger.DebugInfo("account_privileges %v", resourceData.Get("account_privileges")) - logger.DebugInfo("addPrivis %v len %d", addPrivis, addPrivis.Len()) - logger.DebugInfo("removePrivs %v len %d", removePrivs, addPrivis.Len()) if addPrivis != nil && addPrivis.Len() != 0 { callback := volc.Callback{ diff --git a/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go index 80ed7d31..edd1f03b 100644 --- a/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go +++ b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go @@ -29,6 +29,7 @@ func ResourceVolcengineRdsMysqlDatabase() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), Delete: schema.DefaultTimeout(30 * time.Minute), }, Schema: map[string]*schema.Schema{ From 49bcca8a7bace84fd73654c0d006a35aefba2738 Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 24 Feb 2023 11:05:19 +0800 Subject: [PATCH 32/58] sort out code. --- volcengine/provider.go | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/volcengine/provider.go b/volcengine/provider.go index 88c9891f..87996f54 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -262,12 +262,6 @@ func Provider() terraform.ResourceProvider { "volcengine_rds_ip_lists": rds_ip_list.DataSourceVolcengineRdsIpLists(), "volcengine_rds_parameter_templates": rds_parameter_template.DataSourceVolcengineRdsParameterTemplates(), - // ================ RDS V2 ============== - "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), - - // ================ RDS MySQL ============= - "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), - // ================ ESCloud ============= "volcengine_escloud_instances": instance.DataSourceVolcengineESCloudInstances(), "volcengine_escloud_regions": region.DataSourceVolcengineESCloudRegions(), @@ -310,8 +304,12 @@ func Provider() terraform.ResourceProvider { "volcengine_bioos_workspaces": workspace.DataSourceVolcengineBioosWorkspaces(), // ================ RdsMysql ================ - "volcengine_rds_mysql_accounts": rds_mysql_account.DataSourceVolcengineRdsMysqlAccounts(), - "volcengine_rds_mysql_databases": rds_mysql_database.DataSourceVolcengineRdsMysqlDatabases(), + "volcengine_rds_mysql_accounts": rds_mysql_account.DataSourceVolcengineRdsMysqlAccounts(), + "volcengine_rds_mysql_databases": rds_mysql_database.DataSourceVolcengineRdsMysqlDatabases(), + "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), + + // ================ RDS V2 ============== + "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), }, ResourcesMap: map[string]*schema.Resource{ "volcengine_vpc": vpc.ResourceVolcengineVpc(), @@ -408,13 +406,6 @@ func Provider() terraform.ResourceProvider { "volcengine_rds_account_privilege": rds_account_privilege.ResourceVolcengineRdsAccountPrivilege(), "volcengine_rds_parameter_template": rds_parameter_template.ResourceVolcengineRdsParameterTemplate(), - // ================ RDS V2 ============== - "volcengine_rds_instance_v2": rds_instance_v2.ResourceVolcengineRdsInstance(), - - // ================ RDS MySQL ============= - "volcengine_rds_mysql_allowlist": allowlist.ResourceVolcengineRdsMysqlAllowlist(), - "volcengine_rds_mysql_allowlist_associate": allowlist_associate.ResourceVolcengineRdsMysqlAllowlistAssociate(), - // ================ ESCloud ================ "volcengine_escloud_instance": instance.ResourceVolcengineESCloudInstance(), @@ -449,9 +440,14 @@ func Provider() terraform.ResourceProvider { "volcengine_bioos_workspace": workspace.ResourceVolcengineBioosWorkspace(), "volcengine_bioos_cluster_bind": cluster_bind.ResourceVolcengineBioosClusterBind(), + // ================ RDS V2 ============== + "volcengine_rds_instance_v2": rds_instance_v2.ResourceVolcengineRdsInstance(), + // ================ RdsMysql ================ - "volcengine_rds_mysql_account": rds_mysql_account.ResourceVolcengineRdsMysqlAccount(), - "volcengine_rds_mysql_database": rds_mysql_database.ResourceVolcengineRdsMysqlDatabase(), + "volcengine_rds_mysql_account": rds_mysql_account.ResourceVolcengineRdsMysqlAccount(), + "volcengine_rds_mysql_database": rds_mysql_database.ResourceVolcengineRdsMysqlDatabase(), + "volcengine_rds_mysql_allowlist": allowlist.ResourceVolcengineRdsMysqlAllowlist(), + "volcengine_rds_mysql_allowlist_associate": allowlist_associate.ResourceVolcengineRdsMysqlAllowlistAssociate(), }, ConfigureFunc: ProviderConfigure, } From 41d9519f9517f854a7b9b9f6b7e2662fa7dcc82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 15:15:42 +0800 Subject: [PATCH 33/58] feat: add rds mysql allowlist and allowlist_associate --- example/rdsMysqlAllowlist/main.tf | 6 + ..._source_volcengine_rds_mysql_allowlists.go | 78 ++++++++ ...resource_volcengine_rds_mysql_allowlist.go | 116 +++++++++++ .../service_volcengine_rds_mysql_allowlist.go | 187 ++++++++++++++++++ ...olcengine_rds_mysql_allowlist_associate.go | 93 +++++++++ ...olcengine_rds_mysql_allowlist_associate.go | 112 +++++++++++ volcengine/provider.go | 2 + 7 files changed, 594 insertions(+) create mode 100644 volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go create mode 100644 volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go create mode 100644 volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go create mode 100644 volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go create mode 100644 volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go diff --git a/example/rdsMysqlAllowlist/main.tf b/example/rdsMysqlAllowlist/main.tf index 6b0b0b1b..c566db12 100644 --- a/example/rdsMysqlAllowlist/main.tf +++ b/example/rdsMysqlAllowlist/main.tf @@ -1,7 +1,13 @@ resource "volcengine_rds_mysql_allowlist" "foo" { +<<<<<<< HEAD allow_list_name = "tf-test-opt" allow_list_desc = "terraform test zzm" allow_list = [ "127.0.0.1" ] +======= + allow_list_name = "tf-test" + allow_list_desc = "terraform test zzm" + allow_list = "127.0.0.1" +>>>>>>> 7bde4df (feat: add rds mysql allowlist and allowlist_associate) } \ No newline at end of file diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go new file mode 100644 index 00000000..82c6b197 --- /dev/null +++ b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go @@ -0,0 +1,78 @@ +package allowlist + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineRdsMysqlAllowLists() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineRdsMysqlAllowListsRead, + Schema: map[string]*schema.Schema{ + "region_id": { + Required: true, + Type: schema.TypeString, + Description: "The region of the allow lists.", + }, + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of Scaling Activity query.", + }, + "allow_lists": { + Description: "The list of allowed list.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_list_desc": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the allow list.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + "allow_list_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the allow list.", + }, + "allow_list_ip_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of IP addresses (or address ranges) in the whitelist.", + }, + "allow_list_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the allow list.", + }, + "associated_instance_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of instances bound under the whitelist.", + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineRdsMysqlAllowListsRead(d *schema.ResourceData, meta interface{}) error { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineRdsMysqlAllowLists()) +} diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go new file mode 100644 index 00000000..8faeddcc --- /dev/null +++ b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go @@ -0,0 +1,116 @@ +package allowlist + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +RDS AllowList can be imported using the id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist.default acl-d1fd76693bd54e658912e7337d5b**** +``` + +*/ + +func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlAllowlistCreate, + Read: resourceVolcengineRdsMysqlAllowlistRead, + Update: resourceVolcengineRdsMysqlAllowlistUpdate, + Delete: resourceVolcengineRdsMysqlAllowlistDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "allow_list_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of the allow list.", + }, + "allow_list_desc": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the allow list.", + }, + "allow_list_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", + }, + "allow_list": { + Type: schema.TypeString, + Required: true, + Description: "Enter an IP address or a range of IP addresses in CIDR format.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + "modify_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Cover", + "Append", + "Delete", + }, false), + Description: "The modify mode.", + }, + "apply_instance_number": { + Type: schema.TypeInt, + Optional: true, + Description: "The number of instances bound to the current whitelist.", + }, + }, + } +} + +func resourceVolcengineRdsMysqlAllowlistCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error creating RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error reading RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlAllowlistUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error updating RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error deleting RDS Mysql Allowlist service: %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go new file mode 100644 index 00000000..825c1914 --- /dev/null +++ b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -0,0 +1,187 @@ +package allowlist + +import ( + "errors" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlAllowListService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func (s *VolcengineRdsMysqlAllowListService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return volc.WithSimpleQuery(condition, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeAllowLists" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + results, err = volc.ObtainSdkValue("Result.AllowLists", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.AllowLists is not slice ") + } + return data, err + }) +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "AllowListId": id, + } + action := "DescribeAllowListDetail" + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + return data, err + } + results, err = volc.ObtainSdkValue("Result", *resp) + if err != nil { + return data, err + } + if data, ok = results.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + if len(data) == 0 { + return data, fmt.Errorf("Rds instance %s not exist ", id) + } + return data, err +} + +func (s *VolcengineRdsMysqlAllowListService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{} +} + +func (s *VolcengineRdsMysqlAllowListService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return m, map[string]volc.ResponseConvert{}, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "CreateAllowList", + ConvertMode: volc.RequestConvertAll, + ContentType: volc.ContentTypeJson, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + id, _ := volc.ObtainSdkValue("Result.AllowListId", *resp) + d.SetId(id.(string)) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "ModifyAllowList", + ConvertMode: volc.RequestConvertInConvert, + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "AllowListId": data.Id(), + "AllowListName": data.Get("allow_list_name").(string), + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DeleteAllowList", + ConvertMode: volc.RequestConvertIgnore, + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "AllowListId": data.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{ + ContentType: volc.ContentTypeJson, + NameField: "AllowListName", + IdField: "AllowListId", + CollectField: "allow_lists", + ResponseConverts: map[string]volc.ResponseConvert{ + "AllowListIPNum": { + TargetField: "allow_list_ip_num", + }, + }, + } +} + +func (s *VolcengineRdsMysqlAllowListService) ReadResourceId(id string) string { + return id +} + +func NewRdsMysqlAllowListService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListService { + return &VolcengineRdsMysqlAllowListService{ + Client: client, + Dispatcher: &volc.Dispatcher{}, + } +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go new file mode 100644 index 00000000..eaf178e0 --- /dev/null +++ b/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go @@ -0,0 +1,93 @@ +package allowlist_associate + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +RDS AllowList Associate can be imported using the instance id and allow list id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist_associate.default rds-mysql-h441603c68aaa:acl-d1fd76693bd54e658912e7337d5b**** +``` + +*/ + +func ResourceVolcengineRdsMysqlAllowlistAssociate() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlAllowlistAssociateCreate, + Read: resourceVolcengineRdsMysqlAllowlistAssociateRead, + Delete: resourceVolcengineRdsMysqlAllowlistAssociateDelete, + Importer: &schema.ResourceImporter{ + State: importAllowListAssociate, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the mysql instance.", + }, + "allow_list_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the allow list.", + }, + }, + } +} + +func resourceVolcengineRdsMysqlAllowlistAssociateCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error creating RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlAllowlistAssociateRead(d, meta) +} + +func resourceVolcengineRdsMysqlAllowlistAssociateRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error reading RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlAllowlistAssociateDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error deleting RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) + } + return err +} + +func importAllowListAssociate(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + var err error + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must be of the form InstanceId:AllowListId") + } + err = data.Set("instance_id", items[0]) + if err != nil { + return []*schema.ResourceData{data}, err + } + err = data.Set("allow_list_id", items[1]) + if err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go new file mode 100644 index 00000000..763a62ec --- /dev/null +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -0,0 +1,112 @@ +package allowlist_associate + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + volc "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlAllowListAssociateService struct { + Client *volc.SdkClient + Dispatcher *volc.Dispatcher +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) GetClient() *volc.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + return nil, nil +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + return nil, nil +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { + return m, map[string]volc.ResponseConvert{}, nil + } + return []volc.ResourceResponseHandler{handler} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + instanceId := data.Get("instance_id").(string) + allowListId := data.Get("allow_list_id").(string) + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "AssociateAllowList", + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { + d.SetId(fmt.Sprint(instanceId, ":", allowListId)) + return nil + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + return []volc.Callback{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { + instanceId := data.Get("instance_id").(string) + allowListId := data.Get("allow_list_id").(string) + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "DisassociateAllowList", + ContentType: volc.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []volc.Callback{callback} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { + return volc.DataSourceInfo{} +} + +func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResourceId(id string) string { + return id +} + +func NewRdsMysqlAllowListAssociateService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListAssociateService { + return &VolcengineRdsMysqlAllowListAssociateService{ + Client: client, + Dispatcher: &volc.Dispatcher{}, + } +} + +func getUniversalInfo(actionName string) volc.UniversalInfo { + return volc.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: volc.POST, + ContentType: volc.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/provider.go b/volcengine/provider.go index 87996f54..1cbcb709 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -81,6 +81,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/instance_parameter_log" mongodbRegion "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/region" mongodbZone "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/zone" + "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist" + "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/dnat_entry" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/nat_gateway" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/snat_entry" From a48587cae163533fd59bd3c262ac65ec489707e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 15:53:06 +0800 Subject: [PATCH 34/58] feat: opt allowlist_associate read func --- ...olcengine_rds_mysql_allowlist_associate.go | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go index 763a62ec..91aa32a9 100644 --- a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -1,7 +1,9 @@ package allowlist_associate import ( + "errors" "fmt" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -24,7 +26,53 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResources(m map[string } func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { - return nil, nil + var ( + results interface{} + resultsMap = make(map[string]interface{}) + instanceMap = make(map[string]interface{}) + instances = make([]interface{}, 0) + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 2 { + return data, err + } + req := map[string]interface{}{ + "AllowListId": ids[1], + } + action := "DescribeAllowListDetail" + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + return data, err + } + results, err = volc.ObtainSdkValue("Result", *resp) + if err != nil { + return data, err + } + if resultsMap, ok = results.(map[string]interface{}); !ok { + return resultsMap, errors.New("Value is not map ") + } + if len(resultsMap) == 0 { + return resultsMap, fmt.Errorf("Rds instance %s not exist ", id) + } + logger.Debug(logger.ReqFormat, action, resultsMap) + instances = resultsMap["AssociatedInstances"].([]interface{}) + logger.Debug(logger.ReqFormat, action, instances) + for _, instance := range instances { + if instanceMap, ok = instance.(map[string]interface{}); !ok { + return data, errors.New("instance is not map ") + } + if len(instanceMap) == 0 { + continue + } + if instanceMap["InstanceId"].(string) == ids[0] { + data = resultsMap + } + } + return data, err } func (s *VolcengineRdsMysqlAllowListAssociateService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { From 238e23ed5260e3920374efff7e93f4384ed53a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 14 Feb 2023 17:49:51 +0800 Subject: [PATCH 35/58] fix: fix allowlist err --- example/rdsMysqlAllowlist/main.tf | 6 -- ..._source_volcengine_rds_mysql_allowlists.go | 24 +++++ ...resource_volcengine_rds_mysql_allowlist.go | 18 +--- .../service_volcengine_rds_mysql_allowlist.go | 96 ++++++++++++++++--- ...olcengine_rds_mysql_allowlist_associate.go | 5 +- volcengine/provider.go | 2 - 6 files changed, 118 insertions(+), 33 deletions(-) diff --git a/example/rdsMysqlAllowlist/main.tf b/example/rdsMysqlAllowlist/main.tf index c566db12..6b0b0b1b 100644 --- a/example/rdsMysqlAllowlist/main.tf +++ b/example/rdsMysqlAllowlist/main.tf @@ -1,13 +1,7 @@ resource "volcengine_rds_mysql_allowlist" "foo" { -<<<<<<< HEAD allow_list_name = "tf-test-opt" allow_list_desc = "terraform test zzm" allow_list = [ "127.0.0.1" ] -======= - allow_list_name = "tf-test" - allow_list_desc = "terraform test zzm" - allow_list = "127.0.0.1" ->>>>>>> 7bde4df (feat: add rds mysql allowlist and allowlist_associate) } \ No newline at end of file diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go index 82c6b197..274794b0 100644 --- a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go +++ b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go @@ -65,6 +65,30 @@ func DataSourceVolcengineRdsMysqlAllowLists() *schema.Resource { Computed: true, Description: "The total number of instances bound under the whitelist.", }, + "associated_instances": { + Type: schema.TypeList, + Computed: true, + Description: "The list of instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the instance.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the instance.", + }, + "vpc": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the vpc.", + }, + }, + }, + }, }, }, }, diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go index 8faeddcc..dd360058 100644 --- a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go +++ b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go @@ -5,7 +5,6 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" volc "github.com/volcengine/terraform-provider-volcengine/common" ) @@ -51,8 +50,11 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", }, "allow_list": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, Description: "Enter an IP address or a range of IP addresses in CIDR format.", }, "allow_list_id": { @@ -60,16 +62,6 @@ func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { Computed: true, Description: "The id of the allow list.", }, - "modify_mode": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - "Cover", - "Append", - "Delete", - }, false), - Description: "The modify mode.", - }, "apply_instance_number": { Type: schema.TypeInt, Optional: true, diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go index 825c1914..74ee3aae 100644 --- a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go +++ b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -50,32 +50,50 @@ func (s *VolcengineRdsMysqlAllowListService) ReadResources(condition map[string] if data, ok = results.([]interface{}); !ok { return data, errors.New("Result.AllowLists is not slice ") } + for index, ele := range data { + allowList := ele.(map[string]interface{}) + query := map[string]interface{}{ + "AllowListId": allowList["AllowListId"], + } + action = "DescribeAllowListDetail" + logger.Debug(logger.ReqFormat, action, query) + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &query) + if err != nil { + return data, err + } + logger.Debug(logger.RespFormat, action, query, *resp) + instances, err := volc.ObtainSdkValue("Result.AssociatedInstances", *resp) + if err != nil { + return data, err + } + data[index].(map[string]interface{})["AssociatedInstances"] = instances + } return data, err }) } func (s *VolcengineRdsMysqlAllowListService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { var ( - results interface{} - ok bool + results []interface{} ) if id == "" { id = s.ReadResourceId(resourceData.Id()) } req := map[string]interface{}{ - "AllowListId": id, + "RegionId": s.Client.Region, } - action := "DescribeAllowListDetail" - resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + results, err = s.ReadResources(req) if err != nil { return data, err } - results, err = volc.ObtainSdkValue("Result", *resp) - if err != nil { - return data, err - } - if data, ok = results.(map[string]interface{}); !ok { - return data, errors.New("Value is not map ") + for _, v := range results { + result, ok := v.(map[string]interface{}) + if !ok { + return data, errors.New("Value is not map ") + } + if result["AllowListId"].(string) == id { + data = result + } } if len(data) == 0 { return data, fmt.Errorf("Rds instance %s not exist ", id) @@ -100,6 +118,26 @@ func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.Resourc Action: "CreateAllowList", ConvertMode: volc.RequestConvertAll, ContentType: volc.ContentTypeJson, + Convert: map[string]volc.RequestConvert{ + "allow_list": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + allowLists := d.Get("allow_list").([]interface{}) + if len(allowLists) == 1 { + (*call.SdkParam)["AllowList"] = allowLists[0] + return true, nil + } + lists := "" + for _, list := range allowLists { + lists += list.(string) + lists += "," + } + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + return true, nil + }, ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) @@ -120,6 +158,39 @@ func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.Resourc Action: "ModifyAllowList", ConvertMode: volc.RequestConvertInConvert, ContentType: volc.ContentTypeJson, + Convert: map[string]volc.RequestConvert{ + "allow_list": { + Ignore: true, + }, + "apply_instance_num": { + Ignore: true, + }, + "allow_list_desc": { + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + // 修改allowList必须传ApplyInstanceNum + resp, err := s.ReadResource(d, d.Id()) + if err != nil { + return false, err + } + num := resp["AssociatedInstanceNum"].(float64) + (*call.SdkParam)["ApplyInstanceNum"] = int(num) + allowLists := d.Get("allow_list").([]interface{}) + if len(allowLists) == 1 { + (*call.SdkParam)["AllowList"] = allowLists[0] + return true, nil + } + lists := "" + for _, list := range allowLists { + lists += list.(string) + lists += "," + } + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + return true, nil + }, SdkParam: &map[string]interface{}{ "AllowListId": data.Id(), "AllowListName": data.Get("allow_list_name").(string), @@ -161,6 +232,9 @@ func (s *VolcengineRdsMysqlAllowListService) DatasourceResources(data *schema.Re "AllowListIPNum": { TargetField: "allow_list_ip_num", }, + "VPC": { + TargetField: "vpc", + }, }, } } diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go index 91aa32a9..c1376404 100644 --- a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go +++ b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go @@ -56,7 +56,7 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData return resultsMap, errors.New("Value is not map ") } if len(resultsMap) == 0 { - return resultsMap, fmt.Errorf("Rds instance %s not exist ", id) + return resultsMap, fmt.Errorf("Rds allowlist %s not exist ", ids[1]) } logger.Debug(logger.ReqFormat, action, resultsMap) instances = resultsMap["AssociatedInstances"].([]interface{}) @@ -72,6 +72,9 @@ func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData data = resultsMap } } + if len(data) == 0 { + return data, fmt.Errorf("Rds allowlist associate %s not exist ", id) + } return data, err } diff --git a/volcengine/provider.go b/volcengine/provider.go index 1cbcb709..87996f54 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -81,8 +81,6 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/instance_parameter_log" mongodbRegion "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/region" mongodbZone "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/zone" - "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist" - "github.com/volcengine/terraform-provider-volcengine/volcengine/mysql_rds/allowlist_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/dnat_entry" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/nat_gateway" "github.com/volcengine/terraform-provider-volcengine/volcengine/nat/snat_entry" From 5f2240e930bef3dd98829611d310eaa6eaeb3005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Wed, 22 Feb 2023 14:54:04 +0800 Subject: [PATCH 36/58] feat: rename(mysql_rds to rds_mysql) and opt param --- ..._source_volcengine_rds_mysql_allowlists.go | 102 ------- ...resource_volcengine_rds_mysql_allowlist.go | 108 -------- .../service_volcengine_rds_mysql_allowlist.go | 261 ------------------ ...olcengine_rds_mysql_allowlist_associate.go | 93 ------- ...olcengine_rds_mysql_allowlist_associate.go | 163 ----------- 5 files changed, 727 deletions(-) delete mode 100644 volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go delete mode 100644 volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go delete mode 100644 volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go delete mode 100644 volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go delete mode 100644 volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go diff --git a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go b/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go deleted file mode 100644 index 274794b0..00000000 --- a/volcengine/mysql_rds/allowlist/data_source_volcengine_rds_mysql_allowlists.go +++ /dev/null @@ -1,102 +0,0 @@ -package allowlist - -import ( - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - volc "github.com/volcengine/terraform-provider-volcengine/common" -) - -func DataSourceVolcengineRdsMysqlAllowLists() *schema.Resource { - return &schema.Resource{ - Read: dataSourceVolcengineRdsMysqlAllowListsRead, - Schema: map[string]*schema.Schema{ - "region_id": { - Required: true, - Type: schema.TypeString, - Description: "The region of the allow lists.", - }, - "instance_id": { - Type: schema.TypeString, - Optional: true, - Description: "Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance.", - }, - "output_file": { - Type: schema.TypeString, - Optional: true, - Description: "File name where to save data source results.", - }, - "total_count": { - Type: schema.TypeInt, - Computed: true, - Description: "The total count of Scaling Activity query.", - }, - "allow_lists": { - Description: "The list of allowed list.", - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "allow_list_desc": { - Type: schema.TypeString, - Computed: true, - Description: "The description of the allow list.", - }, - "allow_list_id": { - Type: schema.TypeString, - Computed: true, - Description: "The id of the allow list.", - }, - "allow_list_name": { - Type: schema.TypeString, - Computed: true, - Description: "The name of the allow list.", - }, - "allow_list_ip_num": { - Type: schema.TypeInt, - Computed: true, - Description: "The total number of IP addresses (or address ranges) in the whitelist.", - }, - "allow_list_type": { - Type: schema.TypeString, - Computed: true, - Description: "The type of the allow list.", - }, - "associated_instance_num": { - Type: schema.TypeInt, - Computed: true, - Description: "The total number of instances bound under the whitelist.", - }, - "associated_instances": { - Type: schema.TypeList, - Computed: true, - Description: "The list of instances.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "instance_id": { - Type: schema.TypeString, - Computed: true, - Description: "The id of the instance.", - }, - "instance_name": { - Type: schema.TypeString, - Computed: true, - Description: "The name of the instance.", - }, - "vpc": { - Type: schema.TypeString, - Computed: true, - Description: "The id of the vpc.", - }, - }, - }, - }, - }, - }, - }, - }, - } -} - -func dataSourceVolcengineRdsMysqlAllowListsRead(d *schema.ResourceData, meta interface{}) error { - service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) - return service.Dispatcher.Data(service, d, DataSourceVolcengineRdsMysqlAllowLists()) -} diff --git a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go deleted file mode 100644 index dd360058..00000000 --- a/volcengine/mysql_rds/allowlist/resource_volcengine_rds_mysql_allowlist.go +++ /dev/null @@ -1,108 +0,0 @@ -package allowlist - -import ( - "fmt" - "time" - - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - volc "github.com/volcengine/terraform-provider-volcengine/common" -) - -/* - -Import -RDS AllowList can be imported using the id, e.g. -``` -$ terraform import volcengine_rds_mysql_allowlist.default acl-d1fd76693bd54e658912e7337d5b**** -``` - -*/ - -func ResourceVolcengineRdsMysqlAllowlist() *schema.Resource { - return &schema.Resource{ - Create: resourceVolcengineRdsMysqlAllowlistCreate, - Read: resourceVolcengineRdsMysqlAllowlistRead, - Update: resourceVolcengineRdsMysqlAllowlistUpdate, - Delete: resourceVolcengineRdsMysqlAllowlistDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - Schema: map[string]*schema.Schema{ - "allow_list_name": { - Type: schema.TypeString, - Required: true, - Description: "The name of the allow list.", - }, - "allow_list_desc": { - Type: schema.TypeString, - Optional: true, - Description: "The description of the allow list.", - }, - "allow_list_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", - }, - "allow_list": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - Description: "Enter an IP address or a range of IP addresses in CIDR format.", - }, - "allow_list_id": { - Type: schema.TypeString, - Computed: true, - Description: "The id of the allow list.", - }, - "apply_instance_number": { - Type: schema.TypeInt, - Optional: true, - Description: "The number of instances bound to the current whitelist.", - }, - }, - } -} - -func resourceVolcengineRdsMysqlAllowlistCreate(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlist()) - if err != nil { - return fmt.Errorf("error creating RDS Mysql Allowlist service: %q, %w", d.Id(), err) - } - return resourceVolcengineRdsMysqlAllowlistRead(d, meta) -} - -func resourceVolcengineRdsMysqlAllowlistRead(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlist()) - if err != nil { - return fmt.Errorf("error reading RDS Mysql Allowlist service: %q, %w", d.Id(), err) - } - return err -} - -func resourceVolcengineRdsMysqlAllowlistUpdate(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlAllowlist()) - if err != nil { - return fmt.Errorf("error updating RDS Mysql Allowlist service: %q, %w", d.Id(), err) - } - return resourceVolcengineRdsMysqlAllowlistRead(d, meta) -} - -func resourceVolcengineRdsMysqlAllowlistDelete(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlist()) - if err != nil { - return fmt.Errorf("error deleting RDS Mysql Allowlist service: %q, %w", d.Id(), err) - } - return err -} diff --git a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go deleted file mode 100644 index 74ee3aae..00000000 --- a/volcengine/mysql_rds/allowlist/service_volcengine_rds_mysql_allowlist.go +++ /dev/null @@ -1,261 +0,0 @@ -package allowlist - -import ( - "errors" - "fmt" - "time" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - volc "github.com/volcengine/terraform-provider-volcengine/common" - "github.com/volcengine/terraform-provider-volcengine/logger" -) - -type VolcengineRdsMysqlAllowListService struct { - Client *volc.SdkClient - Dispatcher *volc.Dispatcher -} - -func (s *VolcengineRdsMysqlAllowListService) GetClient() *volc.SdkClient { - return s.Client -} - -func (s *VolcengineRdsMysqlAllowListService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { - var ( - resp *map[string]interface{} - results interface{} - ok bool - ) - return volc.WithSimpleQuery(condition, func(m map[string]interface{}) ([]interface{}, error) { - action := "DescribeAllowLists" - logger.Debug(logger.ReqFormat, action, condition) - if condition == nil { - resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) - if err != nil { - return data, err - } - } else { - resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) - if err != nil { - return data, err - } - } - results, err = volc.ObtainSdkValue("Result.AllowLists", *resp) - if err != nil { - return data, err - } - if results == nil { - results = []interface{}{} - } - if data, ok = results.([]interface{}); !ok { - return data, errors.New("Result.AllowLists is not slice ") - } - for index, ele := range data { - allowList := ele.(map[string]interface{}) - query := map[string]interface{}{ - "AllowListId": allowList["AllowListId"], - } - action = "DescribeAllowListDetail" - logger.Debug(logger.ReqFormat, action, query) - resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &query) - if err != nil { - return data, err - } - logger.Debug(logger.RespFormat, action, query, *resp) - instances, err := volc.ObtainSdkValue("Result.AssociatedInstances", *resp) - if err != nil { - return data, err - } - data[index].(map[string]interface{})["AssociatedInstances"] = instances - } - return data, err - }) -} - -func (s *VolcengineRdsMysqlAllowListService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { - var ( - results []interface{} - ) - if id == "" { - id = s.ReadResourceId(resourceData.Id()) - } - req := map[string]interface{}{ - "RegionId": s.Client.Region, - } - results, err = s.ReadResources(req) - if err != nil { - return data, err - } - for _, v := range results { - result, ok := v.(map[string]interface{}) - if !ok { - return data, errors.New("Value is not map ") - } - if result["AllowListId"].(string) == id { - data = result - } - } - if len(data) == 0 { - return data, fmt.Errorf("Rds instance %s not exist ", id) - } - return data, err -} - -func (s *VolcengineRdsMysqlAllowListService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { - return &resource.StateChangeConf{} -} - -func (s *VolcengineRdsMysqlAllowListService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { - handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { - return m, map[string]volc.ResponseConvert{}, nil - } - return []volc.ResourceResponseHandler{handler} -} - -func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "CreateAllowList", - ConvertMode: volc.RequestConvertAll, - ContentType: volc.ContentTypeJson, - Convert: map[string]volc.RequestConvert{ - "allow_list": { - Ignore: true, - }, - }, - BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - allowLists := d.Get("allow_list").([]interface{}) - if len(allowLists) == 1 { - (*call.SdkParam)["AllowList"] = allowLists[0] - return true, nil - } - lists := "" - for _, list := range allowLists { - lists += list.(string) - lists += "," - } - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) - (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] - return true, nil - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { - id, _ := volc.ObtainSdkValue("Result.AllowListId", *resp) - d.SetId(id.(string)) - return nil - }, - }, - } - return []volc.Callback{callback} -} - -func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "ModifyAllowList", - ConvertMode: volc.RequestConvertInConvert, - ContentType: volc.ContentTypeJson, - Convert: map[string]volc.RequestConvert{ - "allow_list": { - Ignore: true, - }, - "apply_instance_num": { - Ignore: true, - }, - "allow_list_desc": { - ForceGet: true, - }, - }, - BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - // 修改allowList必须传ApplyInstanceNum - resp, err := s.ReadResource(d, d.Id()) - if err != nil { - return false, err - } - num := resp["AssociatedInstanceNum"].(float64) - (*call.SdkParam)["ApplyInstanceNum"] = int(num) - allowLists := d.Get("allow_list").([]interface{}) - if len(allowLists) == 1 { - (*call.SdkParam)["AllowList"] = allowLists[0] - return true, nil - } - lists := "" - for _, list := range allowLists { - lists += list.(string) - lists += "," - } - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) - (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] - return true, nil - }, - SdkParam: &map[string]interface{}{ - "AllowListId": data.Id(), - "AllowListName": data.Get("allow_list_name").(string), - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - }, - } - return []volc.Callback{callback} -} - -func (s *VolcengineRdsMysqlAllowListService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "DeleteAllowList", - ConvertMode: volc.RequestConvertIgnore, - ContentType: volc.ContentTypeJson, - SdkParam: &map[string]interface{}{ - "AllowListId": data.Id(), - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - }, - } - return []volc.Callback{callback} -} - -func (s *VolcengineRdsMysqlAllowListService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { - return volc.DataSourceInfo{ - ContentType: volc.ContentTypeJson, - NameField: "AllowListName", - IdField: "AllowListId", - CollectField: "allow_lists", - ResponseConverts: map[string]volc.ResponseConvert{ - "AllowListIPNum": { - TargetField: "allow_list_ip_num", - }, - "VPC": { - TargetField: "vpc", - }, - }, - } -} - -func (s *VolcengineRdsMysqlAllowListService) ReadResourceId(id string) string { - return id -} - -func NewRdsMysqlAllowListService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListService { - return &VolcengineRdsMysqlAllowListService{ - Client: client, - Dispatcher: &volc.Dispatcher{}, - } -} - -func getUniversalInfo(actionName string) volc.UniversalInfo { - return volc.UniversalInfo{ - ServiceName: "rds_mysql", - Version: "2022-01-01", - HttpMethod: volc.POST, - ContentType: volc.ApplicationJSON, - Action: actionName, - } -} diff --git a/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go deleted file mode 100644 index eaf178e0..00000000 --- a/volcengine/mysql_rds/allowlist_associate/resource_volcengine_rds_mysql_allowlist_associate.go +++ /dev/null @@ -1,93 +0,0 @@ -package allowlist_associate - -import ( - "fmt" - "strings" - "time" - - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - volc "github.com/volcengine/terraform-provider-volcengine/common" -) - -/* - -Import -RDS AllowList Associate can be imported using the instance id and allow list id, e.g. -``` -$ terraform import volcengine_rds_mysql_allowlist_associate.default rds-mysql-h441603c68aaa:acl-d1fd76693bd54e658912e7337d5b**** -``` - -*/ - -func ResourceVolcengineRdsMysqlAllowlistAssociate() *schema.Resource { - return &schema.Resource{ - Create: resourceVolcengineRdsMysqlAllowlistAssociateCreate, - Read: resourceVolcengineRdsMysqlAllowlistAssociateRead, - Delete: resourceVolcengineRdsMysqlAllowlistAssociateDelete, - Importer: &schema.ResourceImporter{ - State: importAllowListAssociate, - }, - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - Schema: map[string]*schema.Schema{ - "instance_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "The id of the mysql instance.", - }, - "allow_list_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: "The id of the allow list.", - }, - }, - } -} - -func resourceVolcengineRdsMysqlAllowlistAssociateCreate(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Create(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) - if err != nil { - return fmt.Errorf("error creating RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) - } - return resourceVolcengineRdsMysqlAllowlistAssociateRead(d, meta) -} - -func resourceVolcengineRdsMysqlAllowlistAssociateRead(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Read(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) - if err != nil { - return fmt.Errorf("error reading RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) - } - return err -} - -func resourceVolcengineRdsMysqlAllowlistAssociateDelete(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlAllowListAssociateService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Delete(service, d, ResourceVolcengineRdsMysqlAllowlistAssociate()) - if err != nil { - return fmt.Errorf("error deleting RDS Mysql Allowlist Associate service: %q, %w", d.Id(), err) - } - return err -} - -func importAllowListAssociate(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { - var err error - items := strings.Split(data.Id(), ":") - if len(items) != 2 { - return []*schema.ResourceData{data}, fmt.Errorf("import id must be of the form InstanceId:AllowListId") - } - err = data.Set("instance_id", items[0]) - if err != nil { - return []*schema.ResourceData{data}, err - } - err = data.Set("allow_list_id", items[1]) - if err != nil { - return []*schema.ResourceData{data}, err - } - return []*schema.ResourceData{data}, nil -} diff --git a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go b/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go deleted file mode 100644 index c1376404..00000000 --- a/volcengine/mysql_rds/allowlist_associate/service_volcengine_rds_mysql_allowlist_associate.go +++ /dev/null @@ -1,163 +0,0 @@ -package allowlist_associate - -import ( - "errors" - "fmt" - "strings" - "time" - - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - volc "github.com/volcengine/terraform-provider-volcengine/common" - "github.com/volcengine/terraform-provider-volcengine/logger" -) - -type VolcengineRdsMysqlAllowListAssociateService struct { - Client *volc.SdkClient - Dispatcher *volc.Dispatcher -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) GetClient() *volc.SdkClient { - return s.Client -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { - return nil, nil -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { - var ( - results interface{} - resultsMap = make(map[string]interface{}) - instanceMap = make(map[string]interface{}) - instances = make([]interface{}, 0) - ok bool - ) - if id == "" { - id = s.ReadResourceId(resourceData.Id()) - } - ids := strings.Split(id, ":") - if len(ids) != 2 { - return data, err - } - req := map[string]interface{}{ - "AllowListId": ids[1], - } - action := "DescribeAllowListDetail" - resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) - if err != nil { - return data, err - } - results, err = volc.ObtainSdkValue("Result", *resp) - if err != nil { - return data, err - } - if resultsMap, ok = results.(map[string]interface{}); !ok { - return resultsMap, errors.New("Value is not map ") - } - if len(resultsMap) == 0 { - return resultsMap, fmt.Errorf("Rds allowlist %s not exist ", ids[1]) - } - logger.Debug(logger.ReqFormat, action, resultsMap) - instances = resultsMap["AssociatedInstances"].([]interface{}) - logger.Debug(logger.ReqFormat, action, instances) - for _, instance := range instances { - if instanceMap, ok = instance.(map[string]interface{}); !ok { - return data, errors.New("instance is not map ") - } - if len(instanceMap) == 0 { - continue - } - if instanceMap["InstanceId"].(string) == ids[0] { - data = resultsMap - } - } - if len(data) == 0 { - return data, fmt.Errorf("Rds allowlist associate %s not exist ", id) - } - return data, err -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { - return &resource.StateChangeConf{} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) WithResourceResponseHandlers(m map[string]interface{}) []volc.ResourceResponseHandler { - handler := func() (map[string]interface{}, map[string]volc.ResponseConvert, error) { - return m, map[string]volc.ResponseConvert{}, nil - } - return []volc.ResourceResponseHandler{handler} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - instanceId := data.Get("instance_id").(string) - allowListId := data.Get("allow_list_id").(string) - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "AssociateAllowList", - ContentType: volc.ContentTypeJson, - SdkParam: &map[string]interface{}{ - "InstanceIds": []string{instanceId}, - "AllowListIds": []string{allowListId}, - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - AfterCall: func(d *schema.ResourceData, client *volc.SdkClient, resp *map[string]interface{}, call volc.SdkCall) error { - d.SetId(fmt.Sprint(instanceId, ":", allowListId)) - return nil - }, - }, - } - return []volc.Callback{callback} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - return []volc.Callback{} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) RemoveResource(data *schema.ResourceData, resource *schema.Resource) []volc.Callback { - instanceId := data.Get("instance_id").(string) - allowListId := data.Get("allow_list_id").(string) - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "DisassociateAllowList", - ContentType: volc.ContentTypeJson, - SdkParam: &map[string]interface{}{ - "InstanceIds": []string{instanceId}, - "AllowListIds": []string{allowListId}, - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - }, - } - return []volc.Callback{callback} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) volc.DataSourceInfo { - return volc.DataSourceInfo{} -} - -func (s *VolcengineRdsMysqlAllowListAssociateService) ReadResourceId(id string) string { - return id -} - -func NewRdsMysqlAllowListAssociateService(client *volc.SdkClient) *VolcengineRdsMysqlAllowListAssociateService { - return &VolcengineRdsMysqlAllowListAssociateService{ - Client: client, - Dispatcher: &volc.Dispatcher{}, - } -} - -func getUniversalInfo(actionName string) volc.UniversalInfo { - return volc.UniversalInfo{ - ServiceName: "rds_mysql", - Version: "2022-01-01", - HttpMethod: volc.POST, - ContentType: volc.ApplicationJSON, - Action: actionName, - } -} From 60ce83613ec054513808682d19955e6fe45c51d3 Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 17 Feb 2023 16:43:55 +0800 Subject: [PATCH 37/58] feat:support rds mysql account and database. --- .../rds_mysql_account/service_volcengine_rds_mysql_account.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index b86ac610..801b212a 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -199,6 +199,9 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R } if resourceData.HasChange("account_privileges") { addPrivis, removePrivs, _, _ := common.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) + logger.DebugInfo("account_privileges %v", resourceData.Get("account_privileges")) + logger.DebugInfo("addPrivis %v len %d", addPrivis, addPrivis.Len()) + logger.DebugInfo("removePrivs %v len %d", removePrivs, addPrivis.Len()) if addPrivis != nil && addPrivis.Len() != 0 { callback := volc.Callback{ From c67e1f7899cb880e852032abbdc0f6acf6b60499 Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 24 Feb 2023 10:51:42 +0800 Subject: [PATCH 38/58] fix:add update timeout for rds mysql account&database. --- .../rds_mysql_account/service_volcengine_rds_mysql_account.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index 801b212a..b86ac610 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -199,9 +199,6 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R } if resourceData.HasChange("account_privileges") { addPrivis, removePrivs, _, _ := common.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) - logger.DebugInfo("account_privileges %v", resourceData.Get("account_privileges")) - logger.DebugInfo("addPrivis %v len %d", addPrivis, addPrivis.Len()) - logger.DebugInfo("removePrivs %v len %d", removePrivs, addPrivis.Len()) if addPrivis != nil && addPrivis.Len() != 0 { callback := volc.Callback{ From 1073e1a2b31693f4876c3d0e3d02c1484b56f8d5 Mon Sep 17 00:00:00 2001 From: lixiang Date: Fri, 24 Feb 2023 11:05:19 +0800 Subject: [PATCH 39/58] sort out code. --- volcengine/provider.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/volcengine/provider.go b/volcengine/provider.go index 87996f54..5cb4a832 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -303,13 +303,13 @@ func Provider() terraform.ResourceProvider { "volcengine_bioos_clusters": bioosCluster.DataSourceVolcengineBioosClusters(), "volcengine_bioos_workspaces": workspace.DataSourceVolcengineBioosWorkspaces(), + // ================ RDS V2 ============== + "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), + // ================ RdsMysql ================ "volcengine_rds_mysql_accounts": rds_mysql_account.DataSourceVolcengineRdsMysqlAccounts(), "volcengine_rds_mysql_databases": rds_mysql_database.DataSourceVolcengineRdsMysqlDatabases(), "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), - - // ================ RDS V2 ============== - "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), }, ResourcesMap: map[string]*schema.Resource{ "volcengine_vpc": vpc.ResourceVolcengineVpc(), From 2e7f8e271fb2451944edbd195e05a25d1a75df07 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Thu, 9 Mar 2023 10:59:15 +0800 Subject: [PATCH 40/58] feat: support rds_mysql_instance --- docgen/main.go | 1 + example/dataRdsMysqlInstances/main.tf | 3 + example/rdsMysqlInstance/main.tf | 31 + example/rdsMysqlInstanceReadonlyNode/main.tf | 5 + volcengine/provider.go | 13 +- .../common_volcengine_rds_mysql_instance.go | 29 + ...a_source_volcengine_rds_mysql_instances.go | 473 +++++++++++ .../resource_volcengine_rds_mysql_instance.go | 207 +++++ .../service_volcengine_rds_mysql_instance.go | 741 ++++++++++++++++++ ...engine_rds_mysql_instance_readonly_node.go | 22 + ...engine_rds_mysql_instance_readonly_node.go | 96 +++ ...engine_rds_mysql_instance_readonly_node.go | 411 ++++++++++ .../docs/d/rds_mysql_accounts.html.markdown | 38 + .../docs/d/rds_mysql_allowlists.html.markdown | 38 + .../docs/d/rds_mysql_instances.html.markdown | 127 +++ website/docs/r/rds_database.html.markdown | 2 +- .../docs/r/rds_mysql_account.html.markdown | 67 ++ .../docs/r/rds_mysql_allowlist.html.markdown | 39 + ...ds_mysql_allowlist_associate.html.markdown | 34 + .../docs/r/rds_mysql_instance.html.markdown | 175 +++++ ...mysql_instance_readonly_node.html.markdown | 36 + website/volcengine.erb | 30 + 22 files changed, 2613 insertions(+), 5 deletions(-) create mode 100644 example/dataRdsMysqlInstances/main.tf create mode 100644 example/rdsMysqlInstance/main.tf create mode 100644 example/rdsMysqlInstanceReadonlyNode/main.tf create mode 100644 volcengine/rds_mysql/rds_mysql_instance/common_volcengine_rds_mysql_instance.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance/data_source_volcengine_rds_mysql_instances.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance/resource_volcengine_rds_mysql_instance.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance_readonly_node/common_volcengine_rds_mysql_instance_readonly_node.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance_readonly_node/resource_volcengine_rds_mysql_instance_readonly_node.go create mode 100644 volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go create mode 100644 website/docs/d/rds_mysql_accounts.html.markdown create mode 100644 website/docs/d/rds_mysql_allowlists.html.markdown create mode 100644 website/docs/d/rds_mysql_instances.html.markdown create mode 100644 website/docs/r/rds_mysql_account.html.markdown create mode 100644 website/docs/r/rds_mysql_allowlist.html.markdown create mode 100644 website/docs/r/rds_mysql_allowlist_associate.html.markdown create mode 100644 website/docs/r/rds_mysql_instance.html.markdown create mode 100644 website/docs/r/rds_mysql_instance_readonly_node.html.markdown diff --git a/docgen/main.go b/docgen/main.go index aff19013..680e9216 100644 --- a/docgen/main.go +++ b/docgen/main.go @@ -130,6 +130,7 @@ var resourceKeys = map[string]string{ "autoscaling": "AUTOSCALING", "mongodb": "MONGODB", "bioos": "BIOOS", + "rds_mysql": "RDS_MYSQL", } type Products struct { diff --git a/example/dataRdsMysqlInstances/main.tf b/example/dataRdsMysqlInstances/main.tf new file mode 100644 index 00000000..597b4cad --- /dev/null +++ b/example/dataRdsMysqlInstances/main.tf @@ -0,0 +1,3 @@ +data "volcengine_rds_mysql_instances" "default" { + instance_id = "mysql-72da4258c2c7" +} \ No newline at end of file diff --git a/example/rdsMysqlInstance/main.tf b/example/rdsMysqlInstance/main.tf new file mode 100644 index 00000000..8765ccc0 --- /dev/null +++ b/example/rdsMysqlInstance/main.tf @@ -0,0 +1,31 @@ +resource "volcengine_rds_mysql_instance" "foo" { + db_engine_version = "MySQL_5_7" + node_spec = "rds.mysql.1c2g" + primary_zone_id = "cn-guilin-a" + secondary_zone_id = "cn-guilin-b" + storage_space = 80 + subnet_id = "subnet-2d72yi377stts58ozfdrlk9f6" + instance_name = "tf-test" + lower_case_table_names = "1" + + charge_info { + charge_type = "PostPaid" + } + + allow_list_ids = ["acl-2dd8f8317e4d4159b21630d13ae2e6ec", "acl-2eaa2a053b2a4a58b988e38ae975e81c"] + + parameters { + parameter_name = "auto_increment_increment" + parameter_value = "2" + } + parameters { + parameter_name = "auto_increment_offset" + parameter_value = "4" + } +} + +resource "volcengine_rds_mysql_instance_readonly_node" "readonly" { + instance_id = volcengine_rds_mysql_instance.foo.id + node_spec = "rds.mysql.2c4g" + zone_id = "cn-guilin-a" +} \ No newline at end of file diff --git a/example/rdsMysqlInstanceReadonlyNode/main.tf b/example/rdsMysqlInstanceReadonlyNode/main.tf new file mode 100644 index 00000000..9121f954 --- /dev/null +++ b/example/rdsMysqlInstanceReadonlyNode/main.tf @@ -0,0 +1,5 @@ +resource "volcengine_rds_mysql_instance_readonly_node" "foo" { + instance_id = "mysql-b3fca7f571d6" + node_spec = "rds.mysql.1c2g" + zone_id = "cn-guilin-b" +} \ No newline at end of file diff --git a/volcengine/provider.go b/volcengine/provider.go index 5cb4a832..ff160981 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -92,6 +92,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/rds/rds_parameter_template" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/allowlist" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/allowlist_associate" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_instance" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_instance_readonly_node" "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_v2/rds_instance_v2" "github.com/volcengine/terraform-provider-volcengine/volcengine/tos/bucket" "github.com/volcengine/terraform-provider-volcengine/volcengine/tos/object" @@ -307,6 +309,7 @@ func Provider() terraform.ResourceProvider { "volcengine_rds_instances_v2": rds_instance_v2.DataSourceVolcengineRdsInstances(), // ================ RdsMysql ================ + "volcengine_rds_mysql_instances": rds_mysql_instance.DataSourceVolcengineRdsMysqlInstances(), "volcengine_rds_mysql_accounts": rds_mysql_account.DataSourceVolcengineRdsMysqlAccounts(), "volcengine_rds_mysql_databases": rds_mysql_database.DataSourceVolcengineRdsMysqlDatabases(), "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), @@ -444,10 +447,12 @@ func Provider() terraform.ResourceProvider { "volcengine_rds_instance_v2": rds_instance_v2.ResourceVolcengineRdsInstance(), // ================ RdsMysql ================ - "volcengine_rds_mysql_account": rds_mysql_account.ResourceVolcengineRdsMysqlAccount(), - "volcengine_rds_mysql_database": rds_mysql_database.ResourceVolcengineRdsMysqlDatabase(), - "volcengine_rds_mysql_allowlist": allowlist.ResourceVolcengineRdsMysqlAllowlist(), - "volcengine_rds_mysql_allowlist_associate": allowlist_associate.ResourceVolcengineRdsMysqlAllowlistAssociate(), + "volcengine_rds_mysql_instance": rds_mysql_instance.ResourceVolcengineRdsMysqlInstance(), + "volcengine_rds_mysql_instance_readonly_node": rds_mysql_instance_readonly_node.ResourceVolcengineRdsMysqlInstanceReadonlyNode(), + "volcengine_rds_mysql_account": rds_mysql_account.ResourceVolcengineRdsMysqlAccount(), + "volcengine_rds_mysql_database": rds_mysql_database.ResourceVolcengineRdsMysqlDatabase(), + "volcengine_rds_mysql_allowlist": allowlist.ResourceVolcengineRdsMysqlAllowlist(), + "volcengine_rds_mysql_allowlist_associate": allowlist_associate.ResourceVolcengineRdsMysqlAllowlistAssociate(), }, ConfigureFunc: ProviderConfigure, } diff --git a/volcengine/rds_mysql/rds_mysql_instance/common_volcengine_rds_mysql_instance.go b/volcengine/rds_mysql/rds_mysql_instance/common_volcengine_rds_mysql_instance.go new file mode 100644 index 00000000..5859a749 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance/common_volcengine_rds_mysql_instance.go @@ -0,0 +1,29 @@ +package rds_mysql_instance + +import ( + "bytes" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var parameterHash = func(v interface{}) int { + if v == nil { + return hashcode.String("") + } + m := v.(map[string]interface{}) + var ( + buf bytes.Buffer + ) + buf.WriteString(fmt.Sprintf("%v#%v", m["parameter_name"], m["parameter_value"])) + return hashcode.String(buf.String()) +} + +func RdsMysqlInstanceImportDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + //在计费方式为PostPaid的时候 period的变化会被忽略 + if d.Get("charge_info.0.charge_type").(string) == "PostPaid" && (k == "charge_info.0.period" || k == "charge_info.0.period_unit" || k == "charge_info.0.auto_renew") { + return true + } + + return false +} diff --git a/volcengine/rds_mysql/rds_mysql_instance/data_source_volcengine_rds_mysql_instances.go b/volcengine/rds_mysql/rds_mysql_instance/data_source_volcengine_rds_mysql_instances.go new file mode 100644 index 00000000..6fdb6fa7 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance/data_source_volcengine_rds_mysql_instances.go @@ -0,0 +1,473 @@ +package rds_mysql_instance + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineRdsMysqlInstances() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineRdsMysqlInstancesRead, + Schema: map[string]*schema.Schema{ + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of RDS instance.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of RDS instance query.", + }, + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "The id of the RDS instance.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the RDS instance.", + }, + "instance_status": { + Type: schema.TypeString, + Optional: true, + Description: "The status of the RDS instance.", + }, + "db_engine_version": { + Type: schema.TypeString, + Optional: true, + Description: "The version of the RDS instance.", + }, + "create_time_start": { + Type: schema.TypeString, + Optional: true, + Description: "The start time of creating RDS instance.", + }, + "create_time_end": { + Type: schema.TypeString, + Optional: true, + Description: "The end time of creating RDS instance.", + }, + "zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The available zone of the RDS instance.", + }, + "charge_type": { + Type: schema.TypeString, + Optional: true, + Description: "The charge type of the RDS instance.", + ValidateFunc: validation.StringInSlice([]string{"PostPaid", "PrePaid"}, false), + }, + "rds_mysql_instances": { + Description: "The collection of RDS instance query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the RDS instance.", + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the RDS instance.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the RDS instance.", + }, + "instance_status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the RDS instance.", + }, + "region_id": { + Type: schema.TypeString, + Computed: true, + Description: "The region of the RDS instance.", + }, + "zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The available zone of the RDS instance.", + }, + "db_engine_version": { + Type: schema.TypeString, + Computed: true, + Description: "The engine version of the RDS instance.", + }, + "v_cpu": { + Type: schema.TypeInt, + Computed: true, + Description: "CPU size.", + }, + "memory": { + Type: schema.TypeInt, + Computed: true, + Description: "Memory size.", + }, + "node_spec": { + Type: schema.TypeString, + Computed: true, + Description: "The specification of primary node.", + }, + "node_number": { + Type: schema.TypeInt, + Computed: true, + Description: "The number of nodes.", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: "The create time of the RDS instance.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "The update time of the RDS instance.", + }, + "storage_use": { + Type: schema.TypeInt, + Computed: true, + Description: "The instance has used storage space. Unit: GB.", + }, + "backup_use": { + Type: schema.TypeInt, + Computed: true, + Description: "The instance has used backup space. Unit: GB.", + }, + "storage_space": { + Type: schema.TypeInt, + Computed: true, + Description: "Total instance storage space. Unit: GB.", + }, + "storage_type": { + Type: schema.TypeString, + Computed: true, + Description: "Instance storage type.", + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + Description: "The vpc ID of the RDS instance.", + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + Description: "The subnet ID of the RDS instance.", + }, + "time_zone": { + Type: schema.TypeString, + Computed: true, + Description: "Time zone.", + }, + "lower_case_table_names": { + Type: schema.TypeString, + Computed: true, + Description: "Whether the table name is case sensitive, the default value is 1.\nRanges:\n0: Table names are stored as fixed and table names are case-sensitive.\n1: Table names will be stored in lowercase and table names are not case sensitive.", + }, + "data_sync_mode": { + Type: schema.TypeString, + Computed: true, + Description: "Data synchronization mode.", + }, + "allow_list_version": { + Type: schema.TypeString, + Computed: true, + Description: "The version of allow list.", + }, + "charge_detail": { + Type: schema.TypeList, + Computed: true, + MaxItems: 1, + MinItems: 1, + Description: "Payment methods.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "Payment type. Value:\nPostPaid - Pay-As-You-Go\nPrePaid - Yearly and monthly (default).", + }, + "auto_renew": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether to automatically renew in prepaid scenarios.\nAutorenew_Enable\nAutorenew_Disable (default).", + }, + "period_unit": { + Type: schema.TypeString, + Computed: true, + Description: "The purchase cycle in the prepaid scenario.\nMonth - monthly subscription (default)\nYear - Package year.", + }, + "period": { + Type: schema.TypeInt, + Computed: true, + Description: "Purchase duration in prepaid scenarios. Default: 1.", + }, + "charge_status": { + Type: schema.TypeString, + Computed: true, + Description: "Pay status. Value:\nnormal - normal\noverdue - overdue\n.", + }, + "charge_start_time": { + Type: schema.TypeString, + Computed: true, + Description: "Billing start time (pay-as-you-go & monthly subscription).", + }, + "charge_end_time": { + Type: schema.TypeString, + Computed: true, + Description: "Billing expiry time (yearly and monthly only).", + }, + "overdue_time": { + Type: schema.TypeString, + Computed: true, + Description: "Shutdown time in arrears (pay-as-you-go & monthly subscription).", + }, + "overdue_reclaim_time": { + Type: schema.TypeString, + Computed: true, + Description: "Estimated release time when arrears are closed (pay-as-you-go & monthly subscription).", + }, + }, + }, + }, + "maintenance_window": { + Type: schema.TypeList, + Computed: true, + Description: "Maintenance Window.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "maintenance_time": { + Type: schema.TypeString, + Computed: true, + Description: "The maintainable time of the RDS instance.", + }, + "day_kind": { + Type: schema.TypeString, + Computed: true, + Description: "DayKind of maintainable window. Value: Week. Month.", + }, + "day_of_week": { + Type: schema.TypeList, + Computed: true, + Description: "Days of maintainable window of the week.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "day_of_month": { + Type: schema.TypeList, + Computed: true, + Description: "Days of maintainable window of the month.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "endpoints": { + Type: schema.TypeList, + Computed: true, + Description: "The endpoint info of the RDS instance.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "endpoint_id": { + Type: schema.TypeString, + Computed: true, + Description: "Instance connection terminal ID.", + }, + "endpoint_name": { + Type: schema.TypeString, + Computed: true, + Description: "The instance connection terminal name.", + }, + "endpoint_type": { + Type: schema.TypeString, + Computed: true, + Description: "Terminal type:\nCluster: The default terminal. (created by default)\nPrimary: Primary node terminal.\nCustom: Custom terminal.\nDirect: Direct connection to the terminal. (Only the operation and maintenance side)\nAllNode: All node terminals. (Only the operation and maintenance side).", + }, + "read_write_mode": { + Type: schema.TypeString, + Computed: true, + Description: "Read and write mode:\nReadWrite: read and write\nReadOnly: read only (default).", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "Address description.", + }, + "auto_add_new_nodes": { + Type: schema.TypeString, + Computed: true, + Description: "When the terminal type is read-write terminal or read-only terminal, it supports setting whether new nodes are automatically added.", + }, + "enable_read_write_splitting": { + Type: schema.TypeString, + Computed: true, + Description: "Whether read-write separation is enabled, value: Enable: Enable. Disable: Disabled.", + }, + "enable_read_only": { + Type: schema.TypeString, + Computed: true, + Description: "Whether global read-only is enabled, value: Enable: Enable. Disable: Disabled.", + }, + "node_weight": { + Type: schema.TypeList, + Computed: true, + Description: "The list of nodes configured by the connection terminal and the corresponding read-only weights.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the node.", + }, + "node_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the node.", + }, + "weight": { + Type: schema.TypeInt, + Computed: true, + Description: "The weight of the node.", + }, + }, + }, + }, + "addresses": { + Type: schema.TypeList, + Computed: true, + Description: "Address list.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_type": { + Type: schema.TypeString, + Computed: true, + Description: "Network address type, temporarily Private, Public, PublicService.", + }, + "domain": { + Type: schema.TypeString, + Computed: true, + Description: "Connect domain name.", + }, + "ip_address": { + Type: schema.TypeString, + Computed: true, + Description: "The IP Address.", + }, + "port": { + Type: schema.TypeString, + Computed: true, + Description: "The Port.", + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + Description: "Subnet ID, valid only for private addresses.", + }, + "eip_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the EIP, only valid for Public addresses.", + }, + "dns_visibility": { + Type: schema.TypeBool, + Computed: true, + Description: "DNS Visibility.", + }, + }, + }, + }, + }, + }, + }, + "nodes": { + Type: schema.TypeList, + Computed: true, + Description: "Instance node information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "Instance ID.", + }, + "node_id": { + Type: schema.TypeString, + Computed: true, + Description: "Node ID.", + }, + "region_id": { + Type: schema.TypeString, + Computed: true, + Description: "Region ID, you can call the DescribeRegions query and use this parameter to specify the region where the instance is to be created.", + }, + "zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "Availability zone ID. Subsequent support for multi-availability zones can be separated and displayed by an English colon.", + }, + "node_type": { + Type: schema.TypeString, + Computed: true, + Description: "Node type. Value: Primary: Primary node.\nSecondary: Standby node.\nReadOnly: Read-only node.", + }, + "node_status": { + Type: schema.TypeString, + Computed: true, + Description: "Node state, value: aligned with instance state.", + }, + "node_spec": { + Type: schema.TypeString, + Computed: true, + Description: "General instance type, different from Custom instance type.", + }, + "v_cpu": { + Type: schema.TypeInt, + Computed: true, + Description: "CPU size. For example: 1 means 1U.", + }, + "memory": { + Type: schema.TypeInt, + Computed: true, + Description: "Memory size in GB.", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: "Node creation local time.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "Node updates local time.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineRdsMysqlInstancesRead(d *schema.ResourceData, meta interface{}) error { + rdsMysqlInstanceService := NewRdsMysqlInstanceService(meta.(*ve.SdkClient)) + return rdsMysqlInstanceService.Dispatcher.Data(rdsMysqlInstanceService, d, DataSourceVolcengineRdsMysqlInstances()) +} diff --git a/volcengine/rds_mysql/rds_mysql_instance/resource_volcengine_rds_mysql_instance.go b/volcengine/rds_mysql/rds_mysql_instance/resource_volcengine_rds_mysql_instance.go new file mode 100644 index 00000000..04b2aacb --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance/resource_volcengine_rds_mysql_instance.go @@ -0,0 +1,207 @@ +package rds_mysql_instance + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Rds Mysql Instance can be imported using the id, e.g. +``` +$ terraform import volcengine_rds_mysql_instance.default mysql-72da4258c2c7 +``` + +*/ + +func ResourceVolcengineRdsMysqlInstance() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineRdsMysqlInstanceCreate, + Read: resourceVolcengineRdsMysqlInstanceRead, + Update: resourceVolcengineRdsMysqlInstanceUpdate, + Delete: resourceVolcengineRdsMysqlInstanceDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(1 * time.Hour), + Update: schema.DefaultTimeout(1 * time.Hour), + Delete: schema.DefaultTimeout(1 * time.Hour), + }, + Schema: map[string]*schema.Schema{ + "db_engine_version": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Instance type. Value:\nMySQL_5_7\nMySQL_8_0.", + ValidateFunc: validation.StringInSlice([]string{"MySQL_5_7", "MySQL_8_0"}, false), + }, + "node_spec": { + Type: schema.TypeString, + Required: true, + Description: "The specification of primary node and secondary node.", + }, + "primary_zone_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The available zone of primary node.", + }, + "secondary_zone_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The available zone of secondary node.", + }, + "storage_space": { + Type: schema.TypeInt, + Optional: true, + Default: 100, + Description: "Instance storage space. Value range: [20, 3000], unit: GB, increments every 100GB. Default value: 100.", + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Subnet ID of the RDS instance.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + Description: "Instance name. Cannot start with a number or a dash\nCan only contain Chinese characters, letters, numbers, underscores and dashes\nThe length is limited between 1 ~ 128.", + }, + "lower_case_table_names": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "Whether the table name is case sensitive, the default value is 1.\nRanges:\n0: Table names are stored as fixed and table names are case-sensitive.\n1: Table names will be stored in lowercase and table names are not case sensitive.", + }, + "db_time_zone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Time zone. Support UTC -12:00 ~ +13:00. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", + }, + "charge_info": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: "Payment methods.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "charge_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "PostPaid", + "PrePaid", + }, false), + Description: "Payment type. Value:\nPostPaid - Pay-As-You-Go\nPrePaid - Yearly and monthly (default).", + }, + "auto_renew": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: RdsMysqlInstanceImportDiffSuppress, + Description: "Whether to automatically renew in prepaid scenarios.", + }, + "period_unit": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: RdsMysqlInstanceImportDiffSuppress, + Description: "The purchase cycle in the prepaid scenario.\nMonth - monthly subscription (default)\nYear - Package year.", + }, + "period": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: RdsMysqlInstanceImportDiffSuppress, + Description: "Purchase duration in prepaid scenarios. Default: 1.", + }, + }, + }, + }, + "allow_list_ids": { + Type: schema.TypeSet, + Optional: true, + Set: schema.HashString, + Description: "Allow list Ids of the RDS instance.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "parameters": { + Type: schema.TypeSet, + Optional: true, + Set: parameterHash, + Description: "Parameter of the RDS instance. This field can only be added or modified. Deleting this field is invalid.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "parameter_name": { + Type: schema.TypeString, + Required: true, + Description: "Parameter name.", + }, + "parameter_value": { + Type: schema.TypeString, + Required: true, + Description: "Parameter value.", + }, + }, + }, + }, + }, + } + dataSource := DataSourceVolcengineRdsMysqlInstances().Schema["rds_mysql_instances"].Elem.(*schema.Resource).Schema + delete(dataSource, "id") + ve.MergeDateSourceToResource(dataSource, &resource.Schema) + return resource +} + +func resourceVolcengineRdsMysqlInstanceCreate(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceService := NewRdsMysqlInstanceService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceService.Dispatcher.Create(rdsMysqlInstanceService, d, ResourceVolcengineRdsMysqlInstance()) + if err != nil { + return fmt.Errorf("error on creating RDS mysql instance %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlInstanceRead(d, meta) +} + +func resourceVolcengineRdsMysqlInstanceRead(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceService := NewRdsMysqlInstanceService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceService.Dispatcher.Read(rdsMysqlInstanceService, d, ResourceVolcengineRdsMysqlInstance()) + if err != nil { + return fmt.Errorf("error on reading RDS mysql instance %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlInstanceUpdate(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceService := NewRdsMysqlInstanceService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceService.Dispatcher.Update(rdsMysqlInstanceService, d, ResourceVolcengineRdsMysqlInstance()) + if err != nil { + return fmt.Errorf("error on updating RDS mysql instance %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlInstanceRead(d, meta) +} + +func resourceVolcengineRdsMysqlInstanceDelete(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceService := NewRdsMysqlInstanceService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceService.Dispatcher.Delete(rdsMysqlInstanceService, d, ResourceVolcengineRdsMysqlInstance()) + if err != nil { + return fmt.Errorf("error on deleting RDS mysql instance %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go b/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go new file mode 100644 index 00000000..33189fc3 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go @@ -0,0 +1,741 @@ +package rds_mysql_instance + +import ( + "errors" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineRdsMysqlInstanceService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewRdsMysqlInstanceService(c *ve.SdkClient) *VolcengineRdsMysqlInstanceService { + return &VolcengineRdsMysqlInstanceService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineRdsMysqlInstanceService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlInstanceService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + rdsInstance map[string]interface{} + ) + data, err = ve.WithPageNumberQuery(m, "PageSize", "PageNumber", 10, 1, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeDBInstances" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + + results, err = ve.ObtainSdkValue("Result.Instances", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Instances is not Slice") + } + return data, err + }) + + if err != nil { + return nil, err + } + + for _, v := range data { + if rdsInstance, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } else { + // query rds instance detail + instanceDetailInfo, err := s.Client.UniversalClient.DoCall(getUniversalInfo("DescribeDBInstanceDetail"), &map[string]interface{}{ + "InstanceId": rdsInstance["InstanceId"], + }) + if err != nil { + logger.Info("DescribeDBInstanceDetail error:", err) + continue + } + + // 1. basic info + basicInfo, err := ve.ObtainSdkValue("Result.BasicInfo", *instanceDetailInfo) + if err != nil { + logger.Info("ObtainSdkValue Result.BasicInfo error:", err) + continue + } + if basicInfoMap, ok := basicInfo.(map[string]interface{}); ok { + rdsInstance["VCpu"] = basicInfoMap["VCPU"] + rdsInstance["Memory"] = basicInfoMap["Memory"] + rdsInstance["UpdateTime"] = basicInfoMap["UpdateTime"] + rdsInstance["BackupUse"] = basicInfoMap["BackupUse"] + rdsInstance["DataSyncMode"] = basicInfoMap["DataSyncMode"] + } + + // 2. endpoint info + endpoints, err := ve.ObtainSdkValue("Result.Endpoints", *instanceDetailInfo) + if err != nil { + logger.Info("ObtainSdkValue Result.Endpoints error:", err) + continue + } + for _, v1 := range endpoints.([]interface{}) { + if endpoint, ok := v1.(map[string]interface{}); ok { + endpoint["Addresses"] = convertAddressInfo(endpoint["Addresses"]) + endpoint["NodeWeight"] = endpoint["ReadOnlyNodeWeight"] + delete(endpoint, "ReadOnlyNodeWeight") + } + } + rdsInstance["Endpoints"] = endpoints + + // 3. node info + nodes, err := ve.ObtainSdkValue("Result.Nodes", *instanceDetailInfo) + if err != nil { + logger.Info("ObtainSdkValue Result.Nodes error:", err) + continue + } + for _, v2 := range nodes.([]interface{}) { + if node, ok := v2.(map[string]interface{}); ok { + node["VCpu"] = node["VCPU"] + delete(node, "VCPU") + } + } + rdsInstance["Nodes"] = nodes + } + } + + return data, err +} + +func (s *VolcengineRdsMysqlInstanceService) ReadResource(resourceData *schema.ResourceData, rdsInstanceId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if rdsInstanceId == "" { + rdsInstanceId = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "InstanceId": rdsInstanceId, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("Rds instance %s not exist ", rdsInstanceId) + } + + if nodeArr, ok := data["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeType"] == "Primary" { + data["PrimaryZoneId"] = nodeMap["ZoneId"] + } else if nodeMap["NodeType"] == "Secondary" { + data["SecondaryZoneId"] = nodeMap["ZoneId"] + } + } + } + } + + data["ChargeInfo"] = data["ChargeDetail"] + + return data, err +} + +func (s *VolcengineRdsMysqlInstanceService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + demo map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Error") + + if err = resource.Retry(20*time.Minute, func() *resource.RetryError { + demo, err = s.ReadResource(resourceData, id) + if err != nil { + if ve.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(err) + } + } + return nil + }); err != nil { + return nil, "", err + } + + status, err = ve.ObtainSdkValue("InstanceStatus", demo) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("Rds instance status error, status:%s ", status.(string)) + } + } + //注意 返回的第一个参数不能为空 否则会一直等下去 + return demo, status.(string), err + }, + } + +} + +func (*VolcengineRdsMysqlInstanceService) WithResourceResponseHandlers(rdsInstance map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return rdsInstance, map[string]ve.ResponseConvert{ + "DBEngineVersion": { + TargetField: "db_engine_version", + }, + "TimeZone": { + TargetField: "db_time_zone", + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} + +} + +func (s *VolcengineRdsMysqlInstanceService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + instanceCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDBInstance", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "db_engine_version": { + TargetField: "DBEngineVersion", + }, + "storage_space": { + TargetField: "StorageSpace", + }, + "subnet_id": { + TargetField: "SubnetId", + }, + "instance_name": { + TargetField: "InstanceName", + }, + "lower_case_table_names": { + TargetField: "LowerCaseTableNames", + }, + "db_time_zone": { + TargetField: "DBTimeZone", + }, + "charge_info": { + ConvertType: ve.ConvertJsonObject, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + var ( + nodeInfos []interface{} + subnets []interface{} + results interface{} + ok bool + ) + + // 1. NodeInfo + primaryNodeInfo := make(map[string]interface{}) + primaryNodeInfo["NodeType"] = "Primary" + primaryNodeInfo["ZoneId"] = d.Get("primary_zone_id") + primaryNodeInfo["NodeSpec"] = d.Get("node_spec") + nodeInfos = append(nodeInfos, primaryNodeInfo) + + secondaryNodeInfo := make(map[string]interface{}) + secondaryNodeInfo["NodeType"] = "Secondary" + secondaryNodeInfo["ZoneId"] = d.Get("secondary_zone_id") + secondaryNodeInfo["NodeSpec"] = d.Get("node_spec") + nodeInfos = append(nodeInfos, secondaryNodeInfo) + + // 2. VpcId + subnetId := d.Get("subnet_id") + req := map[string]interface{}{ + "SubnetIds.1": subnetId, + } + action := "DescribeSubnets" + resp, err := s.Client.VpcClient.DescribeSubnetsCommon(&req) + if err != nil { + return false, err + } + logger.Debug(logger.RespFormat, action, req, *resp) + results, err = ve.ObtainSdkValue("Result.Subnets", *resp) + if err != nil { + return false, err + } + if results == nil { + results = []interface{}{} + } + if subnets, ok = results.([]interface{}); !ok { + return false, errors.New("Result.Subnets is not Slice") + } + if len(subnets) == 0 { + return false, fmt.Errorf("subnet %s not exist", subnetId.(string)) + } + vpcId := subnets[0].(map[string]interface{})["VpcId"] + + (*call.SdkParam)["NodeInfo"] = nodeInfos + (*call.SdkParam)["StorageType"] = "LocalSSD" + (*call.SdkParam)["VpcId"] = vpcId + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //创建rdsInstance + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + //注意 获取内容 这个地方不能是指针 需要转一次 + id, _ := ve.ObtainSdkValue("Result.InstanceId", *resp) + d.SetId(id.(string)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, instanceCallback) + + // 关联白名单 + allowListCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AssociateAllowList", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "allow_list_ids": { + ConvertType: ve.ConvertJsonArray, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{d.Id()} + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, allowListCallback) + + // 关联参数 + parameterCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceParameters", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "parameters": { + ConvertType: ve.ConvertJsonObjectArray, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["InstanceId"] = d.Id() + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, parameterCallback) + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + // 1. NodeSpec & StorageSpace + if resourceData.HasChanges("node_spec", "storage_space") { + instanceCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceSpec", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Id() + + if d.HasChange("storage_space") { + (*call.SdkParam)["StorageType"] = "LocalSSD" + (*call.SdkParam)["StorageSpace"] = d.Get("storage_space") + } + + if d.HasChange("node_spec") { + nodeInfos := make([]interface{}, 0) + primaryNodeInfo := make(map[string]interface{}) + secondaryNodeInfo := make(map[string]interface{}) + + instance, err := s.ReadResource(resourceData, d.Id()) + if err != nil { + return false, err + } + if nodeArr, ok := instance["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeType"] == "Primary" { + primaryNodeInfo["NodeId"] = nodeMap["NodeId"] + } else if nodeMap["NodeType"] == "Secondary" { + secondaryNodeInfo["NodeId"] = nodeMap["NodeId"] + } else if nodeMap["NodeType"] == "ReadOnly" { + readonlyNodeInfo := make(map[string]interface{}) + readonlyNodeInfo["NodeId"] = nodeMap["NodeId"] + readonlyNodeInfo["NodeType"] = nodeMap["NodeType"] + readonlyNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + readonlyNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, readonlyNodeInfo) + } + } + } + } + + primaryNodeInfo["NodeType"] = "Primary" + primaryNodeInfo["ZoneId"] = d.Get("primary_zone_id") + primaryNodeInfo["NodeSpec"] = d.Get("node_spec") + primaryNodeInfo["NodeOperateType"] = "Modify" + nodeInfos = append(nodeInfos, primaryNodeInfo) + + secondaryNodeInfo["NodeType"] = "Secondary" + secondaryNodeInfo["ZoneId"] = d.Get("secondary_zone_id") + secondaryNodeInfo["NodeSpec"] = d.Get("node_spec") + secondaryNodeInfo["NodeOperateType"] = "Modify" + nodeInfos = append(nodeInfos, secondaryNodeInfo) + + (*call.SdkParam)["NodeInfo"] = nodeInfos + } + + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + time.Sleep(10 * time.Second) // modify后如果直接refresh,status不会变为Updating,导致refresh直接结束 + return common, nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + callbacks = append(callbacks, instanceCallback) + } + + // InstanceName + if resourceData.HasChange("instance_name") { + nameCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceName", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "instance_name": { + TargetField: "InstanceNewName", + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["InstanceId"] = d.Id() + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + return common, nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + callbacks = append(callbacks, nameCallback) + } + + // AllowList + if resourceData.HasChange("allow_list_ids") { + addAlIds, removeAlIds, _, _ := ve.GetSetDifference("allow_list_ids", resourceData, schema.HashString, false) + + allowListRemoveCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DisassociateAllowList", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if removeAlIds != nil && len(removeAlIds.List()) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{d.Id()} + (*call.SdkParam)["AllowListIds"] = removeAlIds.List() + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + return common, nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + callbacks = append(callbacks, allowListRemoveCallback) + + allowListAddCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AssociateAllowList", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if addAlIds != nil && len(addAlIds.List()) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{d.Id()} + (*call.SdkParam)["AllowListIds"] = addAlIds.List() + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + return common, nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + callbacks = append(callbacks, allowListAddCallback) + } + + // Parameters + if resourceData.HasChange("parameters") { + parameterCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceParameters", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "parameters": { + ConvertType: ve.ConvertJsonObjectArray, + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["InstanceId"] = d.Id() + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + + callbacks = append(callbacks, parameterCallback) + } + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + // 1. Disassociate Allow List + allowListCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DisassociateAllowList", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "allow_list_ids": { + ConvertType: ve.ConvertJsonArray, + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if len(*call.SdkParam) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{d.Id()} + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + }, + }, + } + callbacks = append(callbacks, allowListCallback) + + // 2. delete instance + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDBInstance", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "InstanceId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //删除RdsInstance + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading rds mysql instance on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{ + "db_engine_version": { + TargetField: "DBEngineVersion", + }, + }, + NameField: "InstanceName", + IdField: "InstanceId", + CollectField: "rds_mysql_instances", + ContentType: ve.ContentTypeJson, + ResponseConverts: map[string]ve.ResponseConvert{ + "InstanceId": { + TargetField: "id", + KeepDefault: true, + }, + "DBEngineVersion": { + TargetField: "db_engine_version", + }, + }, + } +} + +func convertAddressInfo(addressesInfo interface{}) interface{} { + if addressesInfo == nil { + return nil + } + var addresses []interface{} + if addressInfoArr, ok := addressesInfo.([]interface{}); ok { + for _, address := range addressInfoArr { + if addressMap, ok := address.(map[string]interface{}); ok { + addressMap["IpAddress"] = addressMap["IPAddress"] + addressMap["DnsVisibility"] = addressMap["DNSVisibility"] + delete(addressMap, "IPAddress") + delete(addressMap, "DNSVisibility") + } + addresses = append(addresses, address) + } + } + + return addresses +} + +func (s *VolcengineRdsMysqlInstanceService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/common_volcengine_rds_mysql_instance_readonly_node.go b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/common_volcengine_rds_mysql_instance_readonly_node.go new file mode 100644 index 00000000..d2594d03 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/common_volcengine_rds_mysql_instance_readonly_node.go @@ -0,0 +1,22 @@ +package rds_mysql_instance_readonly_node + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var rdsMysqlInstanceReadonlyNodeImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("node_id", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/resource_volcengine_rds_mysql_instance_readonly_node.go b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/resource_volcengine_rds_mysql_instance_readonly_node.go new file mode 100644 index 00000000..1eaa1b38 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/resource_volcengine_rds_mysql_instance_readonly_node.go @@ -0,0 +1,96 @@ +package rds_mysql_instance_readonly_node + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Rds Mysql Instance Readonly Node can be imported using the instance_id:node_id, e.g. +``` +$ terraform import volcengine_rds_mysql_instance_readonly_node.default mysql-72da4258c2c7:mysql-72da4258c2c7-r7f93 +``` + +*/ + +func ResourceVolcengineRdsMysqlInstanceReadonlyNode() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineRdsMysqlInstanceReadonlyNodeCreate, + Read: resourceVolcengineRdsMysqlInstanceReadonlyNodeRead, + Update: resourceVolcengineRdsMysqlInstanceReadonlyNodeUpdate, + Delete: resourceVolcengineRdsMysqlInstanceReadonlyNodeDelete, + Importer: &schema.ResourceImporter{ + State: rdsMysqlInstanceReadonlyNodeImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(1 * time.Hour), + Update: schema.DefaultTimeout(1 * time.Hour), + Delete: schema.DefaultTimeout(1 * time.Hour), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The RDS mysql instance id of the readonly node.", + }, + "node_spec": { + Type: schema.TypeString, + Required: true, + Description: "The specification of readonly node.", + }, + "zone_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The available zone of readonly node.", + }, + "node_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the readonly node.", + }, + }, + } +} + +func resourceVolcengineRdsMysqlInstanceReadonlyNodeCreate(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceReadonlyNodeService := NewRdsMysqlInstanceReadonlyNodeService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceReadonlyNodeService.Dispatcher.Create(rdsMysqlInstanceReadonlyNodeService, d, ResourceVolcengineRdsMysqlInstanceReadonlyNode()) + if err != nil { + return fmt.Errorf("error on creating RDS mysql instance readonly node %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlInstanceReadonlyNodeRead(d, meta) +} + +func resourceVolcengineRdsMysqlInstanceReadonlyNodeRead(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceReadonlyNodeService := NewRdsMysqlInstanceReadonlyNodeService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceReadonlyNodeService.Dispatcher.Read(rdsMysqlInstanceReadonlyNodeService, d, ResourceVolcengineRdsMysqlInstanceReadonlyNode()) + if err != nil { + return fmt.Errorf("error on reading RDS mysql instance readonly node %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineRdsMysqlInstanceReadonlyNodeUpdate(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceReadonlyNodeService := NewRdsMysqlInstanceReadonlyNodeService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceReadonlyNodeService.Dispatcher.Update(rdsMysqlInstanceReadonlyNodeService, d, ResourceVolcengineRdsMysqlInstanceReadonlyNode()) + if err != nil { + return fmt.Errorf("error on updating RDS mysql instance readonly node %q, %w", d.Id(), err) + } + return resourceVolcengineRdsMysqlInstanceReadonlyNodeRead(d, meta) +} + +func resourceVolcengineRdsMysqlInstanceReadonlyNodeDelete(d *schema.ResourceData, meta interface{}) (err error) { + rdsMysqlInstanceReadonlyNodeService := NewRdsMysqlInstanceReadonlyNodeService(meta.(*ve.SdkClient)) + err = rdsMysqlInstanceReadonlyNodeService.Dispatcher.Delete(rdsMysqlInstanceReadonlyNodeService, d, ResourceVolcengineRdsMysqlInstanceReadonlyNode()) + if err != nil { + return fmt.Errorf("error on deleting RDS mysql instance readonly node %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go new file mode 100644 index 00000000..b5e09849 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go @@ -0,0 +1,411 @@ +package rds_mysql_instance_readonly_node + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_instance" +) + +type VolcengineRdsMysqlInstanceReadonlyNodeService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher + RdsInstanceService *rds_mysql_instance.VolcengineRdsMysqlInstanceService +} + +func NewRdsMysqlInstanceReadonlyNodeService(c *ve.SdkClient) *VolcengineRdsMysqlInstanceReadonlyNodeService { + return &VolcengineRdsMysqlInstanceReadonlyNodeService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + RdsInstanceService: rds_mysql_instance.NewRdsMysqlInstanceService(c), + } +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + return data, err +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ReadResource(resourceData *schema.ResourceData, rdsInstanceNodeId string) (data map[string]interface{}, err error) { + if rdsInstanceNodeId == "" { + rdsInstanceNodeId = resourceData.Id() + } + + ids := strings.Split(rdsInstanceNodeId, ":") + if len(ids) != 2 { + return map[string]interface{}{}, fmt.Errorf("invalid rdsInstanceNodeId: %s", rdsInstanceNodeId) + } + + instanceId := ids[0] + nodeId := ids[1] + + result, err := s.RdsInstanceService.ReadResource(resourceData, instanceId) + if err != nil { + return result, err + } + if len(result) == 0 { + return result, fmt.Errorf("Rds instance %s not exist ", instanceId) + } + + if nodeArr, ok := result["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeId"] == nodeId { + data = nodeMap + } + } + } + } + data["NodeId"] = nodeId + + return data, err +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return nil +} + +func (*VolcengineRdsMysqlInstanceReadonlyNodeService) WithResourceResponseHandlers(rdsInstance map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return rdsInstance, nil, nil + } + return []ve.ResourceResponseHandler{handler} + +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) CreateResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var ( + callbacks []ve.Callback + existingReadOnlyNodeIds = make(map[string]bool) + ) + + nodeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceSpec", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (common *map[string]interface{}, err error) { + // 在LockId执行后再进行已有Node信息的查询 + (*call.SdkParam)["InstanceId"] = d.Get("instance_id").(string) + + nodeInfos := make([]interface{}, 0) + // 1. 获取当前RdsInstance已有的Node信息 + instance, err := s.RdsInstanceService.ReadResource(resourceData, d.Get("instance_id").(string)) + if err != nil { + return common, err + } + if nodeArr, ok := instance["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeType"] == "Primary" { + primaryNodeInfo := make(map[string]interface{}) + primaryNodeInfo["NodeId"] = nodeMap["NodeId"] + primaryNodeInfo["NodeType"] = nodeMap["NodeType"] + primaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + primaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, primaryNodeInfo) + } else if nodeMap["NodeType"] == "Secondary" { + secondaryNodeInfo := make(map[string]interface{}) + secondaryNodeInfo["NodeId"] = nodeMap["NodeId"] + secondaryNodeInfo["NodeType"] = nodeMap["NodeType"] + secondaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + secondaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, secondaryNodeInfo) + } else if nodeMap["NodeType"] == "ReadOnly" { + readonlyNodeInfo := make(map[string]interface{}) + readonlyNodeInfo["NodeId"] = nodeMap["NodeId"] + readonlyNodeInfo["NodeType"] = nodeMap["NodeType"] + readonlyNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + readonlyNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, readonlyNodeInfo) + + existingReadOnlyNodeIds[readonlyNodeInfo["NodeId"].(string)] = true + } + } + } + } + + // 2. 新增 readonly node + newReadonlyNodeInfo := make(map[string]interface{}) + newReadonlyNodeInfo["NodeType"] = "ReadOnly" + newReadonlyNodeInfo["NodeSpec"] = d.Get("node_spec") + newReadonlyNodeInfo["ZoneId"] = d.Get("zone_id") + newReadonlyNodeInfo["NodeOperateType"] = "Create" + nodeInfos = append(nodeInfos, newReadonlyNodeInfo) + + (*call.SdkParam)["NodeInfo"] = nodeInfos + + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err = s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + time.Sleep(10 * time.Second) // 新增只读节点后,需要等一下 + return common, nil + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + var ( + instance = make(map[string]interface{}) + err error + ) + // 通过retry确保获取当前新建只读节点的Id + resource.Retry(15*time.Minute, func() *resource.RetryError { + instance, err = s.RdsInstanceService.ReadResource(d, d.Get("instance_id").(string)) + if err != nil { + if ve.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading rds instance %q", d.Get("instance_id"))) + } + } + status, err := ve.ObtainSdkValue("InstanceStatus", instance) + if err != nil { + return resource.RetryableError(err) + } + if status.(string) != "Running" { + return resource.RetryableError(fmt.Errorf("rds instance is still in updating")) + } + return nil + }) + logger.Debug(logger.ReqFormat, "testReadonly", instance) + var newReadonlyNodeId string + if nodeArr, ok := instance["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + logger.Debug(logger.ReqFormat, "existingReadOnlyNodeIds", existingReadOnlyNodeIds) + if nodeMap["NodeType"] == "ReadOnly" { + if _, ok := existingReadOnlyNodeIds[nodeMap["NodeId"].(string)]; !ok { + newReadonlyNodeId = nodeMap["NodeId"].(string) + } + } + } + } + } + // ResourceData中,rds_mysql_instance_readonly_node的Id形式为'instance_id:node_id' + logger.Debug(logger.ReqFormat, "newReadonlyNodeId", newReadonlyNodeId) + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), newReadonlyNodeId) + d.SetId(id) + return nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + s.RdsInstanceService: { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + callbacks = append(callbacks, nodeCallback) + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + if resourceData.HasChange("node_spec") { + nodeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceSpec", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (common *map[string]interface{}, err error) { + // 在 LockId 后再进行已有 Node 信息的查询 + ids := strings.Split(d.Id(), ":") + if len(ids) != 2 { + return common, fmt.Errorf("invalid rdsInstanceNodeId: %s", d.Id()) + } + instanceId := ids[0] + nodeId := ids[1] + (*call.SdkParam)["InstanceId"] = instanceId + + nodeInfos := make([]interface{}, 0) + // 1. 获取当前RdsInstance已有的Node信息 + instance, err := s.RdsInstanceService.ReadResource(resourceData, d.Get("instance_id").(string)) + if err != nil { + return common, err + } + if nodeArr, ok := instance["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeType"] == "Primary" { + primaryNodeInfo := make(map[string]interface{}) + primaryNodeInfo["NodeId"] = nodeMap["NodeId"] + primaryNodeInfo["NodeType"] = nodeMap["NodeType"] + primaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + primaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, primaryNodeInfo) + } else if nodeMap["NodeType"] == "Secondary" { + secondaryNodeInfo := make(map[string]interface{}) + secondaryNodeInfo["NodeId"] = nodeMap["NodeId"] + secondaryNodeInfo["NodeType"] = nodeMap["NodeType"] + secondaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + secondaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, secondaryNodeInfo) + } else if nodeMap["NodeType"] == "ReadOnly" && nodeMap["NodeId"] != nodeId { + readonlyNodeInfo := make(map[string]interface{}) + readonlyNodeInfo["NodeId"] = nodeMap["NodeId"] + readonlyNodeInfo["NodeType"] = nodeMap["NodeType"] + readonlyNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + readonlyNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, readonlyNodeInfo) + } + } + } + } + + // 2. 修改当前 readonly node + newReadonlyNodeInfo := make(map[string]interface{}) + newReadonlyNodeInfo["NodeId"] = nodeId + newReadonlyNodeInfo["NodeType"] = "ReadOnly" + newReadonlyNodeInfo["NodeSpec"] = d.Get("node_spec") + newReadonlyNodeInfo["ZoneId"] = d.Get("zone_id") + newReadonlyNodeInfo["NodeOperateType"] = "Modify" + nodeInfos = append(nodeInfos, newReadonlyNodeInfo) + + (*call.SdkParam)["NodeInfo"] = nodeInfos + + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err = s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + time.Sleep(10 * time.Second) // 修改只读节点后,需要等一下 + return common, nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + s.RdsInstanceService: { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutUpdate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + callbacks = append(callbacks, nodeCallback) + } + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + nodeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceSpec", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (common *map[string]interface{}, err error) { + // 在 LockId 后再进行已有 Node 信息的查询 + ids := strings.Split(d.Id(), ":") + if len(ids) != 2 { + return common, fmt.Errorf("invalid rdsInstanceNodeId: %s", d.Id()) + } + instanceId := ids[0] + nodeId := ids[1] + (*call.SdkParam)["InstanceId"] = instanceId + + nodeInfos := make([]interface{}, 0) + // 1. 获取当前RdsInstance已有的Node信息 + instance, err := s.RdsInstanceService.ReadResource(resourceData, d.Get("instance_id").(string)) + if err != nil { + return common, err + } + if nodeArr, ok := instance["Nodes"].([]interface{}); ok { + for _, node := range nodeArr { + if nodeMap, ok1 := node.(map[string]interface{}); ok1 { + if nodeMap["NodeType"] == "Primary" { + primaryNodeInfo := make(map[string]interface{}) + primaryNodeInfo["NodeId"] = nodeMap["NodeId"] + primaryNodeInfo["NodeType"] = nodeMap["NodeType"] + primaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + primaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, primaryNodeInfo) + } else if nodeMap["NodeType"] == "Secondary" { + secondaryNodeInfo := make(map[string]interface{}) + secondaryNodeInfo["NodeId"] = nodeMap["NodeId"] + secondaryNodeInfo["NodeType"] = nodeMap["NodeType"] + secondaryNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + secondaryNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, secondaryNodeInfo) + } else if nodeMap["NodeType"] == "ReadOnly" && nodeMap["NodeId"] != nodeId { + readonlyNodeInfo := make(map[string]interface{}) + readonlyNodeInfo["NodeId"] = nodeMap["NodeId"] + readonlyNodeInfo["NodeType"] = nodeMap["NodeType"] + readonlyNodeInfo["NodeSpec"] = nodeMap["NodeSpec"] + readonlyNodeInfo["ZoneId"] = nodeMap["ZoneId"] + nodeInfos = append(nodeInfos, readonlyNodeInfo) + } + } + } + } + + // 2. 删除 readonly node + newReadonlyNodeInfo := make(map[string]interface{}) + newReadonlyNodeInfo["NodeId"] = nodeId + newReadonlyNodeInfo["NodeType"] = "ReadOnly" + newReadonlyNodeInfo["NodeSpec"] = d.Get("node_spec") + newReadonlyNodeInfo["ZoneId"] = d.Get("zone_id") + newReadonlyNodeInfo["NodeOperateType"] = "Delete" + nodeInfos = append(nodeInfos, newReadonlyNodeInfo) + + (*call.SdkParam)["NodeInfo"] = nodeInfos + + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + common, err = s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + if err != nil { + return common, err + } + time.Sleep(10 * time.Second) // 删除只读节点后,需要等一下 + return common, nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + s.RdsInstanceService: { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + callbacks = append(callbacks, nodeCallback) + + return callbacks +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{} +} + +func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "rds_mysql", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/website/docs/d/rds_mysql_accounts.html.markdown b/website/docs/d/rds_mysql_accounts.html.markdown new file mode 100644 index 00000000..1f7e0dab --- /dev/null +++ b/website/docs/d/rds_mysql_accounts.html.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_accounts" +sidebar_current: "docs-volcengine-datasource-rds_mysql_accounts" +description: |- + Use this data source to query detailed information of rds mysql accounts +--- +# volcengine_rds_mysql_accounts +Use this data source to query detailed information of rds mysql accounts +## Example Usage +```hcl +data "volcengine_rds_mysql_accounts" "default" { + instance_id = "" + account_name = "" +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The id of the RDS instance. +* `account_name` - (Optional) The name of the database account. +* `name_regex` - (Optional) A Name Regex of database account. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `accounts` - The collection of RDS instance account query. + * `account_name` - The name of the database account. + * `account_privileges` - The privilege detail list of RDS mysql instance account. + * `account_privilege_detail` - The privilege detail of the account. + * `account_privilege` - The privilege type of the account. + * `db_name` - The name of database. + * `account_status` - The status of the database account. + * `account_type` - The type of the database account. + * `id` - The ID of the RDS instance account. +* `total_count` - The total count of database account query. + + diff --git a/website/docs/d/rds_mysql_allowlists.html.markdown b/website/docs/d/rds_mysql_allowlists.html.markdown new file mode 100644 index 00000000..ba300f08 --- /dev/null +++ b/website/docs/d/rds_mysql_allowlists.html.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_allowlists" +sidebar_current: "docs-volcengine-datasource-rds_mysql_allowlists" +description: |- + Use this data source to query detailed information of rds mysql allowlists +--- +# volcengine_rds_mysql_allowlists +Use this data source to query detailed information of rds mysql allowlists +## Example Usage +```hcl +data "volcengine_rds_mysql_allowlists" "default" { + region_id = "cn-guilin-boe" +} +``` +## Argument Reference +The following arguments are supported: +* `region_id` - (Required) The region of the allow lists. +* `instance_id` - (Optional) Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `allow_lists` - The list of allowed list. + * `allow_list_desc` - The description of the allow list. + * `allow_list_id` - The id of the allow list. + * `allow_list_ip_num` - The total number of IP addresses (or address ranges) in the whitelist. + * `allow_list_name` - The name of the allow list. + * `allow_list_type` - The type of the allow list. + * `associated_instance_num` - The total number of instances bound under the whitelist. + * `associated_instances` - The list of instances. + * `instance_id` - The id of the instance. + * `instance_name` - The name of the instance. + * `vpc` - The id of the vpc. +* `total_count` - The total count of Scaling Activity query. + + diff --git a/website/docs/d/rds_mysql_instances.html.markdown b/website/docs/d/rds_mysql_instances.html.markdown new file mode 100644 index 00000000..12b92fb8 --- /dev/null +++ b/website/docs/d/rds_mysql_instances.html.markdown @@ -0,0 +1,127 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_instances" +sidebar_current: "docs-volcengine-datasource-rds_mysql_instances" +description: |- + Use this data source to query detailed information of rds mysql instances +--- +# volcengine_rds_mysql_instances +Use this data source to query detailed information of rds mysql instances +## Example Usage +```hcl +data "volcengine_rds_mysql_instances" "default" { + instance_id = "mysql-72da4258c2c7" +} +``` +## Argument Reference +The following arguments are supported: +* `charge_type` - (Optional) The charge type of the RDS instance. +* `create_time_end` - (Optional) The end time of creating RDS instance. +* `create_time_start` - (Optional) The start time of creating RDS instance. +* `db_engine_version` - (Optional) The version of the RDS instance. +* `instance_id` - (Optional) The id of the RDS instance. +* `instance_name` - (Optional) The name of the RDS instance. +* `instance_status` - (Optional) The status of the RDS instance. +* `name_regex` - (Optional) A Name Regex of RDS instance. +* `output_file` - (Optional) File name where to save data source results. +* `zone_id` - (Optional) The available zone of the RDS instance. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `rds_mysql_instances` - The collection of RDS instance query. + * `allow_list_version` - The version of allow list. + * `backup_use` - The instance has used backup space. Unit: GB. + * `charge_detail` - Payment methods. + * `auto_renew` - Whether to automatically renew in prepaid scenarios. +Autorenew_Enable +Autorenew_Disable (default). + * `charge_end_time` - Billing expiry time (yearly and monthly only). + * `charge_start_time` - Billing start time (pay-as-you-go & monthly subscription). + * `charge_status` - Pay status. Value: +normal - normal +overdue - overdue +. + * `charge_type` - Payment type. Value: +PostPaid - Pay-As-You-Go +PrePaid - Yearly and monthly (default). + * `overdue_reclaim_time` - Estimated release time when arrears are closed (pay-as-you-go & monthly subscription). + * `overdue_time` - Shutdown time in arrears (pay-as-you-go & monthly subscription). + * `period_unit` - The purchase cycle in the prepaid scenario. +Month - monthly subscription (default) +Year - Package year. + * `period` - Purchase duration in prepaid scenarios. Default: 1. + * `create_time` - The create time of the RDS instance. + * `data_sync_mode` - Data synchronization mode. + * `db_engine_version` - The engine version of the RDS instance. + * `endpoints` - The endpoint info of the RDS instance. + * `addresses` - Address list. + * `dns_visibility` - DNS Visibility. + * `domain` - Connect domain name. + * `eip_id` - The ID of the EIP, only valid for Public addresses. + * `ip_address` - The IP Address. + * `network_type` - Network address type, temporarily Private, Public, PublicService. + * `port` - The Port. + * `subnet_id` - Subnet ID, valid only for private addresses. + * `auto_add_new_nodes` - When the terminal type is read-write terminal or read-only terminal, it supports setting whether new nodes are automatically added. + * `description` - Address description. + * `enable_read_only` - Whether global read-only is enabled, value: Enable: Enable. Disable: Disabled. + * `enable_read_write_splitting` - Whether read-write separation is enabled, value: Enable: Enable. Disable: Disabled. + * `endpoint_id` - Instance connection terminal ID. + * `endpoint_name` - The instance connection terminal name. + * `endpoint_type` - Terminal type: +Cluster: The default terminal. (created by default) +Primary: Primary node terminal. +Custom: Custom terminal. +Direct: Direct connection to the terminal. (Only the operation and maintenance side) +AllNode: All node terminals. (Only the operation and maintenance side). + * `node_weight` - The list of nodes configured by the connection terminal and the corresponding read-only weights. + * `node_id` - The ID of the node. + * `node_type` - The type of the node. + * `weight` - The weight of the node. + * `read_write_mode` - Read and write mode: +ReadWrite: read and write +ReadOnly: read only (default). + * `id` - The ID of the RDS instance. + * `instance_id` - The ID of the RDS instance. + * `instance_name` - The name of the RDS instance. + * `instance_status` - The status of the RDS instance. + * `lower_case_table_names` - Whether the table name is case sensitive, the default value is 1. +Ranges: +0: Table names are stored as fixed and table names are case-sensitive. +1: Table names will be stored in lowercase and table names are not case sensitive. + * `maintenance_window` - Maintenance Window. + * `day_kind` - DayKind of maintainable window. Value: Week. Month. + * `day_of_month` - Days of maintainable window of the month. + * `day_of_week` - Days of maintainable window of the week. + * `maintenance_time` - The maintainable time of the RDS instance. + * `memory` - Memory size. + * `node_number` - The number of nodes. + * `node_spec` - The specification of primary node. + * `nodes` - Instance node information. + * `create_time` - Node creation local time. + * `instance_id` - Instance ID. + * `memory` - Memory size in GB. + * `node_id` - Node ID. + * `node_spec` - General instance type, different from Custom instance type. + * `node_status` - Node state, value: aligned with instance state. + * `node_type` - Node type. Value: Primary: Primary node. +Secondary: Standby node. +ReadOnly: Read-only node. + * `region_id` - Region ID, you can call the DescribeRegions query and use this parameter to specify the region where the instance is to be created. + * `update_time` - Node updates local time. + * `v_cpu` - CPU size. For example: 1 means 1U. + * `zone_id` - Availability zone ID. Subsequent support for multi-availability zones can be separated and displayed by an English colon. + * `region_id` - The region of the RDS instance. + * `storage_space` - Total instance storage space. Unit: GB. + * `storage_type` - Instance storage type. + * `storage_use` - The instance has used storage space. Unit: GB. + * `subnet_id` - The subnet ID of the RDS instance. + * `time_zone` - Time zone. + * `update_time` - The update time of the RDS instance. + * `v_cpu` - CPU size. + * `vpc_id` - The vpc ID of the RDS instance. + * `zone_id` - The available zone of the RDS instance. +* `total_count` - The total count of RDS instance query. + + diff --git a/website/docs/r/rds_database.html.markdown b/website/docs/r/rds_database.html.markdown index 82026021..aed827fe 100644 --- a/website/docs/r/rds_database.html.markdown +++ b/website/docs/r/rds_database.html.markdown @@ -35,7 +35,7 @@ In addition to all arguments above, the following attributes are exported: ## Import -Database can be imported using the id, e.g. +Database can be imported using the instanceId:dbName, e.g. ``` $ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname ``` diff --git a/website/docs/r/rds_mysql_account.html.markdown b/website/docs/r/rds_mysql_account.html.markdown new file mode 100644 index 00000000..71cafc98 --- /dev/null +++ b/website/docs/r/rds_mysql_account.html.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_account" +sidebar_current: "docs-volcengine-resource-rds_mysql_account" +description: |- + Provides a resource to manage rds mysql account +--- +# volcengine_rds_mysql_account +Provides a resource to manage rds mysql account +## Example Usage +```hcl +resource "volcengine_rds_mysql_account" "default" { + instance_id = "mysql-xxx" + account_name = "xxx" + account_password = "xxx" + account_type = "Normal" + account_privileges { + db_name = "xxx" + account_privilege = "Custom" + account_privilege_detail = "SELECT,UPDATE,INSERT" + } + account_privileges { + db_name = "xx" + account_privilege = "Custom" + account_privilege_detail = "SELECT,UPDATE,INSERT" + } +} +``` +## Argument Reference +The following arguments are supported: +* `account_name` - (Required, ForceNew) Database account name. The rules are as follows: +Unique name. +Start with a letter and end with a letter or number. +Consists of lowercase letters, numbers, or underscores (_). +The length is 2~32 characters. +The [keyword list](https://www.volcengine.com/docs/6313/66162) is disabled for database accounts, and certain reserved words, including root, admin, etc., cannot be used. +* `account_password` - (Required) The password of the database account. +illustrate +Cannot start with `!` or `@`. +The length is 8~32 characters. +It consists of any three of uppercase letters, lowercase letters, numbers, and special characters. +The special characters are `!@#$%^*()_+-=`. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. +* `account_type` - (Required, ForceNew) Database account type, value: +Super: A high-privilege account. Only one database account can be created for an instance. +Normal: An account with ordinary privileges. +* `instance_id` - (Required, ForceNew) The ID of the RDS instance. +* `account_privileges` - (Optional) The privilege information of account. + +The `account_privileges` object supports the following: + +* `account_privilege` - (Required) The privilege type of the account. +* `db_name` - (Required) The name of database. +* `account_privilege_detail` - (Optional) The privilege detail of the account. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +RDS mysql account can be imported using the instance_id:account_name, e.g. +``` +$ terraform import volcengine_rds_account.default mysql-42b38c769c4b:test +``` + diff --git a/website/docs/r/rds_mysql_allowlist.html.markdown b/website/docs/r/rds_mysql_allowlist.html.markdown new file mode 100644 index 00000000..81221379 --- /dev/null +++ b/website/docs/r/rds_mysql_allowlist.html.markdown @@ -0,0 +1,39 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_allowlist" +sidebar_current: "docs-volcengine-resource-rds_mysql_allowlist" +description: |- + Provides a resource to manage rds mysql allowlist +--- +# volcengine_rds_mysql_allowlist +Provides a resource to manage rds mysql allowlist +## Example Usage +```hcl +resource "volcengine_rds_mysql_allowlist" "foo" { + allow_list_name = "tf-test-opt" + allow_list_desc = "terraform test zzm" + allow_list = [ + "127.0.0.1" + ] +} +``` +## Argument Reference +The following arguments are supported: +* `allow_list_name` - (Required) The name of the allow list. +* `allow_list` - (Required) Enter an IP address or a range of IP addresses in CIDR format. +* `allow_list_desc` - (Optional) The description of the allow list. +* `allow_list_type` - (Optional) The type of IP address in the whitelist. Currently only IPv4 addresses are supported. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `allow_list_id` - The id of the allow list. + + +## Import +RDS AllowList can be imported using the id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist.default acl-d1fd76693bd54e658912e7337d5b**** +``` + diff --git a/website/docs/r/rds_mysql_allowlist_associate.html.markdown b/website/docs/r/rds_mysql_allowlist_associate.html.markdown new file mode 100644 index 00000000..7a3b848e --- /dev/null +++ b/website/docs/r/rds_mysql_allowlist_associate.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_allowlist_associate" +sidebar_current: "docs-volcengine-resource-rds_mysql_allowlist_associate" +description: |- + Provides a resource to manage rds mysql allowlist associate +--- +# volcengine_rds_mysql_allowlist_associate +Provides a resource to manage rds mysql allowlist associate +## Example Usage +```hcl +resource "volcengine_rds_mysql_allowlist_associate" "foo" { + instance_id = "mysql-1b2c7b2d7583" + allow_list_id = "acl-15451212dcfa473baeda24be4baa02fe" +} +``` +## Argument Reference +The following arguments are supported: +* `allow_list_id` - (Required, ForceNew) The id of the allow list. +* `instance_id` - (Required, ForceNew) The id of the mysql instance. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +RDS AllowList Associate can be imported using the instance id and allow list id, e.g. +``` +$ terraform import volcengine_rds_mysql_allowlist_associate.default rds-mysql-h441603c68aaa:acl-d1fd76693bd54e658912e7337d5b**** +``` + diff --git a/website/docs/r/rds_mysql_instance.html.markdown b/website/docs/r/rds_mysql_instance.html.markdown new file mode 100644 index 00000000..5c82f0ec --- /dev/null +++ b/website/docs/r/rds_mysql_instance.html.markdown @@ -0,0 +1,175 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_instance" +sidebar_current: "docs-volcengine-resource-rds_mysql_instance" +description: |- + Provides a resource to manage rds mysql instance +--- +# volcengine_rds_mysql_instance +Provides a resource to manage rds mysql instance +## Example Usage +```hcl +resource "volcengine_rds_mysql_instance" "foo" { + db_engine_version = "MySQL_5_7" + node_spec = "rds.mysql.1c2g" + primary_zone_id = "cn-guilin-a" + secondary_zone_id = "cn-guilin-b" + storage_space = 80 + subnet_id = "subnet-2d72yi377stts58ozfdrlk9f6" + instance_name = "tf-test" + lower_case_table_names = "1" + + charge_info { + charge_type = "PostPaid" + } + + allow_list_ids = ["acl-2dd8f8317e4d4159b21630d13ae2e6ec", "acl-2eaa2a053b2a4a58b988e38ae975e81c"] + + parameters { + parameter_name = "auto_increment_increment" + parameter_value = "2" + } + parameters { + parameter_name = "auto_increment_offset" + parameter_value = "4" + } +} + +resource "volcengine_rds_mysql_instance_readonly_node" "readonly" { + instance_id = volcengine_rds_mysql_instance.foo.id + node_spec = "rds.mysql.2c4g" + zone_id = "cn-guilin-a" +} +``` +## Argument Reference +The following arguments are supported: +* `charge_info` - (Required, ForceNew) Payment methods. +* `db_engine_version` - (Required, ForceNew) Instance type. Value: +MySQL_5_7 +MySQL_8_0. +* `node_spec` - (Required) The specification of primary node and secondary node. +* `primary_zone_id` - (Required, ForceNew) The available zone of primary node. +* `secondary_zone_id` - (Required, ForceNew) The available zone of secondary node. +* `subnet_id` - (Required, ForceNew) Subnet ID of the RDS instance. +* `allow_list_ids` - (Optional) Allow list Ids of the RDS instance. +* `db_time_zone` - (Optional, ForceNew) Time zone. Support UTC -12:00 ~ +13:00. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. +* `instance_name` - (Optional) Instance name. Cannot start with a number or a dash +Can only contain Chinese characters, letters, numbers, underscores and dashes +The length is limited between 1 ~ 128. +* `lower_case_table_names` - (Optional, ForceNew) Whether the table name is case sensitive, the default value is 1. +Ranges: +0: Table names are stored as fixed and table names are case-sensitive. +1: Table names will be stored in lowercase and table names are not case sensitive. +* `parameters` - (Optional) Parameter of the RDS instance. This field can only be added or modified. Deleting this field is invalid. +* `storage_space` - (Optional) Instance storage space. Value range: [20, 3000], unit: GB, increments every 100GB. Default value: 100. + +The `charge_info` object supports the following: + +* `charge_type` - (Required, ForceNew) Payment type. Value: +PostPaid - Pay-As-You-Go +PrePaid - Yearly and monthly (default). +* `auto_renew` - (Optional, ForceNew) Whether to automatically renew in prepaid scenarios. +* `period_unit` - (Optional, ForceNew) The purchase cycle in the prepaid scenario. +Month - monthly subscription (default) +Year - Package year. +* `period` - (Optional, ForceNew) Purchase duration in prepaid scenarios. Default: 1. + +The `parameters` object supports the following: + +* `parameter_name` - (Required) Parameter name. +* `parameter_value` - (Required) Parameter value. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `allow_list_version` - The version of allow list. +* `backup_use` - The instance has used backup space. Unit: GB. +* `charge_detail` - Payment methods. + * `auto_renew` - Whether to automatically renew in prepaid scenarios. +Autorenew_Enable +Autorenew_Disable (default). + * `charge_end_time` - Billing expiry time (yearly and monthly only). + * `charge_start_time` - Billing start time (pay-as-you-go & monthly subscription). + * `charge_status` - Pay status. Value: +normal - normal +overdue - overdue +. + * `charge_type` - Payment type. Value: +PostPaid - Pay-As-You-Go +PrePaid - Yearly and monthly (default). + * `overdue_reclaim_time` - Estimated release time when arrears are closed (pay-as-you-go & monthly subscription). + * `overdue_time` - Shutdown time in arrears (pay-as-you-go & monthly subscription). + * `period_unit` - The purchase cycle in the prepaid scenario. +Month - monthly subscription (default) +Year - Package year. + * `period` - Purchase duration in prepaid scenarios. Default: 1. +* `create_time` - The create time of the RDS instance. +* `data_sync_mode` - Data synchronization mode. +* `endpoints` - The endpoint info of the RDS instance. + * `addresses` - Address list. + * `dns_visibility` - DNS Visibility. + * `domain` - Connect domain name. + * `eip_id` - The ID of the EIP, only valid for Public addresses. + * `ip_address` - The IP Address. + * `network_type` - Network address type, temporarily Private, Public, PublicService. + * `port` - The Port. + * `subnet_id` - Subnet ID, valid only for private addresses. + * `auto_add_new_nodes` - When the terminal type is read-write terminal or read-only terminal, it supports setting whether new nodes are automatically added. + * `description` - Address description. + * `enable_read_only` - Whether global read-only is enabled, value: Enable: Enable. Disable: Disabled. + * `enable_read_write_splitting` - Whether read-write separation is enabled, value: Enable: Enable. Disable: Disabled. + * `endpoint_id` - Instance connection terminal ID. + * `endpoint_name` - The instance connection terminal name. + * `endpoint_type` - Terminal type: +Cluster: The default terminal. (created by default) +Primary: Primary node terminal. +Custom: Custom terminal. +Direct: Direct connection to the terminal. (Only the operation and maintenance side) +AllNode: All node terminals. (Only the operation and maintenance side). + * `node_weight` - The list of nodes configured by the connection terminal and the corresponding read-only weights. + * `node_id` - The ID of the node. + * `node_type` - The type of the node. + * `weight` - The weight of the node. + * `read_write_mode` - Read and write mode: +ReadWrite: read and write +ReadOnly: read only (default). +* `instance_id` - The ID of the RDS instance. +* `instance_status` - The status of the RDS instance. +* `maintenance_window` - Maintenance Window. + * `day_kind` - DayKind of maintainable window. Value: Week. Month. + * `day_of_month` - Days of maintainable window of the month. + * `day_of_week` - Days of maintainable window of the week. + * `maintenance_time` - The maintainable time of the RDS instance. +* `memory` - Memory size. +* `node_number` - The number of nodes. +* `nodes` - Instance node information. + * `create_time` - Node creation local time. + * `instance_id` - Instance ID. + * `memory` - Memory size in GB. + * `node_id` - Node ID. + * `node_spec` - General instance type, different from Custom instance type. + * `node_status` - Node state, value: aligned with instance state. + * `node_type` - Node type. Value: Primary: Primary node. +Secondary: Standby node. +ReadOnly: Read-only node. + * `region_id` - Region ID, you can call the DescribeRegions query and use this parameter to specify the region where the instance is to be created. + * `update_time` - Node updates local time. + * `v_cpu` - CPU size. For example: 1 means 1U. + * `zone_id` - Availability zone ID. Subsequent support for multi-availability zones can be separated and displayed by an English colon. +* `region_id` - The region of the RDS instance. +* `storage_type` - Instance storage type. +* `storage_use` - The instance has used storage space. Unit: GB. +* `time_zone` - Time zone. +* `update_time` - The update time of the RDS instance. +* `v_cpu` - CPU size. +* `vpc_id` - The vpc ID of the RDS instance. +* `zone_id` - The available zone of the RDS instance. + + +## Import +Rds Mysql Instance can be imported using the id, e.g. +``` +$ terraform import volcengine_rds_mysql_instance.default mysql-72da4258c2c7 +``` + diff --git a/website/docs/r/rds_mysql_instance_readonly_node.html.markdown b/website/docs/r/rds_mysql_instance_readonly_node.html.markdown new file mode 100644 index 00000000..844e95be --- /dev/null +++ b/website/docs/r/rds_mysql_instance_readonly_node.html.markdown @@ -0,0 +1,36 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_instance_readonly_node" +sidebar_current: "docs-volcengine-resource-rds_mysql_instance_readonly_node" +description: |- + Provides a resource to manage rds mysql instance readonly node +--- +# volcengine_rds_mysql_instance_readonly_node +Provides a resource to manage rds mysql instance readonly node +## Example Usage +```hcl +resource "volcengine_rds_mysql_instance_readonly_node" "foo" { + instance_id = "mysql-b3fca7f571d6" + node_spec = "rds.mysql.1c2g" + zone_id = "cn-guilin-b" +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required, ForceNew) The RDS mysql instance id of the readonly node. +* `node_spec` - (Required) The specification of readonly node. +* `zone_id` - (Required, ForceNew) The available zone of readonly node. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `node_id` - The id of the readonly node. + + +## Import +Rds Mysql Instance Readonly Node can be imported using the instance_id:node_id, e.g. +``` +$ terraform import volcengine_rds_mysql_instance_readonly_node.default mysql-72da4258c2c7:mysql-72da4258c2c7-r7f93 +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index 80fc227f..04d4c689 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -544,6 +544,18 @@
  • rds_parameter_templates
  • +
  • + rds_mysql_allowlists +
  • +
  • + rds_mysql_accounts +
  • +
  • + rds_databases +
  • +
  • + rds_mysql_instances +
  • rds_instances_v2
  • @@ -570,6 +582,24 @@
  • rds_parameter_template
  • +
  • + rds_mysql_allowlist +
  • +
  • + rds_mysql_allowlist_associate +
  • +
  • + rds_mysql_account +
  • +
  • + rds_database +
  • +
  • + rds_mysql_instance +
  • +
  • + rds_mysql_instance_readonly_node +
  • rds_instance_v2
  • From 4cb5eb52a20e2d31d4ce42a0029e788b2a456334 Mon Sep 17 00:00:00 2001 From: lixiang Date: Thu, 9 Mar 2023 15:42:08 +0800 Subject: [PATCH 41/58] update rds_mysql document --- .../docs/d/rds_mysql_databases.html.markdown | 37 ++++++++++++++ website/docs/r/rds_database.html.markdown | 2 +- .../docs/r/rds_mysql_database.html.markdown | 49 +++++++++++++++++++ website/volcengine.erb | 4 +- 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 website/docs/d/rds_mysql_databases.html.markdown create mode 100644 website/docs/r/rds_mysql_database.html.markdown diff --git a/website/docs/d/rds_mysql_databases.html.markdown b/website/docs/d/rds_mysql_databases.html.markdown new file mode 100644 index 00000000..ef484150 --- /dev/null +++ b/website/docs/d/rds_mysql_databases.html.markdown @@ -0,0 +1,37 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_databases" +sidebar_current: "docs-volcengine-datasource-rds_mysql_databases" +description: |- + Use this data source to query detailed information of rds mysql databases +--- +# volcengine_rds_mysql_databases +Use this data source to query detailed information of rds mysql databases +## Example Usage +```hcl +data "volcengine_rds_mysql_databases" "default" { + instance_id = "" + db_name = "" +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The id of the RDS instance. +* `db_name` - (Optional) The name of the RDS database. +* `name_regex` - (Optional) A Name Regex of RDS database. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `databases` - The collection of RDS instance account query. + * `character_set_name` - The character set of the RDS database. + * `database_privileges` - The privilege detail list of RDS mysql instance database. + * `account_name` - The name of account. + * `account_privilege_detail` - The privilege detail of the account. + * `account_privilege` - The privilege type of the account. + * `db_name` - The name of the RDS database. + * `id` - The ID of the RDS database. +* `total_count` - The total count of RDS database query. + + diff --git a/website/docs/r/rds_database.html.markdown b/website/docs/r/rds_database.html.markdown index aed827fe..82026021 100644 --- a/website/docs/r/rds_database.html.markdown +++ b/website/docs/r/rds_database.html.markdown @@ -35,7 +35,7 @@ In addition to all arguments above, the following attributes are exported: ## Import -Database can be imported using the instanceId:dbName, e.g. +Database can be imported using the id, e.g. ``` $ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname ``` diff --git a/website/docs/r/rds_mysql_database.html.markdown b/website/docs/r/rds_mysql_database.html.markdown new file mode 100644 index 00000000..c02a1a77 --- /dev/null +++ b/website/docs/r/rds_mysql_database.html.markdown @@ -0,0 +1,49 @@ +--- +subcategory: "RDS_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_rds_mysql_database" +sidebar_current: "docs-volcengine-resource-rds_mysql_database" +description: |- + Provides a resource to manage rds mysql database +--- +# volcengine_rds_mysql_database +Provides a resource to manage rds mysql database +## Example Usage +```hcl +resource "volcengine_rds_mysql_database" "default" { + instance_id = "mysql-xxx" + db_name = "xxx" + character_set_name = "utf8" +} +``` +## Argument Reference +The following arguments are supported: +* `character_set_name` - (Required, ForceNew) Database character set. Currently supported character sets include: utf8, utf8mb4, latin1, ascii. +* `db_name` - (Required, ForceNew) Name database. +illustrate: +Unique name. +The length is 2~64 characters. +Start with a letter and end with a letter or number. +Consists of lowercase letters, numbers, and underscores (_) or dashes (-). +Database names are disabled [keywords](https://www.volcengine.com/docs/6313/66162). +* `instance_id` - (Required, ForceNew) The ID of the RDS instance. +* `database_privileges` - (Optional) The privilege detail list of RDS mysql instance database. + +The `database_privileges` object supports the following: + +* `account_name` - (Required) The name of account. +* `account_privilege` - (Required) The privilege type of the account. +* `account_privilege_detail` - (Optional) The privilege detail of the account. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +Database can be imported using the instanceId:dbName, e.g. +``` +$ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index 04d4c689..357377bc 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -551,7 +551,7 @@ rds_mysql_accounts
  • - rds_databases + rds_mysql_databases
  • rds_mysql_instances @@ -592,7 +592,7 @@ rds_mysql_account
  • - rds_database + rds_mysql_database
  • rds_mysql_instance From 4b52fad79cd6cbd54c4c39ee8fee06f592955e68 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Mon, 13 Mar 2023 11:30:56 +0800 Subject: [PATCH 42/58] feat: add refresh delay time --- .../service_volcengine_rds_mysql_allowlist.go | 25 ++++++---------- .../service_volcengine_rds_mysql_instance.go | 3 +- ...engine_rds_mysql_instance_readonly_node.go | 30 ++++--------------- 3 files changed, 15 insertions(+), 43 deletions(-) diff --git a/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go b/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go index daf859b8..5a7d5bd3 100644 --- a/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go +++ b/volcengine/rds_mysql/allowlist/service_volcengine_rds_mysql_allowlist.go @@ -3,6 +3,7 @@ package allowlist import ( "errors" "fmt" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -124,19 +125,15 @@ func (s *VolcengineRdsMysqlAllowListService) CreateResource(data *schema.Resourc }, }, BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + var allowStrings []string allowListsSet := d.Get("allow_list").(*schema.Set) allowLists := allowListsSet.List() - if len(allowLists) == 1 { - (*call.SdkParam)["AllowList"] = allowLists[0] - return true, nil - } - lists := "" for _, list := range allowLists { - lists += list.(string) - lists += "," + allowStrings = append(allowStrings, list.(string)) } + lists := strings.Join(allowStrings, ",") logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) - (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + (*call.SdkParam)["AllowList"] = lists return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { @@ -171,6 +168,7 @@ func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.Resourc }, }, BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + var allowStrings []string // 修改allowList必须传ApplyInstanceNum resp, err := s.ReadResource(d, d.Id()) if err != nil { @@ -180,17 +178,12 @@ func (s *VolcengineRdsMysqlAllowListService) ModifyResource(data *schema.Resourc (*call.SdkParam)["ApplyInstanceNum"] = int(num) allowListsSet := d.Get("allow_list").(*schema.Set) allowLists := allowListsSet.List() - if len(allowLists) == 1 { - (*call.SdkParam)["AllowList"] = allowLists[0] - return true, nil - } - lists := "" for _, list := range allowLists { - lists += list.(string) - lists += "," + allowStrings = append(allowStrings, list.(string)) } + lists := strings.Join(allowStrings, ",") logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) - (*call.SdkParam)["AllowList"] = lists[0 : len(lists)-1] + (*call.SdkParam)["AllowList"] = lists return true, nil }, SdkParam: &map[string]interface{}{ diff --git a/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go b/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go index 33189fc3..1e4b8f6a 100644 --- a/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go +++ b/volcengine/rds_mysql/rds_mysql_instance/service_volcengine_rds_mysql_instance.go @@ -171,7 +171,7 @@ func (s *VolcengineRdsMysqlInstanceService) ReadResource(resourceData *schema.Re func (s *VolcengineRdsMysqlInstanceService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { return &resource.StateChangeConf{ Pending: []string{}, - Delay: 1 * time.Second, + Delay: 10 * time.Second, MinTimeout: 1 * time.Second, Target: target, Timeout: timeout, @@ -462,7 +462,6 @@ func (s *VolcengineRdsMysqlInstanceService) ModifyResource(resourceData *schema. if err != nil { return common, err } - time.Sleep(10 * time.Second) // modify后如果直接refresh,status不会变为Updating,导致refresh直接结束 return common, nil }, Refresh: &ve.StateRefresh{ diff --git a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go index b5e09849..265b37ff 100644 --- a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go +++ b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go @@ -148,39 +148,21 @@ func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) CreateResource(resourceD if err != nil { return common, err } - time.Sleep(10 * time.Second) // 新增只读节点后,需要等一下 return common, nil }, - AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + AfterRefresh: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) error { var ( instance = make(map[string]interface{}) err error ) - // 通过retry确保获取当前新建只读节点的Id - resource.Retry(15*time.Minute, func() *resource.RetryError { - instance, err = s.RdsInstanceService.ReadResource(d, d.Get("instance_id").(string)) - if err != nil { - if ve.ResourceNotFoundError(err) { - return resource.RetryableError(err) - } else { - return resource.NonRetryableError(fmt.Errorf("error on reading rds instance %q", d.Get("instance_id"))) - } - } - status, err := ve.ObtainSdkValue("InstanceStatus", instance) - if err != nil { - return resource.RetryableError(err) - } - if status.(string) != "Running" { - return resource.RetryableError(fmt.Errorf("rds instance is still in updating")) - } - return nil - }) - logger.Debug(logger.ReqFormat, "testReadonly", instance) + instance, err = s.RdsInstanceService.ReadResource(d, d.Get("instance_id").(string)) + if err != nil { + return err + } var newReadonlyNodeId string if nodeArr, ok := instance["Nodes"].([]interface{}); ok { for _, node := range nodeArr { if nodeMap, ok1 := node.(map[string]interface{}); ok1 { - logger.Debug(logger.ReqFormat, "existingReadOnlyNodeIds", existingReadOnlyNodeIds) if nodeMap["NodeType"] == "ReadOnly" { if _, ok := existingReadOnlyNodeIds[nodeMap["NodeId"].(string)]; !ok { newReadonlyNodeId = nodeMap["NodeId"].(string) @@ -282,7 +264,6 @@ func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ModifyResource(resourceD if err != nil { return common, err } - time.Sleep(10 * time.Second) // 修改只读节点后,需要等一下 return common, nil }, LockId: func(d *schema.ResourceData) string { @@ -372,7 +353,6 @@ func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) RemoveResource(resourceD if err != nil { return common, err } - time.Sleep(10 * time.Second) // 删除只读节点后,需要等一下 return common, nil }, LockId: func(d *schema.ResourceData) string { From b1a1e1b89dfddcd53ad82024bb634bca83d1c28c Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Mon, 10 Apr 2023 21:25:54 +0800 Subject: [PATCH 43/58] feat: opt readonly node --- .../service_volcengine_rds_mysql_instance_readonly_node.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go index 265b37ff..80dffb64 100644 --- a/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go +++ b/volcengine/rds_mysql/rds_mysql_instance_readonly_node/service_volcengine_rds_mysql_instance_readonly_node.go @@ -64,6 +64,9 @@ func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) ReadResource(resourceDat } } } + if len(data) == 0 { + return data, fmt.Errorf("Rds instance readonly node %s is not exist ", nodeId) + } data["NodeId"] = nodeId return data, err @@ -173,6 +176,9 @@ func (s *VolcengineRdsMysqlInstanceReadonlyNodeService) CreateResource(resourceD } // ResourceData中,rds_mysql_instance_readonly_node的Id形式为'instance_id:node_id' logger.Debug(logger.ReqFormat, "newReadonlyNodeId", newReadonlyNodeId) + if newReadonlyNodeId == "" { + return fmt.Errorf(" Failed to create readonly node ") + } id := fmt.Sprintf("%s:%s", d.Get("instance_id"), newReadonlyNodeId) d.SetId(id) return nil From 07a13c6fa74b4a44b6234583568f689e216e5a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 11 Apr 2023 17:36:41 +0800 Subject: [PATCH 44/58] feat: opt mysql account code --- example/dataRdsMysqlAccounts/main.tf | 2 +- example/rdsMysqlAccount/main.tf | 16 +- ...ta_source_volcengine_rds_mysql_accounts.go | 7 +- .../resource_volcengine_rds_mysql_account.go | 21 ++- .../service_volcengine_rds_mysql_account.go | 150 ++++++++---------- 5 files changed, 97 insertions(+), 99 deletions(-) diff --git a/example/dataRdsMysqlAccounts/main.tf b/example/dataRdsMysqlAccounts/main.tf index 533d3496..f82b2e39 100644 --- a/example/dataRdsMysqlAccounts/main.tf +++ b/example/dataRdsMysqlAccounts/main.tf @@ -1,4 +1,4 @@ data "volcengine_rds_mysql_accounts" "default"{ - instance_id="" + instance_id="mysql-47d6bc58762b" account_name="" } \ No newline at end of file diff --git a/example/rdsMysqlAccount/main.tf b/example/rdsMysqlAccount/main.tf index 667b665c..bb3310c2 100644 --- a/example/rdsMysqlAccount/main.tf +++ b/example/rdsMysqlAccount/main.tf @@ -1,16 +1,16 @@ resource "volcengine_rds_mysql_account" "default"{ - instance_id="mysql-xxx" - account_name="xxx" - account_password="xxx" + instance_id="mysql-e9293705eed6" + account_name="test" + account_password="zhangzheming!@ZZM" account_type="Normal" account_privileges{ - db_name="xxx" - account_privilege="Custom" - account_privilege_detail="SELECT,UPDATE,INSERT" + db_name="tf-test-db" + account_privilege="ReadOnly" + account_privilege_detail="SELECT,UPDATE,INSERT" } account_privileges{ - db_name="xx" - account_privilege="Custom" + db_name="test-xx" + account_privilege="ReadOnly" account_privilege_detail="SELECT,UPDATE,INSERT" } } \ No newline at end of file diff --git a/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go b/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go index 66c35e13..1827375a 100644 --- a/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go +++ b/volcengine/rds_mysql/rds_mysql_account/data_source_volcengine_rds_mysql_accounts.go @@ -35,7 +35,7 @@ func DataSourceVolcengineRdsMysqlAccounts() *schema.Resource { "account_name": { Type: schema.TypeString, Optional: true, - Description: "The name of the database account.", + Description: "The name of the database account. This field supports fuzzy query.", }, "accounts": { Description: "The collection of RDS instance account query.", @@ -43,11 +43,6 @@ func DataSourceVolcengineRdsMysqlAccounts() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, // tf中不支持写值 - Description: "The ID of the RDS instance account.", - }, "account_name": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go index f1de8acc..92a4039e 100644 --- a/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/resource_volcengine_rds_mysql_account.go @@ -2,6 +2,9 @@ package rds_mysql_account import ( "fmt" + "reflect" + "sort" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -14,7 +17,7 @@ import ( Import RDS mysql account can be imported using the instance_id:account_name, e.g. ``` -$ terraform import volcengine_rds_account.default mysql-42b38c769c4b:test +$ terraform import volcengine_rds_mysql_account.default mysql-42b38c769c4b:test ``` */ @@ -50,7 +53,7 @@ func ResourceVolcengineRdsMysqlAccount() *schema.Resource { Type: schema.TypeString, Required: true, Sensitive: true, - Description: "The password of the database account.\nillustrate\nCannot start with `!` or `@`.\nThe length is 8~32 characters.\nIt consists of any three of uppercase letters, lowercase letters, numbers, and special characters.\nThe special characters are `!@#$%^*()_+-=`. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", + Description: "The password of the database account.\nIllustrate:\nCannot start with `!` or `@`.\nThe length is 8~32 characters.\nIt consists of any three of uppercase letters, lowercase letters, numbers, and special characters.\nThe special characters are `!@#$%^*()_+-=`. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", }, "account_type": { Type: schema.TypeString, @@ -77,8 +80,18 @@ func ResourceVolcengineRdsMysqlAccount() *schema.Resource { Description: "The privilege type of the account.", }, "account_privilege_detail": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if len(old) != len(new) { + return false + } + oldArr := strings.Split(old, ",") + newArr := strings.Split(new, ",") + sort.Strings(oldArr) + sort.Strings(newArr) + return reflect.DeepEqual(oldArr, newArr) + }, Description: "The privilege detail of the account.", }, }, diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index b86ac610..e9766eb7 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/volcengine/terraform-provider-volcengine/common" volc "github.com/volcengine/terraform-provider-volcengine/common" "github.com/volcengine/terraform-provider-volcengine/logger" ) @@ -31,7 +30,7 @@ func (s *VolcengineRdsMysqlAccountService) GetClient() *volc.SdkClient { } func (s *VolcengineRdsMysqlAccountService) ReadResources(m map[string]interface{}) ([]interface{}, error) { - list, err := volc.WithPageOffsetQuery(m, "PageSize", "PageNumber", 20, 0, func(condition map[string]interface{}) (data []interface{}, err error) { + return volc.WithPageNumberQuery(m, "PageSize", "PageNumber", 20, 0, func(condition map[string]interface{}) (data []interface{}, err error) { var ( resp *map[string]interface{} results interface{} @@ -65,31 +64,12 @@ func (s *VolcengineRdsMysqlAccountService) ReadResources(m map[string]interface{ } return data, err }) - if err != nil { - return list, err - } - - accountName := m["AccountName"] - res := make([]interface{}, 0) - for _, a := range list { - account, ok := a.(map[string]interface{}) - if !ok { - continue - } - // accountName是模糊搜索,需要过滤一下 - if accountName != "" && accountName != account["AccountName"].(string) { - continue - } - // 拼接id - account["Id"] = fmt.Sprintf("%s:%s", m["InstanceId"], account["AccountName"]) - res = append(res, account) - } - return res, nil } func (s *VolcengineRdsMysqlAccountService) ReadResource(resourceData *schema.ResourceData, RdsMysqlAccountId string) (data map[string]interface{}, err error) { var ( results []interface{} + account = make(map[string]interface{}) ok bool ) if RdsMysqlAccountId == "" { @@ -112,11 +92,18 @@ func (s *VolcengineRdsMysqlAccountService) ReadResource(resourceData *schema.Res if err != nil { return data, err } - for _, v := range results { - if data, ok = v.(map[string]interface{}); !ok { + + for _, r := range results { + account, ok = r.(map[string]interface{}) + if !ok { return data, errors.New("Value is not map ") } + if accountName == account["AccountName"].(string) { + data = account + break + } } + if len(data) == 0 { return data, fmt.Errorf("RDS account %s not exist ", RdsMysqlAccountId) } @@ -148,6 +135,11 @@ func (s *VolcengineRdsMysqlAccountService) CreateResource(resourceData *schema.R "account_privileges": { TargetField: "AccountPrivileges", ConvertType: volc.ConvertJsonObjectArray, + NextLevelConvert: map[string]volc.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, }, }, ContentType: volc.ContentTypeJson, @@ -166,17 +158,6 @@ func (s *VolcengineRdsMysqlAccountService) CreateResource(resourceData *schema.R return []volc.Callback{callback} } -func hasDbNameInSet(dbName string, set *schema.Set) bool { - for _, item := range set.List() { - if m, ok := item.(map[string]interface{}); ok { - if v, ok := m["db_name"]; ok && v.(string) == dbName { - return true - } - } - } - return false -} - func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { callbacks := []volc.Callback{} if resourceData.HasChange("account_password") { @@ -198,47 +179,39 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R callbacks = append(callbacks, callback) } if resourceData.HasChange("account_privileges") { - addPrivis, removePrivs, _, _ := common.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) - - if addPrivis != nil && addPrivis.Len() != 0 { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "GrantDBAccountPrivilege", - ConvertMode: volc.RequestConvertIgnore, - BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - (*call.SdkParam)["InstanceId"] = d.Get("instance_id") - (*call.SdkParam)["AccountName"] = d.Get("account_name") - accountPrivileges := make([]map[string]interface{}, 0) - for _, item := range addPrivis.List() { - m, _ := item.(map[string]interface{}) - privi := make(map[string]interface{}) - if v, ok := m["db_name"]; ok { - privi["DBName"] = v - } - if v, ok := m["account_privilege"]; ok { - privi["AccountPrivilege"] = v - } - if v, ok := m["account_privilege_detail"]; ok { - privi["AccountPrivilegeDetail"] = v - } - accountPrivileges = append(accountPrivileges, privi) - } - (*call.SdkParam)["AccountPrivileges"] = accountPrivileges - logger.DebugInfo("accountPrivileges %v", accountPrivileges) - return true, nil - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + callback := volc.Callback{ + Call: volc.SdkCall{ + Action: "GrantDBAccountPrivilege", + ConvertMode: volc.RequestConvertInConvert, + ContentType: volc.ContentTypeJson, + Convert: map[string]volc.RequestConvert{ + "account_privileges": { + TargetField: "AccountPrivileges", + ForceGet: true, + NextLevelConvert: map[string]volc.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, + ConvertType: volc.ConvertJsonObjectArray, }, }, - } - - callbacks = append(callbacks, callback) - + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["AccountName"] = d.Get("account_name") + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, } - if removePrivs != nil && removePrivs.Len() != 0 { - callback := volc.Callback{ + callbacks = append(callbacks, callback) + + add, remove, _, _ := volc.GetSetDifference("account_privileges", resourceData, RdsMysqlAccountPrivilegeHash, false) + if remove != nil && remove.Len() > 0 { + removeCallback := volc.Callback{ Call: volc.SdkCall{ Action: "RevokeDBAccountPrivilege", ConvertMode: volc.RequestConvertIgnore, @@ -246,22 +219,22 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R (*call.SdkParam)["InstanceId"] = d.Get("instance_id") (*call.SdkParam)["AccountName"] = d.Get("account_name") dbNames := make([]string, 0) - for _, item := range addPrivis.List() { + for _, item := range remove.List() { m, ok := item.(map[string]interface{}) if !ok { continue } - dbName := m["db_name"].(string) + removeDbName := m["db_name"].(string) // 过滤掉有Grant操作的db_name,Grant权限方式为覆盖,先取消原有权限,再赋新权限,此处无需再取消一次。 - if addPrivis != nil && addPrivis.Len() != 0 && hasDbNameInSet(dbName, addPrivis) { + if add != nil && add.Len() > 0 && hasDbNameInSet(removeDbName, add) { continue } - dbNames = append(dbNames, dbName) + dbNames = append(dbNames, removeDbName) } if len(dbNames) == 0 { return false, nil } - (*call.SdkParam)["DBNames"] = dbNames + (*call.SdkParam)["DBNames"] = strings.Join(dbNames, ",") return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { @@ -270,13 +243,30 @@ func (s *VolcengineRdsMysqlAccountService) ModifyResource(resourceData *schema.R }, }, } - callbacks = append(callbacks, callback) + callbacks = append(callbacks, removeCallback) } } - return callbacks } +func hasDbNameInSet(dbName string, set *schema.Set) bool { + for _, item := range set.List() { + if m, ok := item.(map[string]interface{}); ok { + if v, ok := m["db_name"]; ok && v.(string) == dbName { + if detail, ok := m["account_privilege_detail"].(string); ok { + if len(detail) == 0 { + return false + } + } else { + return false + } + return true + } + } + } + return false +} + func (s *VolcengineRdsMysqlAccountService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []volc.Callback { callback := volc.Callback{ Call: volc.SdkCall{ From 1afe4b276ad62e688c6ceaa1668574c3e8427a15 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Tue, 11 Apr 2023 17:10:30 +0800 Subject: [PATCH 45/58] feat: opt rds mysql database --- .../common_volcengine_rds_database.go | 70 ----------- .../common_volcengine_rds_mysql_database.go | 22 ++++ ..._source_volcengine_rds_mysql_databases.go} | 7 +- ...resource_volcengine_rds_mysql_database.go} | 41 +----- ... service_volcengine_rds_mysql_database.go} | 118 ++---------------- 5 files changed, 33 insertions(+), 225 deletions(-) delete mode 100644 volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go create mode 100644 volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_mysql_database.go rename volcengine/rds_mysql/rds_mysql_database/{data_source_volcengine_rds_databases.go => data_source_volcengine_rds_mysql_databases.go} (92%) rename volcengine/rds_mysql/rds_mysql_database/{resource_volcengine_rds_database.go => resource_volcengine_rds_mysql_database.go} (66%) rename volcengine/rds_mysql/rds_mysql_database/{service_volcengine_rds_database.go => service_volcengine_rds_mysql_database.go} (63%) diff --git a/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go deleted file mode 100644 index 004ba9f3..00000000 --- a/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_database.go +++ /dev/null @@ -1,70 +0,0 @@ -package rds_mysql_database - -import ( - "bytes" - "fmt" - "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" - "sort" - "strings" - - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" -) - -var databaseImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { - items := strings.Split(data.Id(), ":") - if len(items) != 2 { - return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") - } - if err := data.Set("instance_id", items[0]); err != nil { - return []*schema.ResourceData{data}, err - } - if err := data.Set("db_name", items[1]); err != nil { - return []*schema.ResourceData{data}, err - } - return []*schema.ResourceData{data}, nil -} - -var rdsMysqlDatabasePrivilegeStrMapping = map[string]string{ - "create tmp table": "create temporary tables", - "CREATE TMP TABLE": "CREATE TEMPORARY TABLES", -} - -func mappingAccountPrivilegeStr(accountPrivilegeStr string) []string { - privileges := strings.Split(accountPrivilegeStr, ",") - mappingPrivileges := make([]string, 0) - for _, privilege := range privileges { - if mappedPrivilege, ok := rdsMysqlDatabasePrivilegeStrMapping[privilege]; ok { - mappingPrivileges = append(mappingPrivileges, mappedPrivilege) - } else { - mappingPrivileges = append(mappingPrivileges, privilege) - } - } - return mappingPrivileges -} - -// mappingAndSortAccountPrivilegeStr RDS account privilege string mapping -func mappingAndSortAccountPrivilegeStr(accountPrivilegeStr string) string { - mappingPrivileges := mappingAccountPrivilegeStr(accountPrivilegeStr) - sort.Strings(mappingPrivileges) - return strings.Join(mappingPrivileges, ",") -} - -func rdsMysqlDatabasePrivilegeHashBase(m map[string]interface{}) (buf bytes.Buffer) { - dbName := strings.ToLower(m["account_name"].(string)) - accountPrivilege := strings.ToLower(m["account_privilege"].(string)) - buf.WriteString(fmt.Sprintf("%s-", dbName)) - buf.WriteString(fmt.Sprintf("%s-", accountPrivilege)) - if accountPrivilege == "custom" { - buf.WriteString(fmt.Sprintf("%s-", mappingAndSortAccountPrivilegeStr(strings.ToLower(m["account_privilege_detail"].(string))))) - } - return buf -} - -func RdsMysqlDatabasePrivilegeHash(v interface{}) int { - if v == nil { - return hashcode.String("") - } - m := v.(map[string]interface{}) - buf := rdsMysqlDatabasePrivilegeHashBase(m) - return hashcode.String(buf.String()) -} diff --git a/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_mysql_database.go b/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_mysql_database.go new file mode 100644 index 00000000..cb4ede99 --- /dev/null +++ b/volcengine/rds_mysql/rds_mysql_database/common_volcengine_rds_mysql_database.go @@ -0,0 +1,22 @@ +package rds_mysql_database + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +var databaseImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("db_name", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go b/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_mysql_databases.go similarity index 92% rename from volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go rename to volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_mysql_databases.go index 6921f459..fa16000d 100644 --- a/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_databases.go +++ b/volcengine/rds_mysql/rds_mysql_database/data_source_volcengine_rds_mysql_databases.go @@ -44,15 +44,10 @@ func DataSourceVolcengineRdsMysqlDatabases() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, // tf中不支持写值 - Description: "The ID of the RDS database.", - }, "db_name": { Type: schema.TypeString, Computed: true, - Description: "The name of the RDS database.", + Description: "The name of the RDS database. This field supports fuzzy queries.", }, "character_set_name": { Type: schema.TypeString, diff --git a/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_mysql_database.go similarity index 66% rename from volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go rename to volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_mysql_database.go index edd1f03b..1054af69 100644 --- a/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_database.go +++ b/volcengine/rds_mysql/rds_mysql_database/resource_volcengine_rds_mysql_database.go @@ -13,7 +13,7 @@ import ( Import Database can be imported using the instanceId:dbName, e.g. ``` -$ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname +$ terraform import volcengine_rds_mysql_database.default mysql-42b38c769c4b:dbname ``` */ @@ -22,14 +22,12 @@ func ResourceVolcengineRdsMysqlDatabase() *schema.Resource { return &schema.Resource{ Create: resourceVolcengineRdsMysqlDatabaseCreate, Read: resourceVolcengineRdsMysqlDatabaseRead, - Update: resourceVolcengineRdsMysqlDatabaseUpdate, Delete: resourceVolcengineRdsMysqlDatabaseDelete, Importer: &schema.ResourceImporter{ State: databaseImporter, }, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(30 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), Delete: schema.DefaultTimeout(30 * time.Minute), }, Schema: map[string]*schema.Schema{ @@ -47,35 +45,11 @@ func ResourceVolcengineRdsMysqlDatabase() *schema.Resource { }, "character_set_name": { Type: schema.TypeString, - Required: true, + Optional: true, + Default: "utf8mb4", ForceNew: true, Description: "Database character set. Currently supported character sets include: utf8, utf8mb4, latin1, ascii.", }, - "database_privileges": { - Type: schema.TypeSet, - Optional: true, - Set: RdsMysqlDatabasePrivilegeHash, - Description: "The privilege detail list of RDS mysql instance database.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "account_name": { - Type: schema.TypeString, - Required: true, - Description: "The name of account.", - }, - "account_privilege": { - Type: schema.TypeString, - Required: true, - Description: "The privilege type of the account.", - }, - "account_privilege_detail": { - Type: schema.TypeString, - Optional: true, - Description: "The privilege detail of the account.", - }, - }, - }, - }, }, } } @@ -98,15 +72,6 @@ func resourceVolcengineRdsMysqlDatabaseRead(d *schema.ResourceData, meta interfa return err } -func resourceVolcengineRdsMysqlDatabaseUpdate(d *schema.ResourceData, meta interface{}) (err error) { - service := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) - err = service.Dispatcher.Update(service, d, ResourceVolcengineRdsMysqlDatabase()) - if err != nil { - return fmt.Errorf("error on updating rds mysql database %q, %s", d.Id(), err) - } - return resourceVolcengineRdsMysqlDatabaseRead(d, meta) -} - func resourceVolcengineRdsMysqlDatabaseDelete(d *schema.ResourceData, meta interface{}) (err error) { databaseService := NewRdsMysqlDatabaseService(meta.(*volc.SdkClient)) err = databaseService.Dispatcher.Delete(databaseService, d, ResourceVolcengineRdsMysqlDatabase()) diff --git a/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go similarity index 63% rename from volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go rename to volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go index 56f4a0ba..98ac49a6 100644 --- a/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_database.go +++ b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/volcengine/terraform-provider-volcengine/common" volc "github.com/volcengine/terraform-provider-volcengine/common" "github.com/volcengine/terraform-provider-volcengine/logger" ) @@ -31,7 +30,7 @@ func (s *VolcengineRdsMysqlDatabaseService) GetClient() *volc.SdkClient { } func (s *VolcengineRdsMysqlDatabaseService) ReadResources(m map[string]interface{}) ([]interface{}, error) { - list, err := volc.WithPageOffsetQuery(m, "PageSize", "PageNumber", 20, 0, func(condition map[string]interface{}) (data []interface{}, err error) { + return volc.WithPageNumberQuery(m, "PageSize", "PageNumber", 10, 1, func(condition map[string]interface{}) (data []interface{}, err error) { var ( resp *map[string]interface{} results interface{} @@ -65,26 +64,6 @@ func (s *VolcengineRdsMysqlDatabaseService) ReadResources(m map[string]interface } return data, err }) - if err != nil { - return list, err - } - - dbName := m["DBName"] - res := make([]interface{}, 0) - for _, d := range list { - db, ok := d.(map[string]interface{}) - if !ok { - continue - } - // DBName是模糊搜索,需要过滤一下 - if dbName != "" && dbName != db["DBName"].(string) { - continue - } - // 拼接id - db["Id"] = fmt.Sprintf("%s:%s", m["InstanceId"], db["DBName"]) - res = append(res, db) - } - return res, nil } func (s *VolcengineRdsMysqlDatabaseService) ReadResource(resourceData *schema.ResourceData, rdsDatabaseId string) (data map[string]interface{}, err error) { @@ -113,9 +92,13 @@ func (s *VolcengineRdsMysqlDatabaseService) ReadResource(resourceData *schema.Re return data, err } for _, v := range results { - if data, ok = v.(map[string]interface{}); !ok { + dbMap := make(map[string]interface{}) + if dbMap, ok = v.(map[string]interface{}); !ok { return data, errors.New("Value is not map ") } + if dbName == dbMap["DBName"].(string) { + data = dbMap + } } if len(data) == 0 { return data, fmt.Errorf("RDS database %s not exist ", rdsDatabaseId) @@ -166,95 +149,8 @@ func (s *VolcengineRdsMysqlDatabaseService) CreateResource(resourceData *schema. return []volc.Callback{callback} } -func hasAccountNameInSet(account string, set *schema.Set) bool { - for _, item := range set.List() { - if m, ok := item.(map[string]interface{}); ok { - if v, ok := m["account_name"]; ok && v.(string) == account { - return true - } - } - } - return false -} - func (s *VolcengineRdsMysqlDatabaseService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []volc.Callback { - callbacks := make([]volc.Callback, 0) - if resourceData.HasChange("database_privileges") { - addPrivis, removePrivs, _, _ := common.GetSetDifference("database_privileges", resourceData, RdsMysqlDatabasePrivilegeHash, false) - if addPrivis.Len() != 0 { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "GrantDatabasePrivilege", - ConvertMode: volc.RequestConvertIgnore, - BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - (*call.SdkParam)["InstanceId"] = d.Get("instance_id") - (*call.SdkParam)["DBName"] = d.Get("db_name") - dbPrivileges := make([]map[string]interface{}, 0) - for _, item := range addPrivis.List() { - m, _ := item.(map[string]interface{}) - privi := make(map[string]interface{}) - if v, ok := m["account_name"]; ok { - privi["AccountName"] = v - } - if v, ok := m["account_privilege"]; ok { - privi["AccountPrivilege"] = v - } - if v, ok := m["account_privilege_detail"]; ok { - privi["AccountPrivilegeDetail"] = v - } - dbPrivileges = append(dbPrivileges, privi) - } - (*call.SdkParam)["DatabasePrivileges"] = dbPrivileges - return true, nil - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - }, - } - - callbacks = append(callbacks, callback) - - } - if removePrivs.Len() != 0 { - callback := volc.Callback{ - Call: volc.SdkCall{ - Action: "RevokeDatabasePrivilege", - ConvertMode: volc.RequestConvertIgnore, - BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - (*call.SdkParam)["InstanceId"] = d.Get("instance_id") - (*call.SdkParam)["DBName"] = d.Get("db_name") - accountNames := make([]string, 0) - for _, item := range addPrivis.List() { - m, ok := item.(map[string]interface{}) - if !ok { - continue - } - account := m["account_name"].(string) - // 过滤掉有Grant操作的account,Grant权限方式为覆盖,先取消原有权限,再赋新权限,此处无需再取消一次。 - if addPrivis != nil && addPrivis.Len() != 0 && hasAccountNameInSet(account, addPrivis) { - continue - } - accountNames = append(accountNames, account) - } - (*call.SdkParam)["AccountNames"] = accountNames - if len(accountNames) == 0 { - return false, nil - } - return true, nil - }, - ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { - logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) - return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) - }, - }, - } - callbacks = append(callbacks, callback) - } - } - - return callbacks + return []volc.Callback{} } func (s *VolcengineRdsMysqlDatabaseService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []volc.Callback { From 3cc1f64f12dee2562af611f0077939e992e08f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 11 Apr 2023 17:38:17 +0800 Subject: [PATCH 46/58] feat: add doc and version --- example/rdsMysqlAccount/main.tf | 4 ++-- .../service_volcengine_rds_mysql_account.go | 22 +++++++++++++++++++ .../service_volcengine_rds_mysql_database.go | 1 + .../docs/d/rds_mysql_accounts.html.markdown | 5 ++--- .../docs/d/rds_mysql_databases.html.markdown | 3 +-- .../docs/r/rds_mysql_account.html.markdown | 18 +++++++-------- .../docs/r/rds_mysql_database.html.markdown | 11 ++-------- 7 files changed, 39 insertions(+), 25 deletions(-) diff --git a/example/rdsMysqlAccount/main.tf b/example/rdsMysqlAccount/main.tf index bb3310c2..66591ea2 100644 --- a/example/rdsMysqlAccount/main.tf +++ b/example/rdsMysqlAccount/main.tf @@ -1,10 +1,10 @@ resource "volcengine_rds_mysql_account" "default"{ instance_id="mysql-e9293705eed6" account_name="test" - account_password="zhangzheming!@ZZM" + account_password="xdjsuiahHUH@" account_type="Normal" account_privileges{ - db_name="tf-test-db" + db_name="tf-test-dbdddddd" account_privilege="ReadOnly" account_privilege_detail="SELECT,UPDATE,INSERT" } diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index e9766eb7..0e1ec997 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" volc "github.com/volcengine/terraform-provider-volcengine/common" "github.com/volcengine/terraform-provider-volcengine/logger" + database "github.com/volcengine/terraform-provider-volcengine/volcengine/rds_mysql/rds_mysql_database" ) type VolcengineRdsMysqlAccountService struct { @@ -143,6 +144,27 @@ func (s *VolcengineRdsMysqlAccountService) CreateResource(resourceData *schema.R }, }, ContentType: volc.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { + privileges, ok := d.GetOk("account_privileges") + if !ok { + return false, fmt.Errorf("account_privileges get error") + } + if privileges == nil || privileges.(*schema.Set).Len() == 0 { + return true, nil + } + for _, privilege := range privileges.(*schema.Set).List() { + privilegeMap, ok := privilege.(map[string]interface{}) + if !ok { + return false, fmt.Errorf("account_privilege is not map") + } + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), privilegeMap["db_name"]) + _, err := database.NewRdsMysqlDatabaseService(client).ReadResource(d, id) + if err != nil { + return false, err + } + } + return true, nil + }, ExecuteCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (*map[string]interface{}, error) { logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) //创建RdsMysqlAccount diff --git a/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go index 98ac49a6..39689541 100644 --- a/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go +++ b/volcengine/rds_mysql/rds_mysql_database/service_volcengine_rds_mysql_database.go @@ -98,6 +98,7 @@ func (s *VolcengineRdsMysqlDatabaseService) ReadResource(resourceData *schema.Re } if dbName == dbMap["DBName"].(string) { data = dbMap + break } } if len(data) == 0 { diff --git a/website/docs/d/rds_mysql_accounts.html.markdown b/website/docs/d/rds_mysql_accounts.html.markdown index 1f7e0dab..b7bd8398 100644 --- a/website/docs/d/rds_mysql_accounts.html.markdown +++ b/website/docs/d/rds_mysql_accounts.html.markdown @@ -11,14 +11,14 @@ Use this data source to query detailed information of rds mysql accounts ## Example Usage ```hcl data "volcengine_rds_mysql_accounts" "default" { - instance_id = "" + instance_id = "mysql-47d6bc58762b" account_name = "" } ``` ## Argument Reference The following arguments are supported: * `instance_id` - (Required) The id of the RDS instance. -* `account_name` - (Optional) The name of the database account. +* `account_name` - (Optional) The name of the database account. This field supports fuzzy query. * `name_regex` - (Optional) A Name Regex of database account. * `output_file` - (Optional) File name where to save data source results. @@ -32,7 +32,6 @@ In addition to all arguments above, the following attributes are exported: * `db_name` - The name of database. * `account_status` - The status of the database account. * `account_type` - The type of the database account. - * `id` - The ID of the RDS instance account. * `total_count` - The total count of database account query. diff --git a/website/docs/d/rds_mysql_databases.html.markdown b/website/docs/d/rds_mysql_databases.html.markdown index ef484150..64b1ffa4 100644 --- a/website/docs/d/rds_mysql_databases.html.markdown +++ b/website/docs/d/rds_mysql_databases.html.markdown @@ -30,8 +30,7 @@ In addition to all arguments above, the following attributes are exported: * `account_name` - The name of account. * `account_privilege_detail` - The privilege detail of the account. * `account_privilege` - The privilege type of the account. - * `db_name` - The name of the RDS database. - * `id` - The ID of the RDS database. + * `db_name` - The name of the RDS database. This field supports fuzzy queries. * `total_count` - The total count of RDS database query. diff --git a/website/docs/r/rds_mysql_account.html.markdown b/website/docs/r/rds_mysql_account.html.markdown index 71cafc98..5fe5a209 100644 --- a/website/docs/r/rds_mysql_account.html.markdown +++ b/website/docs/r/rds_mysql_account.html.markdown @@ -11,18 +11,18 @@ Provides a resource to manage rds mysql account ## Example Usage ```hcl resource "volcengine_rds_mysql_account" "default" { - instance_id = "mysql-xxx" - account_name = "xxx" - account_password = "xxx" + instance_id = "mysql-e9293705eed6" + account_name = "test" + account_password = "x" account_type = "Normal" account_privileges { - db_name = "xxx" - account_privilege = "Custom" + db_name = "tf-test-db" + account_privilege = "ReadOnly" account_privilege_detail = "SELECT,UPDATE,INSERT" } account_privileges { - db_name = "xx" - account_privilege = "Custom" + db_name = "test-xx" + account_privilege = "ReadOnly" account_privilege_detail = "SELECT,UPDATE,INSERT" } } @@ -36,7 +36,7 @@ Consists of lowercase letters, numbers, or underscores (_). The length is 2~32 characters. The [keyword list](https://www.volcengine.com/docs/6313/66162) is disabled for database accounts, and certain reserved words, including root, admin, etc., cannot be used. * `account_password` - (Required) The password of the database account. -illustrate +Illustrate: Cannot start with `!` or `@`. The length is 8~32 characters. It consists of any three of uppercase letters, lowercase letters, numbers, and special characters. @@ -62,6 +62,6 @@ In addition to all arguments above, the following attributes are exported: ## Import RDS mysql account can be imported using the instance_id:account_name, e.g. ``` -$ terraform import volcengine_rds_account.default mysql-42b38c769c4b:test +$ terraform import volcengine_rds_mysql_account.default mysql-42b38c769c4b:test ``` diff --git a/website/docs/r/rds_mysql_database.html.markdown b/website/docs/r/rds_mysql_database.html.markdown index c02a1a77..b84dbd72 100644 --- a/website/docs/r/rds_mysql_database.html.markdown +++ b/website/docs/r/rds_mysql_database.html.markdown @@ -18,7 +18,6 @@ resource "volcengine_rds_mysql_database" "default" { ``` ## Argument Reference The following arguments are supported: -* `character_set_name` - (Required, ForceNew) Database character set. Currently supported character sets include: utf8, utf8mb4, latin1, ascii. * `db_name` - (Required, ForceNew) Name database. illustrate: Unique name. @@ -27,13 +26,7 @@ Start with a letter and end with a letter or number. Consists of lowercase letters, numbers, and underscores (_) or dashes (-). Database names are disabled [keywords](https://www.volcengine.com/docs/6313/66162). * `instance_id` - (Required, ForceNew) The ID of the RDS instance. -* `database_privileges` - (Optional) The privilege detail list of RDS mysql instance database. - -The `database_privileges` object supports the following: - -* `account_name` - (Required) The name of account. -* `account_privilege` - (Required) The privilege type of the account. -* `account_privilege_detail` - (Optional) The privilege detail of the account. +* `character_set_name` - (Optional, ForceNew) Database character set. Currently supported character sets include: utf8, utf8mb4, latin1, ascii. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -44,6 +37,6 @@ In addition to all arguments above, the following attributes are exported: ## Import Database can be imported using the instanceId:dbName, e.g. ``` -$ terraform import volcengine_rds_database.default mysql-42b38c769c4b:dbname +$ terraform import volcengine_rds_mysql_database.default mysql-42b38c769c4b:dbname ``` From daf86173c65dc84304b505bad9e309af22ce8e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Wed, 12 Apr 2023 10:22:09 +0800 Subject: [PATCH 47/58] feat: opt rds account create --- example/rdsMysqlAccount/main.tf | 20 +++++++++---------- .../service_volcengine_rds_mysql_account.go | 5 +---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/example/rdsMysqlAccount/main.tf b/example/rdsMysqlAccount/main.tf index 66591ea2..40d13eb7 100644 --- a/example/rdsMysqlAccount/main.tf +++ b/example/rdsMysqlAccount/main.tf @@ -3,14 +3,14 @@ resource "volcengine_rds_mysql_account" "default"{ account_name="test" account_password="xdjsuiahHUH@" account_type="Normal" - account_privileges{ - db_name="tf-test-dbdddddd" - account_privilege="ReadOnly" - account_privilege_detail="SELECT,UPDATE,INSERT" - } - account_privileges{ - db_name="test-xx" - account_privilege="ReadOnly" - account_privilege_detail="SELECT,UPDATE,INSERT" - } +# account_privileges{ +# db_name="tf-test-dbdddddd" +# account_privilege="ReadOnly" +# account_privilege_detail="SELECT,UPDATE,INSERT" +# } +# account_privileges{ +# db_name="test-xx" +# account_privilege="ReadOnly" +# account_privilege_detail="SELECT,UPDATE,INSERT" +# } } \ No newline at end of file diff --git a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go index 0e1ec997..5c148b62 100644 --- a/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go +++ b/volcengine/rds_mysql/rds_mysql_account/service_volcengine_rds_mysql_account.go @@ -145,10 +145,7 @@ func (s *VolcengineRdsMysqlAccountService) CreateResource(resourceData *schema.R }, ContentType: volc.ContentTypeJson, BeforeCall: func(d *schema.ResourceData, client *volc.SdkClient, call volc.SdkCall) (bool, error) { - privileges, ok := d.GetOk("account_privileges") - if !ok { - return false, fmt.Errorf("account_privileges get error") - } + privileges := d.Get("account_privileges") if privileges == nil || privileges.(*schema.Set).Len() == 0 { return true, nil } From 0addb7d808ce7ed872abc0bcac50ecf445350cb5 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Wed, 12 Apr 2023 11:46:36 +0800 Subject: [PATCH 48/58] feat: add retry in rds v2 --- .../service_volcengine_rds_instance_v2.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/volcengine/rds_v2/rds_instance_v2/service_volcengine_rds_instance_v2.go b/volcengine/rds_v2/rds_instance_v2/service_volcengine_rds_instance_v2.go index fce2f5f2..c23de911 100644 --- a/volcengine/rds_v2/rds_instance_v2/service_volcengine_rds_instance_v2.go +++ b/volcengine/rds_v2/rds_instance_v2/service_volcengine_rds_instance_v2.go @@ -166,10 +166,21 @@ func (s *VolcengineRdsInstanceService) RefreshResourceState(resourceData *schema failStates []string ) failStates = append(failStates, "Error") - demo, err = s.ReadResource(resourceData, id) - if err != nil { + + if err = resource.Retry(20*time.Minute, func() *resource.RetryError { + demo, err = s.ReadResource(resourceData, id) + if err != nil { + if volc.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(err) + } + } + return nil + }); err != nil { return nil, "", err } + status, err = volc.ObtainSdkValue("InstanceStatus", demo) if err != nil { return nil, "", err From 8a35357854d23dbd713eb3170e344697cf76ca96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=93=B2=E9=93=AD?= Date: Tue, 18 Apr 2023 16:08:21 +0800 Subject: [PATCH 49/58] feat: add doc and version --- common/common_volcengine_version.go | 2 +- .../docs/r/rds_mysql_account.html.markdown | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index e6886513..dfddd03e 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.67" + TerraformProviderVersion = "0.0.68" ) diff --git a/website/docs/r/rds_mysql_account.html.markdown b/website/docs/r/rds_mysql_account.html.markdown index 5fe5a209..573ea846 100644 --- a/website/docs/r/rds_mysql_account.html.markdown +++ b/website/docs/r/rds_mysql_account.html.markdown @@ -13,18 +13,18 @@ Provides a resource to manage rds mysql account resource "volcengine_rds_mysql_account" "default" { instance_id = "mysql-e9293705eed6" account_name = "test" - account_password = "x" + account_password = "xdjsuiahHUH@" account_type = "Normal" - account_privileges { - db_name = "tf-test-db" - account_privilege = "ReadOnly" - account_privilege_detail = "SELECT,UPDATE,INSERT" - } - account_privileges { - db_name = "test-xx" - account_privilege = "ReadOnly" - account_privilege_detail = "SELECT,UPDATE,INSERT" - } + # account_privileges{ + # db_name="tf-test-dbdddddd" + # account_privilege="ReadOnly" + # account_privilege_detail="SELECT,UPDATE,INSERT" + # } + # account_privileges{ + # db_name="test-xx" + # account_privilege="ReadOnly" + # account_privilege_detail="SELECT,UPDATE,INSERT" + # } } ``` ## Argument Reference From 5770bf588bd5d64f8da8f94733c7190b9ac7be56 Mon Sep 17 00:00:00 2001 From: xuyaming0800 Date: Tue, 18 Apr 2023 16:49:29 +0800 Subject: [PATCH 50/58] feat: support tos bucket policy --- example/tosBucketPolicy/main.tf | 20 ++ volcengine/provider.go | 6 +- .../bucket/resource_volcengine_tos_bucket.go | 2 +- .../resource_volcengine_tos_bucket_policy.go | 152 ++++++++++++ .../service_volcengine_tos_bucket_policy.go | 230 ++++++++++++++++++ website/docs/r/tos_bucket.html.markdown | 2 +- .../docs/r/tos_bucket_policy.html.markdown | 50 ++++ website/volcengine.erb | 3 + 8 files changed, 461 insertions(+), 4 deletions(-) create mode 100644 example/tosBucketPolicy/main.tf create mode 100644 volcengine/tos/bucket_policy/resource_volcengine_tos_bucket_policy.go create mode 100644 volcengine/tos/bucket_policy/service_volcengine_tos_bucket_policy.go create mode 100644 website/docs/r/tos_bucket_policy.html.markdown diff --git a/example/tosBucketPolicy/main.tf b/example/tosBucketPolicy/main.tf new file mode 100644 index 00000000..4a5222d3 --- /dev/null +++ b/example/tosBucketPolicy/main.tf @@ -0,0 +1,20 @@ +resource "volcengine_tos_bucket_policy" "default" { + bucket_name = "bucket-20230418" + policy = jsonencode({ + Statement = [ + { + Sid = "test" + Effect = "Allow" + Principal = [ + "AccountId/subUserName" + ] + Action = [ + "tos:List*" + ] + Resource = [ + "trn:tos:::bucket-20230418" + ] + } + ] + }) +} \ No newline at end of file diff --git a/volcengine/provider.go b/volcengine/provider.go index ccc6b88c..6fe6f40a 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/ssl_state" + "github.com/volcengine/terraform-provider-volcengine/volcengine/tos/bucket_policy" "github.com/volcengine/terraform-provider-volcengine/volcengine/mongodb/spec" @@ -404,8 +405,9 @@ func Provider() terraform.ResourceProvider { "volcengine_escloud_instance": instance.ResourceVolcengineESCloudInstance(), //================= TOS ================= - "volcengine_tos_bucket": bucket.ResourceVolcengineTosBucket(), - "volcengine_tos_object": object.ResourceVolcengineTosObject(), + "volcengine_tos_bucket": bucket.ResourceVolcengineTosBucket(), + "volcengine_tos_object": object.ResourceVolcengineTosObject(), + "volcengine_tos_bucket_policy": bucket_policy.ResourceVolcengineTosBucketPolicy(), // ================ CR ================ "volcengine_cr_registry": cr_registry.ResourceVolcengineCrRegistry(), diff --git a/volcengine/tos/bucket/resource_volcengine_tos_bucket.go b/volcengine/tos/bucket/resource_volcengine_tos_bucket.go index c7ece4ad..905e9ea3 100644 --- a/volcengine/tos/bucket/resource_volcengine_tos_bucket.go +++ b/volcengine/tos/bucket/resource_volcengine_tos_bucket.go @@ -15,7 +15,7 @@ import ( Import Tos Bucket can be imported using the id, e.g. ``` -$ terraform import volcengine_tos_bucket.default region:bucketName +$ terraform import volcengine_tos_bucket.default bucketName ``` */ diff --git a/volcengine/tos/bucket_policy/resource_volcengine_tos_bucket_policy.go b/volcengine/tos/bucket_policy/resource_volcengine_tos_bucket_policy.go new file mode 100644 index 00000000..6b923ab9 --- /dev/null +++ b/volcengine/tos/bucket_policy/resource_volcengine_tos_bucket_policy.go @@ -0,0 +1,152 @@ +package bucket_policy + +import ( + "encoding/json" + "fmt" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Tos Bucket can be imported using the id, e.g. +``` +$ terraform import volcengine_tos_bucket_policy.default bucketName:policy +``` + +*/ + +func ResourceVolcengineTosBucketPolicy() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineTosBucketPolicyCreate, + Read: resourceVolcengineTosBucketPolicyRead, + Update: resourceVolcengineTosBucketPolicyUpdate, + Delete: resourceVolcengineTosBucketPolicyDelete, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(2 * time.Minute), + Update: schema.DefaultTimeout(2 * time.Minute), + Delete: schema.DefaultTimeout(2 * time.Minute), + }, + Importer: &schema.ResourceImporter{ + State: func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must be of the form bucketName") + } + _ = data.Set("bucket_name", items[0]) + return []*schema.ResourceData{data}, nil + }, + }, + Schema: map[string]*schema.Schema{ + "bucket_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the bucket.", + }, + "policy": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if k == "policy" { + om := map[string]interface{}{} + nm := map[string]interface{}{} + _ = json.Unmarshal([]byte(old), &om) + _ = json.Unmarshal([]byte(new), &nm) + //暂时不支持version 这里忽略掉 + delete(om, "Version") + delete(nm, "Version") + //重构单一Principal Action Resource 字符串转换数组 + if _, ok := om["Statement"].([]interface{}); ok { + for i, st := range om["Statement"].([]interface{}) { + if _, ok1 := st.(map[string]interface{}); ok1 { + temp := map[string]interface{}{} + for k1, v1 := range st.(map[string]interface{}) { + if k1 == "Principal" || k1 == "Action" || k1 == "Resource" { + if reflect.TypeOf(v1).Kind() == reflect.String { + temp[k1] = []string{v1.(string)} + } else { + temp[k1] = v1 + } + } else { + temp[k1] = v1 + } + } + om["Statement"].([]interface{})[i] = temp + } + } + } + + if _, ok := nm["Statement"].([]interface{}); ok { + for i, st := range nm["Statement"].([]interface{}) { + if _, ok1 := st.(map[string]interface{}); ok1 { + temp := map[string]interface{}{} + for k1, v1 := range st.(map[string]interface{}) { + if k1 == "Principal" || k1 == "Action" || k1 == "Resource" { + if reflect.TypeOf(v1).Kind() == reflect.String { + temp[k1] = []string{v1.(string)} + } else { + temp[k1] = v1 + } + } else { + temp[k1] = v1 + } + } + nm["Statement"].([]interface{})[i] = temp + } + } + } + + o, _ := json.MarshalIndent(om, "", "") + n, _ := json.MarshalIndent(nm, "", "") + return string(o) == string(n) + } + return false + }, + Description: "The policy document. This is a JSON formatted string. For more information about building Volcengine IAM policy documents with Terraform, see the [Volcengine IAM Policy Document Guide](https://www.volcengine.com/docs/6349/102127).", + }, + }, + } + return resource +} + +func resourceVolcengineTosBucketPolicyCreate(d *schema.ResourceData, meta interface{}) (err error) { + tosBucketService := NewTosBucketPolicyService(meta.(*ve.SdkClient)) + err = ve.DefaultDispatcher().Create(tosBucketService, d, ResourceVolcengineTosBucketPolicy()) + if err != nil { + return fmt.Errorf("error on creating tos bucket %q, %s", d.Id(), err) + } + return resourceVolcengineTosBucketPolicyRead(d, meta) +} + +func resourceVolcengineTosBucketPolicyRead(d *schema.ResourceData, meta interface{}) (err error) { + tosBucketService := NewTosBucketPolicyService(meta.(*ve.SdkClient)) + err = ve.DefaultDispatcher().Read(tosBucketService, d, ResourceVolcengineTosBucketPolicy()) + if err != nil { + return fmt.Errorf("error on reading tos bucket %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineTosBucketPolicyUpdate(d *schema.ResourceData, meta interface{}) (err error) { + tosBucketService := NewTosBucketPolicyService(meta.(*ve.SdkClient)) + err = ve.DefaultDispatcher().Update(tosBucketService, d, ResourceVolcengineTosBucketPolicy()) + if err != nil { + return fmt.Errorf("error on updating tos bucket %q, %s", d.Id(), err) + } + return resourceVolcengineTosBucketPolicyRead(d, meta) +} + +func resourceVolcengineTosBucketPolicyDelete(d *schema.ResourceData, meta interface{}) (err error) { + tosBucketService := NewTosBucketPolicyService(meta.(*ve.SdkClient)) + err = ve.DefaultDispatcher().Delete(tosBucketService, d, ResourceVolcengineTosBucketPolicy()) + if err != nil { + return fmt.Errorf("error on deleting tos bucket %q, %s", d.Id(), err) + } + return err +} diff --git a/volcengine/tos/bucket_policy/service_volcengine_tos_bucket_policy.go b/volcengine/tos/bucket_policy/service_volcengine_tos_bucket_policy.go new file mode 100644 index 00000000..d1d083a9 --- /dev/null +++ b/volcengine/tos/bucket_policy/service_volcengine_tos_bucket_policy.go @@ -0,0 +1,230 @@ +package bucket_policy + +import ( + "encoding/json" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineTosBucketPolicyService struct { + Client *ve.SdkClient +} + +func NewTosBucketPolicyService(c *ve.SdkClient) *VolcengineTosBucketPolicyService { + return &VolcengineTosBucketPolicyService{ + Client: c, + } +} + +func (s *VolcengineTosBucketPolicyService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineTosBucketPolicyService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + tos := s.Client.TosClient + var ( + action string + resp *map[string]interface{} + results interface{} + ) + action = "GetBucketPolicy" + logger.Debug(logger.ReqFormat, action, nil) + resp, err = tos.DoTosCall(ve.TosInfo{ + HttpMethod: ve.GET, + Domain: condition[ve.TosDomain].(string), + UrlParam: map[string]string{ + "policy": "", + }, + }, nil) + if err != nil { + return data, err + } + results, err = ve.ObtainSdkValue(ve.TosResponse, *resp) + if err != nil { + return data, err + } + + if len(results.(map[string]interface{})) == 0 { + return data, fmt.Errorf("bucket Policy %s not exist ", condition[ve.TosDomain].(string)) + } + + data = append(data, map[string]interface{}{ + "Policy": results.(map[string]interface{}), + }) + return data, err +} + +func (s *VolcengineTosBucketPolicyService) ReadResource(resourceData *schema.ResourceData, instanceId string) (data map[string]interface{}, err error) { + bucketName := resourceData.Get("bucket_name").(string) + if instanceId == "" { + instanceId = s.ReadResourceId(resourceData.Id()) + } else { + instanceId = s.ReadResourceId(instanceId) + } + + var ( + ok bool + results []interface{} + ) + + logger.Debug(logger.ReqFormat, "GetBucketPolicy", bucketName+":"+instanceId) + condition := map[string]interface{}{ + ve.TosDomain: bucketName, + } + results, err = s.ReadResources(condition) + + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, fmt.Errorf("Value is not map ") + } + } + + if len(data) == 0 { + return data, fmt.Errorf("bucket Policy %s not exist ", instanceId) + } + + return data, nil +} + +func (s *VolcengineTosBucketPolicyService) RefreshResourceState(data *schema.ResourceData, strings []string, duration time.Duration, id string) *resource.StateChangeConf { + return nil +} + +func (s *VolcengineTosBucketPolicyService) WithResourceResponseHandlers(m map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return m, map[string]ve.ResponseConvert{ + "Policy": { + Convert: func(i interface{}) interface{} { + b, _ := json.Marshal(i) + return string(b) + }, + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineTosBucketPolicyService) putBucketPolicy(data *schema.ResourceData, resource *schema.Resource, isUpdate bool) ve.Callback { + return ve.Callback{ + Call: ve.SdkCall{ + ServiceCategory: ve.ServiceTos, + Action: "PutBucketPolicy", + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "bucket_name": { + ConvertType: ve.ConvertDefault, + TargetField: "BucketName", + ForceGet: isUpdate, + SpecialParam: &ve.SpecialParam{ + Type: ve.DomainParam, + }, + }, + "policy": { + ForceGet: isUpdate, + ConvertType: ve.ConvertDefault, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + j := (*call.SdkParam)[ve.TosParam].(map[string]interface{})["Policy"] + data := map[string]interface{}{} + err := json.Unmarshal([]byte(j.(string)), &data) + if err != nil { + return false, err + } + delete((*call.SdkParam)[ve.TosParam].(map[string]interface{}), "Policy") + for k, v := range data { + (*call.SdkParam)[ve.TosParam].(map[string]interface{})[k] = v + } + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + param := (*call.SdkParam)[ve.TosParam].(map[string]interface{}) + return s.Client.TosClient.DoTosCall(ve.TosInfo{ + HttpMethod: ve.PUT, + ContentType: ve.ApplicationJSON, + UrlParam: map[string]string{ + "policy": "", + }, + Domain: (*call.SdkParam)[ve.TosDomain].(string), + }, ¶m) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + d.SetId((*call.SdkParam)[ve.TosDomain].(string) + ":POLICY") + return nil + }, + }, + } +} + +func (s *VolcengineTosBucketPolicyService) CreateResource(data *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{s.putBucketPolicy(data, resource, false)} +} + +func (s *VolcengineTosBucketPolicyService) ModifyResource(data *schema.ResourceData, resource *schema.Resource) []ve.Callback { + return []ve.Callback{s.putBucketPolicy(data, resource, true)} +} + +func (s *VolcengineTosBucketPolicyService) RemoveResource(data *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + ServiceCategory: ve.ServiceTos, + Action: "DeleteBucketPolicy", + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "bucket_name": { + ConvertType: ve.ConvertDefault, + TargetField: "BucketName", + ForceGet: true, + SpecialParam: &ve.SpecialParam{ + Type: ve.DomainParam, + }, + }, + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.TosClient.DoTosCall(ve.TosInfo{ + HttpMethod: ve.DELETE, + Domain: (*call.SdkParam)[ve.TosDomain].(string), + UrlParam: map[string]string{ + "policy": "", + }, + }, nil) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading tos bucket policy on delete %q, %w", s.ReadResourceId(d.Id()), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineTosBucketPolicyService) DatasourceResources(data *schema.ResourceData, resource *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{} +} + +func (s *VolcengineTosBucketPolicyService) ReadResourceId(id string) string { + return id +} diff --git a/website/docs/r/tos_bucket.html.markdown b/website/docs/r/tos_bucket.html.markdown index 5502dde9..66e9bee6 100644 --- a/website/docs/r/tos_bucket.html.markdown +++ b/website/docs/r/tos_bucket.html.markdown @@ -48,6 +48,6 @@ In addition to all arguments above, the following attributes are exported: ## Import Tos Bucket can be imported using the id, e.g. ``` -$ terraform import volcengine_tos_bucket.default region:bucketName +$ terraform import volcengine_tos_bucket.default bucketName ``` diff --git a/website/docs/r/tos_bucket_policy.html.markdown b/website/docs/r/tos_bucket_policy.html.markdown new file mode 100644 index 00000000..26b0c40e --- /dev/null +++ b/website/docs/r/tos_bucket_policy.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "TOS(BETA)" +layout: "volcengine" +page_title: "Volcengine: volcengine_tos_bucket_policy" +sidebar_current: "docs-volcengine-resource-tos_bucket_policy" +description: |- + Provides a resource to manage tos bucket policy +--- +# volcengine_tos_bucket_policy +Provides a resource to manage tos bucket policy +## Example Usage +```hcl +resource "volcengine_tos_bucket_policy" "default" { + bucket_name = "bucket-20230418" + policy = jsonencode({ + Statement = [ + { + Sid = "test" + Effect = "Allow" + Principal = [ + "AccountId/subUserName" + ] + Action = [ + "tos:List*" + ] + Resource = [ + "trn:tos:::bucket-20230418" + ] + } + ] + }) +} +``` +## Argument Reference +The following arguments are supported: +* `bucket_name` - (Required, ForceNew) The name of the bucket. +* `policy` - (Required) The policy document. This is a JSON formatted string. For more information about building Volcengine IAM policy documents with Terraform, see the [Volcengine IAM Policy Document Guide](https://www.volcengine.com/docs/6349/102127). + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +Tos Bucket can be imported using the id, e.g. +``` +$ terraform import volcengine_tos_bucket_policy.default bucketName:policy +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index 80fc227f..5c6e0d8e 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -597,6 +597,9 @@
  • tos_bucket
  • +
  • + tos_bucket_policy +
  • tos_object
  • From 53d50bacbcc5c7524869722b5d6bd389a37b9c16 Mon Sep 17 00:00:00 2001 From: "maoshuai.17" Date: Fri, 3 Mar 2023 11:45:26 +0800 Subject: [PATCH 51/58] feat: support ipv6 --- example/dataVpcIpv6AddressBandwidths/main.tf | 3 + example/dataVpcIpv6Gateways/main.tf | 3 + example/vpcIpv6AddressBandwidth/main.tf | 5 + example/vpcIpv6Gateway/main.tf | 5 + .../resource_volcengine_ecs_instance.go | 7 + volcengine/provider.go | 44 +-- ..._volcengine_vpc_ipv6_address_bandwidths.go | 161 +++++++++++ ...e_volcengine_vpc_ipv6_address_bandwidth.go | 96 +++++++ ...e_volcengine_vpc_ipv6_address_bandwidth.go | 267 ++++++++++++++++++ ...ata_source_volcengine_vpc_ipv6_gateways.go | 108 +++++++ .../resource_volcengine_vpc_ipv6_gateway.go | 91 ++++++ .../service_volcengine_vpc_ipv6_gateway.go | 258 +++++++++++++++++ .../subnet/data_source_volcengine_subnets.go | 5 + .../vpc/subnet/resource_volcengine_subnet.go | 25 ++ .../vpc/subnet/service_volcengine_subnet.go | 28 ++ .../vpc/vpc/data_source_volcengine_vpcs.go | 5 + volcengine/vpc/vpc/resource_volcengine_vpc.go | 18 ++ volcengine/vpc/vpc/service_volcengine_vpc.go | 7 + website/docs/d/subnets.html.markdown | 1 + .../vpc_ipv6_address_bandwidths.html.markdown | 49 ++++ .../docs/d/vpc_ipv6_gateways.html.markdown | 38 +++ website/docs/d/vpcs.html.markdown | 1 + website/docs/r/ecs_instance.html.markdown | 1 + website/docs/r/subnet.html.markdown | 2 + website/docs/r/vpc.html.markdown | 3 + .../vpc_ipv6_address_bandwidth.html.markdown | 47 +++ website/docs/r/vpc_ipv6_gateway.html.markdown | 36 +++ website/volcengine.erb | 12 + 28 files changed, 1307 insertions(+), 19 deletions(-) create mode 100644 example/dataVpcIpv6AddressBandwidths/main.tf create mode 100644 example/dataVpcIpv6Gateways/main.tf create mode 100644 example/vpcIpv6AddressBandwidth/main.tf create mode 100644 example/vpcIpv6Gateway/main.tf create mode 100644 volcengine/vpc/ipv6_address_bandwidth/data_source_volcengine_vpc_ipv6_address_bandwidths.go create mode 100644 volcengine/vpc/ipv6_address_bandwidth/resource_volcengine_vpc_ipv6_address_bandwidth.go create mode 100644 volcengine/vpc/ipv6_address_bandwidth/service_volcengine_vpc_ipv6_address_bandwidth.go create mode 100644 volcengine/vpc/ipv6_gateway/data_source_volcengine_vpc_ipv6_gateways.go create mode 100644 volcengine/vpc/ipv6_gateway/resource_volcengine_vpc_ipv6_gateway.go create mode 100644 volcengine/vpc/ipv6_gateway/service_volcengine_vpc_ipv6_gateway.go create mode 100644 website/docs/d/vpc_ipv6_address_bandwidths.html.markdown create mode 100644 website/docs/d/vpc_ipv6_gateways.html.markdown create mode 100644 website/docs/r/vpc_ipv6_address_bandwidth.html.markdown create mode 100644 website/docs/r/vpc_ipv6_gateway.html.markdown diff --git a/example/dataVpcIpv6AddressBandwidths/main.tf b/example/dataVpcIpv6AddressBandwidths/main.tf new file mode 100644 index 00000000..fd989e83 --- /dev/null +++ b/example/dataVpcIpv6AddressBandwidths/main.tf @@ -0,0 +1,3 @@ +data "volcengine_vpc_ipv6_address_bandwidths" "default" { + ids = ["eip-in2y2duvtlhc8gbssyfnhfre"] +} \ No newline at end of file diff --git a/example/dataVpcIpv6Gateways/main.tf b/example/dataVpcIpv6Gateways/main.tf new file mode 100644 index 00000000..bbaf74af --- /dev/null +++ b/example/dataVpcIpv6Gateways/main.tf @@ -0,0 +1,3 @@ +data "volcengine_vpc_ipv6_gateways" "default" { + ids = ["ipv6gw-12bcapllb5ukg17q7y2sd3thx"] +} \ No newline at end of file diff --git a/example/vpcIpv6AddressBandwidth/main.tf b/example/vpcIpv6AddressBandwidth/main.tf new file mode 100644 index 00000000..912b3d17 --- /dev/null +++ b/example/vpcIpv6AddressBandwidth/main.tf @@ -0,0 +1,5 @@ +resource "volcengine_vpc_ipv6_address_bandwidth" "foo" { + ipv6_address = "2000:1000:89ff:ff02:ea70:18ce:dda2:a02e" + billing_type = 3 + bandwidth = 5 +} \ No newline at end of file diff --git a/example/vpcIpv6Gateway/main.tf b/example/vpcIpv6Gateway/main.tf new file mode 100644 index 00000000..e5253fc6 --- /dev/null +++ b/example/vpcIpv6Gateway/main.tf @@ -0,0 +1,5 @@ +resource "volcengine_vpc_ipv6_gateway" "foo" { + vpc_id = "vpc-12afxho4sxyio17q7y2kkp8ej" + name = "tf-test-1" + description = "test" +} \ No newline at end of file diff --git a/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go b/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go index 3d42d422..2cab5227 100644 --- a/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go +++ b/volcengine/ecs/ecs_instance/resource_volcengine_ecs_instance.go @@ -239,6 +239,13 @@ func ResourceVolcengineEcsInstance() *schema.Resource { Description: "The ID of Ecs Deployment Set.", }, + "ipv6_address_count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: "The ipv6 address count of ECS instance. Valid values: 0, 1.", + }, + "data_volumes": { Type: schema.TypeList, Optional: true, diff --git a/volcengine/provider.go b/volcengine/provider.go index 1f3dce70..f0a024aa 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -110,6 +110,8 @@ import ( "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/node" "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/node_pool" "github.com/volcengine/terraform-provider-volcengine/volcengine/vke/support_addon" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/ipv6_address_bandwidth" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/ipv6_gateway" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_acl" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_acl_associate" "github.com/volcengine/terraform-provider-volcengine/volcengine/vpc/network_interface" @@ -186,14 +188,16 @@ func Provider() terraform.ResourceProvider { }, }, DataSourcesMap: map[string]*schema.Resource{ - "volcengine_vpcs": vpc.DataSourceVolcengineVpcs(), - "volcengine_subnets": subnet.DataSourceVolcengineSubnets(), - "volcengine_route_tables": route_table.DataSourceVolcengineRouteTables(), - "volcengine_route_entries": route_entry.DataSourceVolcengineRouteEntries(), - "volcengine_security_groups": security_group.DataSourceVolcengineSecurityGroups(), - "volcengine_security_group_rules": security_group_rule.DataSourceVolcengineSecurityGroupRules(), - "volcengine_network_interfaces": network_interface.DataSourceVolcengineNetworkInterfaces(), - "volcengine_network_acls": network_acl.DataSourceVolcengineNetworkAcls(), + "volcengine_vpcs": vpc.DataSourceVolcengineVpcs(), + "volcengine_subnets": subnet.DataSourceVolcengineSubnets(), + "volcengine_route_tables": route_table.DataSourceVolcengineRouteTables(), + "volcengine_route_entries": route_entry.DataSourceVolcengineRouteEntries(), + "volcengine_security_groups": security_group.DataSourceVolcengineSecurityGroups(), + "volcengine_security_group_rules": security_group_rule.DataSourceVolcengineSecurityGroupRules(), + "volcengine_network_interfaces": network_interface.DataSourceVolcengineNetworkInterfaces(), + "volcengine_network_acls": network_acl.DataSourceVolcengineNetworkAcls(), + "volcengine_vpc_ipv6_gateways": ipv6_gateway.DataSourceVolcengineIpv6Gateways(), + "volcengine_vpc_ipv6_address_bandwidths": ipv6_address_bandwidth.DataSourceVolcengineIpv6AddressBandwidths(), // ================ EIP ================ "volcengine_eip_addresses": eip_address.DataSourceVolcengineEipAddresses(), @@ -316,17 +320,19 @@ func Provider() terraform.ResourceProvider { "volcengine_rds_mysql_allowlists": allowlist.DataSourceVolcengineRdsMysqlAllowLists(), }, ResourcesMap: map[string]*schema.Resource{ - "volcengine_vpc": vpc.ResourceVolcengineVpc(), - "volcengine_subnet": subnet.ResourceVolcengineSubnet(), - "volcengine_route_table": route_table.ResourceVolcengineRouteTable(), - "volcengine_route_entry": route_entry.ResourceVolcengineRouteEntry(), - "volcengine_route_table_associate": route_table_associate.ResourceVolcengineRouteTableAssociate(), - "volcengine_security_group": security_group.ResourceVolcengineSecurityGroup(), - "volcengine_network_interface": network_interface.ResourceVolcengineNetworkInterface(), - "volcengine_network_interface_attach": network_interface_attach.ResourceVolcengineNetworkInterfaceAttach(), - "volcengine_security_group_rule": security_group_rule.ResourceVolcengineSecurityGroupRule(), - "volcengine_network_acl": network_acl.ResourceVolcengineNetworkAcl(), - "volcengine_network_acl_associate": network_acl_associate.ResourceVolcengineNetworkAclAssociate(), + "volcengine_vpc": vpc.ResourceVolcengineVpc(), + "volcengine_subnet": subnet.ResourceVolcengineSubnet(), + "volcengine_route_table": route_table.ResourceVolcengineRouteTable(), + "volcengine_route_entry": route_entry.ResourceVolcengineRouteEntry(), + "volcengine_route_table_associate": route_table_associate.ResourceVolcengineRouteTableAssociate(), + "volcengine_security_group": security_group.ResourceVolcengineSecurityGroup(), + "volcengine_network_interface": network_interface.ResourceVolcengineNetworkInterface(), + "volcengine_network_interface_attach": network_interface_attach.ResourceVolcengineNetworkInterfaceAttach(), + "volcengine_security_group_rule": security_group_rule.ResourceVolcengineSecurityGroupRule(), + "volcengine_network_acl": network_acl.ResourceVolcengineNetworkAcl(), + "volcengine_network_acl_associate": network_acl_associate.ResourceVolcengineNetworkAclAssociate(), + "volcengine_vpc_ipv6_gateway": ipv6_gateway.ResourceVolcengineIpv6Gateway(), + "volcengine_vpc_ipv6_address_bandwidth": ipv6_address_bandwidth.ResourceVolcengineIpv6AddressBandwidth(), // ================ EIP ================ "volcengine_eip_address": eip_address.ResourceVolcengineEipAddress(), diff --git a/volcengine/vpc/ipv6_address_bandwidth/data_source_volcengine_vpc_ipv6_address_bandwidths.go b/volcengine/vpc/ipv6_address_bandwidth/data_source_volcengine_vpc_ipv6_address_bandwidths.go new file mode 100644 index 00000000..8e94215f --- /dev/null +++ b/volcengine/vpc/ipv6_address_bandwidth/data_source_volcengine_vpc_ipv6_address_bandwidths.go @@ -0,0 +1,161 @@ +package ipv6_address_bandwidth + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineIpv6AddressBandwidths() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineIpv6AddressBandwidthsRead, + Schema: map[string]*schema.Schema{ + "ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "Allocation IDs of the Ipv6 address width.", + }, + "associated_instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of the associated instance.", + }, + "associated_instance_type": { + Type: schema.TypeString, + Optional: true, + Description: "The type of the associated instance.", + }, + "isp": { + Type: schema.TypeString, + Optional: true, + Description: "ISP of the ipv6 address.", + }, + "ipv6_addresses": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "The ipv6 addresses.", + }, + "network_type": { + Type: schema.TypeString, + Optional: true, + Description: "The network type of the ipv6 address.", + }, + "vpc_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of Vpc the ipv6 address in.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of Ipv6AddressBandwidth query.", + }, + "ipv6_address_bandwidths": { + Description: "The collection of Ipv6AddressBandwidth query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the Ipv6AddressBandwidth.", + }, + "allocation_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the Ipv6AddressBandwidth.", + }, + "bandwidth": { + Type: schema.TypeInt, + Computed: true, + Description: "Peek bandwidth of the Ipv6 address.", + }, + "billing_type": { + Type: schema.TypeInt, + Computed: true, + Description: "BillingType of the Ipv6 bandwidth.", + }, + "business_status": { + Type: schema.TypeString, + Computed: true, + Description: "The BusinessStatus of the Ipv6AddressBandwidth.", + }, + "isp": { + Type: schema.TypeString, + Computed: true, + Description: "The ISP of the Ipv6AddressBandwidth.", + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the associated instance.", + }, + "instance_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the associated instance.", + }, + "ipv6_address": { + Type: schema.TypeString, + Computed: true, + Description: "The IPv6 address.", + }, + "lock_reason": { + Type: schema.TypeString, + Computed: true, + Description: "The BusinessStatus of the Ipv6AddressBandwidth.", + }, + "network_type": { + Type: schema.TypeString, + Computed: true, + Description: "The network type of the Ipv6AddressBandwidth.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the Ipv6AddressBandwidth.", + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + Description: "Creation time of the Ipv6AddressBandwidth.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "Update time of the Ipv6AddressBandwidth.", + }, + "overdue_time": { + Type: schema.TypeString, + Computed: true, + Description: "Overdue time of the Ipv6AddressBandwidth.", + }, + "delete_time": { + Type: schema.TypeString, + Computed: true, + Description: "Delete time of the Ipv6AddressBandwidth.", + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineIpv6AddressBandwidthsRead(d *schema.ResourceData, meta interface{}) error { + ipv6AddressBandwidthService := NewIpv6AddressBandwidthService(meta.(*ve.SdkClient)) + return ipv6AddressBandwidthService.Dispatcher.Data(ipv6AddressBandwidthService, d, DataSourceVolcengineIpv6AddressBandwidths()) +} diff --git a/volcengine/vpc/ipv6_address_bandwidth/resource_volcengine_vpc_ipv6_address_bandwidth.go b/volcengine/vpc/ipv6_address_bandwidth/resource_volcengine_vpc_ipv6_address_bandwidth.go new file mode 100644 index 00000000..bd57b6ca --- /dev/null +++ b/volcengine/vpc/ipv6_address_bandwidth/resource_volcengine_vpc_ipv6_address_bandwidth.go @@ -0,0 +1,96 @@ +package ipv6_address_bandwidth + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Ipv6AddressBandwidth can be imported using the id, e.g. +``` +$ terraform import volcengine_vpc_ipv6_address_bandwidth.default eip-2fede9fsgnr4059gp674m6ney +``` + +*/ + +func ResourceVolcengineIpv6AddressBandwidth() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineIpv6AddressBandwidthCreate, + Read: resourceVolcengineIpv6AddressBandwidthRead, + Update: resourceVolcengineIpv6AddressBandwidthUpdate, + Delete: resourceVolcengineIpv6AddressBandwidthDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "ipv6_address": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Ipv6 address.", + }, + "billing_type": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "BillingType of the Ipv6 bandwidth. Valid values: 3(Pay by Traffic).", + }, + "bandwidth": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "Peek bandwidth of the Ipv6 address. Valid values: 1 to 200. Unit: Mbit/s.", + }, + }, + } + dataSource := DataSourceVolcengineIpv6AddressBandwidths().Schema["ipv6_address_bandwidths"].Elem.(*schema.Resource).Schema + delete(dataSource, "id") + ve.MergeDateSourceToResource(dataSource, &resource.Schema) + return resource +} + +func resourceVolcengineIpv6AddressBandwidthCreate(d *schema.ResourceData, meta interface{}) (err error) { + ipv6AddressBandwidthService := NewIpv6AddressBandwidthService(meta.(*ve.SdkClient)) + err = ipv6AddressBandwidthService.Dispatcher.Create(ipv6AddressBandwidthService, d, ResourceVolcengineIpv6AddressBandwidth()) + if err != nil { + return fmt.Errorf("error on creating Ipv6AddressBandwidth %q, %w", d.Id(), err) + } + return resourceVolcengineIpv6AddressBandwidthRead(d, meta) +} + +func resourceVolcengineIpv6AddressBandwidthRead(d *schema.ResourceData, meta interface{}) (err error) { + ipv6AddressBandwidthService := NewIpv6AddressBandwidthService(meta.(*ve.SdkClient)) + err = ipv6AddressBandwidthService.Dispatcher.Read(ipv6AddressBandwidthService, d, ResourceVolcengineIpv6AddressBandwidth()) + if err != nil { + return fmt.Errorf("error on reading Ipv6AddressBandwidth %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineIpv6AddressBandwidthUpdate(d *schema.ResourceData, meta interface{}) (err error) { + ipv6AddressBandwidthService := NewIpv6AddressBandwidthService(meta.(*ve.SdkClient)) + err = ipv6AddressBandwidthService.Dispatcher.Update(ipv6AddressBandwidthService, d, ResourceVolcengineIpv6AddressBandwidth()) + if err != nil { + return fmt.Errorf("error on updating Ipv6AddressBandwidth %q, %w", d.Id(), err) + } + return resourceVolcengineIpv6AddressBandwidthRead(d, meta) +} + +func resourceVolcengineIpv6AddressBandwidthDelete(d *schema.ResourceData, meta interface{}) (err error) { + ipv6AddressBandwidthService := NewIpv6AddressBandwidthService(meta.(*ve.SdkClient)) + err = ipv6AddressBandwidthService.Dispatcher.Delete(ipv6AddressBandwidthService, d, ResourceVolcengineIpv6AddressBandwidth()) + if err != nil { + return fmt.Errorf("error on deleting Ipv6AddressBandwidth %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/vpc/ipv6_address_bandwidth/service_volcengine_vpc_ipv6_address_bandwidth.go b/volcengine/vpc/ipv6_address_bandwidth/service_volcengine_vpc_ipv6_address_bandwidth.go new file mode 100644 index 00000000..b2bed3c1 --- /dev/null +++ b/volcengine/vpc/ipv6_address_bandwidth/service_volcengine_vpc_ipv6_address_bandwidth.go @@ -0,0 +1,267 @@ +package ipv6_address_bandwidth + +import ( + "errors" + "fmt" + "time" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineIpv6AddressBandwidthService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewIpv6AddressBandwidthService(c *ve.SdkClient) *VolcengineIpv6AddressBandwidthService { + return &VolcengineIpv6AddressBandwidthService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineIpv6AddressBandwidthService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineIpv6AddressBandwidthService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(condition, "PageSize", "PageNumber", 20, 1, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeIpv6AddressBandwidths" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + logger.Debug(logger.RespFormat, action, condition, *resp) + + results, err = ve.ObtainSdkValue("Result.Ipv6AddressBandwidths", *resp) + if err != nil { + return data, err + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Ipv6AddressBandwidths is not Slice") + } + + return data, err + }) +} + +func (s *VolcengineIpv6AddressBandwidthService) ReadResource(resourceData *schema.ResourceData, allocationId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if allocationId == "" { + allocationId = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "AllocationIds.1": allocationId, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("Ipv6AddressBandwidth %s is not exist ", allocationId) + } + + return data, err +} + +func (s *VolcengineIpv6AddressBandwidthService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + demo map[string]interface{} + status interface{} + ) + //no failed status. + demo, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", demo) + if err != nil { + return nil, "", err + } + return demo, status.(string), err + }, + } +} + +func (VolcengineIpv6AddressBandwidthService) WithResourceResponseHandlers(ipv6AddressBandwidth map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return ipv6AddressBandwidth, map[string]ve.ResponseConvert{ + "ISP": { + TargetField: "isp", + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} + +} + +func (s *VolcengineIpv6AddressBandwidthService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AllocateIpv6AddressBandwidth", + ConvertMode: ve.RequestConvertAll, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["ClientToken"] = uuid.New().String() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.AllocationId", *resp) + d.SetId(id.(string)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + return callbacks +} + +func (s *VolcengineIpv6AddressBandwidthService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyIpv6AddressBandwidth", + ConvertMode: ve.RequestConvertAll, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["AllocationId"] = d.Id() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + return callbacks +} + +func (s *VolcengineIpv6AddressBandwidthService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ReleaseIpv6AddressBandwidth", + ConvertMode: ve.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "AllocationId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading Ipv6AddressBandwidth on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + return callbacks +} + +func (s *VolcengineIpv6AddressBandwidthService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{ + "ids": { + TargetField: "AllocationIds", + ConvertType: ve.ConvertWithN, + }, + "isp": { + TargetField: "ISP", + }, + "ipv6_addresses": { + TargetField: "Ipv6Addresses", + ConvertType: ve.ConvertWithN, + }, + }, + IdField: "AllocationId", + CollectField: "ipv6_address_bandwidths", + ResponseConverts: map[string]ve.ResponseConvert{ + "AllocationId": { + TargetField: "id", + KeepDefault: true, + }, + "ISP": { + TargetField: "isp", + }, + }, + } +} + +func (s *VolcengineIpv6AddressBandwidthService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/vpc/ipv6_gateway/data_source_volcengine_vpc_ipv6_gateways.go b/volcengine/vpc/ipv6_gateway/data_source_volcengine_vpc_ipv6_gateways.go new file mode 100644 index 00000000..ee1e5ff7 --- /dev/null +++ b/volcengine/vpc/ipv6_gateway/data_source_volcengine_vpc_ipv6_gateways.go @@ -0,0 +1,108 @@ +package ipv6_gateway + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineIpv6Gateways() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineIpv6GatewaysRead, + Schema: map[string]*schema.Schema{ + "ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "The ID list of the Ipv6Gateways.", + }, + "name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the Ipv6Gateway.", + }, + "vpc_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "The ID list of the VPC which the Ipv6Gateway belongs to.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of the Ipv6Gateway.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of Ipv6Gateway query.", + }, + "ipv6_gateways": { + Description: "The collection of Ipv6Gateway query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the Ipv6Gateway.", + }, + "ipv6_gateway_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the Ipv6Gateway.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "The Name of the Ipv6Gateway.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the Ipv6Gateway.", + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the VPC which the Ipv6Gateway belongs to.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "The Status of the Ipv6Gateway.", + }, + "creation_time": { + Type: schema.TypeString, + Computed: true, + Description: "Creation time of the Ipv6Gateway.", + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "Update time of the Ipv6Gateway.", + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineIpv6GatewaysRead(d *schema.ResourceData, meta interface{}) error { + ipv6GatewayService := NewIpv6GatewayService(meta.(*ve.SdkClient)) + return ipv6GatewayService.Dispatcher.Data(ipv6GatewayService, d, DataSourceVolcengineIpv6Gateways()) +} diff --git a/volcengine/vpc/ipv6_gateway/resource_volcengine_vpc_ipv6_gateway.go b/volcengine/vpc/ipv6_gateway/resource_volcengine_vpc_ipv6_gateway.go new file mode 100644 index 00000000..995212de --- /dev/null +++ b/volcengine/vpc/ipv6_gateway/resource_volcengine_vpc_ipv6_gateway.go @@ -0,0 +1,91 @@ +package ipv6_gateway + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +Ipv6Gateway can be imported using the id, e.g. +``` +$ terraform import volcengine_vpc_ipv6_gateway.default ipv6gw-12bcapllb5ukg17q7y2sd3thx +``` + +*/ + +func ResourceVolcengineIpv6Gateway() *schema.Resource { + return &schema.Resource{ + Create: resourceVolcengineIpv6GatewayCreate, + Read: resourceVolcengineIpv6GatewayRead, + Update: resourceVolcengineIpv6GatewayUpdate, + Delete: resourceVolcengineIpv6GatewayDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "vpc_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The ID of the VPC which the Ipv6Gateway belongs to.", + }, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The name of the Ipv6Gateway.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the Ipv6Gateway.", + }, + }, + } +} + +func resourceVolcengineIpv6GatewayCreate(d *schema.ResourceData, meta interface{}) (err error) { + ipv6GatewayService := NewIpv6GatewayService(meta.(*ve.SdkClient)) + err = ipv6GatewayService.Dispatcher.Create(ipv6GatewayService, d, ResourceVolcengineIpv6Gateway()) + if err != nil { + return fmt.Errorf("error on creating Ipv6Gateway %q, %w", d.Id(), err) + } + return resourceVolcengineIpv6GatewayRead(d, meta) +} + +func resourceVolcengineIpv6GatewayRead(d *schema.ResourceData, meta interface{}) (err error) { + ipv6GatewayService := NewIpv6GatewayService(meta.(*ve.SdkClient)) + err = ipv6GatewayService.Dispatcher.Read(ipv6GatewayService, d, ResourceVolcengineIpv6Gateway()) + if err != nil { + return fmt.Errorf("error on reading Ipv6Gateway %q, %w", d.Id(), err) + } + return err +} + +func resourceVolcengineIpv6GatewayUpdate(d *schema.ResourceData, meta interface{}) (err error) { + ipv6GatewayService := NewIpv6GatewayService(meta.(*ve.SdkClient)) + err = ipv6GatewayService.Dispatcher.Update(ipv6GatewayService, d, ResourceVolcengineIpv6Gateway()) + if err != nil { + return fmt.Errorf("error on updating Ipv6Gateway %q, %w", d.Id(), err) + } + return resourceVolcengineIpv6GatewayRead(d, meta) +} + +func resourceVolcengineIpv6GatewayDelete(d *schema.ResourceData, meta interface{}) (err error) { + ipv6GatewayService := NewIpv6GatewayService(meta.(*ve.SdkClient)) + err = ipv6GatewayService.Dispatcher.Delete(ipv6GatewayService, d, ResourceVolcengineIpv6Gateway()) + if err != nil { + return fmt.Errorf("error on deleting Ipv6Gateway %q, %w", d.Id(), err) + } + return err +} diff --git a/volcengine/vpc/ipv6_gateway/service_volcengine_vpc_ipv6_gateway.go b/volcengine/vpc/ipv6_gateway/service_volcengine_vpc_ipv6_gateway.go new file mode 100644 index 00000000..cdf56690 --- /dev/null +++ b/volcengine/vpc/ipv6_gateway/service_volcengine_vpc_ipv6_gateway.go @@ -0,0 +1,258 @@ +package ipv6_gateway + +import ( + "errors" + "fmt" + "time" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineIpv6GatewayService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewIpv6GatewayService(c *ve.SdkClient) *VolcengineIpv6GatewayService { + return &VolcengineIpv6GatewayService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineIpv6GatewayService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineIpv6GatewayService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(condition, "PageSize", "PageNumber", 20, 1, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeIpv6Gateways" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + logger.Debug(logger.RespFormat, action, condition, *resp) + + results, err = ve.ObtainSdkValue("Result.Ipv6Gateways", *resp) + if err != nil { + return data, err + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Ipv6Gateways is not Slice") + } + + return data, err + }) +} + +func (s *VolcengineIpv6GatewayService) ReadResource(resourceData *schema.ResourceData, ipv6GatewayId string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if ipv6GatewayId == "" { + ipv6GatewayId = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "Ipv6GatewayIds.1": ipv6GatewayId, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("Ipv6Gateway %s is not exist ", ipv6GatewayId) + } + + return data, err +} + +func (s *VolcengineIpv6GatewayService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + demo map[string]interface{} + status interface{} + ) + //no failed status. + demo, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", demo) + if err != nil { + return nil, "", err + } + return demo, status.(string), err + }, + } +} + +func (VolcengineIpv6GatewayService) WithResourceResponseHandlers(ipv6Gateway map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return ipv6Gateway, nil, nil + } + return []ve.ResourceResponseHandler{handler} + +} + +func (s *VolcengineIpv6GatewayService) CreateResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateIpv6Gateway", + ConvertMode: ve.RequestConvertAll, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["ClientToken"] = uuid.New().String() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.Ipv6GatewayId", *resp) + d.SetId(id.(string)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + return callbacks +} + +func (s *VolcengineIpv6GatewayService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyIpv6GatewayAttribute", + ConvertMode: ve.RequestConvertAll, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["Ipv6GatewayId"] = d.Id() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, callback) + + return callbacks +} + +func (s *VolcengineIpv6GatewayService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteIpv6Gateway", + ConvertMode: ve.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "Ipv6GatewayId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading Ipv6Gateway on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + return callbacks +} + +func (s *VolcengineIpv6GatewayService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{ + "ids": { + TargetField: "Ipv6GatewayIds", + ConvertType: ve.ConvertWithN, + }, + "vpc_ids": { + TargetField: "VpcIds", + ConvertType: ve.ConvertWithN, + }, + }, + NameField: "Name", + IdField: "Ipv6GatewayId", + CollectField: "ipv6_gateways", + ResponseConverts: map[string]ve.ResponseConvert{ + "Ipv6GatewayId": { + TargetField: "id", + KeepDefault: true, + }, + }, + } +} + +func (s *VolcengineIpv6GatewayService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + ContentType: ve.Default, + Action: actionName, + } +} diff --git a/volcengine/vpc/subnet/data_source_volcengine_subnets.go b/volcengine/vpc/subnet/data_source_volcengine_subnets.go index 56bcda8d..613c6553 100644 --- a/volcengine/vpc/subnet/data_source_volcengine_subnets.go +++ b/volcengine/vpc/subnet/data_source_volcengine_subnets.go @@ -136,6 +136,11 @@ func DataSourceVolcengineSubnets() *schema.Resource { Computed: true, Description: "The ID of network acl which this subnet associate with.", }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Computed: true, + Description: "The IPv6 CIDR block of the VPC.", + }, "route_table": { Type: schema.TypeSet, MaxItems: 1, diff --git a/volcengine/vpc/subnet/resource_volcengine_subnet.go b/volcengine/vpc/subnet/resource_volcengine_subnet.go index cd75c401..d750d18b 100644 --- a/volcengine/vpc/subnet/resource_volcengine_subnet.go +++ b/volcengine/vpc/subnet/resource_volcengine_subnet.go @@ -69,6 +69,31 @@ func ResourceVolcengineSubnet() *schema.Resource { ForceNew: true, Description: "Id of the Zone.", }, + "enable_ipv6": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + // 创建时不存在这个参数,修改时存在这个参数 + return d.Id() == "" + }, + Description: "Specifies whether to enable the IPv6 CIDR block of the Subnet. This field is only valid when modifying the Subnet.", + }, + "ipv6_cidr_block": { + Type: schema.TypeInt, + Optional: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if d.Id() == "" { + return false + } else { + if d.HasChange("enable_ipv6") && d.Get("enable_ipv6").(bool) { + return false + } + return true + } + }, + Description: "The last eight bits of the IPv6 CIDR block of the Subnet. Valid values: 0 - 255.", + }, "creation_time": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/vpc/subnet/service_volcengine_subnet.go b/volcengine/vpc/subnet/service_volcengine_subnet.go index c718238b..985a8a2a 100644 --- a/volcengine/vpc/subnet/service_volcengine_subnet.go +++ b/volcengine/vpc/subnet/service_volcengine_subnet.go @@ -3,6 +3,9 @@ package subnet import ( "errors" "fmt" + "net" + "strconv" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -87,6 +90,31 @@ func (s *VolcengineSubnetService) ReadResource(resourceData *schema.ResourceData if len(data) == 0 { return data, fmt.Errorf("Subnet %s not exist ", subnetId) } + + if ipv6CidrBlock, ok1 := data["Ipv6CidrBlock"]; ok1 && ipv6CidrBlock.(string) != "" { + data["EnableIpv6"] = true + + ipv6Address, _, err := net.ParseCIDR(ipv6CidrBlock.(string)) + if err != nil { + return data, err + } + bits := strings.Split(ipv6Address.String(), ":") + if len(bits) < 4 { + data["Ipv6CidrBlock"] = 0 + } else { + temp := bits[3] + temp = strings.Repeat("0", 4-len(temp)) + temp + ipv6CidrValue, err := strconv.ParseInt(temp[2:], 16, 9) + if err != nil { + return data, err + } + data["Ipv6CidrBlock"] = int(ipv6CidrValue) + } + } else { + data["EnableIpv6"] = false + delete(data, "Ipv6CidrBlock") + } + return data, err } diff --git a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go index 674353b3..6bfd3541 100644 --- a/volcengine/vpc/vpc/data_source_volcengine_vpcs.go +++ b/volcengine/vpc/vpc/data_source_volcengine_vpcs.go @@ -175,6 +175,11 @@ func DataSourceVolcengineVpcs() *schema.Resource { Set: schema.HashString, Description: "The auxiliary cidr block list of VPC.", }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Computed: true, + Description: "The IPv6 CIDR block of the VPC.", + }, "project_name": { Type: schema.TypeString, Computed: true, diff --git a/volcengine/vpc/vpc/resource_volcengine_vpc.go b/volcengine/vpc/vpc/resource_volcengine_vpc.go index dbc895fc..740ea7bb 100644 --- a/volcengine/vpc/vpc/resource_volcengine_vpc.go +++ b/volcengine/vpc/vpc/resource_volcengine_vpc.go @@ -62,6 +62,24 @@ func ResourceVolcengineVpc() *schema.Resource { Set: schema.HashString, Description: "The DNS server list of the VPC. And you can specify 0 to 5 servers to this list.", }, + "enable_ipv6": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Specifies whether to enable the IPv6 CIDR block of the VPC.", + }, + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if d.HasChange("enable_ipv6") && d.Get("enable_ipv6").(bool) { + return false + } + return true + }, + Description: "The IPv6 CIDR block of the VPC.", + }, "project_name": { Type: schema.TypeString, Optional: true, diff --git a/volcengine/vpc/vpc/service_volcengine_vpc.go b/volcengine/vpc/vpc/service_volcengine_vpc.go index 85fff040..7a207aba 100644 --- a/volcengine/vpc/vpc/service_volcengine_vpc.go +++ b/volcengine/vpc/vpc/service_volcengine_vpc.go @@ -89,6 +89,13 @@ func (s *VolcengineVpcService) ReadResource(resourceData *schema.ResourceData, v if _, ok1 := data["AuxiliaryCidrBlocks"]; !ok1 { data["AuxiliaryCidrBlocks"] = []string{} } + + if ipv6CidrBlock, ok2 := data["Ipv6CidrBlock"]; ok2 && ipv6CidrBlock != "" { + data["EnableIpv6"] = true + } else { + data["EnableIpv6"] = false + } + return data, err } diff --git a/website/docs/d/subnets.html.markdown b/website/docs/d/subnets.html.markdown index faa5cfbc..f99db349 100644 --- a/website/docs/d/subnets.html.markdown +++ b/website/docs/d/subnets.html.markdown @@ -33,6 +33,7 @@ In addition to all arguments above, the following attributes are exported: * `creation_time` - Creation time of Subnet. * `description` - The description of Subnet. * `id` - The ID of Subnet. + * `ipv6_cidr_block` - The IPv6 CIDR block of the VPC. * `network_acl_id` - The ID of network acl which this subnet associate with. * `route_table_id` - The ID of route table. * `route_table_type` - The type of route table. diff --git a/website/docs/d/vpc_ipv6_address_bandwidths.html.markdown b/website/docs/d/vpc_ipv6_address_bandwidths.html.markdown new file mode 100644 index 00000000..39831e85 --- /dev/null +++ b/website/docs/d/vpc_ipv6_address_bandwidths.html.markdown @@ -0,0 +1,49 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_vpc_ipv6_address_bandwidths" +sidebar_current: "docs-volcengine-datasource-vpc_ipv6_address_bandwidths" +description: |- + Use this data source to query detailed information of vpc ipv6 address bandwidths +--- +# volcengine_vpc_ipv6_address_bandwidths +Use this data source to query detailed information of vpc ipv6 address bandwidths +## Example Usage +```hcl +data "volcengine_vpc_ipv6_address_bandwidths" "default" { + ids = ["eip-in2y2duvtlhc8gbssyfnhfre"] +} +``` +## Argument Reference +The following arguments are supported: +* `associated_instance_id` - (Optional) The ID of the associated instance. +* `associated_instance_type` - (Optional) The type of the associated instance. +* `ids` - (Optional) Allocation IDs of the Ipv6 address width. +* `ipv6_addresses` - (Optional) The ipv6 addresses. +* `isp` - (Optional) ISP of the ipv6 address. +* `network_type` - (Optional) The network type of the ipv6 address. +* `output_file` - (Optional) File name where to save data source results. +* `vpc_id` - (Optional) The ID of Vpc the ipv6 address in. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `ipv6_address_bandwidths` - The collection of Ipv6AddressBandwidth query. + * `allocation_id` - The ID of the Ipv6AddressBandwidth. + * `bandwidth` - Peek bandwidth of the Ipv6 address. + * `billing_type` - BillingType of the Ipv6 bandwidth. + * `business_status` - The BusinessStatus of the Ipv6AddressBandwidth. + * `creation_time` - Creation time of the Ipv6AddressBandwidth. + * `delete_time` - Delete time of the Ipv6AddressBandwidth. + * `id` - The ID of the Ipv6AddressBandwidth. + * `instance_id` - The ID of the associated instance. + * `instance_type` - The type of the associated instance. + * `ipv6_address` - The IPv6 address. + * `isp` - The ISP of the Ipv6AddressBandwidth. + * `lock_reason` - The BusinessStatus of the Ipv6AddressBandwidth. + * `network_type` - The network type of the Ipv6AddressBandwidth. + * `overdue_time` - Overdue time of the Ipv6AddressBandwidth. + * `status` - The status of the Ipv6AddressBandwidth. + * `update_time` - Update time of the Ipv6AddressBandwidth. +* `total_count` - The total count of Ipv6AddressBandwidth query. + + diff --git a/website/docs/d/vpc_ipv6_gateways.html.markdown b/website/docs/d/vpc_ipv6_gateways.html.markdown new file mode 100644 index 00000000..928448f4 --- /dev/null +++ b/website/docs/d/vpc_ipv6_gateways.html.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_vpc_ipv6_gateways" +sidebar_current: "docs-volcengine-datasource-vpc_ipv6_gateways" +description: |- + Use this data source to query detailed information of vpc ipv6 gateways +--- +# volcengine_vpc_ipv6_gateways +Use this data source to query detailed information of vpc ipv6 gateways +## Example Usage +```hcl +data "volcengine_vpc_ipv6_gateways" "default" { + ids = ["ipv6gw-12bcapllb5ukg17q7y2sd3thx"] +} +``` +## Argument Reference +The following arguments are supported: +* `ids` - (Optional) The ID list of the Ipv6Gateways. +* `name_regex` - (Optional) A Name Regex of the Ipv6Gateway. +* `name` - (Optional) The name of the Ipv6Gateway. +* `output_file` - (Optional) File name where to save data source results. +* `vpc_ids` - (Optional) The ID list of the VPC which the Ipv6Gateway belongs to. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `ipv6_gateways` - The collection of Ipv6Gateway query. + * `creation_time` - Creation time of the Ipv6Gateway. + * `description` - The description of the Ipv6Gateway. + * `id` - The ID of the Ipv6Gateway. + * `ipv6_gateway_id` - The ID of the Ipv6Gateway. + * `name` - The Name of the Ipv6Gateway. + * `status` - The Status of the Ipv6Gateway. + * `update_time` - Update time of the Ipv6Gateway. + * `vpc_id` - The id of the VPC which the Ipv6Gateway belongs to. +* `total_count` - The total count of Ipv6Gateway query. + + diff --git a/website/docs/d/vpcs.html.markdown b/website/docs/d/vpcs.html.markdown index 31cdc3a3..18b735e6 100644 --- a/website/docs/d/vpcs.html.markdown +++ b/website/docs/d/vpcs.html.markdown @@ -42,6 +42,7 @@ In addition to all arguments above, the following attributes are exported: * `creation_time` - The create time of VPC. * `description` - The description of VPC. * `dns_servers` - The dns server list of VPC. + * `ipv6_cidr_block` - The IPv6 CIDR block of the VPC. * `nat_gateway_ids` - The nat gateway ID list of VPC. * `project_name` - The ProjectName of the VPC. * `route_table_ids` - The route table ID list of VPC. diff --git a/website/docs/r/ecs_instance.html.markdown b/website/docs/r/ecs_instance.html.markdown index 3738d5b1..5435b5a1 100644 --- a/website/docs/r/ecs_instance.html.markdown +++ b/website/docs/r/ecs_instance.html.markdown @@ -68,6 +68,7 @@ The following arguments are supported: * `include_data_volumes` - (Optional) The include data volumes flag of ECS instance.Only effective when change instance charge type.include_data_volumes. * `instance_charge_type` - (Optional) The charge type of ECS instance, the value can be `PrePaid` or `PostPaid`. * `instance_name` - (Optional) The name of ECS instance. +* `ipv6_address_count` - (Optional, ForceNew) The ipv6 address count of ECS instance. Valid values: 0, 1. * `keep_image_credential` - (Optional) Whether to keep the mirror settings. Only custom images and shared images support this field. When the value of this field is true, the Password and KeyPairName cannot be specified. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. diff --git a/website/docs/r/subnet.html.markdown b/website/docs/r/subnet.html.markdown index 8b44b448..d088089d 100644 --- a/website/docs/r/subnet.html.markdown +++ b/website/docs/r/subnet.html.markdown @@ -23,6 +23,8 @@ The following arguments are supported: * `vpc_id` - (Required, ForceNew) Id of the VPC. * `zone_id` - (Required, ForceNew) Id of the Zone. * `description` - (Optional) The description of the Subnet. +* `enable_ipv6` - (Optional) Specifies whether to enable the IPv6 CIDR block of the Subnet. This field is only valid when modifying the Subnet. +* `ipv6_cidr_block` - (Optional) The last eight bits of the IPv6 CIDR block of the Subnet. Valid values: 0 - 255. * `subnet_name` - (Optional) The name of the Subnet. ## Attributes Reference diff --git a/website/docs/r/vpc.html.markdown b/website/docs/r/vpc.html.markdown index d22ee706..7482aee7 100644 --- a/website/docs/r/vpc.html.markdown +++ b/website/docs/r/vpc.html.markdown @@ -23,6 +23,9 @@ The following arguments are supported: * `description` - (Optional) The description of the VPC. * `dns_servers` - (Optional) The DNS server list of the VPC. And you can specify 0 to 5 servers to this list. * `project_name` - (Optional) The ProjectName of the VPC. +* `enable_ipv6` - (Optional) Specifies whether to enable the IPv6 CIDR block of the VPC. +* `ipv6_cidr_block` - (Optional) The IPv6 CIDR block of the VPC. +* `project_name` - (Optional, ForceNew) The ProjectName of the VPC. * `tags` - (Optional) Tags. * `vpc_name` - (Optional) The name of the VPC. diff --git a/website/docs/r/vpc_ipv6_address_bandwidth.html.markdown b/website/docs/r/vpc_ipv6_address_bandwidth.html.markdown new file mode 100644 index 00000000..11595798 --- /dev/null +++ b/website/docs/r/vpc_ipv6_address_bandwidth.html.markdown @@ -0,0 +1,47 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_vpc_ipv6_address_bandwidth" +sidebar_current: "docs-volcengine-resource-vpc_ipv6_address_bandwidth" +description: |- + Provides a resource to manage vpc ipv6 address bandwidth +--- +# volcengine_vpc_ipv6_address_bandwidth +Provides a resource to manage vpc ipv6 address bandwidth +## Example Usage +```hcl +resource "volcengine_vpc_ipv6_address_bandwidth" "foo" { + ipv6_address = "2000:1000:89ff:ff02:ea70:18ce:dda2:a02e" + billing_type = 3 + bandwidth = 5 +} +``` +## Argument Reference +The following arguments are supported: +* `billing_type` - (Required, ForceNew) BillingType of the Ipv6 bandwidth. Valid values: 3(Pay by Traffic). +* `ipv6_address` - (Required, ForceNew) Ipv6 address. +* `bandwidth` - (Optional) Peek bandwidth of the Ipv6 address. Valid values: 1 to 200. Unit: Mbit/s. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `allocation_id` - The ID of the Ipv6AddressBandwidth. +* `business_status` - The BusinessStatus of the Ipv6AddressBandwidth. +* `creation_time` - Creation time of the Ipv6AddressBandwidth. +* `delete_time` - Delete time of the Ipv6AddressBandwidth. +* `instance_id` - The ID of the associated instance. +* `instance_type` - The type of the associated instance. +* `isp` - The ISP of the Ipv6AddressBandwidth. +* `lock_reason` - The BusinessStatus of the Ipv6AddressBandwidth. +* `network_type` - The network type of the Ipv6AddressBandwidth. +* `overdue_time` - Overdue time of the Ipv6AddressBandwidth. +* `status` - The status of the Ipv6AddressBandwidth. +* `update_time` - Update time of the Ipv6AddressBandwidth. + + +## Import +Ipv6AddressBandwidth can be imported using the id, e.g. +``` +$ terraform import volcengine_vpc_ipv6_address_bandwidth.default eip-2fede9fsgnr4059gp674m6ney +``` + diff --git a/website/docs/r/vpc_ipv6_gateway.html.markdown b/website/docs/r/vpc_ipv6_gateway.html.markdown new file mode 100644 index 00000000..be7ae640 --- /dev/null +++ b/website/docs/r/vpc_ipv6_gateway.html.markdown @@ -0,0 +1,36 @@ +--- +subcategory: "VPC" +layout: "volcengine" +page_title: "Volcengine: volcengine_vpc_ipv6_gateway" +sidebar_current: "docs-volcengine-resource-vpc_ipv6_gateway" +description: |- + Provides a resource to manage vpc ipv6 gateway +--- +# volcengine_vpc_ipv6_gateway +Provides a resource to manage vpc ipv6 gateway +## Example Usage +```hcl +resource "volcengine_vpc_ipv6_gateway" "foo" { + vpc_id = "vpc-12afxho4sxyio17q7y2kkp8ej" + name = "tf-test-1" + description = "test" +} +``` +## Argument Reference +The following arguments are supported: +* `vpc_id` - (Required, ForceNew) The ID of the VPC which the Ipv6Gateway belongs to. +* `description` - (Optional) The description of the Ipv6Gateway. +* `name` - (Optional) The name of the Ipv6Gateway. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +Ipv6Gateway can be imported using the id, e.g. +``` +$ terraform import volcengine_vpc_ipv6_gateway.default ipv6gw-12bcapllb5ukg17q7y2sd3thx +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index faa6e3a8..dac2904f 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -736,6 +736,12 @@
  • Data Sources