def describe_cluster_instances_mock_response(instances):
    result = []
    for instance in instances:
        node_type = instance.get("node_type") or "HeadNode"
        response = {
            "instanceId":
            "i-0a9342a0000000000",
            "instanceType":
            "t2.micro",
            "launchTime":
            to_iso_timestr(to_utc_datetime("2021-04-30T00:00:00+00:00")),
            "nodeType":
            node_type,
            "privateIpAddress":
            "10.0.0.79",
            "publicIpAddress":
            "1.2.3.4",
            "state":
            "running",
        }
        if node_type == "Compute":
            response["nodeType"] = "ComputeNode"
            response["queueName"] = instance.get("queue_name")
        result.append(response)
    return {"instances": result}
 def test_successful_request(self, mocker, client, scheduler, status,
                             last_status_updated_time):
     mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack",
                  return_value=cfn_describe_stack_mock_response(scheduler))
     if scheduler == "slurm":
         if status == "UNKNOWN":
             dynamodb_item = {}  # Test dynamodb item not exist
         else:
             dynamodb_item = {"Item": {"Status": status}}
             if last_status_updated_time:
                 last_status_updated_time = str(last_status_updated_time)
                 dynamodb_item["Item"][
                     "LastUpdatedTime"] = last_status_updated_time
         mocker.patch("pcluster.aws.dynamo.DynamoResource.get_item",
                      return_value=dynamodb_item)
     elif scheduler == "awsbatch":
         mocker.patch(
             "pcluster.aws.batch.BatchClient.get_compute_environment_state",
             return_value=status)
     response = self._send_test_request(client)
     with soft_assertions():
         assert_that(response.status_code).is_equal_to(200)
         expected_response = {"status": status}
         if last_status_updated_time:
             expected_response["lastStatusUpdatedTime"] = to_iso_timestr(
                 to_utc_datetime(last_status_updated_time))
         assert_that(response.get_json()).is_equal_to(expected_response)
 def convert_log(log):
     log["logStreamArn"] = log.pop("arn")
     if "storedBytes" in log:
         del log["storedBytes"]
     for ts_name in ["creationTime", "firstEventTimestamp", "lastEventTimestamp", "lastIngestionTime"]:
         log[ts_name] = to_iso_timestr(to_utc_datetime(log[ts_name]))
     return LogStream.from_dict(log)
Example #4
0
    def test_describe_of_image_already_available(self, client, mocker):
        mocker.patch(
            "pcluster.aws.ec2.Ec2Client.describe_image_by_id_tag",
            return_value=_create_image_info("image1"),
        )
        mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack_resource",
                     return_value=None)
        mocker.patch(
            "pcluster.api.controllers.image_operations_controller._presigned_config_url",
            return_value="https://parallelcluster.aws.com/bucket/key",
        )

        expected_response = {
            "creationTime": to_iso_timestr(datetime(2021, 4, 12)),
            "ec2AmiInfo": {
                "amiId":
                "image1",
                "amiName":
                "image1",
                "architecture":
                "x86_64",
                "state":
                Ec2AmiState.AVAILABLE,
                "description":
                "description",
                "tags": [
                    {
                        "key": "parallelcluster:image_id",
                        "value": "image1"
                    },
                    {
                        "key": "parallelcluster:version",
                        "value": "3.0.0"
                    },
                    {
                        "key": "parallelcluster:build_config",
                        "value": "s3://bucket/key"
                    },
                ],
            },
            "imageBuildStatus": ImageBuildStatus.BUILD_COMPLETE,
            "imageConfiguration": {
                "url": "https://parallelcluster.aws.com/bucket/key"
            },
            "imageId": "image1",
            "region": "us-east-1",
            "version": "3.0.0",
        }

        response = self._send_test_request(client, "image1")

        with soft_assertions():
            assert_that(response.status_code).is_equal_to(200)
            assert_that(response.get_json()).is_equal_to(expected_response)
Example #5
0
 def default(self, obj):
     """Override the base method to add support for model objects serialization."""
     if isinstance(obj, Model):
         dikt = {}
         for attr, _ in six.iteritems(obj.openapi_types):
             value = getattr(obj, attr)
             if value is None and not self.include_nulls:
                 continue
             attr = obj.attribute_map[attr]
             dikt[attr] = value
         return dikt
     elif isinstance(obj, datetime.date):
         return to_iso_timestr(obj)
     return FlaskJSONEncoder.default(self, obj)
 def test_successful_request(self, mocker, client, scheduler, status,
                             last_status_updated_time):
     mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack",
                  return_value=cfn_describe_stack_mock_response(scheduler))
     config_mock = mocker.patch("pcluster.models.cluster.Cluster.config")
     config_mock.scheduling.scheduler = scheduler
     if scheduler == "slurm":
         if status == "UNKNOWN":
             dynamodb_item = {}  # Test dynamodb item not exist
         else:
             dynamodb_item = {"Item": {"Status": status}}
             if last_status_updated_time:
                 last_status_updated_time = str(last_status_updated_time)
                 dynamodb_item["Item"][
                     "LastUpdatedTime"] = last_status_updated_time
         # mock the method to check the status before update
         mocker.patch("pcluster.aws.dynamo.DynamoResource.get_item",
                      return_value=dynamodb_item)
         # mock the method to update the item in dynamodb
         mocker.patch("pcluster.aws.dynamo.DynamoResource.put_item")
     elif scheduler == "awsbatch":
         mocker.patch(
             "pcluster.aws.batch.BatchClient.get_compute_environment_state",
             return_value=status)
         if status == "ENABLED":
             mocker.patch(
                 "pcluster.aws.batch.BatchClient.enable_compute_environment"
             )
         elif status == "DISABLED":
             mocker.patch(
                 "pcluster.aws.batch.BatchClient.disable_compute_environment"
             )
     response = self._send_test_request(client,
                                        request_body={"status": status})
     with soft_assertions():
         assert_that(response.status_code).is_equal_to(200)
         expected_response = {"status": status}
         if last_status_updated_time:
             expected_response["lastStatusUpdatedTime"] = to_iso_timestr(
                 to_utc_datetime(last_status_updated_time))
         assert_that(response.get_json()).is_equal_to(expected_response)
    def test_describe_image_in_failed_state_with_reasons_and_associated_imagebuilder_image(
            self, client, mocker):
        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",
            return_value=_create_stack("image1",
                                       CloudFormationStackStatus.CREATE_FAILED,
                                       "cfn test reason"),
        )
        mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack_resource",
                     return_value=None)
        mocker.patch(
            "pcluster.aws.cfn.CfnClient.describe_stack_resource",
            return_value={
                "StackResourceDetail": {
                    "PhysicalResourceId": "test_id"
                }
            },
        )
        mocker.patch(
            "pcluster.aws.imagebuilder.ImageBuilderClient.get_image_state",
            return_value={
                "status": ImageBuilderImageStatus.FAILED,
                "reason": "img test reason"
            },
        )
        mocker.patch(
            "pcluster.api.controllers.image_operations_controller._presigned_config_url",
            return_value="https://parallelcluster.aws.com/bucket/key",
        )

        expected_response = {
            "cloudformationStackArn":
            "arn:image1",
            "imageBuildLogsArn":
            "arn:image1:build_log",
            "cloudformationStackCreationTime":
            to_iso_timestr(to_utc_datetime("2021-04-12 00:00:00")),
            "cloudformationStackTags": [
                {
                    "key": "parallelcluster:image_id",
                    "value": "image1"
                },
                {
                    "key": "parallelcluster:version",
                    "value": "3.0.0"
                },
                {
                    "key": "parallelcluster:build_config",
                    "value": "s3://bucket/key"
                },
                {
                    "key": "parallelcluster:build_log",
                    "value": "arn:image1:build_log"
                },
            ],
            "cloudformationStackStatus":
            CloudFormationStackStatus.CREATE_FAILED,
            "cloudformationStackStatusReason":
            "cfn test reason",
            "imageBuildStatus":
            ImageBuildStatus.BUILD_FAILED,
            "imageConfiguration": {
                "url": "https://parallelcluster.aws.com/bucket/key"
            },
            "imageId":
            "image1",
            "imagebuilderImageStatus":
            ImageBuilderImageStatus.FAILED,
            "imagebuilderImageStatusReason":
            "img test reason",
            "region":
            "us-east-1",
            "version":
            "3.0.0",
        }

        response = self._send_test_request(client, "image1")

        with soft_assertions():
            assert_that(response.status_code).is_equal_to(200)
            assert_that(response.get_json()).is_equal_to(expected_response)
    def test_describe_of_image_not_yet_available_with_no_associated_imagebuilder_image(
            self, client, mocker):
        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",
            return_value=_create_stack(
                "image1", CloudFormationStackStatus.CREATE_IN_PROGRESS),
        )
        mocker.patch("pcluster.aws.cfn.CfnClient.describe_stack_resource",
                     return_value=None)
        mocker.patch(
            "pcluster.api.controllers.image_operations_controller._presigned_config_url",
            return_value="https://parallelcluster.aws.com/bucket/key",
        )

        expected_response = {
            "imageConfiguration": {
                "url": "https://parallelcluster.aws.com/bucket/key"
            },
            "imageId":
            "image1",
            "imageBuildStatus":
            ImageBuildStatus.BUILD_IN_PROGRESS,
            "cloudformationStackStatus":
            CloudFormationStackStatus.CREATE_IN_PROGRESS,
            "cloudformationStackArn":
            "arn:image1",
            "imageBuildLogsArn":
            "arn:image1:build_log",
            "cloudformationStackCreationTime":
            to_iso_timestr(datetime(2021, 4, 12)),
            "cloudformationStackTags": [
                {
                    "key": "parallelcluster:image_id",
                    "value": "image1"
                },
                {
                    "key": "parallelcluster:version",
                    "value": "3.0.0"
                },
                {
                    "key": "parallelcluster:build_config",
                    "value": "s3://bucket/key"
                },
                {
                    "key": "parallelcluster:build_log",
                    "value": "arn:image1:build_log"
                },
            ],
            "region":
            "us-east-1",
            "version":
            "3.0.0",
        }

        response = self._send_test_request(client, "image1")

        with soft_assertions():
            assert_that(response.status_code).is_equal_to(200)
            assert_that(response.get_json()).is_equal_to(expected_response)
    def test_execute(self, mocker, set_env, args):
        logs = LogStreams()
        logs.log_streams = [
            {
                "logStreamName":
                "ip-10-0-0-102.i-0717e670ad2549e72.cfn-init",
                "creationTime":
                1622802842228,
                "firstEventTimestamp":
                1622802790248,
                "lastEventTimestamp":
                1622802893126,
                "lastIngestionTime":
                1622802903119,
                "uploadSequenceToken":
                "4961...",
                "arn":
                ("arn:aws:logs:eu-west-1:111:log-group:/aws/parallelcluster/"
                 "test22-202106041223:log-stream:ip-10-0-0-102.i-0717e670ad2549e72.cfn-init"
                 ),
                "storedBytes":
                0,
            },
            {
                "logStreamName":
                "ip-10-0-0-102.i-0717e670ad2549e72.chef-client",
                "creationTime":
                1622802842207,
                "firstEventTimestamp":
                1622802837114,
                "lastEventTimestamp":
                1622802861226,
                "lastIngestionTime":
                1622802897558,
                "uploadSequenceToken":
                "4962...",
                "arn":
                ("arn:aws:logs:eu-west-1:111:log-group:/aws/parallelcluster/"
                 "test22-202106041223:log-stream:ip-10-0-0-102.i-0717e670ad2549e72.chef-client"
                 ),
                "storedBytes":
                0,
            },
        ]

        logs.next_token = "123-456"

        list_log_streams_mock = mocker.patch(
            "pcluster.api.controllers.image_logs_controller.ImageBuilder.list_log_streams",
            return_value=logs)
        set_env("AWS_DEFAULT_REGION", "us-east-1")

        base_args = ["list-image-log-streams"]
        command = base_args + self._build_cli_args({**REQUIRED_ARGS, **args})

        out = run(command)
        # cfn stack events are not displayed if next-token is passed
        expected_out = [
            {
                "logStreamName":
                "ip-10-0-0-102.i-0717e670ad2549e72.cfn-init",
                "firstEventTimestamp":
                to_iso_timestr(to_utc_datetime(1622802790248)),
                "lastEventTimestamp":
                to_iso_timestr(to_utc_datetime(1622802893126)),
            },
            {
                "logStreamName":
                "ip-10-0-0-102.i-0717e670ad2549e72.chef-client",
                "firstEventTimestamp":
                to_iso_timestr(to_utc_datetime(1622802837114)),
                "lastEventTimestamp":
                to_iso_timestr(to_utc_datetime(1622802861226)),
            },
        ]
        assert_that(out["nextToken"]).is_equal_to(logs.next_token)
        for i in range(len(logs.log_streams)):
            select_keys = {
                "logStreamName", "firstEventTimestamp", "lastEventTimestamp"
            }
            out_select = {
                k: v
                for k, v in out["logStreams"][i].items() if k in select_keys
            }
            assert_that(out_select).is_equal_to(expected_out[i])
        assert_that(list_log_streams_mock.call_args).is_length(2)

        # verify arguments
        kwargs = {"next_token": None}
        kwargs.update(args)
        list_log_streams_mock.assert_called_with(**kwargs)
 def convert_event(event):
     event = {k[0].lower() + k[1:]: v for k, v in event.items()}
     event["timestamp"] = to_iso_timestr(to_utc_datetime(
         event["timestamp"]))
     return StackEvent.from_dict(event)
 def convert_log_event(event):
     del event["ingestionTime"]
     event["timestamp"] = to_iso_timestr(to_utc_datetime(
         event["timestamp"]))
     return LogEvent.from_dict(event)