def _assert_successful(self, mocker, client, image_id, force, region,
                           image, stack, expected_response):
        if image:
            mocker.patch("pcluster.aws.ec2.Ec2Client.describe_image_by_id_tag",
                         return_value=image)
        else:
            mocker.patch(
                "pcluster.aws.ec2.Ec2Client.describe_image_by_id_tag",
                side_effect=ImageNotFoundError("describe_image_by_id_tag"),
            )

        if stack:
            mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack",
                         return_value=stack)
        else:
            mocker.patch(
                "pcluster.aws.cfn.CfnClient.describe_stack",
                side_effect=StackNotFoundError("describe_stack", "stack_name"),
            )

        mocker.patch("pcluster.models.imagebuilder.ImageBuilder.delete",
                     return_value=None)

        # Ensure we don't hit AWS when creating ImageBuilderStack(s)
        mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack_resource",
                     return_value=None)

        response = self._send_test_request(client, image_id, region, force)

        with soft_assertions():
            assert_that(response.status_code).is_equal_to(202)
            assert_that(response.get_json()).is_equal_to(expected_response)
 def _mock_cluster_stack(cluster_found=True, cluster_valid=True, logging_enabled=True):
     if not cluster_found:
         mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack", side_effect=StackNotFoundError("func", "stack"))
     else:
         edits = {}
         if not cluster_valid:
             edits.update({"Tags": [{"Key": "parallelcluster:version", "Value": "2.0.0"}]})
         if not logging_enabled:
             edits.update({"Parameters": []})
         mocker.patch(
             "pcluster.aws.cfn.CfnClient.describe_stack", return_value=cfn_describe_stack_mock_response(edits=edits)
         )
Exemple #3
0
 def describe_stack(self, stack_name: str):
     """Get information for the given stack."""
     try:
         return self._client.describe_stacks(
             StackName=stack_name).get("Stacks")[0]
     except ClientError as e:
         if e.response["Error"][
                 "Code"] == AWSClientError.ErrorCode.VALIDATION_ERROR.value:
             LOGGER.info("Could not describe CloudFormation stack %s: %s",
                         stack_name, e)
             raise StackNotFoundError(function_name="describe_stack",
                                      stack_name=stack_name)
         raise
 def test_stack_not_exist_request(self, mocker, client):
     mocker.patch(
         "pcluster.aws.cfn.CfnClient.describe_stack",
         side_effect=StackNotFoundError(function_name="describestack",
                                        stack_name="stack_name"),
     )
     response = self._send_test_request(client)
     with soft_assertions():
         assert_that(response.status_code).is_equal_to(404)
         assert_that(response.get_json()).is_equal_to({
             "message":
             "Cluster 'clustername' does not exist or belongs to an "
             "incompatible ParallelCluster major version."
         })
    def test_delete_image_with_no_available_image_or_stack_throws_not_found_exception(
            self, mocker, client):
        mocker.patch(
            "pcluster.aws.ec2.Ec2Client.describe_image_by_id_tag",
            side_effect=ImageNotFoundError("describe_image_by_id_tag"),
        )
        mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack",
                     side_effect=StackNotFoundError("describe_stack",
                                                    "stack_name"))
        response = self._send_test_request(client, "nonExistentImage")

        with soft_assertions():
            assert_that(response.status_code).is_equal_to(404)
            assert_that(response.get_json()).is_equal_to({
                "message":
                "No image or stack associated with ParallelCluster image id: nonExistentImage."
            })
 def test_successful_request(self, mocker, client, stack_exists, force):
     if stack_exists:
         mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack",
                      return_value=cfn_describe_stack_mock_response())
     else:
         mocker.patch(
             "pcluster.aws.cfn.CfnClient.describe_stack",
             side_effect=StackNotFoundError(function_name="describestack",
                                            stack_name="stack_name"),
         )
     instance_ids = ["fakeinstanceid1", "fakeinstanceid2"]
     mocker.patch("pcluster.aws.ec2.Ec2Client.list_instance_ids",
                  return_value=instance_ids)
     terminate_instance_mock = mocker.patch(
         "pcluster.aws.ec2.Ec2Client.terminate_instances")
     response = self._send_test_request(client, force=force)
     with soft_assertions():
         assert_that(response.status_code).is_equal_to(202)
         terminate_instance_mock.assert_called_with(tuple(instance_ids))
 def _mock_image_stack(image_id: str = "image", stack_exists: bool = True):
     uid = "00000000-ffff-1111-9999-000000000000"
     stack_data = {
         "Capabilities": ["CAPABILITY_NAMED_IAM"],
         "CreationTime": datetime(2021, 1, 1, 0, 0, 0, 0, tzinfo=tz.tzutc()),
         "NotificationARNs": [],
         "Parameters": [],
         "RollbackConfiguration": {},
         "StackId": f"arn:aws:cloudformation:us-east-1:000000000000:stack/{image_id}/{uid}",
         "StackName": image_id,
         "StackStatus": "CREATE_COMPLETE",
         "Tags": [
             {"Key": "parallelcluster:version", "Value": "3.0.0"},
             {"Key": "parallelcluster:image_name", "Value": image_id},
             {"Key": "parallelcluster:image_id", "Value": image_id},
             {"Key": "parallelcluster:s3_bucket", "Value": "parallelcluster-0000000000000000-v1-do-not-delete"},
             {
                 "Key": "parallelcluster:s3_image_dir",
                 "Value": f"parallelcluster/3.0.0/images/{image_id}-aaaaaaaaaaaaaaaa",
             },
             {
                 "Key": "parallelcluster:build_log",
                 "Value": (
                     "arn:aws:logs:us-east-1:000000000000:log-group:"
                     "/aws/imagebuilder/ParallelClusterImage-{image_id}"
                 ),
             },
             {
                 "Key": "parallelcluster:build_config",
                 "Value": (
                     "s3://parallelcluster-0cd54f8004a2e0af-v1-do-not-delete/parallelcluster/"
                     "3.0.0/images/custom-image-0-pgdlow92odu5dbvv/configs/image-config.yaml"
                 ),
             },
         ],
     }
     if not stack_exists:
         mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack", side_effect=StackNotFoundError("func", "stack"))
     else:
         mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack", return_value=stack_data)
Exemple #8
0
from tests.utils import MockedBoto3Request

FAKE_STACK_NAME = "parallelcluster-name"
FAKE_IMAGE_ID = "ami-1234567"


@pytest.fixture()
def boto3_stubber_path():
    return "pcluster.aws.common.boto3"


@pytest.mark.parametrize(
    "response,is_error",
    [
        (
            StackNotFoundError(function_name="describe_stack",
                               stack_name=FAKE_STACK_NAME),
            True,
        ),
        ({
            "Stacks": [{
                "StackName": FAKE_STACK_NAME,
                "CreationTime": 0,
                "StackStatus": "CREATED"
            }]
        }, False),
    ],
)
def test_stack_exists(mocker, response, is_error):
    """Verify that CfnClient.stack_exists behaves as expected."""
    should_exist = not is_error
    mock_aws_api(mocker)