Add instance lifecycle property to detect spot instances (#4260)

This commit is contained in:
mello7tre 2021-09-02 15:12:17 +02:00 committed by GitHub
parent edca235623
commit 6d9abe1111
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 0 deletions

View File

@ -526,6 +526,7 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
super(Instance, self).__init__()
self.ec2_backend = ec2_backend
self.id = random_instance_id()
self.lifecycle = kwargs.get("lifecycle", "")
self.image_id = image_id
self._state = InstanceState("running", 16)
self._reason = ""
@ -1001,6 +1002,8 @@ class InstanceBackend(object):
)
else:
new_instance.setup_defaults()
if kwargs.get("instance_market_options"):
new_instance.lifecycle = "spot"
# Tag all created volumes.
for _, device in new_instance.get_block_device_mapping:
volumes = self.describe_volumes(volume_ids=[device.volume_id])
@ -5172,6 +5175,7 @@ class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource):
security_group_ids=self.launch_specification.groups,
spot_fleet_id=self.spot_fleet_id,
tags=self.tags,
lifecycle="spot",
)
instance = reservation.instances[0]
return instance

View File

@ -62,6 +62,10 @@ class InstanceResponse(BaseResponse):
"associate_public_ip": self._get_param("AssociatePublicIpAddress"),
"tags": self._parse_tag_specification("TagSpecification"),
"ebs_optimized": self._get_param("EbsOptimized") or False,
"instance_market_options": self._get_param(
"InstanceMarketOptions.MarketType"
)
or {},
"instance_initiated_shutdown_behavior": self._get_param(
"InstanceInitiatedShutdownBehavior"
),
@ -382,6 +386,7 @@ EC2_RUN_INSTANCES = (
<amiLaunchIndex>{{ instance.ami_launch_index }}</amiLaunchIndex>
<instanceType>{{ instance.instance_type }}</instanceType>
<launchTime>{{ instance.launch_time }}</launchTime>
<instanceLifecycle>{{ instance.lifecycle }}</instanceLifecycle>
<placement>
<availabilityZone>{{ instance.placement}}</availabilityZone>
<groupName/>
@ -533,6 +538,7 @@ EC2_DESCRIBE_INSTANCES = (
<productCodes/>
<instanceType>{{ instance.instance_type }}</instanceType>
<launchTime>{{ instance.launch_time }}</launchTime>
<instanceLifecycle>{{ instance.lifecycle }}</instanceLifecycle>
<placement>
<availabilityZone>{{ instance.placement }}</availabilityZone>
<groupName/>

View File

@ -177,6 +177,7 @@ class Instance(TaggedEC2Object):
self.monitoring_state = None
self.spot_instance_request_id = None
self.subnet_id = None
self.lifecycle = None
self.vpc_id = None
self.private_ip_address = None
self.ip_address = None

View File

@ -39,6 +39,7 @@ class LaunchSpecification(EC2Object):
self.ramdisk = None
self.monitored = False
self.subnet_id = None
self.lifecycle = None
self._in_monitoring_element = False
self.block_device_mapping = None
self.instance_profile = None

View File

@ -257,3 +257,59 @@ def test_request_spot_instances_setting_instance_id():
request = conn.get_all_spot_instance_requests()[0]
assert request.state == "active"
assert request.instance_id == "i-12345678"
@mock_ec2
def test_request_spot_instances_instance_lifecycle():
client = boto3.client("ec2", region_name="us-east-1")
request = client.request_spot_instances(SpotPrice="0.5")
response = client.describe_instances()
instance = response["Reservations"][0]["Instances"][0]
instance["InstanceLifecycle"].should.equal("spot")
@mock_ec2
def test_launch_spot_instance_instance_lifecycle():
client = boto3.client("ec2", region_name="us-east-1")
kwargs = {
"KeyName": "foobar",
"ImageId": "ami-pytest",
"MinCount": 1,
"MaxCount": 1,
"InstanceType": "c4.2xlarge",
"TagSpecifications": [
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "val"}]},
],
"InstanceMarketOptions": {"MarketType": "spot"},
}
client.run_instances(**kwargs)["Instances"][0]
response = client.describe_instances()
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",
"ImageId": "ami-pytest",
"MinCount": 1,
"MaxCount": 1,
"InstanceType": "c4.2xlarge",
"TagSpecifications": [
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "val"}]},
],
}
client.run_instances(**kwargs)["Instances"][0]
response = client.describe_instances()
instance = response["Reservations"][0]["Instances"][0]
instance["InstanceLifecycle"].should.equal("")