2023-11-30 15:55:51 +00:00
|
|
|
from uuid import uuid4
|
|
|
|
|
2016-11-07 14:53:44 +00:00
|
|
|
import boto3
|
2022-05-01 13:52:38 +00:00
|
|
|
import pytest
|
2023-11-30 15:55:51 +00:00
|
|
|
from botocore.exceptions import ClientError
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
from moto import mock_ec2
|
2022-08-13 09:49:43 +00:00
|
|
|
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
|
2021-01-13 09:02:11 +00:00
|
|
|
from tests import EXAMPLE_AMI_ID
|
2016-11-07 14:53:44 +00:00
|
|
|
|
2017-02-24 02:37:43 +00:00
|
|
|
|
2016-11-08 04:08:30 +00:00
|
|
|
def get_subnet_id(conn):
|
2019-05-25 17:35:07 +00:00
|
|
|
vpc = conn.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
|
2017-02-24 02:37:43 +00:00
|
|
|
subnet = conn.create_subnet(
|
|
|
|
VpcId=vpc["VpcId"], CidrBlock="10.0.0.0/16", AvailabilityZone="us-east-1a"
|
|
|
|
)["Subnet"]
|
2016-11-08 04:08:30 +00:00
|
|
|
subnet_id = subnet["SubnetId"]
|
|
|
|
return subnet_id
|
|
|
|
|
|
|
|
|
|
|
|
def spot_config(subnet_id, allocation_strategy="lowestPrice"):
|
|
|
|
return {
|
|
|
|
"ClientToken": "string",
|
|
|
|
"SpotPrice": "0.12",
|
|
|
|
"TargetCapacity": 6,
|
2022-11-17 22:41:08 +00:00
|
|
|
"IamFleetRole": f"arn:aws:iam::{ACCOUNT_ID}:role/fleet",
|
2016-11-08 04:08:30 +00:00
|
|
|
"LaunchSpecifications": [
|
|
|
|
{
|
2021-01-13 09:02:11 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2017-02-24 02:37:43 +00:00
|
|
|
"KeyName": "my-key",
|
|
|
|
"SecurityGroups": [{"GroupId": "sg-123"}],
|
|
|
|
"UserData": "some user data",
|
|
|
|
"InstanceType": "t2.small",
|
|
|
|
"BlockDeviceMappings": [
|
|
|
|
{
|
2016-11-08 04:08:30 +00:00
|
|
|
"VirtualName": "string",
|
|
|
|
"DeviceName": "string",
|
|
|
|
"Ebs": {
|
|
|
|
"SnapshotId": "string",
|
|
|
|
"VolumeSize": 123,
|
2017-02-24 02:37:43 +00:00
|
|
|
"DeleteOnTermination": True | False,
|
2016-11-08 04:08:30 +00:00
|
|
|
"VolumeType": "standard",
|
|
|
|
"Iops": 123,
|
2017-02-24 02:37:43 +00:00
|
|
|
"Encrypted": True | False,
|
2016-11-08 04:08:30 +00:00
|
|
|
},
|
2017-02-24 02:37:43 +00:00
|
|
|
"NoDevice": "string",
|
2016-11-07 14:53:44 +00:00
|
|
|
}
|
2017-02-24 02:37:43 +00:00
|
|
|
],
|
|
|
|
"Monitoring": {"Enabled": True},
|
|
|
|
"SubnetId": subnet_id,
|
2022-11-17 22:41:08 +00:00
|
|
|
"IamInstanceProfile": {"Arn": f"arn:aws:iam::{ACCOUNT_ID}:role/fleet"},
|
2017-02-24 02:37:43 +00:00
|
|
|
"EbsOptimized": False,
|
|
|
|
"WeightedCapacity": 2.0,
|
|
|
|
"SpotPrice": "0.13",
|
|
|
|
},
|
2019-10-31 15:44:26 +00:00
|
|
|
{
|
2021-01-13 09:02:11 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2017-02-24 02:37:43 +00:00
|
|
|
"KeyName": "my-key",
|
2016-11-07 14:53:44 +00:00
|
|
|
"SecurityGroups": [{"GroupId": "sg-123"}],
|
2017-02-24 02:37:43 +00:00
|
|
|
"UserData": "some user data",
|
2016-11-11 22:22:45 +00:00
|
|
|
"InstanceType": "t2.large",
|
2016-11-07 14:53:44 +00:00
|
|
|
"Monitoring": {"Enabled": True},
|
2017-02-24 02:37:43 +00:00
|
|
|
"SubnetId": subnet_id,
|
2022-11-17 22:41:08 +00:00
|
|
|
"IamInstanceProfile": {"Arn": f"arn:aws:iam::{ACCOUNT_ID}:role/fleet"},
|
2017-02-24 02:37:43 +00:00
|
|
|
"EbsOptimized": False,
|
|
|
|
"WeightedCapacity": 4.0,
|
|
|
|
"SpotPrice": "10.00",
|
2023-05-22 20:53:57 +00:00
|
|
|
"TagSpecifications": [
|
|
|
|
{
|
|
|
|
"ResourceType": "instance",
|
|
|
|
"Tags": [{"Key": "test", "Value": "value"}],
|
|
|
|
}
|
|
|
|
],
|
2017-02-24 02:37:43 +00:00
|
|
|
},
|
2016-11-08 04:08:30 +00:00
|
|
|
],
|
|
|
|
"AllocationStrategy": allocation_strategy,
|
|
|
|
"FulfilledCapacity": 6,
|
2023-05-22 20:53:57 +00:00
|
|
|
"TagSpecifications": [
|
|
|
|
{
|
|
|
|
"ResourceType": "spot-fleet-request",
|
|
|
|
"Tags": [{"Key": "test2", "Value": "value2"}],
|
|
|
|
}
|
|
|
|
],
|
2016-11-08 04:08:30 +00:00
|
|
|
}
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
|
2023-05-22 20:53:57 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_create_spot_fleet_with_invalid_tag_specifications():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
config = spot_config(subnet_id)
|
|
|
|
invalid_resource_type = "invalid-resource-type"
|
|
|
|
config["TagSpecifications"] = [
|
|
|
|
{
|
|
|
|
"ResourceType": invalid_resource_type,
|
|
|
|
"Tags": [{"Key": "test2", "Value": "value2"}],
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
with pytest.raises(ClientError) as ex:
|
|
|
|
_ = conn.request_spot_fleet(SpotFleetRequestConfig=config)
|
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert ex.value.response["Error"]["Code"] == "InvalidParameterValue"
|
|
|
|
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
|
|
|
|
assert (
|
|
|
|
ex.value.response["Error"]["Message"]
|
|
|
|
== f"The value for `ResourceType` must be `spot-fleet-request`, but got `{invalid_resource_type}` instead."
|
2023-05-22 20:53:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2016-11-07 14:53:44 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_create_spot_fleet_with_lowest_price():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
2016-11-08 04:08:30 +00:00
|
|
|
subnet_id = get_subnet_id(conn)
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
2016-11-08 04:08:30 +00:00
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
2016-11-07 14:53:44 +00:00
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2017-02-24 02:37:43 +00:00
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_requests) == 1
|
2016-11-07 14:53:44 +00:00
|
|
|
spot_fleet_request = spot_fleet_requests[0]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_request["SpotFleetRequestState"] == "active"
|
|
|
|
assert spot_fleet_request["Tags"] == [{"Key": "test2", "Value": "value2"}]
|
2016-11-07 14:53:44 +00:00
|
|
|
spot_fleet_config = spot_fleet_request["SpotFleetRequestConfig"]
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["SpotPrice"] == "0.12"
|
|
|
|
assert spot_fleet_config["TargetCapacity"] == 6
|
|
|
|
assert spot_fleet_config["IamFleetRole"] == f"arn:aws:iam::{ACCOUNT_ID}:role/fleet"
|
|
|
|
assert spot_fleet_config["AllocationStrategy"] == "lowestPrice"
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 6.0
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_config["LaunchSpecifications"]) == 2
|
2016-11-07 14:53:44 +00:00
|
|
|
launch_spec = spot_fleet_config["LaunchSpecifications"][0]
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert launch_spec["EbsOptimized"] is False
|
|
|
|
assert launch_spec["SecurityGroups"] == [{"GroupId": "sg-123"}]
|
|
|
|
assert launch_spec["IamInstanceProfile"] == {
|
|
|
|
"Arn": f"arn:aws:iam::{ACCOUNT_ID}:role/fleet"
|
|
|
|
}
|
|
|
|
assert launch_spec["ImageId"] == EXAMPLE_AMI_ID
|
|
|
|
assert launch_spec["InstanceType"] == "t2.small"
|
|
|
|
assert launch_spec["KeyName"] == "my-key"
|
|
|
|
assert launch_spec["Monitoring"] == {"Enabled": True}
|
|
|
|
assert launch_spec["SpotPrice"] == "0.13"
|
|
|
|
assert launch_spec["SubnetId"] == subnet_id
|
|
|
|
assert launch_spec["UserData"] == "some user data"
|
|
|
|
assert launch_spec["WeightedCapacity"] == 2.0
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 3
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_diversified_spot_fleet():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
2016-11-08 04:08:30 +00:00
|
|
|
subnet_id = get_subnet_id(conn)
|
2017-02-24 02:37:43 +00:00
|
|
|
diversified_config = spot_config(subnet_id, allocation_strategy="diversified")
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(SpotFleetRequestConfig=diversified_config)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 2
|
2016-11-11 22:22:45 +00:00
|
|
|
instance_types = set([instance["InstanceType"] for instance in instances])
|
2023-07-17 09:31:05 +00:00
|
|
|
assert instance_types == set(["t2.small", "t2.large"])
|
|
|
|
assert "i-" in instances[0]["InstanceId"]
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
|
2022-05-01 13:52:38 +00:00
|
|
|
@mock_ec2
|
|
|
|
@pytest.mark.parametrize("allocation_strategy", ["diversified", "lowestCost"])
|
|
|
|
def test_request_spot_fleet_using_launch_template_config__name(allocation_strategy):
|
|
|
|
conn = boto3.client("ec2", region_name="us-east-2")
|
|
|
|
|
|
|
|
template_data = {
|
2022-05-26 16:04:36 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2022-05-01 13:52:38 +00:00
|
|
|
"InstanceType": "t2.medium",
|
|
|
|
"DisableApiTermination": False,
|
|
|
|
"TagSpecifications": [
|
|
|
|
{"ResourceType": "instance", "Tags": [{"Key": "test", "Value": "value"}]}
|
|
|
|
],
|
|
|
|
"SecurityGroupIds": ["sg-abcd1234"],
|
|
|
|
}
|
|
|
|
|
|
|
|
template_name = str(uuid4())
|
|
|
|
conn.create_launch_template(
|
|
|
|
LaunchTemplateName=template_name, LaunchTemplateData=template_data
|
|
|
|
)
|
|
|
|
|
|
|
|
template_config = {
|
|
|
|
"ClientToken": "string",
|
|
|
|
"SpotPrice": "0.01",
|
|
|
|
"TargetCapacity": 1,
|
|
|
|
"IamFleetRole": "arn:aws:iam::486285699788:role/aws-ec2-spot-fleet-tagging-role",
|
|
|
|
"LaunchTemplateConfigs": [
|
|
|
|
{
|
|
|
|
"LaunchTemplateSpecification": {
|
|
|
|
"LaunchTemplateName": template_name,
|
|
|
|
"Version": "$Latest",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"AllocationStrategy": allocation_strategy,
|
|
|
|
}
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(SpotFleetRequestConfig=template_config)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 1
|
2022-05-01 13:52:38 +00:00
|
|
|
instance_types = set([instance["InstanceType"] for instance in instances])
|
2023-07-17 09:31:05 +00:00
|
|
|
assert instance_types == set(["t2.medium"])
|
|
|
|
assert "i-" in instances[0]["InstanceId"]
|
2022-05-01 13:52:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_request_spot_fleet_using_launch_template_config__id():
|
|
|
|
conn = boto3.client("ec2", region_name="us-east-2")
|
|
|
|
|
|
|
|
template_data = {
|
2022-05-26 16:04:36 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2022-05-01 13:52:38 +00:00
|
|
|
"InstanceType": "t2.medium",
|
|
|
|
"DisableApiTermination": False,
|
|
|
|
"TagSpecifications": [
|
|
|
|
{"ResourceType": "instance", "Tags": [{"Key": "test", "Value": "value"}]}
|
|
|
|
],
|
|
|
|
"SecurityGroupIds": ["sg-abcd1234"],
|
|
|
|
}
|
|
|
|
|
|
|
|
template_name = str(uuid4())
|
|
|
|
template = conn.create_launch_template(
|
|
|
|
LaunchTemplateName=template_name, LaunchTemplateData=template_data
|
|
|
|
)["LaunchTemplate"]
|
|
|
|
template_id = template["LaunchTemplateId"]
|
|
|
|
|
|
|
|
template_config = {
|
|
|
|
"ClientToken": "string",
|
|
|
|
"SpotPrice": "0.01",
|
|
|
|
"TargetCapacity": 1,
|
|
|
|
"IamFleetRole": "arn:aws:iam::486285699788:role/aws-ec2-spot-fleet-tagging-role",
|
|
|
|
"LaunchTemplateConfigs": [
|
|
|
|
{"LaunchTemplateSpecification": {"LaunchTemplateId": template_id}}
|
|
|
|
],
|
|
|
|
"AllocationStrategy": "lowestCost",
|
|
|
|
}
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(SpotFleetRequestConfig=template_config)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 1
|
2022-05-01 13:52:38 +00:00
|
|
|
instance_types = set([instance["InstanceType"] for instance in instances])
|
2023-07-17 09:31:05 +00:00
|
|
|
assert instance_types == set(["t2.medium"])
|
|
|
|
assert "i-" in instances[0]["InstanceId"]
|
2022-05-01 13:52:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_request_spot_fleet_using_launch_template_config__overrides():
|
|
|
|
conn = boto3.client("ec2", region_name="us-east-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
template_data = {
|
2022-05-26 16:04:36 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2022-05-01 13:52:38 +00:00
|
|
|
"InstanceType": "t2.medium",
|
|
|
|
"DisableApiTermination": False,
|
|
|
|
"TagSpecifications": [
|
|
|
|
{"ResourceType": "instance", "Tags": [{"Key": "test", "Value": "value"}]}
|
|
|
|
],
|
|
|
|
"SecurityGroupIds": ["sg-abcd1234"],
|
|
|
|
}
|
|
|
|
|
|
|
|
template_name = str(uuid4())
|
|
|
|
template = conn.create_launch_template(
|
|
|
|
LaunchTemplateName=template_name, LaunchTemplateData=template_data
|
|
|
|
)["LaunchTemplate"]
|
|
|
|
template_id = template["LaunchTemplateId"]
|
|
|
|
|
|
|
|
template_config = {
|
|
|
|
"ClientToken": "string",
|
|
|
|
"SpotPrice": "0.01",
|
|
|
|
"TargetCapacity": 1,
|
|
|
|
"IamFleetRole": "arn:aws:iam::486285699788:role/aws-ec2-spot-fleet-tagging-role",
|
|
|
|
"LaunchTemplateConfigs": [
|
|
|
|
{
|
|
|
|
"LaunchTemplateSpecification": {"LaunchTemplateId": template_id},
|
|
|
|
"Overrides": [
|
|
|
|
{
|
|
|
|
"InstanceType": "t2.nano",
|
|
|
|
"SubnetId": subnet_id,
|
|
|
|
"AvailabilityZone": "us-west-1",
|
|
|
|
"WeightedCapacity": 2,
|
|
|
|
}
|
|
|
|
],
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"AllocationStrategy": "lowestCost",
|
|
|
|
}
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(SpotFleetRequestConfig=template_config)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 1
|
|
|
|
assert instances[0]["InstanceType"] == "t2.nano"
|
2022-05-01 13:52:38 +00:00
|
|
|
|
|
|
|
instance = conn.describe_instances(
|
|
|
|
InstanceIds=[i["InstanceId"] for i in instances]
|
|
|
|
)["Reservations"][0]["Instances"][0]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert instance["SubnetId"] == subnet_id
|
2022-05-01 13:52:38 +00:00
|
|
|
|
|
|
|
|
2019-01-23 23:59:31 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_create_spot_fleet_request_with_tag_spec():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
tag_spec = [
|
|
|
|
{
|
|
|
|
"ResourceType": "instance",
|
|
|
|
"Tags": [
|
|
|
|
{"Key": "tag-1", "Value": "foo"},
|
|
|
|
{"Key": "tag-2", "Value": "bar"},
|
|
|
|
],
|
|
|
|
}
|
|
|
|
]
|
|
|
|
config = spot_config(subnet_id)
|
|
|
|
config["LaunchSpecifications"][0]["TagSpecifications"] = tag_spec
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(SpotFleetRequestConfig=config)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
|
|
|
spot_fleet_config = spot_fleet_requests[0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
fleet_tag_spec = spot_fleet_config["LaunchSpecifications"][0]["TagSpecifications"][
|
|
|
|
0
|
|
|
|
]
|
|
|
|
assert fleet_tag_spec["ResourceType"] == "instance"
|
2019-01-23 23:59:31 +00:00
|
|
|
for tag in tag_spec[0]["Tags"]:
|
2023-07-17 09:31:05 +00:00
|
|
|
assert tag in fleet_tag_spec["Tags"]
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2019-01-23 23:59:31 +00:00
|
|
|
instance_res = conn.describe_spot_fleet_instances(SpotFleetRequestId=spot_fleet_id)
|
|
|
|
instances = conn.describe_instances(
|
|
|
|
InstanceIds=[i["InstanceId"] for i in instance_res["ActiveInstances"]]
|
|
|
|
)
|
|
|
|
for instance in instances["Reservations"][0]["Instances"]:
|
|
|
|
for tag in tag_spec[0]["Tags"]:
|
2023-07-17 09:31:05 +00:00
|
|
|
assert tag in instance["Tags"]
|
2019-01-23 23:59:31 +00:00
|
|
|
|
|
|
|
|
2016-11-07 14:53:44 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_cancel_spot_fleet_request():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
2016-11-08 04:08:30 +00:00
|
|
|
subnet_id = get_subnet_id(conn)
|
2016-11-07 14:53:44 +00:00
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
2016-11-08 04:08:30 +00:00
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
2016-11-07 14:53:44 +00:00
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2017-02-24 02:37:43 +00:00
|
|
|
conn.cancel_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id], TerminateInstances=True
|
|
|
|
)
|
2016-11-07 14:53:44 +00:00
|
|
|
|
2017-02-24 02:37:43 +00:00
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_requests) == 0
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_cancel_spot_fleet_request__but_dont_terminate_instances():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(get_active_instances(conn, spot_fleet_id)) == 3
|
2022-10-03 12:30:51 +00:00
|
|
|
|
|
|
|
conn.cancel_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id], TerminateInstances=False
|
|
|
|
)
|
|
|
|
|
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_requests) == 1
|
|
|
|
assert spot_fleet_requests[0]["SpotFleetRequestState"] == "cancelled_running"
|
2022-10-03 12:30:51 +00:00
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(get_active_instances(conn, spot_fleet_id)) == 3
|
2022-10-03 12:30:51 +00:00
|
|
|
|
|
|
|
# Cancel again and terminate instances
|
|
|
|
conn.cancel_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id], TerminateInstances=True
|
|
|
|
)
|
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(get_active_instances(conn, spot_fleet_id)) == 0
|
2022-10-03 12:30:51 +00:00
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_requests) == 0
|
2022-10-03 12:30:51 +00:00
|
|
|
|
|
|
|
|
2017-10-05 19:50:42 +00:00
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_up():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(SpotFleetRequestId=spot_fleet_id, TargetCapacity=20)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 10
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 20
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 20.0
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_up_diversified():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id, allocation_strategy="diversified")
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(SpotFleetRequestId=spot_fleet_id, TargetCapacity=19)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 7
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 19
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 20.0
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_down_no_terminate():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(
|
|
|
|
SpotFleetRequestId=spot_fleet_id,
|
|
|
|
TargetCapacity=1,
|
|
|
|
ExcessCapacityTerminationPolicy="noTermination",
|
|
|
|
)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 3
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 1
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 6.0
|
2017-10-06 01:46:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_down_odd():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(SpotFleetRequestId=spot_fleet_id, TargetCapacity=7)
|
|
|
|
conn.modify_spot_fleet_request(SpotFleetRequestId=spot_fleet_id, TargetCapacity=5)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 3
|
2017-10-06 01:46:58 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 5
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 6.0
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_down():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(SpotFleetRequestId=spot_fleet_id, TargetCapacity=1)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 1
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 1
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 2.0
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_modify_spot_fleet_request_down_no_terminate_after_custom_terminate():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
spot_fleet_res = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config(subnet_id)
|
|
|
|
)
|
|
|
|
spot_fleet_id = spot_fleet_res["SpotFleetRequestId"]
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2017-10-05 19:50:42 +00:00
|
|
|
conn.terminate_instances(InstanceIds=[i["InstanceId"] for i in instances[1:]])
|
|
|
|
|
|
|
|
conn.modify_spot_fleet_request(
|
|
|
|
SpotFleetRequestId=spot_fleet_id,
|
|
|
|
TargetCapacity=1,
|
|
|
|
ExcessCapacityTerminationPolicy="noTermination",
|
|
|
|
)
|
|
|
|
|
2022-10-03 12:30:51 +00:00
|
|
|
instances = get_active_instances(conn, spot_fleet_id)
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(instances) == 1
|
2017-10-05 19:50:42 +00:00
|
|
|
|
|
|
|
spot_fleet_config = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"][0]["SpotFleetRequestConfig"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert spot_fleet_config["TargetCapacity"] == 1
|
|
|
|
assert spot_fleet_config["FulfilledCapacity"] == 2.0
|
2018-02-01 22:09:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_ec2
|
|
|
|
def test_create_spot_fleet_without_spot_price():
|
|
|
|
conn = boto3.client("ec2", region_name="us-west-2")
|
|
|
|
subnet_id = get_subnet_id(conn)
|
|
|
|
|
|
|
|
# remove prices to force a fallback to ondemand price
|
|
|
|
spot_config_without_price = spot_config(subnet_id)
|
|
|
|
del spot_config_without_price["SpotPrice"]
|
|
|
|
for spec in spot_config_without_price["LaunchSpecifications"]:
|
|
|
|
del spec["SpotPrice"]
|
|
|
|
|
|
|
|
spot_fleet_id = conn.request_spot_fleet(
|
|
|
|
SpotFleetRequestConfig=spot_config_without_price
|
|
|
|
)["SpotFleetRequestId"]
|
|
|
|
spot_fleet_requests = conn.describe_spot_fleet_requests(
|
|
|
|
SpotFleetRequestIds=[spot_fleet_id]
|
|
|
|
)["SpotFleetRequestConfigs"]
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_requests) == 1
|
2018-02-01 22:09:10 +00:00
|
|
|
spot_fleet_request = spot_fleet_requests[0]
|
|
|
|
spot_fleet_config = spot_fleet_request["SpotFleetRequestConfig"]
|
|
|
|
|
2023-07-17 09:31:05 +00:00
|
|
|
assert len(spot_fleet_config["LaunchSpecifications"]) == 2
|
2018-02-01 22:09:10 +00:00
|
|
|
launch_spec1 = spot_fleet_config["LaunchSpecifications"][0]
|
|
|
|
launch_spec2 = spot_fleet_config["LaunchSpecifications"][1]
|
|
|
|
|
|
|
|
# AWS will figure out the price
|
|
|
|
assert "SpotPrice" not in launch_spec1
|
|
|
|
assert "SpotPrice" not in launch_spec2
|
2022-10-03 12:30:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_active_instances(conn, spot_fleet_id):
|
|
|
|
instance_res = conn.describe_spot_fleet_instances(SpotFleetRequestId=spot_fleet_id)
|
|
|
|
return instance_res["ActiveInstances"]
|