From 94868073356413c208b44a6f3cf0878813a6d667 Mon Sep 17 00:00:00 2001 From: yejingtao <250234464@qq.com> Date: Thu, 5 Sep 2019 11:15:27 +0800 Subject: [PATCH] =?UTF-8?q?=E8=85=BE=E8=AE=AF=E4=BA=91deploy=E6=97=B6?= =?UTF-8?q?=E4=BB=8E=E8=80=81=E4=BC=B8=E7=BC=A9=E7=BB=84=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E3=80=81=E4=BC=B8=E7=BC=A9=E8=A7=84=E5=88=99?= =?UTF-8?q?=E3=80=81schedule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tencent/client/AutoScalingClient.groovy | 30 +++- .../TencentDeployDescription.groovy | 5 +- .../handlers/TencentDeployHandler.groovy | 161 +++++++++++++++++- ...neTencentServerGroupAtomicOperation.groovy | 6 +- 4 files changed, 196 insertions(+), 6 deletions(-) diff --git a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/client/AutoScalingClient.groovy b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/client/AutoScalingClient.groovy index 8121fd9e..4950ae2c 100644 --- a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/client/AutoScalingClient.groovy +++ b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/client/AutoScalingClient.groovy @@ -629,4 +629,32 @@ class AutoScalingClient extends AbstractTencentServiceClient { throw new TencentOperationException(e.toString()) } } -} + + def getNotification(String asgId=null) { + iterQuery { offset, limit -> + def request = new DescribeNotificationConfigurationsRequest(offset: offset, limit: limit) + + if (asgId) { + request.filters = [new Filter(name: 'auto-scaling-group-id', values: [asgId])] + } + + def response = client.DescribeNotificationConfigurations request + response.autoScalingNotificationSet + } as List + } + + def createNotification(String asgId, AutoScalingNotification notification) { + try { + def request = new CreateNotificationConfigurationRequest().with { + it.autoScalingGroupId=asgId + it.notificationUserGroupIds=notification.notificationUserGroupIds + it.notificationTypes=notification.notificationTypes + it + } + def response = client.CreateNotificationConfiguration request + response + } catch (TencentCloudSDKException e) { + throw new TencentOperationException(e.toString()) + } + } +} \ No newline at end of file diff --git a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/description/TencentDeployDescription.groovy b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/description/TencentDeployDescription.groovy index f1bdfea0..abfe4b4e 100644 --- a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/description/TencentDeployDescription.groovy +++ b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/description/TencentDeployDescription.groovy @@ -58,15 +58,18 @@ class TencentDeployDescription extends AbstractTencentCredentialsDescription imp */ Source source = new Source() + boolean copySourceScalingPoliciesAndActions = true + @Canonical static class Source implements ServerGroupsNameable { String region String serverGroupName + Boolean useSourceCapacity @Override Collection getServerGroupNames() { return Collections.singletonList(serverGroupName) } } -} +} \ No newline at end of file diff --git a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/handlers/TencentDeployHandler.groovy b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/handlers/TencentDeployHandler.groovy index a84092c3..697d6338 100644 --- a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/handlers/TencentDeployHandler.groovy +++ b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/handlers/TencentDeployHandler.groovy @@ -7,11 +7,16 @@ import com.netflix.spinnaker.clouddriver.deploy.DeployHandler import com.netflix.spinnaker.clouddriver.deploy.DeploymentResult import com.netflix.spinnaker.clouddriver.tencent.deploy.TencentServerGroupNameResolver import com.netflix.spinnaker.clouddriver.tencent.deploy.description.TencentDeployDescription +import com.netflix.spinnaker.clouddriver.tencent.deploy.description.UpsertTencentScalingPolicyDescription +import com.netflix.spinnaker.clouddriver.tencent.deploy.description.UpsertTencentScheduledActionDescription +import com.netflix.spinnaker.clouddriver.tencent.exception.TencentOperationException import com.netflix.spinnaker.clouddriver.tencent.provider.view.TencentClusterProvider import com.netflix.spinnaker.clouddriver.tencent.client.AutoScalingClient +import com.tencentcloudapi.common.exception.TencentCloudSDKException import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component +import groovy.time.TimeCategory /* curl -X POST \ @@ -63,6 +68,20 @@ class TencentDeployHandler implements DeployHandler { region ) + if (description?.source?.useSourceCapacity) { + log.info('copy source server group capacity') + String sourceServerGroupName = description?.source?.serverGroupName + String sourceRegion = description?.source?.region + def sourceServerGroup = tencentClusterProvider.getServerGroup(accountName, sourceRegion, sourceServerGroupName) + if (!sourceServerGroup) { + log.warn("source server group $sourceServerGroupName is not found") + } else { + description.desiredCapacity = sourceServerGroup.asg.desiredCapacity as Integer + description.maxSize = sourceServerGroup.asg.maxSize as Integer + description.minSize = sourceServerGroup.asg.minSize as Integer + } + } + task.updateStatus BASE_PHASE, "Composing server group $serverGroupName..." autoScalingClient.deploy(description) @@ -72,7 +91,145 @@ class TencentDeployHandler implements DeployHandler { DeploymentResult deploymentResult = new DeploymentResult() deploymentResult.serverGroupNames = ["$region:$serverGroupName".toString()] deploymentResult.serverGroupNameByRegion[region] = serverGroupName - deploymentResult + + if (description.copySourceScalingPoliciesAndActions) { + copyScalingPolicyAndScheduledAction(description, deploymentResult) + copyNotification(description, deploymentResult) // copy notification by the way + } + return deploymentResult } -} + + private def copyNotification(TencentDeployDescription description, DeploymentResult deployResult) { + task.updateStatus BASE_PHASE, "Enter copyNotification." + String sourceServerGroupName = description?.source?.serverGroupName + String sourceRegion = description?.source?.region + String accountName = description?.accountName + def sourceServerGroup = tencentClusterProvider.getServerGroup(accountName, sourceRegion, sourceServerGroupName) + + if (!sourceServerGroup) { + log.warn("source server group not found, account $accountName, region $sourceRegion, source sg name $sourceServerGroupName") + return + } + + String sourceAsgId = sourceServerGroup.asg.autoScalingGroupId + + task.updateStatus BASE_PHASE, "Initializing copy notification from $sourceAsgId." + + AutoScalingClient autoScalingClient = new AutoScalingClient( + description.credentials.credentials.secretId, + description.credentials.credentials.secretKey, + sourceRegion + ) + + String newServerGroupName = deployResult.serverGroupNameByRegion[sourceRegion] + def newAsg = autoScalingClient.getAutoScalingGroupsByName(newServerGroupName)[0] + String newAsgId = newAsg.autoScalingGroupId + + def notifications = autoScalingClient.getNotification(sourceAsgId) + for (notification in notifications) { + try { + autoScalingClient.createNotification(newAsgId, notification) + } catch (TencentOperationException toe) { + // something bad happened during creation, log the error and continue + log.warn "create notification error $toe" + } + } + } + + private def copyScalingPolicyAndScheduledAction(TencentDeployDescription description, DeploymentResult deployResult) { + task.updateStatus BASE_PHASE, "Enter copyScalingPolicyAndScheduledAction." + + String sourceServerGroupName = description?.source?.serverGroupName + String sourceRegion = description?.source?.region + String accountName = description?.accountName + def sourceServerGroup = tencentClusterProvider.getServerGroup(accountName, sourceRegion, sourceServerGroupName) + + if (!sourceServerGroup) { + log.warn("description is $description") + log.warn("source server group not found, account $accountName, region $sourceRegion, source sg name $sourceServerGroupName") + return + } + + String sourceAsgId = sourceServerGroup.asg.autoScalingGroupId + + task.updateStatus BASE_PHASE, "Initializing copy scaling policy and scheduled action from $sourceAsgId." + + AutoScalingClient autoScalingClient = new AutoScalingClient( + description.credentials.credentials.secretId, + description.credentials.credentials.secretKey, + sourceRegion + ) + + String newServerGroupName = deployResult.serverGroupNameByRegion[sourceRegion] + def newAsg = autoScalingClient.getAutoScalingGroupsByName(newServerGroupName)[0] + String newAsgId = newAsg.autoScalingGroupId + + // copy all scaling policies + def scalingPolicies = autoScalingClient.getScalingPolicies(sourceAsgId) + for (scalingPolicy in scalingPolicies) { + try { + def scalingPolicyDescription = new UpsertTencentScalingPolicyDescription().with { + it.serverGroupName = newServerGroupName + it.region = sourceRegion + it.accountName = accountName + it.operationType = UpsertTencentScalingPolicyDescription.OperationType.CREATE + it.adjustmentType = scalingPolicy.adjustmentType + it.adjustmentValue = scalingPolicy.adjustmentValue + it.metricAlarm = scalingPolicy.metricAlarm + // it.notificationUserGroupIds = scalingPolicy.notificationUserGroupIds + it.cooldown = scalingPolicy.cooldown + it + } + autoScalingClient.createScalingPolicy(newAsgId, scalingPolicyDescription) + } catch (TencentCloudSDKException sdk_e) { + // something bad happened during creation, log the error and continue + log.warn "create scaling policy error $sdk_e" + } + } + + // copy all scheduled actions + def scheduledActions = autoScalingClient.getScheduledAction(sourceAsgId) + for (scheduledAction in scheduledActions) { + try { + def original_start_time = Date.parse("yyyy-MM-dd'T'HH:mm:ss'+08:00'", scheduledAction.startTime) + def current_time = new Date() + def new_start_time + + if (original_start_time < current_time) { + log.info('original start time is before current time') + if (scheduledAction.endTime == "0000-00-00T00:00:00+08:00") { + // schedule action just run for once, and had finished + continue + } else { + log.info('scheduled action is for once, set new start time to current time') + use (TimeCategory) { + new_start_time = current_time + 60.minutes + } + } + } else { + log.info('scheduled action is not trigger, use original start time') + new_start_time = original_start_time + } + + def scheduledActionDescription = new UpsertTencentScheduledActionDescription().with { + it.serverGroupName = newServerGroupName + it.region = sourceRegion + it.accountName = accountName + it.operationType = UpsertTencentScheduledActionDescription.OperationType.CREATE + it.maxSize = scheduledAction.maxSize + it.minSize = scheduledAction.minSize + it.desiredCapacity = scheduledAction.desiredCapacity + it.startTime = new_start_time.format("yyyy-MM-dd'T'HH:mm:ss'+08:00'") + it.endTime = scheduledAction.endTime + it.recurrence = scheduledAction.recurrence + it + } + autoScalingClient.createScheduledAction(newAsgId as String, scheduledActionDescription) + } catch (TencentCloudSDKException sdk_e) { + // something bad happened during creation, log the error and continue + log.warn "create scheduled action error $sdk_e" + } + } + } +} \ No newline at end of file diff --git a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/ops/CloneTencentServerGroupAtomicOperation.groovy b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/ops/CloneTencentServerGroupAtomicOperation.groovy index 817b58de..1c1878e2 100644 --- a/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/ops/CloneTencentServerGroupAtomicOperation.groovy +++ b/clouddriver-tencent/src/main/groovy/com/netflix/spinnaker/clouddriver/tencent/deploy/ops/CloneTencentServerGroupAtomicOperation.groovy @@ -4,12 +4,14 @@ import com.netflix.spinnaker.clouddriver.data.task.Task import com.netflix.spinnaker.clouddriver.data.task.TaskRepository import com.netflix.spinnaker.clouddriver.deploy.DeploymentResult import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation +import com.netflix.spinnaker.clouddriver.tencent.client.AutoScalingClient import com.netflix.spinnaker.clouddriver.tencent.deploy.description.TencentDeployDescription import com.netflix.spinnaker.clouddriver.tencent.deploy.handlers.TencentDeployHandler import com.netflix.spinnaker.clouddriver.tencent.provider.view.TencentClusterProvider +import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired -import com.netflix.spinnaker.clouddriver.tencent.client.AutoScalingClient +@Slf4j class CloneTencentServerGroupAtomicOperation implements AtomicOperation { private static final String BASE_PHASE = "CLONE_SERVER_GROUP" @@ -116,4 +118,4 @@ class CloneTencentServerGroupAtomicOperation implements AtomicOperation