664 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			664 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import boto3 | ||
|  | import sure  # noqa # pylint: disable=unused-import | ||
|  | import pytest | ||
|  | 
 | ||
|  | from moto import mock_ec2 | ||
|  | from tests import EXAMPLE_AMI_ID | ||
|  | from uuid import uuid4 | ||
|  | 
 | ||
|  | 
 | ||
|  | def get_subnet_id(conn): | ||
|  |     vpc = conn.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] | ||
|  |     subnet = conn.create_subnet( | ||
|  |         VpcId=vpc["VpcId"], CidrBlock="10.0.0.0/16", AvailabilityZone="us-east-1a" | ||
|  |     )["Subnet"] | ||
|  |     subnet_id = subnet["SubnetId"] | ||
|  |     return subnet_id | ||
|  | 
 | ||
|  | 
 | ||
|  | def get_launch_template(conn, instance_type="t2.micro"): | ||
|  |     launch_template = conn.create_launch_template( | ||
|  |         LaunchTemplateName="test" + str(uuid4()), | ||
|  |         LaunchTemplateData={ | ||
|  |             "ImageId": EXAMPLE_AMI_ID, | ||
|  |             "InstanceType": instance_type, | ||
|  |             "KeyName": "test", | ||
|  |             "SecurityGroups": ["sg-123456"], | ||
|  |             "DisableApiTermination": False, | ||
|  |             "TagSpecifications": [ | ||
|  |                 { | ||
|  |                     "ResourceType": "instance", | ||
|  |                     "Tags": [ | ||
|  |                         {"Key": "test", "Value": "value"}, | ||
|  |                         {"Key": "Name", "Value": "test"}, | ||
|  |                     ], | ||
|  |                 } | ||
|  |             ], | ||
|  |         }, | ||
|  |     )["LaunchTemplate"] | ||
|  |     launch_template_id = launch_template["LaunchTemplateId"] | ||
|  |     launch_template_name = launch_template["LaunchTemplateName"] | ||
|  |     return launch_template_id, launch_template_name | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_spot_fleet_with_lowest_price(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         ExcessCapacityTerminationPolicy="terminate", | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 0, | ||
|  |             "SpotTargetCapacity": 1, | ||
|  |             "TotalTargetCapacity": 1, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  |     fleet_id.should.be.a(str) | ||
|  |     fleet_id.should.have.length_of(42) | ||
|  | 
 | ||
|  |     fleets_res = conn.describe_fleets(FleetIds=[fleet_id]) | ||
|  |     fleets_res.should.have.key("Fleets") | ||
|  |     fleets = fleets_res["Fleets"] | ||
|  | 
 | ||
|  |     fleet = fleets[0] | ||
|  |     fleet["FleetState"].should.equal("active") | ||
|  |     fleet_config = fleet["LaunchTemplateConfigs"][0] | ||
|  | 
 | ||
|  |     launch_template_spec = fleet_config["LaunchTemplateSpecification"] | ||
|  | 
 | ||
|  |     launch_template_spec["LaunchTemplateId"].should.equal(launch_template_id) | ||
|  |     launch_template_spec["Version"].should.equal("1") | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     len(instances).should.equal(1) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_on_demand_fleet(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         ExcessCapacityTerminationPolicy="terminate", | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "on-demand", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 0, | ||
|  |             "TotalTargetCapacity": 1, | ||
|  |         }, | ||
|  |         OnDemandOptions={ | ||
|  |             "AllocationStrategy": "lowestPrice", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  |     fleet_id.should.be.a(str) | ||
|  |     fleet_id.should.have.length_of(42) | ||
|  | 
 | ||
|  |     fleets_res = conn.describe_fleets(FleetIds=[fleet_id]) | ||
|  |     fleets_res.should.have.key("Fleets") | ||
|  |     fleets = fleets_res["Fleets"] | ||
|  | 
 | ||
|  |     fleet = fleets[0] | ||
|  |     fleet["FleetState"].should.equal("active") | ||
|  |     fleet_config = fleet["LaunchTemplateConfigs"][0] | ||
|  | 
 | ||
|  |     launch_template_spec = fleet_config["LaunchTemplateSpecification"] | ||
|  | 
 | ||
|  |     launch_template_spec["LaunchTemplateId"].should.equal(launch_template_id) | ||
|  |     launch_template_spec["Version"].should.equal("1") | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     len(instances).should.equal(1) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_diversified_spot_fleet(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  |     launch_template_id_1, _ = get_launch_template(conn, instance_type="t2.small") | ||
|  |     launch_template_id_2, _ = get_launch_template(conn, instance_type="t2.large") | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         ExcessCapacityTerminationPolicy="terminate", | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id_1, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id_2, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 0, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 2, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "diversified", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     len(instances).should.equal(2) | ||
|  |     instance_types = set([instance["InstanceType"] for instance in instances]) | ||
|  |     instance_types.should.equal(set(["t2.small", "t2.large"])) | ||
|  |     instances[0]["InstanceId"].should.contain("i-") | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | @pytest.mark.parametrize( | ||
|  |     "spot_allocation_strategy", | ||
|  |     [ | ||
|  |         "diversified", | ||
|  |         "lowest-price", | ||
|  |         "capacity-optimized", | ||
|  |         "capacity-optimized-prioritized", | ||
|  |     ], | ||
|  | ) | ||
|  | @pytest.mark.parametrize( | ||
|  |     "on_demand_allocation_strategy", | ||
|  |     ["lowestPrice", "prioritized"], | ||
|  | ) | ||
|  | def test_request_fleet_using_launch_template_config__name( | ||
|  |     spot_allocation_strategy, on_demand_allocation_strategy | ||
|  | ): | ||
|  | 
 | ||
|  |     conn = boto3.client("ec2", region_name="us-east-2") | ||
|  | 
 | ||
|  |     _, launch_template_name = get_launch_template(conn, instance_type="t2.medium") | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateName": launch_template_name, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 3, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": spot_allocation_strategy, | ||
|  |         }, | ||
|  |         OnDemandOptions={ | ||
|  |             "AllocationStrategy": on_demand_allocation_strategy, | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     len(instances).should.equal(3) | ||
|  |     instance_types = set([instance["InstanceType"] for instance in instances]) | ||
|  |     instance_types.should.equal(set(["t2.medium"])) | ||
|  |     instances[0]["InstanceId"].should.contain("i-") | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_fleet_request_with_tags(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  | 
 | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  |     tags = [ | ||
|  |         {"Key": "Name", "Value": "test-fleet"}, | ||
|  |         {"Key": "Another", "Value": "tag"}, | ||
|  |     ] | ||
|  |     tags_instance = [ | ||
|  |         {"Key": "test", "Value": "value"}, | ||
|  |         {"Key": "Name", "Value": "test"}, | ||
|  |     ] | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         DryRun=False, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowestPrice", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |         }, | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 3, | ||
|  |         }, | ||
|  |         Type="request", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |         TagSpecifications=[ | ||
|  |             { | ||
|  |                 "ResourceType": "fleet", | ||
|  |                 "Tags": tags, | ||
|  |             }, | ||
|  |         ], | ||
|  |     ) | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  |     fleets = conn.describe_fleets(FleetIds=[fleet_id])["Fleets"] | ||
|  | 
 | ||
|  |     fleets[0]["Tags"].should.equal(tags) | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=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 tags_instance: | ||
|  |             instance["Tags"].should.contain(tag) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_fleet_using_launch_template_config__overrides(): | ||
|  | 
 | ||
|  |     conn = boto3.client("ec2", region_name="us-east-2") | ||
|  |     subnet_id = get_subnet_id(conn) | ||
|  | 
 | ||
|  |     template_id, _ = get_launch_template(conn, instance_type="t2.medium") | ||
|  | 
 | ||
|  |     template_config_overrides = [ | ||
|  |         { | ||
|  |             "InstanceType": "t2.nano", | ||
|  |             "SubnetId": subnet_id, | ||
|  |             "AvailabilityZone": "us-west-1", | ||
|  |             "WeightedCapacity": 2, | ||
|  |         } | ||
|  |     ] | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |                 "Overrides": template_config_overrides, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 0, | ||
|  |             "TotalTargetCapacity": 1, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  | 
 | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     instances.should.have.length_of(1) | ||
|  |     instances[0].should.have.key("InstanceType").equals("t2.nano") | ||
|  | 
 | ||
|  |     instance = conn.describe_instances( | ||
|  |         InstanceIds=[i["InstanceId"] for i in instances] | ||
|  |     )["Reservations"][0]["Instances"][0] | ||
|  |     instance.should.have.key("SubnetId").equals(subnet_id) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_delete_fleet(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  | 
 | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 3, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowestPrice", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  | 
 | ||
|  |     delete_fleet_out = conn.delete_fleets(FleetIds=[fleet_id], TerminateInstances=True) | ||
|  | 
 | ||
|  |     delete_fleet_out["SuccessfulFleetDeletions"].should.have.length_of(1) | ||
|  |     delete_fleet_out["SuccessfulFleetDeletions"][0]["FleetId"].should.equal(fleet_id) | ||
|  |     delete_fleet_out["SuccessfulFleetDeletions"][0]["CurrentFleetState"].should.equal( | ||
|  |         "deleted" | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleets = conn.describe_fleets(FleetIds=[fleet_id])["Fleets"] | ||
|  |     len(fleets).should.equal(1) | ||
|  | 
 | ||
|  |     target_capacity_specification = fleets[0]["TargetCapacitySpecification"] | ||
|  |     target_capacity_specification.should.have.key("TotalTargetCapacity").equals(0) | ||
|  |     fleets[0]["FleetState"].should.equal("deleted") | ||
|  | 
 | ||
|  |     # Instances should be terminated | ||
|  |     instance_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  |     instances = instance_res["ActiveInstances"] | ||
|  |     len(instances).should.equal(0) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_describe_fleet_instences_api(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-1") | ||
|  | 
 | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 3, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowestPrice", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |         }, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  |     fleet_res = conn.describe_fleet_instances(FleetId=fleet_id) | ||
|  | 
 | ||
|  |     fleet_res["FleetId"].should.equal(fleet_id) | ||
|  |     fleet_res["ActiveInstances"].should.have.length_of(3) | ||
|  | 
 | ||
|  |     instance_ids = [i["InstanceId"] for i in fleet_res["ActiveInstances"]] | ||
|  |     for instance_id in instance_ids: | ||
|  |         instance_id.startswith("i-").should.be.true | ||
|  | 
 | ||
|  |     instance_types = [i["InstanceType"] for i in fleet_res["ActiveInstances"]] | ||
|  |     instance_types.should.equal(["t2.micro", "t2.micro", "t2.micro"]) | ||
|  | 
 | ||
|  |     instance_healths = [i["InstanceHealth"] for i in fleet_res["ActiveInstances"]] | ||
|  |     instance_healths.should.equal(["healthy", "healthy", "healthy"]) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_fleet_api(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-1") | ||
|  | 
 | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         LaunchTemplateConfigs=[ | ||
|  |             { | ||
|  |                 "LaunchTemplateSpecification": { | ||
|  |                     "LaunchTemplateId": launch_template_id, | ||
|  |                     "Version": "1", | ||
|  |                 }, | ||
|  |             }, | ||
|  |         ], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "spot", | ||
|  |             "OnDemandTargetCapacity": 1, | ||
|  |             "SpotTargetCapacity": 2, | ||
|  |             "TotalTargetCapacity": 3, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowestPrice", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |         }, | ||
|  |         Type="instant", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  | 
 | ||
|  |     fleet_res.should.have.key("FleetId") | ||
|  |     fleet_res["FleetId"].startswith("fleet-").should.be.true | ||
|  | 
 | ||
|  |     fleet_res.should.have.key("Instances") | ||
|  |     fleet_res["Instances"].should.have.length_of(3) | ||
|  | 
 | ||
|  |     instance_ids = [i["InstanceIds"] for i in fleet_res["Instances"]] | ||
|  |     for instance_id in instance_ids: | ||
|  |         instance_id[0].startswith("i-").should.be.true | ||
|  | 
 | ||
|  |     instance_types = [i["InstanceType"] for i in fleet_res["Instances"]] | ||
|  |     instance_types.should.equal(["t2.micro", "t2.micro", "t2.micro"]) | ||
|  | 
 | ||
|  |     lifecycle = [i["Lifecycle"] for i in fleet_res["Instances"]] | ||
|  |     lifecycle.should.contain("spot") | ||
|  |     lifecycle.should.contain("on-demand") | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_ec2 | ||
|  | def test_create_fleet_api_response(): | ||
|  |     conn = boto3.client("ec2", region_name="us-west-2") | ||
|  |     subnet_id = get_subnet_id(conn) | ||
|  | 
 | ||
|  |     launch_template_id, _ = get_launch_template(conn) | ||
|  | 
 | ||
|  |     lt_config = { | ||
|  |         "LaunchTemplateSpecification": { | ||
|  |             "LaunchTemplateId": launch_template_id, | ||
|  |             "Version": "1", | ||
|  |         }, | ||
|  |         "Overrides": [ | ||
|  |             { | ||
|  |                 "AvailabilityZone": "us-west-1a", | ||
|  |                 "InstanceRequirements": { | ||
|  |                     "AcceleratorCount": { | ||
|  |                         "Max": 10, | ||
|  |                         "Min": 1, | ||
|  |                     }, | ||
|  |                     "AcceleratorManufacturers": ["nvidia"], | ||
|  |                     "AcceleratorNames": ["t4"], | ||
|  |                     "AcceleratorTotalMemoryMiB": { | ||
|  |                         "Max": 20972, | ||
|  |                         "Min": 1, | ||
|  |                     }, | ||
|  |                     "AcceleratorTypes": ["gpu"], | ||
|  |                     "BareMetal": "included", | ||
|  |                     "BaselineEbsBandwidthMbps": { | ||
|  |                         "Max": 10000, | ||
|  |                         "Min": 125, | ||
|  |                     }, | ||
|  |                     "BurstablePerformance": "included", | ||
|  |                     "CpuManufacturers": ["amd", "intel"], | ||
|  |                     "ExcludedInstanceTypes": ["m5.8xlarge"], | ||
|  |                     "InstanceGenerations": ["current"], | ||
|  |                     "LocalStorage": "included", | ||
|  |                     "LocalStorageTypes": ["ssd"], | ||
|  |                     "MemoryGiBPerVCpu": { | ||
|  |                         "Min": 1, | ||
|  |                         "Max": 160, | ||
|  |                     }, | ||
|  |                     "MemoryMiB": { | ||
|  |                         "Min": 2048, | ||
|  |                         "Max": 40960, | ||
|  |                     }, | ||
|  |                     "NetworkInterfaceCount": { | ||
|  |                         "Max": 1, | ||
|  |                         "Min": 1, | ||
|  |                     }, | ||
|  |                     "OnDemandMaxPricePercentageOverLowestPrice": 99999, | ||
|  |                     "RequireHibernateSupport": True, | ||
|  |                     "SpotMaxPricePercentageOverLowestPrice": 99999, | ||
|  |                     "TotalLocalStorageGB": { | ||
|  |                         "Min": 100, | ||
|  |                         "Max": 10000, | ||
|  |                     }, | ||
|  |                     "VCpuCount": { | ||
|  |                         "Min": 2, | ||
|  |                         "Max": 160, | ||
|  |                     }, | ||
|  |                 }, | ||
|  |                 "MaxPrice": "0.5", | ||
|  |                 "Priority": 2, | ||
|  |                 "SubnetId": subnet_id, | ||
|  |                 "WeightedCapacity": 1, | ||
|  |             }, | ||
|  |         ], | ||
|  |     } | ||
|  | 
 | ||
|  |     fleet_res = conn.create_fleet( | ||
|  |         ExcessCapacityTerminationPolicy="no-termination", | ||
|  |         LaunchTemplateConfigs=[lt_config], | ||
|  |         TargetCapacitySpecification={ | ||
|  |             "DefaultTargetCapacityType": "on-demand", | ||
|  |             "OnDemandTargetCapacity": 10, | ||
|  |             "SpotTargetCapacity": 10, | ||
|  |             "TotalTargetCapacity": 30, | ||
|  |         }, | ||
|  |         SpotOptions={ | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |             "InstancePoolsToUseCount": 1, | ||
|  |             "MaintenanceStrategies": { | ||
|  |                 "CapacityRebalance": { | ||
|  |                     "ReplacementStrategy": "launch-before-terminate", | ||
|  |                     "TerminationDelay": 120, | ||
|  |                 }, | ||
|  |             }, | ||
|  |             "MaxTotalPrice": "50", | ||
|  |             "MinTargetCapacity": 1, | ||
|  |             "SingleAvailabilityZone": True, | ||
|  |             "SingleInstanceType": True, | ||
|  |         }, | ||
|  |         OnDemandOptions={ | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |             "MaxTotalPrice": "50", | ||
|  |             "MinTargetCapacity": 1, | ||
|  |             "SingleAvailabilityZone": True, | ||
|  |             "SingleInstanceType": True, | ||
|  |         }, | ||
|  |         ReplaceUnhealthyInstances=True, | ||
|  |         TerminateInstancesWithExpiration=True, | ||
|  |         Type="maintain", | ||
|  |         ValidFrom="2020-01-01T00:00:00Z", | ||
|  |         ValidUntil="2020-12-31T00:00:00Z", | ||
|  |     ) | ||
|  |     fleet_id = fleet_res["FleetId"] | ||
|  | 
 | ||
|  |     fleet_res = conn.describe_fleets(FleetIds=[fleet_id])["Fleets"] | ||
|  |     fleet_res.should.have.length_of(1) | ||
|  |     fleet_res[0].should.have.key("FleetId").equals(fleet_id) | ||
|  |     fleet_res[0].should.have.key("ExcessCapacityTerminationPolicy").equals( | ||
|  |         "no-termination" | ||
|  |     ) | ||
|  |     fleet_res[0].should.have.key("LaunchTemplateConfigs").equals([lt_config]) | ||
|  |     fleet_res[0].should.have.key("TargetCapacitySpecification").equals( | ||
|  |         { | ||
|  |             "DefaultTargetCapacityType": "on-demand", | ||
|  |             "OnDemandTargetCapacity": 10, | ||
|  |             "SpotTargetCapacity": 10, | ||
|  |             "TotalTargetCapacity": 30, | ||
|  |         } | ||
|  |     ) | ||
|  |     fleet_res[0].should.have.key("SpotOptions").equals( | ||
|  |         { | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |             "InstanceInterruptionBehavior": "terminate", | ||
|  |             "InstancePoolsToUseCount": 1, | ||
|  |             "MaintenanceStrategies": { | ||
|  |                 "CapacityRebalance": { | ||
|  |                     "ReplacementStrategy": "launch-before-terminate", | ||
|  |                     "TerminationDelay": 120, | ||
|  |                 }, | ||
|  |             }, | ||
|  |             "MaxTotalPrice": "50", | ||
|  |             "MinTargetCapacity": 1, | ||
|  |             "SingleAvailabilityZone": True, | ||
|  |             "SingleInstanceType": True, | ||
|  |         } | ||
|  |     ) | ||
|  |     fleet_res[0].should.have.key("OnDemandOptions").equals( | ||
|  |         { | ||
|  |             "AllocationStrategy": "lowest-price", | ||
|  |             "MaxTotalPrice": "50", | ||
|  |             "MinTargetCapacity": 1, | ||
|  |             "SingleAvailabilityZone": True, | ||
|  |             "SingleInstanceType": True, | ||
|  |         } | ||
|  |     ) | ||
|  |     fleet_res[0].should.have.key("ReplaceUnhealthyInstances").equals(True) | ||
|  |     fleet_res[0].should.have.key("TerminateInstancesWithExpiration").equals(True) | ||
|  |     fleet_res[0].should.have.key("Type").equals("maintain") | ||
|  |     fleet_res[0].should.have.key("ValidFrom") | ||
|  |     fleet_res[0]["ValidFrom"].isoformat().should.equal("2020-01-01T00:00:00+00:00") | ||
|  |     fleet_res[0].should.have.key("ValidUntil") | ||
|  |     fleet_res[0]["ValidUntil"].isoformat().should.equal("2020-12-31T00:00:00+00:00") |