Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(moniker): Use moniker in TrafficGuard. #1727

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ import com.netflix.spinnaker.orca.pipeline.model.Stage
*/
class TargetServerGroup {
// Delegates all Map interface calls to this object.
@Delegate private final Map<String, Object> serverGroup
@Delegate
private final Map<String, Object> serverGroup

TargetServerGroup(Map<String, Object> serverGroupData) {
if (serverGroupData.instances && serverGroupData.instances instanceof Collection) {
Expand Down Expand Up @@ -73,12 +74,21 @@ class TargetServerGroup {
return (serverGroup.instances ?: []) as List<Map>
}

/**
* Used in TrafficGuard, which is Java, which doesn't play nice with @Delegate
*/
Moniker getMoniker() {
return serverGroup.moniker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is indeed a Map ... may be safer to objectMapper.convert(serverGroup.moniker, Moniker) rather than rely on groovy "magic".

}


Map toClouddriverOperationPayload(String account) {
//TODO(cfieber) - add an endpoint on Clouddriver to do provider appropriate conversion of a TargetServerGroup
def op = [
credentials : account,
accountName : account,
serverGroupName: serverGroup.name,
moniker : serverGroup.moniker,
asgName : serverGroup.name,
cloudProvider : serverGroup.cloudProvider ?: serverGroup.type
]
Expand Down Expand Up @@ -173,19 +183,21 @@ class TargetServerGroup {
/**
* "Previous Server Group"
*/
ancestor_asg_dynamic,
ancestor_asg_dynamic,
/**
* "Oldest Server Group"
*/
oldest_asg_dynamic,
oldest_asg_dynamic,
/**
* "(Deprecated) Current Server Group"
*/
@Deprecated current_asg,
@Deprecated
current_asg,
/**
* "(Deprecated) Last Server Group"
*/
@Deprecated ancestor_asg,
@Deprecated
ancestor_asg,

boolean isDynamic() {
return this.name().endsWith("dynamic")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.netflix.spinnaker.orca.clouddriver.pipeline.instance.TerminatingInsta
import com.netflix.spinnaker.orca.clouddriver.pipeline.instance.TerminatingInstanceSupport
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.Location
import com.netflix.spinnaker.orca.clouddriver.tasks.AbstractCloudProviderAwareTask
import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard
import com.netflix.spinnaker.orca.pipeline.model.Stage
import org.springframework.beans.factory.annotation.Autowired
Expand Down Expand Up @@ -53,6 +54,7 @@ class TerminateInstanceAndDecrementServerGroupTask extends AbstractCloudProvider

trafficGuard.verifyInstanceTermination(
serverGroupName,
MonikerHelper.monikerFromStage(stage, serverGroupName),
[stage.context.instance] as List<String>,
account,
Location.region(stage.context.region as String),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.netflix.spinnaker.orca.clouddriver.pipeline.instance.TerminatingInsta
import com.netflix.spinnaker.orca.clouddriver.pipeline.instance.TerminatingInstanceSupport
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.Location
import com.netflix.spinnaker.orca.clouddriver.tasks.AbstractCloudProviderAwareTask
import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard
import com.netflix.spinnaker.orca.pipeline.model.Stage
import org.springframework.beans.factory.annotation.Autowired
Expand Down Expand Up @@ -53,6 +54,7 @@ class TerminateInstancesTask extends AbstractCloudProviderAwareTask implements T

trafficGuard.verifyInstanceTermination(
serverGroupName,
MonikerHelper.monikerFromStage(stage, serverGroupName),
stage.context.instanceIds as List<String>,
account,
Location.region(stage.context.region as String),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup

import com.netflix.spinnaker.moniker.Moniker
import com.netflix.spinnaker.orca.ExecutionStatus
import com.netflix.spinnaker.orca.RetryableTask
import com.netflix.spinnaker.orca.TaskResult
Expand Down Expand Up @@ -96,6 +97,7 @@ abstract class AbstractServerGroupTask extends AbstractCloudProviderAwareTask im
def tsg = TargetServerGroupResolver.fromPreviousStage(stage)
operation.asgName = tsg.name
operation.serverGroupName = tsg.name
operation.moniker = tsg.getMoniker()

def location = tsg.getLocation()
operation.deployServerGroupsRegion = tsg.region
Expand Down Expand Up @@ -138,5 +140,4 @@ abstract class AbstractServerGroupTask extends AbstractCloudProviderAwareTask im
operation.namespace ? new Location(Type.NAMESPACE, operation.namespace) :
null
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup;

import com.netflix.spinnaker.moniker.Moniker;
import com.netflix.spinnaker.orca.RetryableTask;
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -38,6 +39,7 @@ String getClouddriverOperation() {
@Override
void validateClusterStatus(Map<String, Object> operation) {
trafficGuard.verifyTrafficRemoval((String) operation.get("serverGroupName"),
(Moniker) operation.get("moniker"),
getCredentials(operation),
getLocation(operation),
getCloudProvider(operation), "Destroying");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup;

import com.netflix.spinnaker.moniker.Moniker;
import com.netflix.spinnaker.orca.RetryableTask;
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -37,6 +38,7 @@ String getClouddriverOperation() {
@Override
void validateClusterStatus(Map<String, Object> operation) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could pass a Moniker in to this method rather than extracting it each time since every implementation seems to need it

trafficGuard.verifyTrafficRemoval((String) operation.get("serverGroupName"),
(Moniker) operation.get("moniker"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this require an ObjectMapper? I remember that biting us in a prior PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(there's a few other places in this PR that does the same)

getCredentials(operation),
getLocation(operation),
getCloudProvider(operation), "Disabling");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup

import com.netflix.spinnaker.moniker.Moniker
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.DestroyServerGroupStage
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -31,6 +32,7 @@ class DestroyServerGroupTask extends AbstractServerGroupTask {
@Override
void validateClusterStatus(Map operation) {
trafficGuard.verifyTrafficRemoval(operation.serverGroupName as String,
operation.moniker as Moniker,
getCredentials(operation),
getLocation(operation),
getCloudProvider(operation), "Destroying")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup

import com.netflix.spinnaker.moniker.Moniker
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.DisableServerGroupStage
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -36,6 +37,7 @@ class DisableServerGroupTask extends AbstractServerGroupTask {
@Override
void validateClusterStatus(Map operation) {
trafficGuard.verifyTrafficRemoval(operation.serverGroupName as String,
operation.moniker as Moniker,
getCredentials(operation),
getLocation(operation),
getCloudProvider(operation), "Disabling")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.servergroup

import com.netflix.spinnaker.moniker.Moniker
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.ResizeServerGroupStage
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.Location
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.TargetServerGroup
Expand Down Expand Up @@ -66,6 +67,7 @@ class ResizeServerGroupTask extends AbstractServerGroupTask {
void validateClusterStatus(Map operation) {
if (operation.capacity.desired == 0) {
trafficGuard.verifyTrafficRemoval(operation.serverGroupName as String,
operation.moniker as Moniker,
getCredentials(operation),
getLocation(operation),
getCloudProvider(operation), "Removal of all instances in ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,21 @@

package com.netflix.spinnaker.orca.clouddriver.utils;

import com.netflix.frigga.Names;
import com.netflix.spinnaker.moniker.Moniker;

import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class ClusterMatcher {

public static ClusterMatchRule getMatchingRule(String account, String location, String clusterName, List<ClusterMatchRule> rules) {
public static ClusterMatchRule getMatchingRule(String account, String location, Moniker clusterMoniker, List<ClusterMatchRule> rules) {
if (!Optional.ofNullable(rules).isPresent()) {
return null;
}
Names nameParts = Names.parseName(clusterName);

String stack = nameParts.getStack() == null ? "" : nameParts.getStack();
String detail = nameParts.getDetail() == null ? "" : nameParts.getDetail();
String stack = clusterMoniker.getStack() == null ? "" : clusterMoniker.getStack();
String detail = clusterMoniker.getDetail() == null ? "" : clusterMoniker.getDetail();

List<ClusterMatchRule> candidates = rules.stream().filter(rule -> {
String ruleAccount = rule.getAccount();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/
@Component
public class MonikerHelper {

public String getAppNameFromStage(Stage stage, String fallbackFriggaName) {
Names names = Names.parseName(fallbackFriggaName);
Moniker moniker = monikerFromStage(stage);
Expand Down Expand Up @@ -58,4 +59,20 @@ static public Moniker monikerFromStage(Stage stage) {
return null;
}
}

static public Moniker monikerFromStage(Stage stage, String fallbackFriggaName) {
Moniker moniker = monikerFromStage(stage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: what happens when you have a stage that's dealing with potentially > 1 server group or cluster?

stage.context.moniker seems to imply there only ever being one, and nothing in the context key indicates it's intent.

The rollback stages are a current example with > 1 server group specified.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats a great point. I just tried a rollback and noticed this is what is sent from Deck to Orca:

{
  "application" : "nginx",
  "name" : "Rollback Server Group: nginx-trafficguards-v011",
  "appConfig" : null,
  "stages" : [ {
    "rollbackType" : "EXPLICIT",
    "rollbackContext" : {
      "rollbackServerGroupName" : "nginx-trafficguards-v011",
      "targetHealthyRollbackPercentage" : 100,
      "restoreServerGroupName" : "nginx-trafficguards-v010"
    },
    "platformHealthOnlyShowOverride" : false,
    "type" : "rollbackServerGroup",
    "moniker" : {
      "app" : "nginx",
      "cluster" : "nginx-trafficguards",
      "detail" : null,
      "sequence" : 11,
      "stack" : "trafficguards"
    },
    "region" : "us-west-2",
    "credentials" : "aws-dev",
    "cloudProvider" : "aws",
    "user" : "anonymous",
    "refId" : "0",
    "requisiteStageRefIds" : [ ]
  } ],
  "origin" : "deck"
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in the case of TrafficGuard, the moniker:

"moniker" : {
      "app" : "nginx",
      "cluster" : "nginx-trafficguards",
      "detail" : null,
      "sequence" : 11,
      "stack" : "trafficguards"
    }

would be passed through. In TrafficGuard itself only moniker.cluster is used. In ClusterMatcher only moniker.stack and moniker.detail are used. moniker.sequence is not used. So the moniker is more of a cluster moniker than a server group moniker.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajordens Do you know an example of a stage that uses multiple clusters?

if (moniker == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If interested, a one liner equivalent: Optional.ofNullable(moniker).orElse(friggerToMoniker(friggaName)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or moniker == null ? friggaToMoniker(friggaName) : moniker

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s even better.

Names names = Names.parseName(fallbackFriggaName);
return Moniker.builder()
.app(names.getApp())
.stack(names.getStack())
.detail(names.getDetail())
.cluster(names.getCluster())
.sequence(names.getSequence())
.build();
}
return moniker;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@

import java.util.*;
import java.util.stream.Collectors;
import com.netflix.frigga.Names;
import com.netflix.spinnaker.moniker.Moniker;
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.Location;
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.TargetServerGroup;
import com.netflix.spinnaker.orca.front50.Front50Service;
import com.netflix.spinnaker.orca.front50.model.Application;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -47,6 +46,7 @@ public TrafficGuard(OortHelper oortHelper, Optional<Front50Service> front50Servi
}

public void verifyInstanceTermination(String serverGroupNameFromStage,
Moniker serverGroupMonikerFromStage,
List<String> instanceIds,
String account,
Location location,
Expand All @@ -67,16 +67,15 @@ public void verifyInstanceTermination(String serverGroupNameFromStage,

instancesPerServerGroup.entrySet().forEach(entry -> {
String serverGroupName = entry.getKey();
Names names = Names.parseName(serverGroupName);
if (hasDisableLock(names.getCluster(), account, location)) {
if (hasDisableLock(serverGroupMonikerFromStage, account, location)) {
Optional<TargetServerGroup> targetServerGroup = oortHelper.getTargetServerGroup(account, serverGroupName, location.getValue(), cloudProvider);

targetServerGroup.ifPresent(serverGroup -> {
Optional<Map> thisInstance = serverGroup.getInstances().stream().filter(i -> "Up".equals(i.get("healthState"))).findFirst();
if (thisInstance.isPresent() && "Up".equals(thisInstance.get().get("healthState"))) {
long otherActiveInstances = serverGroup.getInstances().stream().filter(i -> "Up".equals(i.get("healthState")) && !entry.getValue().contains(i.get("name"))).count();
if (otherActiveInstances == 0) {
verifyOtherServerGroupsAreTakingTraffic(serverGroupName, location, account, cloudProvider, operationDescriptor);
verifyOtherServerGroupsAreTakingTraffic(serverGroupName, serverGroup.getMoniker(), location, account, cloudProvider, operationDescriptor);
}
}
});
Expand All @@ -91,22 +90,19 @@ private Optional<String> resolveServerGroupNameForInstance(String instanceId, St
return Optional.ofNullable((String) instance.orElse(new HashMap<>()).get("serverGroup"));
}

public void verifyTrafficRemoval(String serverGroupName, String account, Location location, String cloudProvider, String operationDescriptor) {
Names names = Names.parseName(serverGroupName);

if (!hasDisableLock(names.getCluster(), account, location)) {
public void verifyTrafficRemoval(String serverGroupName, Moniker serverGroupMoniker, String account, Location location, String cloudProvider, String operationDescriptor) {
if (!hasDisableLock(serverGroupMoniker, account, location)) {
return;
}

verifyOtherServerGroupsAreTakingTraffic(serverGroupName, location, account, cloudProvider, operationDescriptor);
verifyOtherServerGroupsAreTakingTraffic(serverGroupName, serverGroupMoniker,location, account, cloudProvider, operationDescriptor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing needed serverGroupMoniker,location

}

private void verifyOtherServerGroupsAreTakingTraffic(String serverGroupName, Location location, String account, String cloudProvider, String operationDescriptor) {
Names names = Names.parseName(serverGroupName);
Optional<Map> cluster = oortHelper.getCluster(names.getApp(), account, names.getCluster(), cloudProvider);
private void verifyOtherServerGroupsAreTakingTraffic(String serverGroupName, Moniker serverGroupMoniker, Location location, String account, String cloudProvider, String operationDescriptor) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to pass around serverGroupName if we've got a moniker? Maybe we do now as a transition but couldn't you compare moniker's instead of !serverGroupName.equals(tsg.getName()) &&?

Copy link
Member Author

@andrewbackes andrewbackes Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The server group name isn't contained in the moniker object (only app, stack, detail, cluster, sequence). In the case of the Frigga naming convention, you can reconstruct the name using the moniker object. But that reconstruction won't work for the manifest based k8s provider.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it silly to ask why we couldn’t have it also contain the serverGroupName?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lwander can probably give you a more thorough explanation. From my POV, I think that it isn't necessary to facilitate the migration away from frigga. It would also require a significant amount of effort. If you search for serverGroupName in Orca there are 362 occurrences.

FYI: This is related to another point. There is now a lot of redundancy with application/stack/detail in the stage data payload. In many places, those fields are already included at the root level of the stage and are now in the moniker as well. A follow up task will probably be to consolidate those.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No that's a good question. We don't want the moniker to be the identifier for the object since the point of the moniker is to decouple the name from the relationships (app, cluster) that frigga presented us. The separation of concerns is: name is a way to identify an object and moniker is to decide which cluster & application an object belongs to.

When you assign or derive a moniker from an object, that object doesn't even have to provide us with a name, (e.g. ec2 tags), so the idea is really to keep these concepts separate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point about including the name was somewhat predicated in that when I hear Moniker, I think of name.

The relationships are really part of the identity of an object, which is why we need to pass application/cluster/region/name/etc. around everywhere.

My biggest grief is that we're slowly developing more and more ways to specify the coordinates for an object: serverGroupName, asgName, regions, region, zone, zones, moniker, etc.

In the case of moniker it's only dealing with names, so we can ignore regions/region/zone/zones and think about it only as a partial coordinate.

I hold out hope that there will be some consolidation, as it's difficult and error prone to keep everything straight.

Just my 2c.

I think it would be cleaner and possible to pass a Moniker into validateClusterStatus but otherwise this PR fits the existing patterns and can be merged.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My hope is this kind of clean up/refactor will point out more places where we can consolidate the many names/coordinates you point out. We'll keep this in mind going forward.

Optional<Map> cluster = oortHelper.getCluster(serverGroupMoniker.getApp(), account, serverGroupMoniker.getCluster(), cloudProvider);

if (!cluster.isPresent()) {
throw new IllegalStateException(format("Could not find cluster '%s' in %s/%s with traffic guard configured.", names.getCluster(), account, location.getValue()));
throw new IllegalStateException(format("Could not find cluster '%s' in %s/%s with traffic guard configured.", serverGroupMoniker.getCluster(), account, location.getValue()));
}
List<TargetServerGroup> targetServerGroups = ((List<Map<String, Object>>) cluster.get().get("serverGroups"))
.stream()
Expand All @@ -120,19 +116,18 @@ private void verifyOtherServerGroupsAreTakingTraffic(String serverGroupName, Loc
);
if (!otherEnabledServerGroupFound) {
throw new IllegalStateException(format("This cluster ('%s' in %s/%s) has traffic guards enabled. " +
"%s %s would leave the cluster with no instances taking traffic.", names.getCluster(), account, location.getValue(), operationDescriptor, serverGroupName));
"%s %s would leave the cluster with no instances taking traffic.", serverGroupMoniker.getCluster(), account, location.getValue(), operationDescriptor, serverGroupName));
}
}

public boolean hasDisableLock(String cluster, String account, Location location) {
public boolean hasDisableLock(Moniker clusterMoniker, String account, Location location) {
if (front50Service == null) {
log.warn("Front50 has not been configured, no way to check disable lock. Fix this by setting front50.enabled: true");
return false;
}
Names names = Names.parseName(cluster);
Application application;
try {
application = front50Service.get(names.getApp());
application = front50Service.get(clusterMoniker.getApp());
} catch (RetrofitError e) {
if (e.getResponse() != null && e.getResponse().getStatus() == 404) {
application = null;
Expand All @@ -147,6 +142,6 @@ public boolean hasDisableLock(String cluster, String account, Location location)
List<ClusterMatchRule> rules = trafficGuards.stream().map(guard ->
new ClusterMatchRule(guard.get("account"), guard.get("location"), guard.get("stack"), guard.get("detail"), 1)
).collect(Collectors.toList());
return ClusterMatcher.getMatchingRule(account, location.getValue(), cluster, rules) != null;
return ClusterMatcher.getMatchingRule(account, location.getValue(), clusterMoniker, rules) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.netflix.spinnaker.orca.clouddriver.KatoService
import com.netflix.spinnaker.orca.clouddriver.pipeline.servergroup.support.Location
import com.netflix.spinnaker.orca.clouddriver.utils.CloudProviderAware
import com.netflix.spinnaker.orca.clouddriver.utils.HealthHelper
import com.netflix.spinnaker.orca.clouddriver.utils.MonikerHelper
import com.netflix.spinnaker.orca.clouddriver.utils.TrafficGuard
import com.netflix.spinnaker.orca.pipeline.model.Stage
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -46,6 +47,7 @@ class DisableInstancesTask implements CloudProviderAware, Task {

trafficGuard.verifyInstanceTermination(
serverGroupName,
MonikerHelper.monikerFromStage(stage, serverGroupName),
stage.context.instanceIds as List<String>,
account,
Location.region(stage.context.region as String),
Expand Down
Loading