Autoscaling - add support for TargetTracking/StepAdjustments in scaling policy (#4449)
This commit is contained in:
parent
ecd8d2478f
commit
fff69b9faa
@ -7,7 +7,7 @@ from moto.packages.boto.ec2.blockdevicemapping import (
|
||||
from moto.ec2.exceptions import InvalidInstanceIdError
|
||||
|
||||
from collections import OrderedDict
|
||||
from moto.core import BaseBackend, BaseModel, CloudFormationModel
|
||||
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel, CloudFormationModel
|
||||
from moto.core.utils import camelcase_to_underscores
|
||||
from moto.ec2 import ec2_backends
|
||||
from moto.elb import elb_backends
|
||||
@ -70,6 +70,8 @@ class FakeScalingPolicy(BaseModel):
|
||||
as_name,
|
||||
scaling_adjustment,
|
||||
cooldown,
|
||||
target_tracking_config,
|
||||
step_adjustments,
|
||||
autoscaling_backend,
|
||||
):
|
||||
self.name = name
|
||||
@ -81,8 +83,14 @@ class FakeScalingPolicy(BaseModel):
|
||||
self.cooldown = cooldown
|
||||
else:
|
||||
self.cooldown = DEFAULT_COOLDOWN
|
||||
self.target_tracking_config = target_tracking_config
|
||||
self.step_adjustments = step_adjustments
|
||||
self.autoscaling_backend = autoscaling_backend
|
||||
|
||||
@property
|
||||
def arn(self):
|
||||
return f"arn:aws:autoscaling:{self.autoscaling_backend.region}:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{self.as_name}:policyName/{self.name}"
|
||||
|
||||
def execute(self):
|
||||
if self.adjustment_type == "ExactCapacity":
|
||||
self.autoscaling_backend.set_desired_capacity(
|
||||
@ -612,6 +620,7 @@ class AutoScalingBackend(BaseBackend):
|
||||
self.ec2_backend = ec2_backend
|
||||
self.elb_backend = elb_backend
|
||||
self.elbv2_backend = elbv2_backend
|
||||
self.region = self.elbv2_backend.region_name
|
||||
|
||||
def reset(self):
|
||||
ec2_backend = self.ec2_backend
|
||||
@ -943,7 +952,15 @@ class AutoScalingBackend(BaseBackend):
|
||||
self.lifecycle_hooks.pop("%s_%s" % (as_name, name), None)
|
||||
|
||||
def create_autoscaling_policy(
|
||||
self, name, policy_type, adjustment_type, as_name, scaling_adjustment, cooldown
|
||||
self,
|
||||
name,
|
||||
policy_type,
|
||||
adjustment_type,
|
||||
as_name,
|
||||
scaling_adjustment,
|
||||
cooldown,
|
||||
target_tracking_config,
|
||||
step_adjustments,
|
||||
):
|
||||
policy = FakeScalingPolicy(
|
||||
name,
|
||||
@ -952,6 +969,8 @@ class AutoScalingBackend(BaseBackend):
|
||||
as_name,
|
||||
scaling_adjustment,
|
||||
cooldown,
|
||||
target_tracking_config,
|
||||
step_adjustments,
|
||||
self,
|
||||
)
|
||||
|
||||
|
@ -273,13 +273,16 @@ class AutoScalingResponse(BaseResponse):
|
||||
return template.render()
|
||||
|
||||
def put_scaling_policy(self):
|
||||
params = self._get_params()
|
||||
policy = self.autoscaling_backend.create_autoscaling_policy(
|
||||
name=self._get_param("PolicyName"),
|
||||
policy_type=self._get_param("PolicyType"),
|
||||
adjustment_type=self._get_param("AdjustmentType"),
|
||||
as_name=self._get_param("AutoScalingGroupName"),
|
||||
name=params.get("PolicyName"),
|
||||
policy_type=params.get("PolicyType", "SimpleScaling"),
|
||||
adjustment_type=params.get("AdjustmentType"),
|
||||
as_name=params.get("AutoScalingGroupName"),
|
||||
scaling_adjustment=self._get_int_param("ScalingAdjustment"),
|
||||
cooldown=self._get_int_param("Cooldown"),
|
||||
target_tracking_config=params.get("TargetTrackingConfiguration", {}),
|
||||
step_adjustments=params.get("StepAdjustments", []),
|
||||
)
|
||||
template = self.response_template(CREATE_SCALING_POLICY_TEMPLATE)
|
||||
return template.render(policy=policy)
|
||||
@ -801,14 +804,39 @@ DESCRIBE_SCALING_POLICIES_TEMPLATE = """<DescribePoliciesResponse xmlns="http://
|
||||
<ScalingPolicies>
|
||||
{% for policy in policies %}
|
||||
<member>
|
||||
<PolicyARN>arn:aws:autoscaling:us-east-1:803981987763:scalingPolicy:c322
|
||||
761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/my-test-asg:policyName/MyScaleDownPolicy</PolicyARN>
|
||||
<PolicyARN>{{ policy.arn }}</PolicyARN>
|
||||
<AdjustmentType>{{ policy.adjustment_type }}</AdjustmentType>
|
||||
{% if policy.scaling_adjustment %}
|
||||
<ScalingAdjustment>{{ policy.scaling_adjustment }}</ScalingAdjustment>
|
||||
{% endif %}
|
||||
<PolicyName>{{ policy.name }}</PolicyName>
|
||||
<PolicyType>{{ policy.policy_type }}</PolicyType>
|
||||
<AutoScalingGroupName>{{ policy.as_name }}</AutoScalingGroupName>
|
||||
{% if policy.policy_type == 'SimpleScaling' %}
|
||||
<Cooldown>{{ policy.cooldown }}</Cooldown>
|
||||
{% endif %}
|
||||
{% if policy.policy_type == 'TargetTrackingScaling' %}
|
||||
<TargetTrackingConfiguration>
|
||||
<PredefinedMetricSpecification>
|
||||
<PredefinedMetricType>{{ policy.target_tracking_config.get("PredefinedMetricSpecification", {}).get("PredefinedMetricType", "") }}</PredefinedMetricType>
|
||||
{% if policy.target_tracking_config.get("PredefinedMetricSpecification", {}).get("ResourceLabel") %}
|
||||
<ResourceLabel>{{ policy.target_tracking_config.get("PredefinedMetricSpecification", {}).get("ResourceLabel") }}</ResourceLabel>
|
||||
{% endif %}
|
||||
</PredefinedMetricSpecification>
|
||||
<TargetValue>{{ policy.target_tracking_config.get("TargetValue") }}</TargetValue>
|
||||
</TargetTrackingConfiguration>
|
||||
{% endif %}
|
||||
{% if policy.policy_type == 'StepScaling' %}
|
||||
<StepAdjustments>
|
||||
{% for step in policy.step_adjustments %}
|
||||
<entry>
|
||||
<MetricIntervalLowerBound>{{ step.get("MetricIntervalLowerBound") }}</MetricIntervalLowerBound>
|
||||
<MetricIntervalUpperBound>{{ step.get("MetricIntervalUpperBound") }}</MetricIntervalUpperBound>
|
||||
<ScalingAdjustment>{{ step.get("ScalingAdjustment") }}</ScalingAdjustment>
|
||||
</entry>
|
||||
{% endfor %}
|
||||
</StepAdjustments>
|
||||
{% endif %}
|
||||
<Alarms/>
|
||||
</member>
|
||||
{% endfor %}
|
||||
|
@ -17,6 +17,7 @@ from moto import (
|
||||
mock_autoscaling_deprecated,
|
||||
mock_ec2,
|
||||
)
|
||||
from moto.core import ACCOUNT_ID
|
||||
from tests.helpers import requires_boto_gte
|
||||
|
||||
from .utils import (
|
||||
@ -1597,7 +1598,16 @@ def test_autoscaling_describe_policies_boto3():
|
||||
PolicyTypes=["SimpleScaling"],
|
||||
)
|
||||
response["ScalingPolicies"].should.have.length_of(1)
|
||||
response["ScalingPolicies"][0]["PolicyName"].should.equal("test_policy_down")
|
||||
policy = response["ScalingPolicies"][0]
|
||||
policy["PolicyType"].should.equal("SimpleScaling")
|
||||
policy["AdjustmentType"].should.equal("PercentChangeInCapacity")
|
||||
policy["ScalingAdjustment"].should.equal(-10)
|
||||
policy["Cooldown"].should.equal(60)
|
||||
policy["PolicyARN"].should.equal(
|
||||
f"arn:aws:autoscaling:us-east-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/test_asg:policyName/test_policy_down"
|
||||
)
|
||||
policy["PolicyName"].should.equal("test_policy_down")
|
||||
policy.shouldnt.have.key("TargetTrackingConfiguration")
|
||||
|
||||
|
||||
@mock_elb
|
||||
@ -1677,6 +1687,114 @@ def test_detach_one_instance_decrement():
|
||||
)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_create_autoscaling_policy_with_policytype__targettrackingscaling():
|
||||
mocked_networking = setup_networking(region_name="us-west-1")
|
||||
client = boto3.client("autoscaling", region_name="us-west-1")
|
||||
configuration_name = "test"
|
||||
asg_name = "asg_test"
|
||||
|
||||
client.create_launch_configuration(
|
||||
LaunchConfigurationName=configuration_name,
|
||||
ImageId=EXAMPLE_AMI_ID,
|
||||
InstanceType="m1.small",
|
||||
)
|
||||
client.create_auto_scaling_group(
|
||||
LaunchConfigurationName=configuration_name,
|
||||
AutoScalingGroupName=asg_name,
|
||||
MinSize=1,
|
||||
MaxSize=2,
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
client.put_scaling_policy(
|
||||
AutoScalingGroupName=asg_name,
|
||||
PolicyName=configuration_name,
|
||||
PolicyType="TargetTrackingScaling",
|
||||
EstimatedInstanceWarmup=100,
|
||||
TargetTrackingConfiguration={
|
||||
"PredefinedMetricSpecification": {
|
||||
"PredefinedMetricType": "ASGAverageNetworkIn",
|
||||
},
|
||||
"TargetValue": 1000000.0,
|
||||
},
|
||||
)
|
||||
|
||||
resp = client.describe_policies(AutoScalingGroupName=asg_name)
|
||||
policy = resp["ScalingPolicies"][0]
|
||||
policy.should.have.key("PolicyName").equals(configuration_name)
|
||||
policy.should.have.key("PolicyARN").equals(
|
||||
f"arn:aws:autoscaling:us-west-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{asg_name}:policyName/{configuration_name}"
|
||||
)
|
||||
policy.should.have.key("PolicyType").equals("TargetTrackingScaling")
|
||||
policy.should.have.key("TargetTrackingConfiguration").should.equal(
|
||||
{
|
||||
"PredefinedMetricSpecification": {
|
||||
"PredefinedMetricType": "ASGAverageNetworkIn",
|
||||
},
|
||||
"TargetValue": 1000000.0,
|
||||
}
|
||||
)
|
||||
policy.shouldnt.have.key("ScalingAdjustment")
|
||||
policy.shouldnt.have.key("Cooldown")
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_create_autoscaling_policy_with_policytype__stepscaling():
|
||||
mocked_networking = setup_networking(region_name="eu-west-1")
|
||||
client = boto3.client("autoscaling", region_name="eu-west-1")
|
||||
launch_config_name = "lg_name"
|
||||
asg_name = "asg_test"
|
||||
|
||||
client.create_launch_configuration(
|
||||
LaunchConfigurationName=launch_config_name,
|
||||
ImageId=EXAMPLE_AMI_ID,
|
||||
InstanceType="m1.small",
|
||||
)
|
||||
client.create_auto_scaling_group(
|
||||
LaunchConfigurationName=launch_config_name,
|
||||
AutoScalingGroupName=asg_name,
|
||||
MinSize=1,
|
||||
MaxSize=2,
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
client.put_scaling_policy(
|
||||
AutoScalingGroupName=asg_name,
|
||||
PolicyName=launch_config_name,
|
||||
PolicyType="StepScaling",
|
||||
StepAdjustments=[
|
||||
{
|
||||
"MetricIntervalLowerBound": 2,
|
||||
"MetricIntervalUpperBound": 8,
|
||||
"ScalingAdjustment": 1,
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
resp = client.describe_policies(AutoScalingGroupName=asg_name)
|
||||
policy = resp["ScalingPolicies"][0]
|
||||
policy.should.have.key("PolicyName").equals(launch_config_name)
|
||||
policy.should.have.key("PolicyARN").equals(
|
||||
f"arn:aws:autoscaling:eu-west-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{asg_name}:policyName/{launch_config_name}"
|
||||
)
|
||||
policy.should.have.key("PolicyType").equals("StepScaling")
|
||||
policy.should.have.key("StepAdjustments").equal(
|
||||
[
|
||||
{
|
||||
"MetricIntervalLowerBound": 2,
|
||||
"MetricIntervalUpperBound": 8,
|
||||
"ScalingAdjustment": 1,
|
||||
}
|
||||
]
|
||||
)
|
||||
policy.shouldnt.have.key("TargetTrackingConfiguration")
|
||||
policy.shouldnt.have.key("ScalingAdjustment")
|
||||
policy.shouldnt.have.key("Cooldown")
|
||||
|
||||
|
||||
@mock_elb
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
|
@ -4,14 +4,14 @@ from moto import mock_ec2, mock_ec2_deprecated
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def setup_networking():
|
||||
ec2 = boto3.resource("ec2", region_name="us-east-1")
|
||||
def setup_networking(region_name="us-east-1"):
|
||||
ec2 = boto3.resource("ec2", region_name=region_name)
|
||||
vpc = ec2.create_vpc(CidrBlock="10.11.0.0/16")
|
||||
subnet1 = ec2.create_subnet(
|
||||
VpcId=vpc.id, CidrBlock="10.11.1.0/24", AvailabilityZone="us-east-1a"
|
||||
VpcId=vpc.id, CidrBlock="10.11.1.0/24", AvailabilityZone=f"{region_name}a"
|
||||
)
|
||||
subnet2 = ec2.create_subnet(
|
||||
VpcId=vpc.id, CidrBlock="10.11.2.0/24", AvailabilityZone="us-east-1b"
|
||||
VpcId=vpc.id, CidrBlock="10.11.2.0/24", AvailabilityZone=f"{region_name}b"
|
||||
)
|
||||
return {"vpc": vpc.id, "subnet1": subnet1.id, "subnet2": subnet2.id}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user