alibabacloudstack/resource_apsarastack_slb_vservergroup.go (372 lines of code) (raw):

package alibabacloudstack import ( "fmt" "strconv" "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/aliyun/alibaba-cloud-sdk-go/services/slb" "github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/connectivity" "github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/errmsgs" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func resourceAlibabacloudStackSlbServerGroup() *schema.Resource { resource := &schema.Resource{ Schema: map[string]*schema.Schema{ "load_balancer_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, "name": { Type: schema.TypeString, Optional: true, Computed: true, Deprecated: "Field 'name' is deprecated and will be removed in a future release. Please use new field 'vserver_group_name' instead.", ConflictsWith: []string{"vserver_group_name"}, }, "vserver_group_name": { Type: schema.TypeString, Optional: true, Computed: true, ValidateFunc: validation.StringLenBetween(2, 128), ConflictsWith: []string{"name"}, }, "servers": { Type: schema.TypeSet, Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "server_ids": { Type: schema.TypeList, Required: true, Elem: &schema.Schema{Type: schema.TypeString}, MinItems: 1, }, "port": { Type: schema.TypeInt, Required: true, ValidateFunc: validation.IntBetween(1, 65535), }, "weight": { Type: schema.TypeInt, Optional: true, Default: 100, ValidateFunc: validation.IntBetween(1, 100), }, "type": { Type: schema.TypeString, Optional: true, Default: string(ECS), ValidateFunc: validation.StringInSlice([]string{"eni", "ecs"}, false), }, }, }, }, "delete_protection_validation": { Type: schema.TypeBool, Optional: true, Default: false, }, }, } setResourceFunc(resource, resourceAlibabacloudStackSlbServerGroupCreate, resourceAlibabacloudStackSlbServerGroupRead, resourceAlibabacloudStackSlbServerGroupUpdate, resourceAlibabacloudStackSlbServerGroupDelete) return resource } func resourceAlibabacloudStackSlbServerGroupCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) request := slb.CreateCreateVServerGroupRequest() client.InitRpcRequest(*request.RpcRequest) request.LoadBalancerId = d.Get("load_balancer_id").(string) if v, ok := connectivity.GetResourceDataOk(d, "vserver_group_name", "name"); ok { request.VServerGroupName = v.(string) } raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.CreateVServerGroup(request) }) if err != nil { errmsg := "" if response, ok := raw.(*slb.CreateVServerGroupResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_slb_server_group", request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) response := raw.(*slb.CreateVServerGroupResponse) d.SetId(response.VServerGroupId) return nil } func resourceAlibabacloudStackSlbServerGroupRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) slbService := SlbService{client} object, err := slbService.DescribeSlbServerGroup(d.Id()) if err != nil { if errmsgs.NotFoundError(err) { d.SetId("") return nil } return errmsgs.WrapError(err) } connectivity.SetResourceData(d, object.VServerGroupName, "vserver_group_name", "name") if object.LoadBalancerId != "" { d.Set("load_balancer_id", object.LoadBalancerId) } servers := make([]map[string]interface{}, 0) portAndWeight := make(map[string][]string) for _, server := range object.BackendServers.BackendServer { key := fmt.Sprintf("%d%s%d%s%s", server.Port, COLON_SEPARATED, server.Weight, COLON_SEPARATED, server.Type) if v, ok := portAndWeight[key]; !ok { portAndWeight[key] = []string{server.ServerId} } else { v = append(v, server.ServerId) portAndWeight[key] = v } } for key, value := range portAndWeight { k := strings.Split(key, COLON_SEPARATED) p, e := strconv.Atoi(k[0]) if e != nil { return errmsgs.WrapError(e) } w, e := strconv.Atoi(k[1]) if e != nil { return errmsgs.WrapError(e) } t := k[2] s := map[string]interface{}{ "server_ids": value, "port": p, "weight": w, "type": t, } servers = append(servers, s) } if err := d.Set("servers", servers); err != nil { return errmsgs.WrapError(err) } return nil } func resourceAlibabacloudStackSlbServerGroupUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) d.Partial(true) var removeserverSet, addServerSet, updateServerSet *schema.Set serverUpdate := false step := 20 if d.HasChange("servers") { o, n := d.GetChange("servers") os := o.(*schema.Set) ns := n.(*schema.Set) remove := os.Difference(ns).List() add := ns.Difference(os).List() oldIdPort := getIdPortSetFromServers(remove) newIdPort := getIdPortSetFromServers(add) updateServerSet = oldIdPort.Intersection(newIdPort) removeserverSet = oldIdPort.Difference(newIdPort) addServerSet = newIdPort.Difference(oldIdPort) if removeserverSet.Len() > 0 { rmservers := make([]interface{}, 0) for _, rmserver := range remove { rms := rmserver.(map[string]interface{}) if v, ok := rms["server_ids"]; ok { server_ids := v.([]interface{}) for _, id := range server_ids { idPort := fmt.Sprintf("%s:%d", id, rms["port"]) if removeserverSet.Contains(idPort) { rmsm := map[string]interface{}{ "server_id": id, "port": rms["port"], "type": rms["type"], "weight": rms["weight"], } rmservers = append(rmservers, rmsm) } } } } request := slb.CreateRemoveVServerGroupBackendServersRequest() client.InitRpcRequest(*request.RpcRequest) request.VServerGroupId = d.Id() segs := len(rmservers)/step + 1 for i := 0; i < segs; i++ { start := i * step end := (i + 1) * step if end >= len(rmservers) { end = len(rmservers) } request.BackendServers = expandBackendServersWithPortToString(rmservers[start:end]) raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.RemoveVServerGroupBackendServers(request) }) if err != nil { errmsg := "" if response, ok := raw.(*slb.RemoveVServerGroupBackendServersResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) } } if addServerSet.Len() > 0 { addservers := make([]interface{}, 0) for _, addserver := range add { adds := addserver.(map[string]interface{}) if v, ok := adds["server_ids"]; ok { server_ids := v.([]interface{}) for _, id := range server_ids { idPort := fmt.Sprintf("%s:%d", id, adds["port"]) if addServerSet.Contains(idPort) { addsm := map[string]interface{}{ "server_id": id, "port": adds["port"], "type": adds["type"], "weight": adds["weight"], } addservers = append(addservers, addsm) } } } } request := slb.CreateAddVServerGroupBackendServersRequest() client.InitRpcRequest(*request.RpcRequest) request.VServerGroupId = d.Id() segs := len(addservers)/step + 1 for i := 0; i < segs; i++ { start := i * step end := (i + 1) * step if end >= len(addservers) { end = len(addservers) } request.BackendServers = expandBackendServersWithPortToString(addservers[start:end]) raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.AddVServerGroupBackendServers(request) }) if err != nil { errmsg := "" if response, ok := raw.(*slb.AddVServerGroupBackendServersResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) } } } name := connectivity.GetResourceData(d, "vserver_group_name", "name").(string) nameUpdate := false if d.HasChanges("name", "vserver_group_name") { nameUpdate = true } if d.HasChange("servers") { serverUpdate = true } if serverUpdate || nameUpdate { request := slb.CreateSetVServerGroupAttributeRequest() client.InitRpcRequest(*request.RpcRequest) request.VServerGroupId = d.Id() if nameUpdate { request.VServerGroupName = name } if serverUpdate { servers := make([]interface{}, 0) for _, server := range d.Get("servers").(*schema.Set).List() { s := server.(map[string]interface{}) if v, ok := s["server_ids"]; ok { server_ids := v.([]interface{}) for _, id := range server_ids { idPort := fmt.Sprintf("%s:%d", id, s["port"]) if updateServerSet.Contains(idPort) { sm := map[string]interface{}{ "server_id": id, "port": s["port"], "type": s["type"], "weight": s["weight"], } servers = append(servers, sm) } } } } segs := len(servers)/step + 1 for i := 0; i < segs; i++ { start := i * step end := (i + 1) * step if end >= len(servers) { end = len(servers) } request.BackendServers = expandBackendServersWithPortToString(servers[start:end]) raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.SetVServerGroupAttribute(request) }) if err != nil { errmsg := "" if response, ok := raw.(*slb.SetVServerGroupAttributeResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) } } else { raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.SetVServerGroupAttribute(request) }) if err != nil { errmsg := "" if response, ok := raw.(*slb.SetVServerGroupAttributeResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) } } d.Partial(false) return nil } func resourceAlibabacloudStackSlbServerGroupDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*connectivity.AlibabacloudStackClient) slbService := SlbService{client} if d.Get("delete_protection_validation").(bool) { lbId := d.Get("load_balancer_id").(string) lbInstance, err := slbService.DescribeSlb(lbId) if err != nil { if errmsgs.NotFoundError(err) { return nil } return errmsgs.WrapError(err) } if lbInstance.DeleteProtection == "on" { return errmsgs.WrapError(fmt.Errorf("Current VServerGroup's SLB Instance %s has enabled DeleteProtection. Please set delete_protection_validation to false to delete the group.", lbId)) } } request := slb.CreateDeleteVServerGroupRequest() client.InitRpcRequest(*request.RpcRequest) request.VServerGroupId = d.Id() err := resource.Retry(5*time.Minute, func() *resource.RetryError { raw, err := client.WithSlbClient(func(slbClient *slb.Client) (interface{}, error) { return slbClient.DeleteVServerGroup(request) }) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"RspoolVipExist"}) { return resource.RetryableError(err) } errmsg := "" if response, ok := raw.(*slb.DeleteVServerGroupResponse); ok { errmsg = errmsgs.GetBaseResponseErrorMessage(response.BaseResponse) } return resource.NonRetryableError(errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR, errmsg)) } addDebug(request.GetActionName(), raw, request.RpcRequest, request) return nil }) if err != nil { if errmsgs.IsExpectedErrors(err, []string{"The specified VServerGroupId does not exist", "InvalidParameter"}) { return nil } return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, d.Id(), request.GetActionName(), errmsgs.AlibabacloudStackSdkGoERROR) } return errmsgs.WrapError(slbService.WaitForSlbServerGroup(d.Id(), Deleted, DefaultTimeoutMedium)) }