| 
									
										
										
										
											2017-05-10 21:33:30 -04:00
										 |  |  | import boto3 | 
					
						
							| 
									
										
										
										
											2017-12-22 18:50:18 +05:30
										 |  |  | from botocore.exceptions import ClientError | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2021-10-18 19:44:29 +00:00
										 |  |  | import sure  # noqa # pylint: disable=unused-import | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											2013-02-21 23:13:01 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-18 14:18:57 -01:00
										 |  |  | from moto import mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-05-03 11:40:15 +00:00
										 |  |  | from moto.ec2.models.amis import AMIS | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  | from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_PARAVIRTUAL | 
					
						
							|  |  |  | from uuid import uuid4 | 
					
						
							| 
									
										
										
										
											2013-02-21 23:13:01 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | def test_snapshots_for_initial_amis(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     snapshots = ec2.describe_snapshots()["Snapshots"] | 
					
						
							|  |  |  |     snapshot_descs = [s["Description"] for s in snapshots] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     initial_ami_count = len(AMIS) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert ( | 
					
						
							|  |  |  |         len(snapshots) >= initial_ami_count | 
					
						
							|  |  |  |     ), "Should have at least as many snapshots as AMIs" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for ami in AMIS: | 
					
						
							|  |  |  |         ami_id = ami["ami_id"] | 
					
						
							|  |  |  |         expected_description = f"Auto-created snapshot for AMI {ami_id}" | 
					
						
							|  |  |  |         snapshot_descs.should.contain(expected_description) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_create_and_delete(): | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance_id = instance["InstanceId"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.create_image( | 
					
						
							|  |  |  |             InstanceId=instance["InstanceId"], Name="test-ami", DryRun=True | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							|  |  |  |     err["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     err["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image( | 
					
						
							| 
									
										
										
										
											2022-03-10 13:39:59 -01:00
										 |  |  |         InstanceId=instance_id, Name="test-ami", Description="this is a test ami" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     all_images = ec2.describe_images()["Images"] | 
					
						
							|  |  |  |     set([i["ImageId"] for i in all_images]).should.contain(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     retrieved_image = [i for i in all_images if i["ImageId"] == image_id][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     retrieved_image.should.have.key("ImageId").equal(image_id) | 
					
						
							|  |  |  |     retrieved_image.should.have.key("VirtualizationType").equal( | 
					
						
							|  |  |  |         instance["VirtualizationType"] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     retrieved_image.should.have.key("Architecture").equal(instance["Architecture"]) | 
					
						
							|  |  |  |     retrieved_image.should.have.key("KernelId").equal(instance["KernelId"]) | 
					
						
							|  |  |  |     retrieved_image.should.have.key("Platform").equal(instance["Platform"]) | 
					
						
							|  |  |  |     retrieved_image.should.have.key("CreationDate") | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     ec2.terminate_instances(InstanceIds=[instance_id]) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Ensure we're no longer creating a volume | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     volumes_for_instance = [ | 
					
						
							|  |  |  |         v | 
					
						
							|  |  |  |         for v in ec2.describe_volumes()["Volumes"] | 
					
						
							|  |  |  |         if "Attachment" in v and v["Attachment"][0]["InstanceId"] == instance_id | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     volumes_for_instance.should.have.length_of(0) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Validate auto-created snapshot | 
					
						
							|  |  |  |     snapshots = ec2.describe_snapshots()["Snapshots"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     retrieved_image_snapshot_id = retrieved_image["BlockDeviceMappings"][0]["Ebs"][ | 
					
						
							|  |  |  |         "SnapshotId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     [s["SnapshotId"] for s in snapshots].should.contain(retrieved_image_snapshot_id) | 
					
						
							|  |  |  |     snapshot = [s for s in snapshots if s["SnapshotId"] == retrieved_image_snapshot_id][ | 
					
						
							|  |  |  |         0 | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-12-25 20:37:39 -01:00
										 |  |  |     image_id = retrieved_image["ImageId"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     snapshot["Description"].should.equal( | 
					
						
							| 
									
										
										
										
											2021-12-25 20:37:39 -01:00
										 |  |  |         f"Created by CreateImage({instance_id}) for {image_id}" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # root device should be in AMI's block device mappings | 
					
						
							|  |  |  |     root_mapping = [ | 
					
						
							|  |  |  |         m | 
					
						
							|  |  |  |         for m in retrieved_image["BlockDeviceMappings"] | 
					
						
							|  |  |  |         if m["DeviceName"] == retrieved_image["RootDeviceName"] | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     root_mapping.should_not.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Deregister | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.deregister_image(ImageId=image_id, DryRun=True) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							|  |  |  |     err["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     err["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     success = ec2.deregister_image(ImageId=image_id) | 
					
						
							|  |  |  |     success["ResponseMetadata"]["HTTPStatusCode"].should.equal(200) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.deregister_image(ImageId=image_id) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							| 
									
										
										
										
											2022-04-22 15:40:30 +00:00
										 |  |  |     err["Code"].should.equal("InvalidAMIID.Unavailable") | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["RequestId"].should_not.equal(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_deregister_image__unknown(): | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.deregister_image(ImageId="ami-unknown-ami") | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     err["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  |     ex.value.response["ResponseMetadata"]["RequestId"].should_not.equal(None) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-22 15:40:30 +00:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_deregister_image__and_describe(): | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  |     instance_id = instance["InstanceId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image( | 
					
						
							|  |  |  |         InstanceId=instance_id, Name="test-ami", Description="this is a test ami" | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ec2.deregister_image(ImageId=image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Searching for a deleted image ID should not throw an error | 
					
						
							|  |  |  |     # It should simply not return this image | 
					
						
							|  |  |  |     ec2.describe_images(ImageIds=[image_id])["Images"].should.have.length_of(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_copy_dryrun(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     source_image_id = ec2.create_image( | 
					
						
							|  |  |  |         InstanceId=instance["InstanceId"], | 
					
						
							|  |  |  |         Name="test-ami", | 
					
						
							|  |  |  |         Description="this is a test ami", | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  |     source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.copy_image( | 
					
						
							|  |  |  |             SourceRegion="us-west-1", | 
					
						
							|  |  |  |             SourceImageId=source_image["ImageId"], | 
					
						
							|  |  |  |             Name="test-copy-ami", | 
					
						
							|  |  |  |             Description="this is a test copy ami", | 
					
						
							|  |  |  |             DryRun=True, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							|  |  |  |     err["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     err["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_copy(): | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     source_image_id = ec2.create_image( | 
					
						
							|  |  |  |         InstanceId=instance["InstanceId"], | 
					
						
							|  |  |  |         Name="test-ami", | 
					
						
							|  |  |  |         Description="this is a test ami", | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  |     ec2.terminate_instances(InstanceIds=[instance["InstanceId"]]) | 
					
						
							|  |  |  |     source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     copy_image_ref = ec2.copy_image( | 
					
						
							|  |  |  |         SourceRegion="us-west-1", | 
					
						
							|  |  |  |         SourceImageId=source_image["ImageId"], | 
					
						
							|  |  |  |         Name="test-copy-ami", | 
					
						
							|  |  |  |         Description="this is a test copy ami", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     copy_image_id = copy_image_ref["ImageId"] | 
					
						
							|  |  |  |     copy_image = ec2.describe_images(ImageIds=[copy_image_id])["Images"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     copy_image["Name"].should.equal("test-copy-ami") | 
					
						
							|  |  |  |     copy_image["Description"].should.equal("this is a test copy ami") | 
					
						
							|  |  |  |     copy_image["ImageId"].should.equal(copy_image_id) | 
					
						
							|  |  |  |     copy_image["VirtualizationType"].should.equal(source_image["VirtualizationType"]) | 
					
						
							|  |  |  |     copy_image["Architecture"].should.equal(source_image["Architecture"]) | 
					
						
							|  |  |  |     copy_image["KernelId"].should.equal(source_image["KernelId"]) | 
					
						
							|  |  |  |     copy_image["Platform"].should.equal(source_image["Platform"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Validate auto-created snapshot | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     source_image_snapshot_id = source_image["BlockDeviceMappings"][0]["Ebs"][ | 
					
						
							|  |  |  |         "SnapshotId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     copied_image_snapshot_id = copy_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     snapshot_ids = [s["SnapshotId"] for s in ec2.describe_snapshots()["Snapshots"]] | 
					
						
							|  |  |  |     snapshot_ids.should.contain(source_image_snapshot_id) | 
					
						
							|  |  |  |     snapshot_ids.should.contain(copied_image_snapshot_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     copied_image_snapshot_id.shouldnt.equal(source_image_snapshot_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_copy_nonexistent_source_id(): | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Copy from non-existent source ID. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.copy_image( | 
					
						
							|  |  |  |             SourceRegion="us-west-1", | 
					
						
							|  |  |  |             SourceImageId="ami-abcd1234", | 
					
						
							|  |  |  |             Name="test-copy-ami", | 
					
						
							|  |  |  |             Description="this is a test copy ami", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_copy_nonexisting_source_region(): | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     source_image_id = ec2.create_image( | 
					
						
							|  |  |  |         InstanceId=instance["InstanceId"], | 
					
						
							|  |  |  |         Name="test-ami", | 
					
						
							|  |  |  |         Description="this is a test ami", | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  |     source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     # Copy from non-existent source region. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.copy_image( | 
					
						
							|  |  |  |             SourceRegion="us-east-1", | 
					
						
							|  |  |  |             SourceImageId=source_image["ImageId"], | 
					
						
							|  |  |  |             Name="test-copy-ami", | 
					
						
							|  |  |  |             Description="this is a test copy ami", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_copy_image_changes_owner_id(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # this source AMI ID is from moto/ec2/resources/amis.json | 
					
						
							|  |  |  |     source_ami_id = "ami-03cf127a" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # confirm the source ami owner id is different from the default owner id. | 
					
						
							|  |  |  |     # if they're ever the same it means this test is invalid. | 
					
						
							|  |  |  |     check_resp = conn.describe_images(ImageIds=[source_ami_id]) | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  |     check_resp["Images"][0]["OwnerId"].should_not.equal(ACCOUNT_ID) | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     new_image_name = str(uuid4())[0:6] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  |     copy_resp = conn.copy_image( | 
					
						
							|  |  |  |         SourceImageId=source_ami_id, | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Name=new_image_name, | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  |         Description="a copy of an image", | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         SourceRegion="us-east-1", | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     describe_resp = conn.describe_images( | 
					
						
							|  |  |  |         Owners=["self"], Filters=[{"Name": "name", "Values": [new_image_name]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     describe_resp.should.have.length_of(1) | 
					
						
							| 
									
										
										
										
											2022-08-13 09:49:43 +00:00
										 |  |  |     describe_resp[0]["OwnerId"].should.equal(ACCOUNT_ID) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     describe_resp[0]["ImageId"].should.equal(copy_resp["ImageId"]) | 
					
						
							| 
									
										
										
										
											2019-07-22 21:57:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_tagging(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     res = boto3.resource("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  |     image_id = ec2.create_image( | 
					
						
							|  |  |  |         InstanceId=instance["InstanceId"], | 
					
						
							|  |  |  |         Name="test-ami", | 
					
						
							|  |  |  |         Description="this is a test ami", | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  |     image = res.Image(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.create_tags(Tags=[{"Key": "a key", "Value": "some value"}], DryRun=True) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     err = ex.value.response["Error"] | 
					
						
							|  |  |  |     err["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     err["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) | 
					
						
							|  |  |  |     image.tags.should.equal([{"Value": "some value", "Key": "a key"}]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image = ec2.describe_images(ImageIds=[image_id])["Images"][0] | 
					
						
							|  |  |  |     image["Tags"].should.equal([{"Value": "some value", "Key": "a key"}]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_create_from_missing_instance(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.create_image( | 
					
						
							|  |  |  |             InstanceId="i-abcdefg", Name="test-ami", Description="this is a test ami" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidInstanceID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_pulls_attributes_from_instance(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  |     ec2.modify_instance_attribute( | 
					
						
							|  |  |  |         InstanceId=instance["InstanceId"], Kernel={"Value": "test-kernel"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     image = boto3.resource("ec2", region_name="us-east-1").Image(image_id) | 
					
						
							|  |  |  |     image.kernel_id.should.equal("test-kernel") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_uses_account_id_if_valid_access_key_is_supplied(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     # The boto-equivalent required an access_key to be passed in, but Moto will always mock this in boto3 | 
					
						
							|  |  |  |     # So the only thing we're testing here, really.. is whether OwnerId is equal to ACCOUNT_ID? | 
					
						
							|  |  |  |     # TODO: Maybe patch account_id with multiple values, and verify it always  matches with OwnerId | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     images = ec2.describe_images(Owners=["self"])["Images"] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     [(ami["ImageId"], ami["OwnerId"]) for ami in images].should.contain( | 
					
						
							|  |  |  |         (image_id, ACCOUNT_ID) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_filters(): | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     image_name_A = f"test-ami-{str(uuid4())[0:6]}" | 
					
						
							|  |  |  |     kernel_value_A = f"k-{str(uuid4())[0:6]}" | 
					
						
							|  |  |  |     kernel_value_B = f"k-{str(uuid4())[0:6]}" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instanceA = reservationA["Instances"][0] | 
					
						
							|  |  |  |     ec2.modify_instance_attribute( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         InstanceId=instanceA["InstanceId"], Kernel={"Value": kernel_value_A} | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name=image_name_A)[ | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reservationB = ec2.run_instances( | 
					
						
							|  |  |  |         ImageId=EXAMPLE_AMI_PARAVIRTUAL, MinCount=1, MaxCount=1 | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     instanceB = reservationB["Instances"][0] | 
					
						
							|  |  |  |     ec2.modify_instance_attribute( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         InstanceId=instanceB["InstanceId"], Kernel={"Value": kernel_value_B} | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  |     imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id) | 
					
						
							|  |  |  |     imageB.modify_attribute(LaunchPermission={"Add": [{"Group": "all"}]}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     amis_by_architecture = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "architecture", "Values": ["x86_64"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_architecture].should.contain(imageB_id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert ( | 
					
						
							|  |  |  |         len(amis_by_architecture) >= 40 | 
					
						
							|  |  |  |     ), "Should have at least 40 AMI's of type x86_64" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_kernel = ec2.describe_images( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Filters=[{"Name": "kernel-id", "Values": [kernel_value_B]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_kernel].should.equal([imageB.id]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     amis_by_virtualization = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "virtualization-type", "Values": ["paravirtual"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_virtualization].should.contain(imageB.id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert len(amis_by_virtualization) >= 3, "Should have at least 3 paravirtual AMI's" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_platform = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "platform", "Values": ["windows"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_platform].should.contain(imageA_id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert len(amis_by_platform) >= 25, "Should have at least 25 Windows images" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_id = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "image-id", "Values": [imageA_id]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_id].should.equal([imageA_id]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     amis_by_state = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "state", "Values": ["available"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     ami_ids_by_state = [ami["ImageId"] for ami in amis_by_state] | 
					
						
							|  |  |  |     ami_ids_by_state.should.contain(imageA_id) | 
					
						
							|  |  |  |     ami_ids_by_state.should.contain(imageB.id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert len(amis_by_state) >= 40, "Should have at least 40 images available" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_name = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "name", "Values": [imageA.name]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_name].should.equal([imageA.id]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     amis_by_public = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "is-public", "Values": ["true"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert len(amis_by_public) >= 38, "Should have at least 38 public images" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_nonpublic = ec2.describe_images( | 
					
						
							|  |  |  |         Filters=[{"Name": "is-public", "Values": ["false"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_nonpublic].should.contain(imageA.id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     assert len(amis_by_nonpublic) >= 2, "Should have at least 2 non-public images" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_filtering_via_tag(): | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     tag_value = f"value {str(uuid4())}" | 
					
						
							|  |  |  |     other_value = f"value {str(uuid4())}" | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instanceA = reservationA["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name="test-ami-A")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     imageA.create_tags(Tags=[{"Key": "a key", "Value": tag_value}]) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     reservationB = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instanceB = reservationB["Instances"][0] | 
					
						
							|  |  |  |     imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id) | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     imageB.create_tags(Tags=[{"Key": "another key", "Value": other_value}]) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     amis_by_tagA = ec2.describe_images( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Filters=[{"Name": "tag:a key", "Values": [tag_value]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_tagA].should.equal([imageA_id]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     amis_by_tagB = ec2.describe_images( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Filters=[{"Name": "tag:another key", "Values": [other_value]}] | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     )["Images"] | 
					
						
							|  |  |  |     [ami["ImageId"] for ami in amis_by_tagB].should.equal([imageB_id]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_getting_missing_ami(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.resource("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.Image("ami-missing").load() | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_getting_malformed_ami(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.resource("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         ec2.Image("foo-missing").load() | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.Malformed") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_attribute_group_permissions(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     image = boto3.resource("ec2", region_name="us-east-1").Image(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Baseline | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ADD_GROUP_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image_id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserGroups": ["all"], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     REMOVE_GROUP_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image_id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "remove", | 
					
						
							|  |  |  |         "UserGroups": ["all"], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add 'all' group and confirm | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute(DryRun=True) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image.modify_attribute(**ADD_GROUP_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([{"Group": "all"}]) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add is idempotent | 
					
						
							|  |  |  |     image.modify_attribute(**ADD_GROUP_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove 'all' group and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_GROUP_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove is idempotent | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_GROUP_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_attribute_user_permissions(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     image = boto3.resource("ec2", region_name="us-east-1").Image(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Baseline | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     USER1 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							|  |  |  |     USER2 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ADD_USERS_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image.id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserIds": [USER1, USER2], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     REMOVE_USERS_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image.id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "remove", | 
					
						
							|  |  |  |         "UserIds": [USER1, USER2], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     REMOVE_SINGLE_USER_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image.id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "remove", | 
					
						
							|  |  |  |         "UserIds": [USER1], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add multiple users and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**ADD_USERS_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.have.length_of(2) | 
					
						
							|  |  |  |     permissions.should.contain({"UserId": USER1}) | 
					
						
							|  |  |  |     permissions.should.contain({"UserId": USER2}) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add is idempotent | 
					
						
							|  |  |  |     image.modify_attribute(**ADD_USERS_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove single user and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_SINGLE_USER_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([{"UserId": USER2}]) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove multiple users and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_USERS_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove is idempotent | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_USERS_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | def test_ami_describe_executable_users(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     ec2 = boto3.resource("ec2", "us-east-1") | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |     ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = conn.describe_instances( | 
					
						
							|  |  |  |         Filters=[{"Name": "instance-state-name", "Values": ["running"]}] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"] | 
					
						
							|  |  |  |     image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     USER1 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ADD_USER_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image_id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserIds": [USER1], | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Add users and get no images | 
					
						
							|  |  |  |     conn.modify_image_attribute(**ADD_USER_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     attributes = conn.describe_image_attribute( | 
					
						
							|  |  |  |         ImageId=image_id, Attribute="LaunchPermissions", DryRun=False | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"].should.have.length_of(1) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"][0]["UserId"].should.equal(USER1) | 
					
						
							|  |  |  |     images = conn.describe_images(ExecutableUsers=[USER1])["Images"] | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     images.should.have.length_of(1) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     images[0]["ImageId"].should.equal(image_id) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | def test_ami_describe_executable_users_negative(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     ec2 = boto3.resource("ec2", "us-east-1") | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |     ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = conn.describe_instances( | 
					
						
							|  |  |  |         Filters=[{"Name": "instance-state-name", "Values": ["running"]}] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"] | 
					
						
							|  |  |  |     image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     USER1 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							|  |  |  |     USER2 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ADD_USER_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image_id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserIds": [USER1], | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  |     # Add users and get no images | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     # Add users and get no images | 
					
						
							|  |  |  |     conn.modify_image_attribute(**ADD_USER_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     attributes = conn.describe_image_attribute( | 
					
						
							|  |  |  |         ImageId=image_id, Attribute="LaunchPermissions", DryRun=False | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"].should.have.length_of(1) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"][0]["UserId"].should.equal(USER1) | 
					
						
							|  |  |  |     images = conn.describe_images(ExecutableUsers=[USER2])["Images"] | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     images.should.have.length_of(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | def test_ami_describe_executable_users_and_filter(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     conn = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     ec2 = boto3.resource("ec2", "us-east-1") | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |     ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     response = conn.describe_instances( | 
					
						
							|  |  |  |         Filters=[{"Name": "instance-state-name", "Values": ["running"]}] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"] | 
					
						
							|  |  |  |     image_id = conn.create_image(InstanceId=instance_id, Name="ImageToDelete")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |     USER1 = "".join([f"{random.randint(0, 9)}" for _ in range(0, 12)]) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ADD_USER_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image_id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserIds": [USER1], | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Add users and get no images | 
					
						
							|  |  |  |     conn.modify_image_attribute(**ADD_USER_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     attributes = conn.describe_image_attribute( | 
					
						
							|  |  |  |         ImageId=image_id, Attribute="LaunchPermissions", DryRun=False | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"].should.have.length_of(1) | 
					
						
							|  |  |  |     attributes["LaunchPermissions"][0]["UserId"].should.equal(USER1) | 
					
						
							|  |  |  |     images = conn.describe_images( | 
					
						
							|  |  |  |         ExecutableUsers=[USER1], Filters=[{"Name": "state", "Values": ["available"]}] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  |     images.should.have.length_of(1) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     images[0]["ImageId"].should.equal(image_id) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:58:42 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_attribute_user_and_group_permissions(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     Boto supports adding/removing both users and groups at the same time. | 
					
						
							|  |  |  |     Just spot-check this -- input variations, idempotency, etc are validated | 
					
						
							|  |  |  |       via user-specific and group-specific tests above. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     image = boto3.resource("ec2", region_name="us-east-1").Image(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Baseline | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     USER1 = "123456789011" | 
					
						
							|  |  |  |     USER2 = "123456789022" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ADD_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image.id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "add", | 
					
						
							|  |  |  |         "UserGroups": ["all"], | 
					
						
							|  |  |  |         "UserIds": [USER1, USER2], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     REMOVE_ARGS = { | 
					
						
							|  |  |  |         "ImageId": image.id, | 
					
						
							|  |  |  |         "Attribute": "launchPermission", | 
					
						
							|  |  |  |         "OperationType": "remove", | 
					
						
							|  |  |  |         "UserGroups": ["all"], | 
					
						
							|  |  |  |         "UserIds": [USER1, USER2], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Add and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**ADD_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.have.length_of(3) | 
					
						
							|  |  |  |     permissions.should.contain({"Group": "all"}) | 
					
						
							|  |  |  |     permissions.should.contain({"UserId": "123456789022"}) | 
					
						
							|  |  |  |     permissions.should.contain({"UserId": "123456789011"}) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Remove and confirm | 
					
						
							|  |  |  |     image.modify_attribute(**REMOVE_ARGS) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  |     image.reload() | 
					
						
							|  |  |  |     image.public.should.equal(False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-23 11:29:16 +00:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_filter_description(): | 
					
						
							| 
									
										
										
										
											2023-01-07 11:35:14 +00:00
										 |  |  |     # https://github.com/getmoto/moto/issues/4460 | 
					
						
							| 
									
										
										
										
											2021-10-23 11:29:16 +00:00
										 |  |  |     client = boto3.client("ec2", region_name="us-west-2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Search for partial description | 
					
						
							|  |  |  |     resp = client.describe_images( | 
					
						
							|  |  |  |         Owners=["amazon"], | 
					
						
							|  |  |  |         Filters=[{"Name": "description", "Values": ["Amazon Linux AMI*"]}], | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							| 
									
										
										
										
											2023-03-04 11:36:00 -01:00
										 |  |  |     len(resp).should.be.greater_than(9) | 
					
						
							| 
									
										
										
										
											2021-10-23 11:29:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Search for full description | 
					
						
							|  |  |  |     resp = client.describe_images( | 
					
						
							|  |  |  |         Owners=["amazon"], | 
					
						
							|  |  |  |         Filters=[ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "Name": "description", | 
					
						
							|  |  |  |                 "Values": ["Amazon Linux AMI 2018.03.0.20210721.0 x86_64 VPC HVM ebs"], | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     resp.should.have.length_of(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  | @mock_ec2 | 
					
						
							| 
									
										
										
										
											2022-04-18 20:44:56 +00:00
										 |  |  | def test_ami_attribute_error_cases(): | 
					
						
							| 
									
										
										
										
											2021-09-25 11:13:07 +00:00
										 |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance = reservation["Instances"][0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami-A")[ | 
					
						
							|  |  |  |         "ImageId" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     image = boto3.resource("ec2", region_name="us-east-1").Image(image_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with group != 'all' | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId=image_id, | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserGroups=["everyone"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with user ID that isn't an integer. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId=image_id, | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserIds=["12345678901A"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with user ID that is > length 12. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId=image_id, | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserIds=["1234567890123"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with user ID that is < length 12. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId=image_id, | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserIds=["12345678901"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with one invalid user ID among other valid IDs, ensure no | 
					
						
							|  |  |  |     # partial changes. | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId=image_id, | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserIds=["123456789011", "foo", "123456789022"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIAttributeItemValue") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     permissions = image.describe_attribute(Attribute="launchPermission")[ | 
					
						
							|  |  |  |         "LaunchPermissions" | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     permissions.should.equal([]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Add with invalid image ID | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId="ami-abcd1234", | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="add", | 
					
						
							|  |  |  |             UserGroups=["all"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Error: Remove with invalid image ID | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         image.modify_attribute( | 
					
						
							|  |  |  |             ImageId="ami-abcd1234", | 
					
						
							|  |  |  |             Attribute="launchPermission", | 
					
						
							|  |  |  |             OperationType="remove", | 
					
						
							|  |  |  |             UserGroups=["all"], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"].should.have.key("RequestId") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-22 18:50:18 +05:30
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_describe_non_existent(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ec2 = boto3.resource("ec2", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2017-12-22 18:50:18 +05:30
										 |  |  |     # Valid pattern but non-existent id | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     img = ec2.Image("ami-abcd1234") | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError): | 
					
						
							| 
									
										
										
										
											2017-12-22 18:50:18 +05:30
										 |  |  |         img.load() | 
					
						
							|  |  |  |     # Invalid ami pattern | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     img = ec2.Image("not_an_ami_id") | 
					
						
							| 
									
										
										
										
											2020-10-06 07:54:49 +02:00
										 |  |  |     with pytest.raises(ClientError): | 
					
						
							| 
									
										
										
										
											2017-12-22 18:50:18 +05:30
										 |  |  |         img.load() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 08:51:26 -04:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_registration(): | 
					
						
							|  |  |  |     ec2 = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     image_id = ec2.register_image(Name="test-register-image").get("ImageId", "") | 
					
						
							|  |  |  |     images = ec2.describe_images(ImageIds=[image_id]).get("Images", []) | 
					
						
							|  |  |  |     assert images[0]["Name"] == "test-register-image", "No image was registered." | 
					
						
							|  |  |  |     assert images[0]["RootDeviceName"] == "/dev/sda1", "Wrong root device name." | 
					
						
							|  |  |  |     assert images[0]["State"] == "available", "State should be available." | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-10 21:33:30 -04:00
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_wildcard(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ec2_resource = boto3.resource("ec2", region_name="us-west-1") | 
					
						
							|  |  |  |     ec2_client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2018-01-11 14:51:42 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-14 21:40:48 -01:00
										 |  |  |     image_name = str(uuid4())[0:12] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     instance = ec2_resource.create_instances( | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |         ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )[0] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance.create_image(Name=image_name) | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # create an image with the same owner but will not match the filter | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance.create_image(Name=str(uuid4())[0:6]) | 
					
						
							| 
									
										
										
										
											2017-12-05 16:53:30 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-11 14:51:42 -05:00
										 |  |  |     my_images = ec2_client.describe_images( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         Owners=[ACCOUNT_ID], | 
					
						
							| 
									
										
										
										
											2022-02-14 21:40:48 -01:00
										 |  |  |         Filters=[{"Name": "name", "Values": [f"{image_name[0:8]}*"]}], | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )["Images"] | 
					
						
							| 
									
										
										
										
											2018-01-11 14:51:42 -05:00
										 |  |  |     my_images.should.have.length_of(1) | 
					
						
							| 
									
										
										
										
											2017-05-10 21:33:30 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-12 11:18:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_by_owner_id(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							| 
									
										
										
										
											2017-11-12 11:18:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ubuntu_id = "099720109477" | 
					
						
							| 
									
										
										
										
											2017-11-12 11:18:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ubuntu_images = client.describe_images(Owners=[ubuntu_id]) | 
					
						
							|  |  |  |     all_images = client.describe_images() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ubuntu_ids = [ami["OwnerId"] for ami in ubuntu_images["Images"]] | 
					
						
							|  |  |  |     all_ids = [ami["OwnerId"] for ami in all_images["Images"]] | 
					
						
							| 
									
										
										
										
											2017-11-12 11:18:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Assert all ubuntu_ids are the same and one equals ubuntu_id | 
					
						
							|  |  |  |     assert all(ubuntu_ids) and ubuntu_ids[0] == ubuntu_id | 
					
						
							|  |  |  |     # Check we actually have a subset of images | 
					
						
							|  |  |  |     assert len(ubuntu_ids) < len(all_ids) | 
					
						
							| 
									
										
										
										
											2018-01-04 15:31:17 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-11 14:51:42 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-04 15:31:17 +05:30
										 |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_by_self(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ec2_resource = boto3.resource("ec2", region_name="us-west-1") | 
					
						
							|  |  |  |     ec2_client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2018-01-04 15:31:17 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     unique_name = str(uuid4())[0:6] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     images = ec2_client.describe_images(Owners=["self"])["Images"] | 
					
						
							|  |  |  |     image_names = [i["Name"] for i in images] | 
					
						
							|  |  |  |     image_names.shouldnt.contain(unique_name) | 
					
						
							| 
									
										
										
										
											2018-01-04 15:31:17 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     # Create a new image | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     instance = ec2_resource.create_instances( | 
					
						
							| 
									
										
										
										
											2021-01-13 09:02:11 +00:00
										 |  |  |         ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     )[0] | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     instance.create_image(Name=unique_name) | 
					
						
							| 
									
										
										
										
											2018-01-04 15:31:17 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     images = ec2_client.describe_images(Owners=["self"])["Images"] | 
					
						
							|  |  |  |     image_names = [i["Name"] for i in images] | 
					
						
							|  |  |  |     image_names.should.contain(unique_name) | 
					
						
							| 
									
										
										
										
											2018-03-21 15:55:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_snapshots_have_correct_owner(): | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     ec2_client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							| 
									
										
										
										
											2018-03-21 15:55:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     images_response = ec2_client.describe_images() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     owner_id_to_snapshot_ids = {} | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |     for image in images_response["Images"]: | 
					
						
							|  |  |  |         owner_id = image["OwnerId"] | 
					
						
							| 
									
										
										
										
											2018-03-21 15:55:58 +00:00
										 |  |  |         snapshot_ids = [ | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |             block_device_mapping["Ebs"]["SnapshotId"] | 
					
						
							|  |  |  |             for block_device_mapping in image["BlockDeviceMappings"] | 
					
						
							| 
									
										
										
										
											2018-03-21 15:55:58 +00:00
										 |  |  |         ] | 
					
						
							|  |  |  |         existing_snapshot_ids = owner_id_to_snapshot_ids.get(owner_id, []) | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         owner_id_to_snapshot_ids[owner_id] = existing_snapshot_ids + snapshot_ids | 
					
						
							| 
									
										
										
										
											2020-06-15 15:02:43 +05:30
										 |  |  |         # adding an assertion to volumeType | 
					
						
							|  |  |  |         assert ( | 
					
						
							|  |  |  |             image.get("BlockDeviceMappings", {})[0].get("Ebs", {}).get("VolumeType") | 
					
						
							|  |  |  |             == "standard" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-03-21 15:55:58 +00:00
										 |  |  |     for owner_id in owner_id_to_snapshot_ids: | 
					
						
							|  |  |  |         snapshots_rseponse = ec2_client.describe_snapshots( | 
					
						
							|  |  |  |             SnapshotIds=owner_id_to_snapshot_ids[owner_id] | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-31 08:44:26 -07:00
										 |  |  |         for snapshot in snapshots_rseponse["Snapshots"]: | 
					
						
							|  |  |  |             assert owner_id == snapshot["OwnerId"] | 
					
						
							| 
									
										
										
										
											2021-01-23 04:57:34 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_create_image_with_tag_specification(): | 
					
						
							|  |  |  |     ec2 = boto3.resource("ec2", region_name="us-west-1") | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  |     tag_specifications = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "ResourceType": "image", | 
					
						
							|  |  |  |             "Tags": [ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "Key": "Base_AMI_Name", | 
					
						
							|  |  |  |                     "Value": "Deep Learning Base AMI (Amazon Linux 2) Version 31.0", | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2022-03-10 13:39:59 -01:00
										 |  |  |                 {"Key": "OS_Version", "Value": "AWS Linux 2"}, | 
					
						
							| 
									
										
										
										
											2021-01-23 04:57:34 -08:00
										 |  |  |             ], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] | 
					
						
							|  |  |  |     image_id = client.create_image( | 
					
						
							|  |  |  |         InstanceId=instance.instance_id, | 
					
						
							|  |  |  |         Name="test-image", | 
					
						
							|  |  |  |         Description="test ami", | 
					
						
							|  |  |  |         TagSpecifications=tag_specifications, | 
					
						
							|  |  |  |     )["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     image = client.describe_images(ImageIds=[image_id])["Images"][0] | 
					
						
							|  |  |  |     image["Tags"].should.equal(tag_specifications[0]["Tags"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.create_image( | 
					
						
							|  |  |  |             InstanceId=instance.instance_id, | 
					
						
							|  |  |  |             Name="test-image", | 
					
						
							|  |  |  |             Description="test ami", | 
					
						
							|  |  |  |             TagSpecifications=[ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "ResourceType": "invalid-resource-type", | 
					
						
							|  |  |  |                     "Tags": [{"Key": "key", "Value": "value"}], | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("InvalidParameterValue") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "'invalid-resource-type' is not a valid taggable resource type for this operation." | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-01-24 04:00:25 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_by_empty_tag(): | 
					
						
							|  |  |  |     ec2 = boto3.resource("ec2", region_name="us-west-1") | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-west-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fake_images = [] | 
					
						
							|  |  |  |     instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] | 
					
						
							|  |  |  |     for i in range(10): | 
					
						
							|  |  |  |         image = client.create_image( | 
					
						
							|  |  |  |             InstanceId=instance.instance_id, | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |             Name=f"MyAMI{i}", | 
					
						
							| 
									
										
										
										
											2021-01-24 04:00:25 -08:00
										 |  |  |             Description="Test", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ec2.create_tags( | 
					
						
							|  |  |  |             Resources=[image["ImageId"]], | 
					
						
							|  |  |  |             Tags=[ | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     "Key": "Base_AMI_Name", | 
					
						
							|  |  |  |                     "Value": "Deep Learning Base AMI (Amazon Linux 2) Version 31.0", | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 {"Key": "OS_Version", "Value": "AWS Linux 2"}, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         fake_images.append(image) | 
					
						
							|  |  |  |     # Add release tags to some of the images in the middle | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |     release_version = str(uuid4())[0:6] | 
					
						
							| 
									
										
										
										
											2021-01-24 04:00:25 -08:00
										 |  |  |     for image in fake_images[3:6]: | 
					
						
							|  |  |  |         ec2.create_tags( | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |             Resources=[image["ImageId"]], | 
					
						
							|  |  |  |             Tags=[{"Key": "RELEASE", "Value": release_version}], | 
					
						
							| 
									
										
										
										
											2021-01-24 04:00:25 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  |     images_filter = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "Name": "tag:Base_AMI_Name", | 
					
						
							|  |  |  |             "Values": ["Deep Learning Base AMI (Amazon Linux 2) Version 31.0"], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         {"Name": "tag:OS_Version", "Values": ["AWS Linux 2"]}, | 
					
						
							| 
									
										
										
										
											2021-10-05 17:11:07 +00:00
										 |  |  |         {"Name": "tag:RELEASE", "Values": [release_version]}, | 
					
						
							| 
									
										
										
										
											2021-01-24 04:00:25 -08:00
										 |  |  |     ] | 
					
						
							|  |  |  |     assert len(client.describe_images(Filters=images_filter)["Images"]) == 3 | 
					
						
							| 
									
										
										
										
											2021-09-01 13:23:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_by_ownerid(): | 
					
						
							|  |  |  |     ec2_connection = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     images = ec2_connection.describe_images( | 
					
						
							|  |  |  |         Filters=[ | 
					
						
							| 
									
										
										
										
											2022-03-10 13:39:59 -01:00
										 |  |  |             {"Name": "name", "Values": ["amzn-ami-*"]}, | 
					
						
							|  |  |  |             {"Name": "owner-alias", "Values": ["amazon"]}, | 
					
						
							| 
									
										
										
										
											2021-09-01 13:23:24 +01:00
										 |  |  |         ] | 
					
						
							|  |  |  |     )["Images"] | 
					
						
							|  |  |  |     assert len(images) > 0, "We should have at least 1 image created by amazon" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_ami_filter_by_unknown_ownerid(): | 
					
						
							|  |  |  |     ec2_connection = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     images = ec2_connection.describe_images( | 
					
						
							| 
									
										
										
										
											2022-03-10 13:39:59 -01:00
										 |  |  |         Filters=[{"Name": "owner-alias", "Values": ["unknown"]}] | 
					
						
							| 
									
										
										
										
											2021-09-01 13:23:24 +01:00
										 |  |  |     )["Images"] | 
					
						
							|  |  |  |     images.should.have.length_of(0) | 
					
						
							| 
									
										
										
										
											2021-10-15 22:43:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_describe_images_dryrun(): | 
					
						
							|  |  |  |     client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.describe_images(DryRun=True) | 
					
						
							|  |  |  |     ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) | 
					
						
							|  |  |  |     ex.value.response["Error"]["Code"].should.equal("DryRunOperation") | 
					
						
							|  |  |  |     ex.value.response["Error"]["Message"].should.equal( | 
					
						
							|  |  |  |         "An error occurred (DryRunOperation) when calling the DescribeImages operation: Request would have succeeded, but DryRun flag is set" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-12-25 20:37:39 -01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_ec2 | 
					
						
							|  |  |  | def test_delete_snapshot_from_create_image(): | 
					
						
							|  |  |  |     ec2_client = boto3.client("ec2", region_name="us-east-1") | 
					
						
							|  |  |  |     resp = ec2_client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) | 
					
						
							|  |  |  |     instance_id = resp["Instances"][0]["InstanceId"] | 
					
						
							|  |  |  |     ami = ec2_client.create_image(InstanceId=instance_id, Name="test") | 
					
						
							|  |  |  |     ami_id = ami["ImageId"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     snapshots = ec2_client.describe_snapshots( | 
					
						
							|  |  |  |         Filters=[ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 "Name": "description", | 
					
						
							|  |  |  |                 "Values": ["Created by CreateImage(" + instance_id + "*"], | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     )["Snapshots"] | 
					
						
							|  |  |  |     snapshot_id = snapshots[0]["SnapshotId"] | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as exc: | 
					
						
							|  |  |  |         ec2_client.delete_snapshot(SnapshotId=snapshot_id) | 
					
						
							|  |  |  |     err = exc.value.response["Error"] | 
					
						
							|  |  |  |     err["Code"].should.equal("InvalidSnapshot.InUse") | 
					
						
							|  |  |  |     err["Message"].should.equal( | 
					
						
							|  |  |  |         f"The snapshot {snapshot_id} is currently in use by {ami_id}" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Deregister the Ami first | 
					
						
							|  |  |  |     ec2_client.deregister_image(ImageId=ami_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Now we can delete the snapshot without problems | 
					
						
							|  |  |  |     ec2_client.delete_snapshot(SnapshotId=snapshot_id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as exc: | 
					
						
							|  |  |  |         ec2_client.describe_snapshots(SnapshotIds=[snapshot_id]) | 
					
						
							|  |  |  |     exc.value.response["Error"]["Code"].should.equal("InvalidSnapshot.NotFound") |