diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py index 8db419354..0aebec08a 100644 --- a/moto/ec2/exceptions.py +++ b/moto/ec2/exceptions.py @@ -233,10 +233,13 @@ class InvalidRouteError(EC2ClientError): class InvalidInstanceIdError(EC2ClientError): def __init__(self, instance_id): - super().__init__( - "InvalidInstanceID.NotFound", - "The instance ID '{0}' does not exist".format(instance_id), - ) + if isinstance(instance_id, str): + instance_id = [instance_id] + if len(instance_id) > 1: + msg = f"The instance IDs '{', '.join(instance_id)}' do not exist" + else: + msg = f"The instance ID '{instance_id[0]}' does not exist" + super().__init__("InvalidInstanceID.NotFound", msg) class InvalidInstanceTypeError(EC2ClientError): diff --git a/moto/ec2/models.py b/moto/ec2/models.py index e8d5b2b36..7681b380a 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1284,9 +1284,10 @@ class InstanceBackend(object): if instance.applies(filters): result.append(instance) - # TODO: Trim error message down to specific invalid id. if instance_ids and len(instance_ids) > len(result): - raise InvalidInstanceIdError(instance_ids) + result_ids = [i.id for i in result] + missing_instance_ids = [i for i in instance_ids if i not in result_ids] + raise InvalidInstanceIdError(missing_instance_ids) return result diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py index b05078e2d..2813f8932 100644 --- a/tests/test_ec2/test_instances.py +++ b/tests/test_ec2/test_instances.py @@ -2049,6 +2049,43 @@ def test_instance_termination_protection(): instance["State"]["Name"].should.equal("terminated") +@mock_ec2 +def test_terminate_unknown_instances(): + client = boto3.client("ec2", region_name="us-west-1") + + # Correct error message for single unknown instance + with pytest.raises(ClientError) as ex: + client.terminate_instances(InstanceIds=["i-12345678"]) + error = ex.value.response["Error"] + error["Code"].should.equal("InvalidInstanceID.NotFound") + error["Message"].should.equal("The instance ID 'i-12345678' does not exist") + + # Correct error message for multiple unknown instances + with pytest.raises(ClientError) as ex: + client.terminate_instances(InstanceIds=["i-12345678", "i-12345668"]) + error = ex.value.response["Error"] + error["Code"].should.equal("InvalidInstanceID.NotFound") + error["Message"].should.equal( + "The instance IDs 'i-12345678, i-12345668' do not exist" + ) + + # Create an instance + resp = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) + instance_id = resp["Instances"][0]["InstanceId"] + + # Correct error message if one instance is known + with pytest.raises(ClientError) as ex: + client.terminate_instances(InstanceIds=["i-12345678", instance_id]) + error = ex.value.response["Error"] + error["Code"].should.equal("InvalidInstanceID.NotFound") + error["Message"].should.equal("The instance ID 'i-12345678' does not exist") + + # status = still running + resp = client.describe_instances(InstanceIds=[instance_id]) + instance = resp["Reservations"][0]["Instances"][0] + instance["State"]["Name"].should.equal("running") + + @mock_ec2 def test_instance_lifecycle(): ec2_resource = boto3.resource("ec2", "us-west-1")