alicloud/service_alicloud_ess.go (893 lines of code) (raw):
package alicloud
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"time"
"github.com/PaesslerAG/jsonpath"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ess"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
)
type EssService struct {
client *connectivity.AliyunClient
}
func (s *EssService) DescribeInstances(scalingGroupId string, lifecycleState string) (instances []ess.ScalingInstance, err error) {
request := ess.CreateDescribeScalingInstancesRequest()
request.RegionId = s.client.RegionId
request.ScalingGroupId = scalingGroupId
request.LifecycleState = lifecycleState
v, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingInstances(request)
})
if err != nil {
return instances, WrapErrorf(err, DefaultErrorMsg, scalingGroupId, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
resp, _ := v.(*ess.DescribeScalingInstancesResponse)
return resp.ScalingInstances.ScalingInstance, nil
}
func (s *EssService) DescribeEssAlarm(id string) (alarm ess.Alarm, err error) {
request := ess.CreateDescribeAlarmsRequest()
request.RegionId = s.client.RegionId
request.AlarmTaskId = id
request.MetricType = "system"
Alarms, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeAlarms(request)
})
if err != nil {
return alarm, WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), Alarms, request.RpcRequest, request)
AlarmsResponse, _ := Alarms.(*ess.DescribeAlarmsResponse)
systemAlarms := AlarmsResponse.AlarmList.Alarm
if len(systemAlarms) > 0 {
return systemAlarms[0], nil
}
AlarmsRequest := ess.CreateDescribeAlarmsRequest()
AlarmsRequest.RegionId = s.client.RegionId
AlarmsRequest.AlarmTaskId = id
AlarmsRequest.MetricType = "custom"
raw, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeAlarms(AlarmsRequest)
})
if err != nil {
return alarm, WrapErrorf(err, DefaultErrorMsg, id, AlarmsRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(AlarmsRequest.GetActionName(), raw, AlarmsRequest.RpcRequest, AlarmsRequest)
response, _ := raw.(*ess.DescribeAlarmsResponse)
customAlarms := response.AlarmList.Alarm
if len(customAlarms) > 0 {
return customAlarms[0], nil
}
return alarm, WrapErrorf(NotFoundErr("EssAlarm", id), NotFoundMsg, ProviderERROR)
}
func (s *EssService) DescribeEssLifecycleHook(id string) (hook ess.LifecycleHook, err error) {
request := ess.CreateDescribeLifecycleHooksRequest()
request.LifecycleHookId = &[]string{id}
request.RegionId = s.client.RegionId
raw, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeLifecycleHooks(request)
})
if err != nil {
err = WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
return
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeLifecycleHooksResponse)
for _, v := range response.LifecycleHooks.LifecycleHook {
if v.LifecycleHookId == id {
return v, nil
}
}
err = WrapErrorf(NotFoundErr("EssLifecycleHook", id), NotFoundMsg, ProviderERROR)
return
}
func (s *EssService) WaitForEssLifecycleHook(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssLifecycleHook(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if object.LifecycleHookId == id && status != Deleted {
return nil
}
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object.LifecycleHookId, id, ProviderERROR)
}
}
}
func (s *EssService) DescribeEssNotification(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
parts := strings.SplitN(id, ":", 2)
scalingGroupId, notificationArn := parts[0], parts[1]
request := map[string]interface{}{
"ScalingGroupId": scalingGroupId,
"RegionId": s.client.RegionId,
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeNotificationConfigurations", nil, request, true)
if err != nil {
if IsExpectedErrors(err, []string{"NotificationConfigurationNotExist", "InvalidScalingGroupId.NotFound"}) {
err = WrapErrorf(NotFoundErr("EssNotification", id), NotFoundMsg, ProviderERROR)
}
err = WrapErrorf(err, DefaultErrorMsg, id, "DescribeNotificationConfigurations", AlibabaCloudSdkGoERROR)
return
}
addDebug("DescribeNotificationConfigurations", response, request)
v, err := jsonpath.Get("$.NotificationConfigurationModels", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.NotificationConfigurationModels", response)
}
vv, err := jsonpath.Get("$.NotificationConfigurationModel", v)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.NotificationConfigurationModel", response)
}
for _, w := range vv.([]interface{}) {
m := w.(map[string]interface{})
if m["NotificationArn"] == notificationArn {
return m, nil
}
}
err = WrapErrorf(NotFoundErr("EssNotificationConfiguration", id), NotFoundMsg, ProviderERROR)
return
}
func (s *EssService) WaitForEssNotification(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssNotification(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
resourceId := fmt.Sprintf("%s:%s", object["ScalingGroupId"], object["NotificationArn"])
if resourceId == id && status != Deleted {
return nil
}
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, resourceId, id, ProviderERROR)
}
}
}
func (s *EssService) ActivityStateRefreshFunc(activityId string, failStates []string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
request := ess.CreateDescribeScalingActivitiesRequest()
request.ScalingActivityId = &[]string{activityId}
request.RegionId = s.client.RegionId
raw, e := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingActivities(request)
})
if e != nil {
return nil, "", WrapErrorf(e, activityId, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
response, _ := raw.(*ess.DescribeScalingActivitiesResponse)
for _, v := range response.ScalingActivities.ScalingActivity {
if v.ScalingActivityId == activityId {
for _, failState := range failStates {
if fmt.Sprint(v.StatusCode) == failState {
return v, fmt.Sprint(v.StatusCode), WrapError(Error(FailedToReachTargetStatus, fmt.Sprint(v.StatusCode)))
}
}
return v, fmt.Sprint(v.StatusCode), nil
}
}
return nil, "", Error("activity not found")
}
}
func (s *EssService) DescribeEssScalingGroupById(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScalingGroupId.1": id,
"RegionId": s.client.RegionId,
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeScalingGroups", nil, request, true)
if err != nil {
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeScalingGroups", AlibabaCloudSdkGoERROR)
}
v, err := jsonpath.Get("$.ScalingGroups.ScalingGroup", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingGroups.ScalingGroup", response)
}
if len(v.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("ScalingGroups", id), NotFoundMsg, ProviderERROR)
}
object = v.([]interface{})[0].(map[string]interface{})
return object, nil
}
// Deprecated: Use method DescribeEssScalingGroupById instead.
func (s *EssService) DescribeEssScalingGroup(id string) (group ess.ScalingGroup, err error) {
request := ess.CreateDescribeScalingGroupsRequest()
request.ScalingGroupId = &[]string{id}
request.RegionId = s.client.RegionId
raw, e := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingGroups(request)
})
if e != nil {
err = WrapErrorf(e, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
return
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeScalingGroupsResponse)
for _, v := range response.ScalingGroups.ScalingGroup {
if v.ScalingGroupId == id {
return v, nil
}
}
err = WrapErrorf(NotFoundErr("EssScalingGroup", id), NotFoundMsg, ProviderERROR)
return
}
func (s *EssService) DescribeEssScalingGroupSuspendProcess(id string) (object map[string]interface{}, err error) {
strs, err := ParseResourceId(id, 2)
if err != nil {
return object, WrapError(err)
}
idExist := false
scalingGroupId, processTemp := strs[0], strs[1]
request := ess.CreateDescribeScalingGroupsRequest()
request.ScalingGroupId = &[]string{scalingGroupId}
request.RegionId = s.client.RegionId
raw, e := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingGroups(request)
})
if e != nil {
err = WrapErrorf(e, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
return object, err
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeScalingGroupsResponse)
for _, v := range response.ScalingGroups.ScalingGroup {
if v.ScalingGroupId == scalingGroupId {
process := v.SuspendedProcesses.SuspendedProcess
for i := 0; i < len(process); i++ {
if strings.EqualFold(processTemp, process[i]) {
idExist = true
return object, nil
}
}
}
}
if !idExist {
return object, WrapErrorf(NotFoundErr("EssScalingGroup", id), NotFoundWithResponse, response)
}
return
}
func (s *EssService) DescribeEssScalingConfiguration(id string) (config ess.ScalingConfigurationInDescribeScalingConfigurations, err error) {
request := ess.CreateDescribeScalingConfigurationsRequest()
request.ScalingConfigurationId = &[]string{id}
request.RegionId = s.client.RegionId
raw, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingConfigurations(request)
})
if err != nil {
err = WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
return
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeScalingConfigurationsResponse)
for _, v := range response.ScalingConfigurations.ScalingConfiguration {
if v.ScalingConfigurationId == id {
return v, nil
}
}
err = GetNotFoundErrorFromString(GetNotFoundMessage("Scaling Configuration", id))
return
}
func (s *EssService) DescribeEssEciScalingConfiguration(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScalingConfigurationId.1": id,
"RegionId": s.client.RegionId,
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeEciScalingConfigurations", nil, request, true)
if err != nil {
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeEciScalingConfigurations", AlibabaCloudSdkGoERROR)
}
v, err := jsonpath.Get("$.ScalingConfigurations", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingConfigurations", response)
}
if len(v.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("EciScalingConfiguration", id), NotFoundMsg, ProviderERROR)
}
object = v.([]interface{})[0].(map[string]interface{})
return object, nil
}
//********
func (s *EssService) DescribeEssScalingConfigurationByCommonApi(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScalingConfigurationId.1": id,
"RegionId": s.client.RegionId,
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeScalingConfigurations", nil, request, true)
if err != nil {
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeScalingConfigurations", AlibabaCloudSdkGoERROR)
}
v, err := jsonpath.Get("$.ScalingConfigurations", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingConfigurations", response)
}
vv, err := jsonpath.Get("$.ScalingConfiguration", v)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingConfigurations", response)
}
if len(vv.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("ScalingConfiguration", id), NotFoundMsg, ProviderERROR)
}
object = vv.([]interface{})[0].(map[string]interface{})
//.(map[string]interface{}) .(map[string]interface{})
w := object["WeightedCapacities"]
ww := object["InstanceTypes"]
if w != nil && ww != nil {
weightedCapacity := w.(map[string]interface{})["WeightedCapacity"].([]interface{})
instanceType := ww.(map[string]interface{})["InstanceType"].([]interface{})
instanceTypeOverride := make([]ess.ModifyScalingConfigurationInstanceTypeOverride, 0)
if len(weightedCapacity) != 0 && len(instanceType) != 0 {
for i := 0; i < len(weightedCapacity); i++ {
l := ess.ModifyScalingConfigurationInstanceTypeOverride{
InstanceType: instanceType[i].(string),
WeightedCapacity: weightedCapacity[i].(json.Number).String(),
}
instanceTypeOverride = append(instanceTypeOverride, l)
}
m := make(map[string][]ess.ModifyScalingConfigurationInstanceTypeOverride)
m["InstanceTypeOverride"] = instanceTypeOverride
object["InstanceTypeOverrides"] = m
}
}
return object, nil
}
func (s *EssService) ActiveEssScalingConfiguration(sgId, id string) error {
request := ess.CreateModifyScalingGroupRequest()
request.ScalingGroupId = sgId
request.ActiveScalingConfigurationId = id
request.RegionId = s.client.RegionId
raw, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.ModifyScalingGroup(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
return err
}
func (s *EssService) WaitForScalingConfiguration(id string, status Status, timeout int) (err error) {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssScalingConfiguration(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if object.ScalingConfigurationId == id && status != Deleted {
return nil
}
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object.ScalingConfigurationId, id, ProviderERROR)
}
}
}
// Flattens an array of datadisk into a []map[string]interface{}
func (s *EssService) flattenDataDiskMappings(list []ess.DataDisk) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
l := map[string]interface{}{
"size": i.Size,
"category": i.Category,
"snapshot_id": i.SnapshotId,
"device": i.Device,
"delete_with_instance": i.DeleteWithInstance,
"encrypted": i.Encrypted,
"kms_key_id": i.KMSKeyId,
"disk_name": i.DiskName,
"description": i.Description,
"auto_snapshot_policy_id": i.AutoSnapshotPolicyId,
"performance_level": i.PerformanceLevel,
}
result = append(result, l)
}
return result
}
func (s *EssService) flattenSpotPriceLimitMappings(list []ess.SpotPriceModel) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
p, _ := strconv.ParseFloat(strconv.FormatFloat(i.PriceLimit, 'f', 2, 64), 64)
l := map[string]interface{}{
"instance_type": i.InstanceType,
"price_limit": p,
}
result = append(result, l)
}
return result
}
func (s *EssService) flattenInstancePatternInfoMappings(list []ess.InstancePatternInfo) []map[string]interface{} {
result := make([]map[string]interface{}, 0, len(list))
for _, i := range list {
memeory, _ := strconv.ParseFloat(strconv.FormatFloat(i.Memory, 'f', 2, 64), 64)
maxPrice, _ := strconv.ParseFloat(strconv.FormatFloat(i.MaxPrice, 'f', 2, 64), 64)
l := map[string]interface{}{
"instance_family_level": i.InstanceFamilyLevel,
"memory": memeory,
"cores": i.Cores,
"max_price": maxPrice,
"burstable_performance": i.BurstablePerformance,
"architectures": i.Architectures.Architecture,
"excluded_instance_types": i.ExcludedInstanceTypes.ExcludedInstanceType,
}
result = append(result, l)
}
return result
}
func (s *EssService) flattenVserverGroupList(vServerGroups []ess.VServerGroup) []map[string]interface{} {
groups := make([]map[string]interface{}, 0, len(vServerGroups))
for _, v := range vServerGroups {
vserverGroupAttributes := v.VServerGroupAttributes.VServerGroupAttribute
attrs := make([]map[string]interface{}, 0, len(vserverGroupAttributes))
for _, a := range vserverGroupAttributes {
attr := map[string]interface{}{
"vserver_group_id": a.VServerGroupId,
"port": a.Port,
"weight": a.Weight,
}
attrs = append(attrs, attr)
}
group := map[string]interface{}{
"loadbalancer_id": v.LoadBalancerId,
"vserver_attributes": attrs,
}
groups = append(groups, group)
}
return groups
}
func (s *EssService) DescribeEssScalingRule(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScalingRuleId.1": id,
"RegionId": s.client.RegionId,
"ShowAlarmRules": "false",
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeScalingRules", nil, request, true)
if err != nil {
if IsExpectedErrors(err, []string{"InvalidScalingRuleId.NotFound"}) {
return object, WrapErrorf(err, NotFoundMsg, AlibabaCloudSdkGoERROR)
}
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeScalingRules", AlibabaCloudSdkGoERROR)
}
addDebug("DescribeScalingRules", response, request)
get, err := jsonpath.Get("$.ScalingRules", response)
if err != nil || get == nil {
return object, WrapErrorf(NotFoundErr("ScalingRules", id), NotFoundMsg, ProviderERROR)
}
v, err := jsonpath.Get("$.ScalingRules.ScalingRule", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingRules.ScalingRule", response)
}
if len(v.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("ScalingRules", id), NotFoundMsg, ProviderERROR)
}
object = v.([]interface{})[0].(map[string]interface{})
return object, nil
}
func (s *EssService) DescribeEssScalingRuleWithAlarm(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScalingRuleId.1": id,
"RegionId": s.client.RegionId,
"ShowAlarmRules": "true",
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeScalingRules", nil, request, true)
if err != nil {
if IsExpectedErrors(err, []string{"InvalidScalingRuleId.NotFound"}) {
return object, WrapErrorf(err, NotFoundMsg, AlibabaCloudSdkGoERROR)
}
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeScalingRules", AlibabaCloudSdkGoERROR)
}
addDebug("DescribeScalingRules", response, request)
w, err := jsonpath.Get("$.ScalingRules", response)
if err != nil {
return object, WrapErrorf(err, NotFoundMsg, id, "$.ScalingRules", response)
}
v, err := jsonpath.Get("$.ScalingRule", w)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScalingRules.ScalingRule", response)
}
if len(v.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("ScalingRules", id), NotFoundMsg, ProviderERROR)
}
object = v.([]interface{})[0].(map[string]interface{})
return object, nil
}
func (s *EssService) WaitForEssScalingRule(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssScalingRule(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
}
return WrapError(err)
}
if object["ScalingRuleId"] == id && status != Deleted {
return nil
}
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object["ScalingRuleId"], id, ProviderERROR)
}
}
}
func (s *EssService) DescribeEssScheduledTask(id string) (object map[string]interface{}, err error) {
var response map[string]interface{}
client := s.client
request := map[string]interface{}{
"ScheduledTaskId.1": id,
"RegionId": s.client.RegionId,
}
response, err = client.RpcPost("Ess", "2014-08-28", "DescribeScheduledTasks", nil, request, true)
if err != nil {
return object, WrapErrorf(err, DefaultErrorMsg, id, "DescribeScheduledTasks", AlibabaCloudSdkGoERROR)
}
addDebug("DescribeScheduledTasks", response, request, request)
v, err := jsonpath.Get("$.ScheduledTasks.ScheduledTask", response)
if err != nil {
return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.ScheduledTasks.ScheduledTask", response)
}
if len(v.([]interface{})) == 0 {
return object, WrapErrorf(NotFoundErr("ScheduledTasks", id), NotFoundMsg, ProviderERROR)
}
for _, w := range v.([]interface{}) {
m := w.(map[string]interface{})
if m["ScheduledTaskId"] == id {
return m, nil
}
}
err = WrapErrorf(NotFoundErr("EssScheduledTask", id), NotFoundMsg, ProviderERROR)
return
}
func (s *EssService) WaitForEssScheduledTask(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssScheduledTask(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if object["TaskEnabled"] == "true" {
return nil
}
time.Sleep(DefaultIntervalShort * time.Second)
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object["ScheduledTaskId"], id, ProviderERROR)
}
}
}
func (srv *EssService) DescribeEssAttachment(id string, instanceIds []string) (instances []ess.ScalingInstance, err error) {
request := ess.CreateDescribeScalingInstancesRequest()
request.RegionId = srv.client.RegionId
request.ScalingGroupId = id
request.CreationType = "Attached"
if len(instanceIds) > 0 {
request.InstanceId = &instanceIds
}
raw, err := srv.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingInstances(request)
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidScalingGroupId.NotFound"}) {
err = WrapErrorf(err, NotFoundMsg, AlibabaCloudSdkGoERROR)
} else {
err = WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
return
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeScalingInstancesResponse)
if len(response.ScalingInstances.ScalingInstance) < 1 {
err = WrapErrorf(NotFoundErr("EssAttachment", id), NotFoundMsg, ProviderERROR)
return
}
return response.ScalingInstances.ScalingInstance, nil
}
func (s *EssService) DescribeEssScalingConfifurations(id string) (configs []ess.ScalingConfigurationInDescribeScalingConfigurations, err error) {
request := ess.CreateDescribeScalingConfigurationsRequest()
request.ScalingGroupId = id
request.PageNumber = requests.NewInteger(1)
request.PageSize = requests.NewInteger(PageSizeLarge)
request.RegionId = s.client.RegionId
for {
raw, err := s.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.DescribeScalingConfigurations(request)
})
if err != nil {
return configs, WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
response, _ := raw.(*ess.DescribeScalingConfigurationsResponse)
if len(response.ScalingConfigurations.ScalingConfiguration) < 1 {
break
}
configs = append(configs, response.ScalingConfigurations.ScalingConfiguration...)
if len(response.ScalingConfigurations.ScalingConfiguration) < PageSizeLarge {
break
}
if page, err := getNextpageNumber(request.PageNumber); err != nil {
return configs, WrapError(err)
} else {
request.PageNumber = page
}
}
if len(configs) < 1 {
return configs, WrapErrorf(NotFoundErr("EssScalingConfifuration", id), NotFoundMsg, ProviderERROR)
}
return
}
func (srv *EssService) EssRemoveInstances(client *connectivity.AliyunClient, d *schema.ResourceData, id string, instanceIds []string) error {
if len(instanceIds) < 1 {
return nil
}
group, err := srv.DescribeEssScalingGroup(id)
if err != nil {
return WrapError(err)
}
if group.LifecycleState == string(Inactive) {
return WrapError(Error("Scaling group current status is %s, please active it before attaching or removing ECS instances.", group.LifecycleState))
} else {
if err := srv.WaitForEssScalingGroup(group.ScalingGroupId, Active, DefaultTimeout); err != nil {
if NotFoundError(err) {
return nil
}
return WrapError(err)
}
}
removed := instanceIds
if err := resource.Retry(5*time.Minute, func() *resource.RetryError {
request := ess.CreateRemoveInstancesRequest()
request.ScalingGroupId = id
request.RegionId = srv.client.RegionId
if len(removed) > 0 {
request.InstanceId = &removed
} else {
return nil
}
raw, err := srv.client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.RemoveInstances(request)
})
if err != nil {
if IsExpectedErrors(err, []string{"InvalidScalingGroupId.NotFound"}) {
return nil
}
if IsExpectedErrors(err, []string{"IncorrectCapacity.MinSize"}) {
instances, err := srv.DescribeEssAttachment(id, instanceIds)
if len(instances) > 0 {
if group.MinSize == 0 {
return resource.RetryableError(WrapError(err))
}
return resource.NonRetryableError(WrapError(err))
}
}
if IsExpectedErrors(err, []string{"ScalingActivityInProgress", "IncorrectScalingGroupStatus"}) {
time.Sleep(5)
return resource.RetryableError(WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR))
}
return resource.NonRetryableError(WrapErrorf(err, DefaultErrorMsg, id, request.GetActionName(), AlibabaCloudSdkGoERROR))
}
response, _ := raw.(*ess.RemoveInstancesResponse)
essService := EssService{client}
stateConf := BuildStateConf([]string{}, []string{"Successful"}, d.Timeout(schema.TimeoutCreate), 1*time.Minute, essService.ActivityStateRefreshFunc(response.ScalingActivityId, []string{"Failed", "Rejected"}))
if _, err := stateConf.WaitForState(); err != nil {
return resource.NonRetryableError(WrapError(err))
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
time.Sleep(3 * time.Second)
instances, err := srv.DescribeEssAttachment(id, instanceIds)
if err != nil {
if NotFoundError(err) {
return nil
}
return resource.NonRetryableError(WrapError(err))
}
if len(instances) > 0 {
removed = make([]string, 0)
for _, inst := range instances {
removed = append(removed, inst.InstanceId)
}
return resource.RetryableError(WrapError(Error("There are still ECS instances in the scaling group.")))
}
return nil
}); err != nil {
return WrapError(err)
}
return nil
}
// WaitForScalingGroup waits for group to given status
func (s *EssService) WaitForEssScalingGroup(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssScalingGroup(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if object.LifecycleState == string(status) {
return nil
}
time.Sleep(DefaultIntervalShort * time.Second)
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object.LifecycleState, string(status), ProviderERROR)
}
}
}
// ess dimensions to map
func (s *EssService) flattenDimensionsToMap(dimensions []ess.Dimension) map[string]string {
result := make(map[string]string)
for _, dimension := range dimensions {
if dimension.DimensionKey == UserId || dimension.DimensionKey == ScalingGroup {
continue
}
result[dimension.DimensionKey] = dimension.DimensionValue
}
return result
}
func (s *EssService) WaitForEssAttachment(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssAttachment(id, make([]string, 0))
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if len(object) > 0 && status != Deleted {
return nil
}
time.Sleep(DefaultIntervalShort * time.Second)
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, Null, string(status), ProviderERROR)
}
}
}
func (s *EssService) WaitForEssAlarm(id string, status Status, timeout int) error {
deadline := time.Now().Add(time.Duration(timeout) * time.Second)
for {
object, err := s.DescribeEssAlarm(id)
if err != nil {
if NotFoundError(err) {
if status == Deleted {
return nil
}
} else {
return WrapError(err)
}
}
if object.AlarmTaskId == id && status != Deleted {
return nil
}
time.Sleep(DefaultIntervalShort * time.Second)
if time.Now().After(deadline) {
return WrapErrorf(err, WaitTimeoutMsg, id, GetFunc(1), timeout, object.AlarmTaskId, id, ProviderERROR)
}
}
}
func (s *EssService) SetResourceTags(d *schema.ResourceData, scalingGroupId string, client *connectivity.AliyunClient) error {
if d.HasChange("tags") {
added, removed := parsingTags(d)
// untag resources
if len(removed) > 0 {
removedTagKeys := make([]string, 0)
for _, v := range removed {
if !ignoredTags(v, "") {
removedTagKeys = append(removedTagKeys, v)
}
}
untagRequest := ess.CreateUntagResourcesRequest()
resourceId := []string{scalingGroupId}
untagRequest.ResourceId = &resourceId
untagRequest.ResourceType = "scalinggroup"
untagRequest.TagKey = &removedTagKeys
raw, err := client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.UntagResources(untagRequest)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), untagRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(untagRequest.GetActionName(), raw, untagRequest.RpcRequest, untagRequest)
}
// tag resources
if len(added) > 0 {
tagRequest := ess.CreateTagResourcesRequest()
resourceId := []string{scalingGroupId}
tagRequest.ResourceId = &resourceId
tagRequest.ResourceType = "scalinggroup"
tags := make([]ess.TagResourcesTag, 0)
for k, v := range added {
if !ignoredTags(v.(string), "") {
tags = append(tags, ess.TagResourcesTag{
Key: k,
Value: v.(string),
})
}
}
tagRequest.Tag = &tags
raw, err := client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.TagResources(tagRequest)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), tagRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(tagRequest.GetActionName(), raw, tagRequest.RpcRequest, tagRequest)
}
}
return nil
}
func (s *EssService) ChangeResourceGroup(d *schema.ResourceData, scalingGroupId string, client *connectivity.AliyunClient) error {
if d.HasChange("resource_group_id") {
request := ess.CreateChangeResourceGroupRequest()
request.ResourceId = scalingGroupId
request.ResourceType = "scalinggroup"
request.RegionId = client.RegionId
if v, ok := d.GetOk("resource_group_id"); ok {
request.NewResourceGroupId = v.(string)
}
raw, err := client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.ChangeResourceGroup(request)
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), request.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(request.GetActionName(), raw, request.RpcRequest, request)
}
return nil
}
func (s *EssService) ListTagResources(scalingGroupId string, client *connectivity.AliyunClient) (object interface{}, err error) {
listTagsRequest := ess.CreateListTagResourcesRequest()
listTagsRequest.ResourceType = "scalinggroup"
resourceIds := []string{scalingGroupId}
listTagsRequest.ResourceId = &resourceIds
raw, err := client.WithEssClient(func(essClient *ess.Client) (interface{}, error) {
return essClient.ListTagResources(listTagsRequest)
})
if err != nil {
return nil, WrapErrorf(err, DefaultErrorMsg, scalingGroupId, listTagsRequest.GetActionName(), AlibabaCloudSdkGoERROR)
}
addDebug(listTagsRequest.GetActionName(), raw, listTagsRequest.RpcRequest, listTagsRequest)
response, _ := raw.(*ess.ListTagResourcesResponse)
tags := make([]interface{}, 0)
for _, v := range response.TagResources.TagResource {
tags = append(tags, map[string]interface{}{
"TagKey": v.TagKey,
"TagValue": v.TagValue,
})
}
return tags, nil
}