| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | import datetime | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 23:08:30 -05:00
										 |  |  | import boto3 | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | from botocore.exceptions import ClientError | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  | import sure  # noqa # pylint: disable=unused-import | 
					
						
							| 
									
										
										
										
											2013-02-21 23:13:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-18 14:18:57 -01:00
										 |  |  | from moto import mock_ec2, settings | 
					
						
							| 
									
										
										
										
											2014-11-29 23:34:40 -05:00
										 |  |  | from moto.core.utils import iso_8601_datetime_with_milliseconds | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  | from tests import EXAMPLE_AMI_ID | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | from uuid import uuid4 | 
					
						
							|  |  |  | from unittest import SkipTest | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_request_spot_instances(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", "us-east-1") | 
					
						
							|  |  |  |     vpc = conn.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |     subnet = conn.create_subnet( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         VpcId=vpc["VpcId"], CidrBlock="10.0.0.0/16", AvailabilityZone="us-east-1a" | 
					
						
							|  |  |  |     )["Subnet"] | 
					
						
							|  |  |  |     subnet_id = subnet["SubnetId"] | 
					
						
							| 
									
										
										
										
											2016-11-07 23:08:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     sec_name_1 = str(uuid4()) | 
					
						
							|  |  |  |     sec_name_2 = str(uuid4()) | 
					
						
							|  |  |  |     conn.create_security_group(GroupName=sec_name_1, Description="description") | 
					
						
							|  |  |  |     conn.create_security_group(GroupName=sec_name_2, Description="description") | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-10 00:56:08 +01:00
										 |  |  |     start_dt = datetime.datetime(2013, 1, 1).replace(tzinfo=datetime.timezone.utc) | 
					
						
							|  |  |  |     end_dt = datetime.datetime(2013, 1, 2).replace(tzinfo=datetime.timezone.utc) | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  |     start = iso_8601_datetime_with_milliseconds(start_dt) | 
					
						
							|  |  |  |     end = iso_8601_datetime_with_milliseconds(end_dt) | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							| 
									
										
										
										
											2016-10-15 23:08:44 +10:00
										 |  |  |         request = conn.request_spot_instances( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             SpotPrice="0.5", | 
					
						
							|  |  |  |             InstanceCount=1, | 
					
						
							|  |  |  |             Type="one-time", | 
					
						
							|  |  |  |             ValidFrom=start, | 
					
						
							|  |  |  |             ValidUntil=end, | 
					
						
							|  |  |  |             LaunchGroup="the-group", | 
					
						
							|  |  |  |             AvailabilityZoneGroup="my-group", | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  |             LaunchSpecification={ | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |                 "ImageId": EXAMPLE_AMI_ID, | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  |                 "KeyName": "test", | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |                 "SecurityGroups": [sec_name_1, sec_name_2], | 
					
						
							| 
									
										
										
										
											2017-02-23 22:28:09 -05:00
										 |  |  |                 "UserData": "some test data", | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "InstanceType": "m1.small", | 
					
						
							|  |  |  |                 "Placement": {"AvailabilityZone": "us-east-1c"}, | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  |                 "KernelId": "test-kernel", | 
					
						
							|  |  |  |                 "RamdiskId": "test-ramdisk", | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |                 "Monitoring": {"Enabled": True}, | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  |                 "SubnetId": subnet_id, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             DryRun=True, | 
					
						
							| 
									
										
										
										
											2016-10-15 23:08:44 +10:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     ex.value.response["Error"]["Code"].should.equal("DryRunOperation") | 
					
						
							| 
									
										
										
										
											2021-09-07 17:10:01 +01:00
										 |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							| 
									
										
										
										
											2020-10-06 08:04:09 +02:00
										 |  |  |     ex.value.response["Error"]["Message"].should.equal( | 
					
						
							| 
									
										
										
										
											2023-02-14 12:43:28 -01:00
										 |  |  |         "An error occurred (DryRunOperation) when calling the RequestSpotInstances operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2016-10-15 23:08:44 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     request = conn.request_spot_instances( | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         SpotPrice="0.5", | 
					
						
							|  |  |  |         InstanceCount=1, | 
					
						
							|  |  |  |         Type="one-time", | 
					
						
							|  |  |  |         ValidFrom=start, | 
					
						
							|  |  |  |         ValidUntil=end, | 
					
						
							|  |  |  |         LaunchGroup="the-group", | 
					
						
							|  |  |  |         AvailabilityZoneGroup="my-group", | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |         LaunchSpecification={ | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |             "ImageId": EXAMPLE_AMI_ID, | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |             "KeyName": "test", | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |             "SecurityGroups": [sec_name_1, sec_name_2], | 
					
						
							| 
									
										
										
										
											2017-02-23 22:28:09 -05:00
										 |  |  |             "UserData": "some test data", | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "InstanceType": "m1.small", | 
					
						
							|  |  |  |             "Placement": {"AvailabilityZone": "us-east-1c"}, | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |             "KernelId": "test-kernel", | 
					
						
							|  |  |  |             "RamdiskId": "test-ramdisk", | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             "Monitoring": {"Enabled": True}, | 
					
						
							| 
									
										
										
										
											2017-02-23 21:37:43 -05:00
										 |  |  |             "SubnetId": subnet_id, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     all_requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"] | 
					
						
							|  |  |  |     requests = [r for r in all_requests if r["SpotInstanceRequestId"] == request_id] | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  |     request = requests[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request["State"].should.equal("active") | 
					
						
							|  |  |  |     request["SpotPrice"].should.equal("0.500000") | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     request["Type"].should.equal("one-time") | 
					
						
							|  |  |  |     request["ValidFrom"].should.equal(start_dt) | 
					
						
							|  |  |  |     request["ValidUntil"].should.equal(end_dt) | 
					
						
							|  |  |  |     request["LaunchGroup"].should.equal("the-group") | 
					
						
							|  |  |  |     request["AvailabilityZoneGroup"].should.equal("my-group") | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     launch_spec = request["LaunchSpecification"] | 
					
						
							|  |  |  |     security_group_names = [ | 
					
						
							|  |  |  |         group["GroupName"] for group in launch_spec["SecurityGroups"] | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     set(security_group_names).should.equal(set([sec_name_1, sec_name_2])) | 
					
						
							| 
									
										
										
										
											2013-02-21 23:13:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |     launch_spec["ImageId"].should.equal(EXAMPLE_AMI_ID) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     launch_spec["KeyName"].should.equal("test") | 
					
						
							|  |  |  |     launch_spec["InstanceType"].should.equal("m1.small") | 
					
						
							|  |  |  |     launch_spec["KernelId"].should.equal("test-kernel") | 
					
						
							|  |  |  |     launch_spec["RamdiskId"].should.equal("test-ramdisk") | 
					
						
							|  |  |  |     launch_spec["SubnetId"].should.equal(subnet_id) | 
					
						
							| 
									
										
										
										
											2013-02-21 23:13:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | def test_request_spot_instances_default_arguments(): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Test that moto set the correct default arguments | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", "us-east-1") | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     request = conn.request_spot_instances( | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     all_requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"] | 
					
						
							|  |  |  |     requests = [r for r in all_requests if r["SpotInstanceRequestId"] == request_id] | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  |     request = requests[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request["State"].should.equal("active") | 
					
						
							|  |  |  |     request["SpotPrice"].should.equal("0.500000") | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     request["Type"].should.equal("one-time") | 
					
						
							|  |  |  |     request.shouldnt.contain("ValidFrom") | 
					
						
							|  |  |  |     request.shouldnt.contain("ValidUntil") | 
					
						
							|  |  |  |     request.shouldnt.contain("LaunchGroup") | 
					
						
							|  |  |  |     request.shouldnt.contain("AvailabilityZoneGroup") | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request.should.have.key("InstanceInterruptionBehavior").equals("terminate") | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     launch_spec = request["LaunchSpecification"] | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     security_group_names = [ | 
					
						
							|  |  |  |         group["GroupName"] for group in launch_spec["SecurityGroups"] | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  |     security_group_names.should.equal(["default"]) | 
					
						
							| 
									
										
										
										
											2017-02-23 19:43:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |     launch_spec["ImageId"].should.equal(EXAMPLE_AMI_ID) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     request.shouldnt.contain("KeyName") | 
					
						
							|  |  |  |     launch_spec["InstanceType"].should.equal("m1.small") | 
					
						
							|  |  |  |     request.shouldnt.contain("KernelId") | 
					
						
							|  |  |  |     request.shouldnt.contain("RamdiskId") | 
					
						
							|  |  |  |     request.shouldnt.contain("SubnetId") | 
					
						
							| 
									
										
										
										
											2013-08-17 18:11:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_cancel_spot_instance_request(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     rsi = client.request_spot_instances( | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     spot_id = rsi["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     requests = client.describe_spot_instance_requests(SpotInstanceRequestIds=[spot_id])[ | 
					
						
							|  |  |  |         "SpotInstanceRequests" | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  |     request = requests[0] | 
					
						
							|  |  |  |     request.should.have.key("CreateTime") | 
					
						
							|  |  |  |     request.should.have.key("Type").equal("one-time") | 
					
						
							|  |  |  |     request.should.have.key("SpotInstanceRequestId") | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request.should.have.key("SpotPrice").equal("0.500000") | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     request["LaunchSpecification"]["ImageId"].should.equal(EXAMPLE_AMI_ID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.cancel_spot_instance_requests( | 
					
						
							|  |  |  |             SpotInstanceRequestIds=[request["SpotInstanceRequestId"]], DryRun=True | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Message"].should.equal( | 
					
						
							| 
									
										
										
										
											2023-02-14 12:43:28 -01:00
										 |  |  |         "An error occurred (DryRunOperation) when calling the CancelSpotInstanceRequests operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.cancel_spot_instance_requests( | 
					
						
							|  |  |  |         SpotInstanceRequestIds=[request["SpotInstanceRequestId"]] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     requests = client.describe_spot_instance_requests(SpotInstanceRequestIds=[spot_id])[ | 
					
						
							|  |  |  |         "SpotInstanceRequests" | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     requests.should.have.length_of(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_request_spot_instances_fulfilled(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Test that moto correctly fullfills a spot instance request | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							|  |  |  |         SpotInstanceRequestIds=[request_id] | 
					
						
							|  |  |  |     )["SpotInstanceRequests"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  |     request = requests[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request["State"].should.equal("active") | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_tag_spot_instance_request(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Test that moto correctly tags a spot instance request | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  |     client.create_tags( | 
					
						
							|  |  |  |         Resources=[request_id], | 
					
						
							|  |  |  |         Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							|  |  |  |         SpotInstanceRequestIds=[request_id] | 
					
						
							|  |  |  |     )["SpotInstanceRequests"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  |     request = requests[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request["Tags"].should.have.length_of(2) | 
					
						
							|  |  |  |     request["Tags"].should.contain({"Key": "tag1", "Value": "value1"}) | 
					
						
							|  |  |  |     request["Tags"].should.contain({"Key": "tag2", "Value": "value2"}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_get_all_spot_instance_requests_filtering(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Test that moto correctly filters spot instance requests | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request1 = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     request1_id = request1["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  |     request2 = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     request2_id = request2["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  |     client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     tag_value1 = str(uuid4()) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     client.create_tags( | 
					
						
							|  |  |  |         Resources=[request1_id], | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Tags=[{"Key": "tag1", "Value": tag_value1}, {"Key": "tag2", "Value": "value2"}], | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     client.create_tags( | 
					
						
							|  |  |  |         Resources=[request2_id], | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Tags=[{"Key": "tag1", "Value": tag_value1}, {"Key": "tag2", "Value": "wrong"}], | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |         Filters=[{"Name": "state", "Values": ["failed"]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["SpotInstanceRequests"] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     r_ids = [r["SpotInstanceRequestId"] for r in requests] | 
					
						
							|  |  |  |     r_ids.shouldnt.contain(request1_id) | 
					
						
							|  |  |  |     r_ids.shouldnt.contain(request2_id) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |         Filters=[{"Name": "state", "Values": ["active"]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["SpotInstanceRequests"] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     r_ids = [r["SpotInstanceRequestId"] for r in requests] | 
					
						
							|  |  |  |     r_ids.should.contain(request1_id) | 
					
						
							|  |  |  |     r_ids.should.contain(request2_id) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Filters=[{"Name": "tag:tag1", "Values": [tag_value1]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["SpotInstanceRequests"] | 
					
						
							|  |  |  |     requests.should.have.length_of(2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     requests = client.describe_spot_instance_requests( | 
					
						
							|  |  |  |         Filters=[ | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |             {"Name": "tag:tag1", "Values": [tag_value1]}, | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |             {"Name": "tag:tag2", "Values": ["value2"]}, | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     )["SpotInstanceRequests"] | 
					
						
							|  |  |  |     requests.should.have.length_of(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-08-17 14:01:22 +00:00
										 |  |  | @pytest.mark.filterwarnings("ignore") | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | def test_request_spot_instances_instance_lifecycle(): | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     if settings.TEST_SERVER_MODE: | 
					
						
							|  |  |  |         # Currently no easy way to check which instance was created by request_spot_instance | 
					
						
							|  |  |  |         # And we can't just pick the first instance in ServerMode and expect it to be the right one | 
					
						
							|  |  |  |         raise SkipTest("ServerMode is not guaranteed to be empty") | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  |     client.request_spot_instances(SpotPrice="0.5") | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     response = client.describe_instances() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     instance = response["Reservations"][0]["Instances"][0] | 
					
						
							|  |  |  |     instance["InstanceLifecycle"].should.equal("spot") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-08-17 14:01:22 +00:00
										 |  |  | @pytest.mark.filterwarnings("ignore") | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_request_spot_instances_with_tags(): | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     request = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", | 
					
						
							|  |  |  |         TagSpecifications=[ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "ResourceType": "spot-instances-request", | 
					
						
							|  |  |  |                 "Tags": [{"Key": "k", "Value": "v"}], | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     request = client.describe_spot_instance_requests( | 
					
						
							|  |  |  |         SpotInstanceRequestIds=[request_id] | 
					
						
							|  |  |  |     )["SpotInstanceRequests"][0] | 
					
						
							|  |  |  |     request.should.have.key("Tags").equals([{"Key": "k", "Value": "v"}]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_launch_spot_instance_instance_lifecycle(): | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwargs = { | 
					
						
							|  |  |  |         "KeyName": "foobar", | 
					
						
							| 
									
										
										
										
											2022-05-26 18:04:36 +02:00
										 |  |  |         "ImageId": EXAMPLE_AMI_ID, | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  |         "MinCount": 1, | 
					
						
							|  |  |  |         "MaxCount": 1, | 
					
						
							|  |  |  |         "InstanceType": "c4.2xlarge", | 
					
						
							|  |  |  |         "TagSpecifications": [ | 
					
						
							|  |  |  |             {"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "val"}]}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         "InstanceMarketOptions": {"MarketType": "spot"}, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance = client.run_instances(**kwargs)["Instances"][0] | 
					
						
							|  |  |  |     instance_id = instance["InstanceId"] | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     response = client.describe_instances(InstanceIds=[instance_id]) | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  |     instance = response["Reservations"][0]["Instances"][0] | 
					
						
							|  |  |  |     instance["InstanceLifecycle"].should.equal("spot") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_launch_instance_instance_lifecycle(): | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwargs = { | 
					
						
							|  |  |  |         "KeyName": "foobar", | 
					
						
							| 
									
										
										
										
											2022-05-26 18:04:36 +02:00
										 |  |  |         "ImageId": EXAMPLE_AMI_ID, | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  |         "MinCount": 1, | 
					
						
							|  |  |  |         "MaxCount": 1, | 
					
						
							|  |  |  |         "InstanceType": "c4.2xlarge", | 
					
						
							|  |  |  |         "TagSpecifications": [ | 
					
						
							|  |  |  |             {"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "val"}]}, | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance = client.run_instances(**kwargs)["Instances"][0] | 
					
						
							|  |  |  |     instance_id = instance["InstanceId"] | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     response = client.describe_instances(InstanceIds=[instance_id]) | 
					
						
							| 
									
										
										
										
											2021-09-02 15:12:17 +02:00
										 |  |  |     instance = response["Reservations"][0]["Instances"][0] | 
					
						
							| 
									
										
										
										
											2021-09-22 09:32:30 -07:00
										 |  |  |     instance.get("InstanceLifecycle").should.equal(None) | 
					
						
							| 
									
										
										
										
											2021-09-04 17:57:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_spot_price_history(): | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     # test filter | 
					
						
							|  |  |  |     response = client.describe_spot_price_history( | 
					
						
							|  |  |  |         Filters=[ | 
					
						
							|  |  |  |             {"Name": "availability-zone", "Values": ["us-east-1a"]}, | 
					
						
							|  |  |  |             {"Name": "instance-type", "Values": ["t3a.micro"]}, | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     price = response["SpotPriceHistory"][0] | 
					
						
							|  |  |  |     price["InstanceType"].should.equal("t3a.micro") | 
					
						
							|  |  |  |     price["AvailabilityZone"].should.equal("us-east-1a") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # test instance types | 
					
						
							|  |  |  |     i_types = ["t3a.micro", "t3.micro"] | 
					
						
							|  |  |  |     response = client.describe_spot_price_history(InstanceTypes=i_types) | 
					
						
							|  |  |  |     price = response["SpotPriceHistory"][0] | 
					
						
							|  |  |  |     assert price["InstanceType"] in i_types | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  | def test_request_spot_instances__instance_should_exist(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     request = client.request_spot_instances( | 
					
						
							|  |  |  |         SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     request = client.describe_spot_instance_requests( | 
					
						
							|  |  |  |         SpotInstanceRequestIds=[request_id] | 
					
						
							|  |  |  |     )["SpotInstanceRequests"][0] | 
					
						
							|  |  |  |     request.should.have.key("InstanceId") | 
					
						
							|  |  |  |     instance_id = request["InstanceId"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-02 15:00:06 +00:00
										 |  |  |     response = client.describe_instances(InstanceIds=[instance_id]) | 
					
						
							|  |  |  |     instance = response["Reservations"][0]["Instances"][0] | 
					
						
							|  |  |  |     instance.should.have.key("InstanceId").equals(instance_id) | 
					
						
							|  |  |  |     instance.should.have.key("ImageId").equals(EXAMPLE_AMI_ID) |