Skip to content

Commit

Permalink
feat(ecs): suspend/resume autoscaling during disable/enable service o…
Browse files Browse the repository at this point in the history
…perations (#3995)

Fixes spinnaker/spinnaker#4707
  • Loading branch information
clareliguori authored and ezimanyi committed Sep 4, 2019
1 parent 6650178 commit 031bcec
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.netflix.spinnaker.clouddriver.ecs.deploy.ops;

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling;
import com.amazonaws.services.ecs.AmazonECS;
import com.netflix.spinnaker.clouddriver.aws.security.AmazonClientProvider;
import com.netflix.spinnaker.clouddriver.aws.security.AmazonCredentials;
Expand Down Expand Up @@ -59,6 +60,14 @@ AmazonECS getAmazonEcsClient() {
return amazonClientProvider.getAmazonEcs(credentialAccount, region, false);
}

AWSApplicationAutoScaling getAmazonApplicationAutoScalingClient() {
AWSCredentialsProvider credentialsProvider = getCredentials().getCredentialsProvider();
String region = getRegion();
NetflixAmazonCredentials credentialAccount = description.getCredentials();

return amazonClientProvider.getAmazonApplicationAutoScaling(credentialAccount, region, false);
}

protected String getRegion() {
return description.getRegion();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,14 +702,6 @@ private AmazonECS getSourceAmazonEcsClient() {
return amazonClientProvider.getAmazonEcs(sourceCredentials, sourceRegion, false);
}

private AWSApplicationAutoScaling getAmazonApplicationAutoScalingClient() {
AWSCredentialsProvider credentialsProvider = getCredentials().getCredentialsProvider();
NetflixAmazonCredentials credentialAccount = description.getCredentials();

return amazonClientProvider.getAmazonApplicationAutoScaling(
credentialAccount, getRegion(), false);
}

private AmazonElasticLoadBalancing getAmazonElasticLoadBalancingClient() {
AWSCredentialsProvider credentialsProvider = getCredentials().getCredentialsProvider();
NetflixAmazonCredentials credentialAccount = description.getCredentials();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

package com.netflix.spinnaker.clouddriver.ecs.deploy.ops;

import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling;
import com.amazonaws.services.applicationautoscaling.model.RegisterScalableTargetRequest;
import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;
import com.amazonaws.services.applicationautoscaling.model.SuspendedState;
import com.amazonaws.services.ecs.AmazonECS;
import com.amazonaws.services.ecs.model.UpdateServiceRequest;
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ModifyServiceDescription;
Expand All @@ -37,11 +42,28 @@ public Void operate(List priorOutputs) {

private void disableService() {
AmazonECS ecs = getAmazonEcsClient();
AWSApplicationAutoScaling autoScalingClient = getAmazonApplicationAutoScalingClient();

String service = description.getServerGroupName();
String account = description.getCredentialAccount();
String cluster = getCluster(service, account);

updateTaskStatus(
String.format("Suspending autoscaling on %s server group for %s.", service, account));
RegisterScalableTargetRequest suspendRequest =
new RegisterScalableTargetRequest()
.withServiceNamespace(ServiceNamespace.Ecs)
.withScalableDimension(ScalableDimension.EcsServiceDesiredCount)
.withResourceId(String.format("service/%s/%s", cluster, service))
.withSuspendedState(
new SuspendedState()
.withDynamicScalingInSuspended(true)
.withDynamicScalingOutSuspended(true)
.withScheduledScalingSuspended(true));
autoScalingClient.registerScalableTarget(suspendRequest);
updateTaskStatus(
String.format("Autoscaling on server group %s suspended for %s.", service, account));

updateTaskStatus(String.format("Disabling %s server group for %s.", service, account));
UpdateServiceRequest request =
new UpdateServiceRequest().withCluster(cluster).withService(service).withDesiredCount(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,10 @@

package com.netflix.spinnaker.clouddriver.ecs.deploy.ops;

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsRequest;
import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsResult;
import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
import com.amazonaws.services.applicationautoscaling.model.ScalableTarget;
import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;
import com.amazonaws.services.applicationautoscaling.model.*;
import com.amazonaws.services.ecs.AmazonECS;
import com.amazonaws.services.ecs.model.UpdateServiceRequest;
import com.netflix.spinnaker.clouddriver.aws.security.NetflixAmazonCredentials;
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ModifyServiceDescription;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -46,6 +40,7 @@ public Void operate(List priorOutputs) {

private void enableService() {
AmazonECS ecsClient = getAmazonEcsClient();
AWSApplicationAutoScaling autoScalingClient = getAmazonApplicationAutoScalingClient();

String service = description.getServerGroupName();
String account = description.getCredentialAccount();
Expand All @@ -60,6 +55,22 @@ private void enableService() {
updateTaskStatus(String.format("Enabling %s server group for %s.", service, account));
ecsClient.updateService(request);
updateTaskStatus(String.format("Server group %s enabled for %s.", service, account));

updateTaskStatus(
String.format("Resuming autoscaling on %s server group for %s.", service, account));
RegisterScalableTargetRequest resumeRequest =
new RegisterScalableTargetRequest()
.withServiceNamespace(ServiceNamespace.Ecs)
.withScalableDimension(ScalableDimension.EcsServiceDesiredCount)
.withResourceId(String.format("service/%s/%s", cluster, service))
.withSuspendedState(
new SuspendedState()
.withDynamicScalingInSuspended(false)
.withDynamicScalingOutSuspended(false)
.withScheduledScalingSuspended(false));
autoScalingClient.registerScalableTarget(resumeRequest);
updateTaskStatus(
String.format("Autoscaling on server group %s resumed for %s.", service, account));
}

private Integer getMaxCapacity(String cluster) {
Expand Down Expand Up @@ -94,12 +105,4 @@ private ScalableTarget getScalableTarget(String cluster) {

throw new Error("Multiple Scalable Targets found");
}

private AWSApplicationAutoScaling getAmazonApplicationAutoScalingClient() {
AWSCredentialsProvider credentialsProvider = getCredentials().getCredentialsProvider();
String region = description.getRegion();
NetflixAmazonCredentials credentialAccount = description.getCredentials();

return amazonClientProvider.getAmazonApplicationAutoScaling(credentialAccount, region, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@

package com.netflix.spinnaker.clouddriver.ecs.deploy.ops;

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling;
import com.amazonaws.services.applicationautoscaling.model.RegisterScalableTargetRequest;
import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;
import com.amazonaws.services.ecs.AmazonECS;
import com.amazonaws.services.ecs.model.Service;
import com.amazonaws.services.ecs.model.UpdateServiceRequest;
import com.netflix.spinnaker.clouddriver.aws.security.NetflixAmazonCredentials;
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ResizeServiceDescription;
import com.netflix.spinnaker.clouddriver.ecs.services.ContainerInformationService;
import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
Expand Down Expand Up @@ -98,12 +96,4 @@ private void resizeAutoScalingGroup(Service service) {
"Done resizing Scalable Target of %s to %s instances",
service.getServiceName(), desiredCount));
}

private AWSApplicationAutoScaling getAmazonApplicationAutoScalingClient() {
AWSCredentialsProvider credentialsProvider = getCredentials().getCredentialsProvider();
String region = description.getRegion();
NetflixAmazonCredentials credentialAccount = description.getCredentials();

return amazonClientProvider.getAmazonApplicationAutoScaling(credentialAccount, region, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.clouddriver.ecs.deploy.ops

import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling
import com.amazonaws.services.ecs.AmazonECS
import com.netflix.spinnaker.clouddriver.aws.security.AmazonClientProvider
import com.netflix.spinnaker.clouddriver.data.task.Task
Expand All @@ -29,6 +30,7 @@ class CommonAtomicOperation extends Specification{
def accountCredentialsProvider = Mock(AccountCredentialsProvider)
def containerInformationService = Mock(ContainerInformationService)
def ecs = Mock(AmazonECS)
def autoscaling = Mock(AWSApplicationAutoScaling)

def setupSpec() {
TaskRepository.threadLocalTask.set(Mock(Task))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ class DisableServiceAtomicOperationSpec extends CommonAtomicOperation {
operation.containerInformationService = containerInformationService

amazonClientProvider.getAmazonEcs(_, _, _) >> ecs
amazonClientProvider.getAmazonApplicationAutoScaling(_, _, _) >> autoscaling
containerInformationService.getClusterName(_, _, _) >> 'cluster-name'
accountCredentialsProvider.getCredentials(_) >> TestCredential.named("test")

when:
operation.operate([])

then:
1 * autoscaling.registerScalableTarget(_)
1 * ecs.updateService(_)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import com.netflix.spinnaker.clouddriver.ecs.TestCredential
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ModifyServiceDescription

class EnableServiceAtomicOperationSpec extends CommonAtomicOperation {
def autoscaling = Mock(AWSApplicationAutoScaling)

void 'should execute the operation'() {
given:
def operation = new EnableServiceAtomicOperation(new ModifyServiceDescription(
Expand All @@ -47,5 +45,6 @@ class EnableServiceAtomicOperationSpec extends CommonAtomicOperation {
then:
1 * autoscaling.describeScalableTargets(_) >> new DescribeScalableTargetsResult().withScalableTargets([])
1 * ecs.updateService(_)
1 * autoscaling.registerScalableTarget(_)
}
}

0 comments on commit 031bcec

Please sign in to comment.