672 lines
23 KiB
Python
672 lines
23 KiB
Python
import re
|
|
|
|
import boto3
|
|
import pytest
|
|
|
|
from moto import mock_aws
|
|
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
|
|
|
DEFAULT_REGION = "us-east-1"
|
|
DEFAULT_ECS_CLUSTER = "default"
|
|
DEFAULT_ECS_TASK = "test_ecs_task"
|
|
DEFAULT_ECS_SERVICE = "sample-webapp"
|
|
DEFAULT_SERVICE_NAMESPACE = "ecs"
|
|
DEFAULT_RESOURCE_ID = f"service/{DEFAULT_ECS_CLUSTER}/{DEFAULT_ECS_SERVICE}"
|
|
DEFAULT_SCALABLE_DIMENSION = "ecs:service:DesiredCount"
|
|
DEFAULT_MIN_CAPACITY = 1
|
|
DEFAULT_MAX_CAPACITY = 1
|
|
DEFAULT_ROLE_ARN = "test:arn"
|
|
DEFAULT_SUSPENDED_STATE = {
|
|
"DynamicScalingInSuspended": True,
|
|
"DynamicScalingOutSuspended": True,
|
|
"ScheduledScalingSuspended": True,
|
|
}
|
|
|
|
|
|
def _create_ecs_defaults(ecs, create_service=True):
|
|
_ = ecs.create_cluster(clusterName=DEFAULT_ECS_CLUSTER)
|
|
_ = ecs.register_task_definition(
|
|
family=DEFAULT_ECS_TASK,
|
|
containerDefinitions=[
|
|
{
|
|
"name": "hello_world",
|
|
"image": "docker/hello-world:latest",
|
|
"cpu": 1024,
|
|
"memory": 400,
|
|
"essential": True,
|
|
"environment": [
|
|
{"name": "AWS_ACCESS_KEY_ID", "value": "SOME_ACCESS_KEY"}
|
|
],
|
|
"logConfiguration": {"logDriver": "json-file"},
|
|
}
|
|
],
|
|
)
|
|
if create_service:
|
|
_ = ecs.create_service(
|
|
cluster=DEFAULT_ECS_CLUSTER,
|
|
serviceName=DEFAULT_ECS_SERVICE,
|
|
taskDefinition=DEFAULT_ECS_TASK,
|
|
desiredCount=2,
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scalable_targets_one_basic_ecs_success():
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs)
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
client.register_scalable_target(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE,
|
|
ResourceId=DEFAULT_RESOURCE_ID,
|
|
ScalableDimension=DEFAULT_SCALABLE_DIMENSION,
|
|
)
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalableTargets"]) == 1
|
|
t = response["ScalableTargets"][0]
|
|
assert t["ServiceNamespace"] == DEFAULT_SERVICE_NAMESPACE
|
|
assert t["ResourceId"] == DEFAULT_RESOURCE_ID
|
|
assert t["ScalableDimension"] == DEFAULT_SCALABLE_DIMENSION
|
|
assert "CreationTime" in t
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scalable_targets_one_full_ecs_success():
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs)
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
register_scalable_target(client)
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalableTargets"]) == 1
|
|
t = response["ScalableTargets"][0]
|
|
assert t["ServiceNamespace"] == DEFAULT_SERVICE_NAMESPACE
|
|
assert t["ResourceId"] == DEFAULT_RESOURCE_ID
|
|
assert t["ScalableDimension"] == DEFAULT_SCALABLE_DIMENSION
|
|
assert t["MinCapacity"] == DEFAULT_MIN_CAPACITY
|
|
assert t["MaxCapacity"] == DEFAULT_MAX_CAPACITY
|
|
assert t["RoleARN"] == DEFAULT_ROLE_ARN
|
|
assert "CreationTime" in t
|
|
assert (
|
|
t["SuspendedState"]["DynamicScalingInSuspended"]
|
|
== DEFAULT_SUSPENDED_STATE["DynamicScalingInSuspended"]
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scalable_targets_only_return_ecs_targets():
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs, create_service=False)
|
|
_ = ecs.create_service(
|
|
cluster=DEFAULT_ECS_CLUSTER,
|
|
serviceName="test1",
|
|
taskDefinition=DEFAULT_ECS_TASK,
|
|
desiredCount=2,
|
|
)
|
|
_ = ecs.create_service(
|
|
cluster=DEFAULT_ECS_CLUSTER,
|
|
serviceName="test2",
|
|
taskDefinition=DEFAULT_ECS_TASK,
|
|
desiredCount=2,
|
|
)
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
register_scalable_target(
|
|
client,
|
|
ServiceNamespace="ecs",
|
|
ResourceId=f"service/{DEFAULT_ECS_CLUSTER}/test1",
|
|
)
|
|
register_scalable_target(
|
|
client,
|
|
ServiceNamespace="ecs",
|
|
ResourceId=f"service/{DEFAULT_ECS_CLUSTER}/test2",
|
|
)
|
|
register_scalable_target(
|
|
client,
|
|
ServiceNamespace="elasticmapreduce",
|
|
ResourceId="instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0",
|
|
ScalableDimension="elasticmapreduce:instancegroup:InstanceCount",
|
|
)
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalableTargets"]) == 2
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scalable_targets_next_token_success():
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs, create_service=False)
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
for i in range(0, 100):
|
|
_ = ecs.create_service(
|
|
cluster=DEFAULT_ECS_CLUSTER,
|
|
serviceName=str(i),
|
|
taskDefinition=DEFAULT_ECS_TASK,
|
|
desiredCount=2,
|
|
)
|
|
register_scalable_target(
|
|
client,
|
|
ServiceNamespace="ecs",
|
|
ResourceId=f"service/{DEFAULT_ECS_CLUSTER}/{i}",
|
|
)
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalableTargets"]) == 50
|
|
assert response["ScalableTargets"][0]["ResourceId"] == "service/default/0"
|
|
assert response["NextToken"] == "49"
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE, NextToken=str(response["NextToken"])
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalableTargets"]) == 50
|
|
assert response["ScalableTargets"][0]["ResourceId"] == "service/default/50"
|
|
assert "NextToken" not in response
|
|
|
|
|
|
def register_scalable_target(client, **kwargs):
|
|
"""Build a default scalable target object for use in tests."""
|
|
return client.register_scalable_target(
|
|
ServiceNamespace=kwargs.get("ServiceNamespace", DEFAULT_SERVICE_NAMESPACE),
|
|
ResourceId=kwargs.get("ResourceId", DEFAULT_RESOURCE_ID),
|
|
ScalableDimension=kwargs.get("ScalableDimension", DEFAULT_SCALABLE_DIMENSION),
|
|
MinCapacity=kwargs.get("MinCapacity", DEFAULT_MIN_CAPACITY),
|
|
MaxCapacity=kwargs.get("MaxCapacity", DEFAULT_MAX_CAPACITY),
|
|
RoleARN=kwargs.get("RoleARN", DEFAULT_ROLE_ARN),
|
|
SuspendedState=kwargs.get("SuspendedState", DEFAULT_SUSPENDED_STATE),
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_register_scalable_target_resource_id_variations():
|
|
# Required to register an ECS target in moto
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs)
|
|
|
|
# See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-applicationautoscaling-scalabletarget.html
|
|
resource_id_variations = [
|
|
(
|
|
DEFAULT_SERVICE_NAMESPACE,
|
|
DEFAULT_RESOURCE_ID,
|
|
DEFAULT_SCALABLE_DIMENSION,
|
|
), # ECS
|
|
(
|
|
"ec2",
|
|
"spot-fleet-request/sfr-73fbd2ce-aa30-494c-8788-1cee4EXAMPLE",
|
|
"ec2:spot-fleet-request:TargetCapacity",
|
|
),
|
|
(
|
|
"elasticmapreduce",
|
|
"instancegroup/j-2EEZNYKUA1NTV/ig-1791Y4E1L8YI0",
|
|
"elasticmapreduce:instancegroup:InstanceCount",
|
|
),
|
|
("appstream", "fleet/sample-fleet", "appstream:fleet:DesiredCapacity"),
|
|
("dynamodb", "table/my-table", "dynamodb:table:ReadCapacityUnits"),
|
|
(
|
|
"dynamodb",
|
|
"table/my-table/index/my-table-index",
|
|
"dynamodb:index:ReadCapacityUnits",
|
|
),
|
|
("rds", "cluster:my-db-cluster", "rds:cluster:ReadReplicaCount"),
|
|
(
|
|
"sagemaker",
|
|
"endpoint/MyEndPoint/variant/MyVariant",
|
|
"sagemaker:variant:DesiredInstanceCount",
|
|
),
|
|
(
|
|
"comprehend",
|
|
"arn:aws:comprehend:us-west-2:123456789012:document-classifier-endpoint/EXAMPLE",
|
|
"comprehend:document-classifier-endpoint:DesiredInferenceUnits",
|
|
),
|
|
(
|
|
"lambda",
|
|
"function:my-function:prod",
|
|
"lambda:function:ProvisionedConcurrency",
|
|
),
|
|
(
|
|
"cassandra",
|
|
"keyspace/mykeyspace/table/mytable",
|
|
"cassandra:table:ReadCapacityUnits",
|
|
),
|
|
(
|
|
"custom-resource",
|
|
"https://test-endpoint.amazon.com/ScalableDimension/test-resource",
|
|
"custom-resource:ResourceType:Property",
|
|
),
|
|
]
|
|
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
for namespace, resource_id, scalable_dimension in resource_id_variations:
|
|
client.register_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
MinCapacity=1,
|
|
MaxCapacity=8,
|
|
)
|
|
response = client.describe_scalable_targets(ServiceNamespace=namespace)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
num_targets = 2 if namespace == "dynamodb" and "index" in resource_id else 1
|
|
assert len(response["ScalableTargets"]) == num_targets
|
|
t = response["ScalableTargets"][-1]
|
|
assert t["ServiceNamespace"] == namespace
|
|
assert t["ResourceId"] == resource_id
|
|
assert t["ScalableDimension"] == scalable_dimension
|
|
assert "CreationTime" in t
|
|
|
|
|
|
@mock_aws
|
|
def test_register_scalable_target_updates_existing_target():
|
|
ecs = boto3.client("ecs", region_name=DEFAULT_REGION)
|
|
_create_ecs_defaults(ecs)
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
register_scalable_target(client)
|
|
|
|
updated_min_capacity = 3
|
|
updated_max_capacity = 10
|
|
updated_suspended_state = {
|
|
"DynamicScalingInSuspended": False,
|
|
"DynamicScalingOutSuspended": False,
|
|
"ScheduledScalingSuspended": False,
|
|
}
|
|
|
|
client.register_scalable_target(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE,
|
|
ResourceId=DEFAULT_RESOURCE_ID,
|
|
ScalableDimension=DEFAULT_SCALABLE_DIMENSION,
|
|
MinCapacity=updated_min_capacity,
|
|
MaxCapacity=updated_max_capacity,
|
|
SuspendedState=updated_suspended_state,
|
|
)
|
|
response = client.describe_scalable_targets(
|
|
ServiceNamespace=DEFAULT_SERVICE_NAMESPACE
|
|
)
|
|
|
|
assert len(response["ScalableTargets"]) == 1
|
|
t = response["ScalableTargets"][0]
|
|
assert t["MinCapacity"] == updated_min_capacity
|
|
assert t["MaxCapacity"] == updated_max_capacity
|
|
assert (
|
|
t["SuspendedState"]["DynamicScalingInSuspended"]
|
|
== updated_suspended_state["DynamicScalingInSuspended"]
|
|
)
|
|
assert (
|
|
t["SuspendedState"]["DynamicScalingOutSuspended"]
|
|
== updated_suspended_state["DynamicScalingOutSuspended"]
|
|
)
|
|
assert (
|
|
t["SuspendedState"]["ScheduledScalingSuspended"]
|
|
== updated_suspended_state["ScheduledScalingSuspended"]
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
["policy_type", "policy_body_kwargs"],
|
|
[
|
|
[
|
|
"TargetTrackingScaling",
|
|
{
|
|
"TargetTrackingScalingPolicyConfiguration": {
|
|
"TargetValue": 70.0,
|
|
"PredefinedMetricSpecification": {
|
|
"PredefinedMetricType": "SageMakerVariantInvocationsPerInstance"
|
|
},
|
|
}
|
|
},
|
|
],
|
|
[
|
|
"TargetTrackingScaling",
|
|
{
|
|
"StepScalingPolicyConfiguration": {
|
|
"AdjustmentType": "ChangeCapacity",
|
|
"StepAdjustments": [{"ScalingAdjustment": 10}],
|
|
"MinAdjustmentMagnitude": 2,
|
|
},
|
|
},
|
|
],
|
|
],
|
|
)
|
|
@mock_aws
|
|
def test_put_scaling_policy(policy_type, policy_body_kwargs):
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
namespace = "sagemaker"
|
|
resource_id = "endpoint/MyEndPoint/variant/MyVariant"
|
|
scalable_dimension = "sagemaker:variant:DesiredInstanceCount"
|
|
|
|
client.register_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
MinCapacity=1,
|
|
MaxCapacity=8,
|
|
)
|
|
|
|
policy_name = "MyPolicy"
|
|
|
|
with pytest.raises(client.exceptions.ValidationException) as e:
|
|
client.put_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
PolicyType="ABCDEFG",
|
|
**policy_body_kwargs,
|
|
)
|
|
assert (
|
|
e.value.response["Error"]["Message"] == "Unknown policy type ABCDEFG specified."
|
|
)
|
|
|
|
response = client.put_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
PolicyType=policy_type,
|
|
**policy_body_kwargs,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert (
|
|
re.match(
|
|
pattern=rf"arn:aws:autoscaling:{DEFAULT_REGION}:{ACCOUNT_ID}:scalingPolicy:.*:resource/{namespace}/{resource_id}:policyName/{policy_name}",
|
|
string=response["PolicyARN"],
|
|
)
|
|
is not None
|
|
)
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scaling_policies():
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
namespace = "sagemaker"
|
|
resource_id = "endpoint/MyEndPoint/variant/MyVariant"
|
|
scalable_dimension = "sagemaker:variant:DesiredInstanceCount"
|
|
|
|
client.register_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
MinCapacity=1,
|
|
MaxCapacity=8,
|
|
)
|
|
|
|
policy_name = "MyPolicy"
|
|
policy_type = "TargetTrackingScaling"
|
|
policy_body = {
|
|
"TargetValue": 70.0,
|
|
"PredefinedMetricSpecification": {
|
|
"PredefinedMetricType": "SageMakerVariantInvocationsPerInstance"
|
|
},
|
|
}
|
|
|
|
response = client.put_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
PolicyType=policy_type,
|
|
TargetTrackingScalingPolicyConfiguration=policy_body,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
|
|
response = client.describe_scaling_policies(
|
|
PolicyNames=[policy_name],
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
policy = response["ScalingPolicies"][0]
|
|
assert policy["PolicyName"] == policy_name
|
|
assert policy["ServiceNamespace"] == namespace
|
|
assert policy["ResourceId"] == resource_id
|
|
assert policy["ScalableDimension"] == scalable_dimension
|
|
assert policy["PolicyType"] == policy_type
|
|
assert policy["TargetTrackingScalingPolicyConfiguration"] == policy_body
|
|
assert (
|
|
re.match(
|
|
pattern=rf"arn:aws:autoscaling:{DEFAULT_REGION}:{ACCOUNT_ID}:scalingPolicy:.*:resource/{namespace}/{resource_id}:policyName/{policy_name}",
|
|
string=policy["PolicyARN"],
|
|
)
|
|
is not None
|
|
)
|
|
assert "CreationTime" in policy
|
|
|
|
|
|
@mock_aws
|
|
def test_delete_scaling_policies():
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
namespace = "sagemaker"
|
|
resource_id = "endpoint/MyEndPoint/variant/MyVariant"
|
|
scalable_dimension = "sagemaker:variant:DesiredInstanceCount"
|
|
|
|
client.register_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
MinCapacity=1,
|
|
MaxCapacity=8,
|
|
)
|
|
|
|
policy_name = "MyPolicy"
|
|
policy_type = "TargetTrackingScaling"
|
|
policy_body = {
|
|
"TargetValue": 70.0,
|
|
"PredefinedMetricSpecification": {
|
|
"PredefinedMetricType": "SageMakerVariantInvocationsPerInstance"
|
|
},
|
|
}
|
|
|
|
with pytest.raises(client.exceptions.ValidationException) as e:
|
|
client.delete_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
assert "No scaling policy found" in e.value.response["Error"]["Message"]
|
|
|
|
response = client.put_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
PolicyType=policy_type,
|
|
TargetTrackingScalingPolicyConfiguration=policy_body,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
|
|
response = client.delete_scaling_policy(
|
|
PolicyName=policy_name,
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
|
|
response = client.describe_scaling_policies(
|
|
PolicyNames=[policy_name],
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|
|
assert len(response["ScalingPolicies"]) == 0
|
|
|
|
|
|
@mock_aws
|
|
def test_deregister_scalable_target():
|
|
client = boto3.client("application-autoscaling", region_name=DEFAULT_REGION)
|
|
namespace = "sagemaker"
|
|
resource_id = "endpoint/MyEndPoint/variant/MyVariant"
|
|
scalable_dimension = "sagemaker:variant:DesiredInstanceCount"
|
|
|
|
client.register_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
MinCapacity=1,
|
|
MaxCapacity=8,
|
|
)
|
|
|
|
response = client.describe_scalable_targets(ServiceNamespace=namespace)
|
|
assert len(response["ScalableTargets"]) == 1
|
|
|
|
client.deregister_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
|
|
response = client.describe_scalable_targets(ServiceNamespace=namespace)
|
|
assert len(response["ScalableTargets"]) == 0
|
|
|
|
with pytest.raises(client.exceptions.ValidationException) as e:
|
|
client.deregister_scalable_target(
|
|
ServiceNamespace=namespace,
|
|
ResourceId=resource_id,
|
|
ScalableDimension=scalable_dimension,
|
|
)
|
|
assert "No scalable target found" in e.value.response["Error"]["Message"]
|
|
|
|
|
|
@mock_aws
|
|
def test_delete_scheduled_action():
|
|
client = boto3.client("application-autoscaling", region_name="eu-west-1")
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 0
|
|
|
|
for i in range(3):
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName=f"ecs_action_{i}",
|
|
ResourceId=f"ecs:cluster:{i}",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
)
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 3
|
|
|
|
client.delete_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName="ecs_action_0",
|
|
ResourceId="ecs:cluster:0",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
)
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 2
|
|
|
|
|
|
@mock_aws
|
|
def test_describe_scheduled_actions():
|
|
client = boto3.client("application-autoscaling", region_name="eu-west-1")
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 0
|
|
|
|
for i in range(3):
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName=f"ecs_action_{i}",
|
|
ResourceId=f"ecs:cluster:{i}",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
)
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="dynamodb",
|
|
ScheduledActionName=f"ddb_action_{i}",
|
|
ResourceId=f"table/table_{i}",
|
|
ScalableDimension="dynamodb:table:ReadCapacityUnits",
|
|
)
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 3
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ec2")
|
|
assert len(resp["ScheduledActions"]) == 0
|
|
|
|
resp = client.describe_scheduled_actions(
|
|
ServiceNamespace="dynamodb", ScheduledActionNames=["ddb_action_0"]
|
|
)
|
|
assert len(resp["ScheduledActions"]) == 1
|
|
|
|
resp = client.describe_scheduled_actions(
|
|
ServiceNamespace="dynamodb",
|
|
ResourceId="table/table_0",
|
|
ScalableDimension="dynamodb:table:ReadCapacityUnits",
|
|
)
|
|
assert len(resp["ScheduledActions"]) == 1
|
|
|
|
resp = client.describe_scheduled_actions(
|
|
ServiceNamespace="dynamodb",
|
|
ResourceId="table/table_0",
|
|
ScalableDimension="dynamodb:table:WriteCapacityUnits",
|
|
)
|
|
assert len(resp["ScheduledActions"]) == 0
|
|
|
|
|
|
@mock_aws
|
|
def test_put_scheduled_action():
|
|
client = boto3.client("application-autoscaling", region_name="ap-southeast-1")
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName="action_name",
|
|
ResourceId="ecs:cluster:x",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
)
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 1
|
|
|
|
action = resp["ScheduledActions"][0]
|
|
assert action["ScheduledActionName"] == "action_name"
|
|
assert (
|
|
action["ScheduledActionARN"]
|
|
== f"arn:aws:autoscaling:ap-southeast-1:{ACCOUNT_ID}:scheduledAction:ecs:scheduledActionName/action_name"
|
|
)
|
|
assert action["ServiceNamespace"] == "ecs"
|
|
assert action["ResourceId"] == "ecs:cluster:x"
|
|
assert action["ScalableDimension"] == "ecs:service:DesiredCount"
|
|
assert "CreationTime" in action
|
|
assert "ScalableTargetAction" not in action
|
|
|
|
|
|
@mock_aws
|
|
def test_put_scheduled_action__use_update():
|
|
client = boto3.client("application-autoscaling", region_name="ap-southeast-1")
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName="action_name",
|
|
ResourceId="ecs:cluster:x",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
)
|
|
client.put_scheduled_action(
|
|
ServiceNamespace="ecs",
|
|
ScheduledActionName="action_name_updated",
|
|
ResourceId="ecs:cluster:x",
|
|
ScalableDimension="ecs:service:DesiredCount",
|
|
ScalableTargetAction={
|
|
"MinCapacity": 12,
|
|
"MaxCapacity": 23,
|
|
},
|
|
)
|
|
|
|
resp = client.describe_scheduled_actions(ServiceNamespace="ecs")
|
|
assert len(resp["ScheduledActions"]) == 1
|
|
|
|
action = resp["ScheduledActions"][0]
|
|
assert action["ScheduledActionName"] == "action_name_updated"
|
|
assert (
|
|
action["ScheduledActionARN"]
|
|
== f"arn:aws:autoscaling:ap-southeast-1:{ACCOUNT_ID}:scheduledAction:ecs:scheduledActionName/action_name"
|
|
)
|
|
assert action["ServiceNamespace"] == "ecs"
|
|
assert action["ResourceId"] == "ecs:cluster:x"
|
|
assert action["ScalableDimension"] == "ecs:service:DesiredCount"
|
|
assert "CreationTime" in action
|
|
assert action["ScalableTargetAction"] == {"MaxCapacity": 23, "MinCapacity": 12}
|