diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index e1b52bef..5c5dd1ee 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.82" + TerraformProviderVersion = "0.0.83" ) diff --git a/example/securityGroupRule/main.tf b/example/securityGroupRule/main.tf index 740351ca..e3b75f65 100644 --- a/example/securityGroupRule/main.tf +++ b/example/securityGroupRule/main.tf @@ -1,8 +1,53 @@ resource "volcengine_security_group_rule" "g1test3" { - direction = "egress" - security_group_id = "sg-273ycgql3ig3k7fap8t3dyvqx" - protocol = "tcp" - port_start = "8000" - port_end = "9003" - cidr_ip = "10.0.0.0/8" + direction = "egress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + cidr_ip = "10.0.0.0/8" + description = "tft1234" +} + +resource "volcengine_security_group_rule" "g1test2" { + direction = "egress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + cidr_ip = "10.0.0.0/24" +} + +resource "volcengine_security_group_rule" "g1test1" { + direction = "egress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + cidr_ip = "10.0.0.0/24" + priority = 2 +} + + +resource "volcengine_security_group_rule" "g1test0" { + direction = "ingress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 80 + port_end = 80 + cidr_ip = "10.0.0.0/24" + priority = 2 + policy = "drop" + description = "tft" +} + +resource "volcengine_security_group_rule" "g1test06" { + direction = "ingress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + source_group_id = "sg-3rfe5j4xdnklc5zsk2hcw5c6q" + priority = 2 + policy = "drop" + description = "tft" } \ No newline at end of file diff --git a/volcengine/vpc/security_group_rule/resource_volcengine_security_group_rule.go b/volcengine/vpc/security_group_rule/resource_volcengine_security_group_rule.go index f14d53aa..ed1e20df 100644 --- a/volcengine/vpc/security_group_rule/resource_volcengine_security_group_rule.go +++ b/volcengine/vpc/security_group_rule/resource_volcengine_security_group_rule.go @@ -2,6 +2,8 @@ package security_group_rule import ( "fmt" + "strconv" + "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -14,7 +16,7 @@ import ( Import SecurityGroupRule can be imported using the id, e.g. ``` -$ terraform import volcengine_security_group_rule.default ID is a string concatenated with colons(SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp) +$ terraform import volcengine_security_group_rule.default ID is a string concatenated with colons(SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp:SourceGroupId:Direction:Policy:Priority) ``` */ @@ -60,6 +62,7 @@ func ResourceVolcengineSecurityGroupRule() *schema.Resource { "security_group_id": { Type: schema.TypeString, Required: true, + ForceNew: true, Description: "Id of SecurityGroup.", }, "port_start": { @@ -77,20 +80,18 @@ func ResourceVolcengineSecurityGroupRule() *schema.Resource { Description: "Port end of egress/ingress Rule.", }, "cidr_ip": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "Cidr ip of egress/ingress Rule.", - }, - "status": { - Type: schema.TypeString, - Computed: true, - Description: "Status of SecurityGroup.", + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"source_group_id"}, + Description: "Cidr ip of egress/ingress Rule.", }, "source_group_id": { - Type: schema.TypeString, - Optional: true, - Description: "ID of the source security group whose access permission you want to set.", + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"cidr_ip"}, + Description: "ID of the source security group whose access permission you want to set.", }, "policy": { Type: schema.TypeString, @@ -107,6 +108,7 @@ func ResourceVolcengineSecurityGroupRule() *schema.Resource { Type: schema.TypeInt, Optional: true, Default: 1, + ForceNew: true, ValidateFunc: validation.IntBetween(1, 100), Description: "Priority of a security group rule.", }, @@ -115,10 +117,86 @@ func ResourceVolcengineSecurityGroupRule() *schema.Resource { Optional: true, Description: "description of a egress rule.", }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "Status of SecurityGroup.", + }, }, } } +func importSecurityGroupRule(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + var err error + items := strings.Split(d.Id(), ":") + if len(items) != 9 { + return []*schema.ResourceData{d}, fmt.Errorf("import id must be of the form " + + "SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp:SourceGroupId:Direction:Policy:Priority") + } + err = d.Set("security_group_id", items[0]) + if err != nil { + return []*schema.ResourceData{d}, err + } + err = d.Set("protocol", items[1]) + if err != nil { + return []*schema.ResourceData{d}, err + } + + if len(items[2]) > 0 { + ps, err := strconv.Atoi(items[2]) + if err != nil { + return []*schema.ResourceData{d}, err + } + err = d.Set("port_start", ps) + if err != nil { + return []*schema.ResourceData{d}, err + } + } + + if len(items[3]) > 0 { + pn, err := strconv.Atoi(items[3]) + if err != nil { + return []*schema.ResourceData{d}, err + } + err = d.Set("port_end", pn) + if err != nil { + return []*schema.ResourceData{d}, err + } + } + + err = d.Set("cidr_ip", items[4]) + if err != nil { + return []*schema.ResourceData{d}, err + } + + err = d.Set("source_group_id", items[5]) + if err != nil { + return []*schema.ResourceData{d}, err + } + + err = d.Set("direction", items[6]) + if err != nil { + return []*schema.ResourceData{d}, err + } + + err = d.Set("policy", items[7]) + if err != nil { + return []*schema.ResourceData{d}, err + } + + if len(items[8]) > 0 { + pr, err := strconv.Atoi(items[8]) + if err != nil { + return []*schema.ResourceData{d}, err + } + err = d.Set("priority", pr) + if err != nil { + return []*schema.ResourceData{d}, err + } + } + return []*schema.ResourceData{d}, nil +} + func resourceVolcengineSecurityGroupRuleCreate(d *schema.ResourceData, meta interface{}) (err error) { securityGroupRuleService := NewSecurityGroupRuleService(meta.(*ve.SdkClient)) err = ve.DefaultDispatcher().Create(securityGroupRuleService, d, ResourceVolcengineSecurityGroupRule()) diff --git a/volcengine/vpc/security_group_rule/service_volcengine_security_group_rule.go b/volcengine/vpc/security_group_rule/service_volcengine_security_group_rule.go index acb803cf..2f4aee2d 100644 --- a/volcengine/vpc/security_group_rule/service_volcengine_security_group_rule.go +++ b/volcengine/vpc/security_group_rule/service_volcengine_security_group_rule.go @@ -77,14 +77,20 @@ func (s *VolcengineSecurityGroupRuleService) CreateResource(resourceData *schema }, AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { var ( - securityGroupId = resourceData.Get("security_group_id").(string) - cidrIp = resourceData.Get("cidr_ip").(string) - protocol = resourceData.Get("protocol").(string) - portStart = resourceData.Get("port_start").(int) - portEnd = resourceData.Get("port_end").(int) + securityGroupId = resourceData.Get("security_group_id") + cidrIp = resourceData.Get("cidr_ip") + protocol = resourceData.Get("protocol") + portStart = resourceData.Get("port_start") + portEnd = resourceData.Get("port_end") + sourceGroupId = resourceData.Get("source_group_id") + dir = resourceData.Get("direction") + policy = resourceData.Get("policy") + priority = resourceData.Get("priority") ) - id, _ := ve.ObtainSdkValue("Result.RuleId", securityGroupId+":"+protocol+":"+strconv.Itoa(portStart)+":"+strconv.Itoa(portEnd)+":"+cidrIp) - d.SetId(id.(string)) + d.SetId(fmt.Sprintf("%v:%v:%v:%v:%v:%v:%v:%v:%v", + securityGroupId, protocol, portStart, + portEnd, cidrIp, sourceGroupId, + dir, policy, priority)) return nil }, }, @@ -114,6 +120,7 @@ func (s *VolcengineSecurityGroupRuleService) ReadResources(condition map[string] return data, err } } + logger.Debug(logger.RespFormat, action, condition, *resp) results, err = ve.ObtainSdkValue("Result.Permissions", *resp) @@ -126,13 +133,71 @@ func (s *VolcengineSecurityGroupRuleService) ReadResources(condition map[string] if data, ok = results.([]interface{}); !ok { return data, errors.New("Result.Permissions is not Slice") } - logger.Debug(logger.ReqFormat, "", data) + + securityGroupStatus, err := ve.ObtainSdkValue("Result.Status", *resp) + if err != nil { + return nil, err + } + + // Resource 里定义了 status,已经发布无法修改,这里将 status 回填 + for index := range data { + data[index].(map[string]interface{})["Status"] = securityGroupStatus + + ele := data[index].(map[string]interface{}) + data[index].(map[string]interface{})["PortStart"] = int(ele["PortStart"].(float64)) + data[index].(map[string]interface{})["PortEnd"] = int(ele["PortEnd"].(float64)) + data[index].(map[string]interface{})["Priority"] = int(ele["Priority"].(float64)) + } return data, err } -func (s *VolcengineSecurityGroupRuleService) ReadResource(resourceData *schema.ResourceData, tmpId string) (data map[string]interface{}, err error) { - return data, err +func (s *VolcengineSecurityGroupRuleService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + + ids := strings.Split(id, ":") + + req := map[string]interface{}{ + "SecurityGroupId": ids[0], + "Direction": resourceData.Get("direction"), + "Protocol": resourceData.Get("protocol"), + } + if len(resourceData.Get("cidr_ip").(string)) > 0 { + req["CidrIp"] = resourceData.Get("cidr_ip") + } + if len(resourceData.Get("source_group_id").(string)) > 0 { + req["SourceGroupId"] = resourceData.Get("source_group_id") + } + + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + + for _, v := range results { + data = v.(map[string]interface{}) + + if data["PortStart"] != resourceData.Get("port_start") { + continue + } + if data["PortEnd"] != resourceData.Get("port_end") { + continue + } + if data["Policy"] != resourceData.Get("policy") { + continue + } + if data["Priority"] != resourceData.Get("priority") { + continue + } + return data, nil + } + + return data, fmt.Errorf("SecurityGroupRule %s not exist ", id) } func (s *VolcengineSecurityGroupRuleService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { @@ -151,36 +216,35 @@ func (s *VolcengineSecurityGroupRuleService) ModifyResource(resourceData *schema callback := ve.Callback{ Call: ve.SdkCall{ Action: action, - ConvertMode: ve.RequestConvertAll, + ConvertMode: ve.RequestConvertInConvert, + Convert: map[string]ve.RequestConvert{ + "description": { + TargetField: "Description", + }, + }, BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { items := strings.Split(d.Id(), ":") - if len(items) != 5 { - return false, fmt.Errorf("import id must be of the form SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp") - } - securityGroupId := items[0] - protocol := items[1] - portStart := items[2] - portEnd := items[3] - cidrIp := items[4] - ruleId := securityGroupId + ":" + protocol + ":" + portStart + ":" + portEnd + ":" + cidrIp + start, _ := strconv.Atoi(items[2]) + end, _ := strconv.Atoi(items[3]) - (*call.SdkParam)["Protocol"] = protocol - (*call.SdkParam)["PortStart"] = portStart - (*call.SdkParam)["PortEnd"] = portEnd - (*call.SdkParam)["CidrIp"] = cidrIp - (*call.SdkParam)["SecurityGroupId"] = securityGroupId - (*call.SdkParam)["RuleId"] = ruleId - - start, _ := strconv.Atoi((*call.SdkParam)["PortStart"].(string)) - end, _ := strconv.Atoi((*call.SdkParam)["PortEnd"].(string)) + (*call.SdkParam)["SecurityGroupId"] = items[0] + (*call.SdkParam)["Protocol"] = items[1] + (*call.SdkParam)["PortStart"] = start + (*call.SdkParam)["PortEnd"] = end + if len(items[4]) > 0 { + (*call.SdkParam)["CidrIp"] = items[4] + } + if len(items[5]) > 0 { + (*call.SdkParam)["SourceGroupId"] = items[5] + } + (*call.SdkParam)["Policy"] = items[7] + (*call.SdkParam)["Priority"] = resourceData.Get("priority") - if err := validateProtocol(protocol, start, end); err != nil { + // validate protocol + if err := validateProtocol(items[1], start, end); err != nil { return false, err } - - d.SetId(ruleId) - return true, nil }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -210,31 +274,19 @@ func (s *VolcengineSecurityGroupRuleService) RemoveResource(resourceData *schema action = "RevokeSecurityGroupIngress" } - items := strings.Split(resourceData.Id(), ":") - if len(items) != 5 { - return []ve.Callback{} - } - - securityGroupId := items[0] - protocol := items[1] - portStart := items[2] - portEnd := items[3] - cidrIp := items[4] - callback := ve.Callback{ Call: ve.SdkCall{ Action: action, ConvertMode: ve.RequestConvertIgnore, SdkParam: &map[string]interface{}{ - "RuleId": resourceData.Id(), - "PortStart": portStart, - "PortEnd": portEnd, - "Protocol": protocol, - "SecurityGroupId": securityGroupId, - "CidrIp": cidrIp, - "Priority": resourceData.Get("priority"), - "Policy": resourceData.Get("policy"), + "SecurityGroupId": resourceData.Get("security_group_id"), + "Protocol": resourceData.Get("protocol"), + "PortStart": resourceData.Get("port_start"), + "PortEnd": resourceData.Get("port_end"), + "CidrIp": resourceData.Get("cidr_ip"), "SourceGroupId": resourceData.Get("source_group_id"), + "Policy": resourceData.Get("policy"), + "Priority": resourceData.Get("priority"), }, ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { @@ -265,42 +317,8 @@ func (s *VolcengineSecurityGroupRuleService) DatasourceResources(d *schema.Resou } } -func importSecurityGroupRule(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - var err error - items := strings.Split(d.Id(), ":") - if len(items) != 5 { - return []*schema.ResourceData{d}, fmt.Errorf("import id must be of the form SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp") - } - err = d.Set("security_group_id", items[0]) - if err != nil { - return []*schema.ResourceData{d}, err - } - err = d.Set("protocol", items[1]) - if err != nil { - return []*schema.ResourceData{d}, err - } - - err = d.Set("port_start", items[2]) - if err != nil { - return []*schema.ResourceData{d}, err - } - - err = d.Set("port_end", items[3]) - if err != nil { - return []*schema.ResourceData{d}, err - } - - err = d.Set("cidr_ip", items[4]) - if err != nil { - return []*schema.ResourceData{d}, err - } - - return []*schema.ResourceData{d}, nil -} - func (s *VolcengineSecurityGroupRuleService) ReadResourceId(id string) string { - items := strings.Split(id, ":") - return items[0] + return id } func validateProtocol(protocol string, start, end int) error { @@ -324,3 +342,13 @@ func validateProtocol(protocol string, start, end int) error { } return nil } + +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/r/security_group_rule.html.markdown b/website/docs/r/security_group_rule.html.markdown index 27df2e5d..e3885530 100644 --- a/website/docs/r/security_group_rule.html.markdown +++ b/website/docs/r/security_group_rule.html.markdown @@ -12,11 +12,56 @@ Provides a resource to manage security group rule ```hcl resource "volcengine_security_group_rule" "g1test3" { direction = "egress" - security_group_id = "sg-273ycgql3ig3k7fap8t3dyvqx" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" protocol = "tcp" - port_start = "8000" - port_end = "9003" + port_start = 8000 + port_end = 9003 cidr_ip = "10.0.0.0/8" + description = "tft1234" +} + +resource "volcengine_security_group_rule" "g1test2" { + direction = "egress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + cidr_ip = "10.0.0.0/24" +} + +resource "volcengine_security_group_rule" "g1test1" { + direction = "egress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + cidr_ip = "10.0.0.0/24" + priority = 2 +} + + +resource "volcengine_security_group_rule" "g1test0" { + direction = "ingress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 80 + port_end = 80 + cidr_ip = "10.0.0.0/24" + priority = 2 + policy = "drop" + description = "tft" +} + +resource "volcengine_security_group_rule" "g1test06" { + direction = "ingress" + security_group_id = "sg-2d6722jpp55og58ozfd1sqtdb" + protocol = "tcp" + port_start = 8000 + port_end = 9003 + source_group_id = "sg-3rfe5j4xdnklc5zsk2hcw5c6q" + priority = 2 + policy = "drop" + description = "tft" } ``` ## Argument Reference @@ -25,12 +70,12 @@ The following arguments are supported: * `port_end` - (Required, ForceNew) Port end of egress/ingress Rule. * `port_start` - (Required, ForceNew) Port start of egress/ingress Rule. * `protocol` - (Required, ForceNew) Protocol of the SecurityGroup, the value can be `tcp` or `udp` or `icmp` or `all` or `icmpv6`. -* `security_group_id` - (Required) Id of SecurityGroup. +* `security_group_id` - (Required, ForceNew) Id of SecurityGroup. * `cidr_ip` - (Optional, ForceNew) Cidr ip of egress/ingress Rule. * `description` - (Optional) description of a egress rule. * `policy` - (Optional, ForceNew) Access strategy. -* `priority` - (Optional) Priority of a security group rule. -* `source_group_id` - (Optional) ID of the source security group whose access permission you want to set. +* `priority` - (Optional, ForceNew) Priority of a security group rule. +* `source_group_id` - (Optional, ForceNew) ID of the source security group whose access permission you want to set. ## Attributes Reference In addition to all arguments above, the following attributes are exported: @@ -41,6 +86,6 @@ In addition to all arguments above, the following attributes are exported: ## Import SecurityGroupRule can be imported using the id, e.g. ``` -$ terraform import volcengine_security_group_rule.default ID is a string concatenated with colons(SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp) +$ terraform import volcengine_security_group_rule.default ID is a string concatenated with colons(SecurityGroupId:Protocol:PortStart:PortEnd:CidrIp:SourceGroupId:Direction:Policy:Priority) ```