def test_single_array_job(self, args, expected, capsys, boto3_stubber, test_datadir, shared_datadir): response_parent = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_single_array_job.json") ) response_children = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_single_array_job_children.json") ) boto3_stubber( "batch", [ MockedBoto3Request( method="describe_jobs", response=response_parent, expected_params={"jobs": ["3286a19c-68a9-47c9-8000-427d23ffc7ca"]}, ), MockedBoto3Request( method="describe_jobs", response=response_children, expected_params={ "jobs": ["3286a19c-68a9-47c9-8000-427d23ffc7ca:0", "3286a19c-68a9-47c9-8000-427d23ffc7ca:1"] }, ), ], ) awsbstat.main(["-c", "cluster"] + args) assert capsys.readouterr().out == read_text(test_datadir / expected)
def test_verify_stack_status_retry(self, boto3_stubber, mocker): sleep_mock = mocker.patch("pcluster.aws.common.time.sleep") mocker.patch( "pcluster.aws.cfn.CfnClient.describe_stack", side_effect=[{ "StackStatus": "CREATE_IN_PROGRESS" }, { "StackStatus": "CREATE_FAILED" }], ) mocked_requests = [ MockedBoto3Request( method="describe_stack_events", response="Error", expected_params={"StackName": FAKE_NAME}, generate_error=True, error_code="Throttling", ), MockedBoto3Request( method="describe_stack_events", response={"StackEvents": [_generate_stack_event()]}, expected_params={"StackName": FAKE_NAME}, ), ] boto3_stubber("cloudformation", mocked_requests) verified = utils.verify_stack_status(FAKE_NAME, ["CREATE_IN_PROGRESS"], "CREATE_COMPLETE") assert_that(verified).is_false() sleep_mock.assert_called_with(5)
def test_get_stack_retry(self, boto3_stubber, mocker): sleep_mock = mocker.patch("pcluster.aws.common.time.sleep") expected_stack = { "StackName": FAKE_NAME, "CreationTime": 0, "StackStatus": "CREATED" } mocked_requests = [ MockedBoto3Request( method="describe_stacks", response="Error", expected_params={"StackName": FAKE_NAME}, generate_error=True, error_code="Throttling", ), MockedBoto3Request( method="describe_stacks", response={"Stacks": [expected_stack]}, expected_params={"StackName": FAKE_NAME}, ), ] boto3_stubber("cloudformation", mocked_requests) stack = CfnClient().describe_stack(FAKE_NAME) assert_that(stack).is_equal_to(expected_stack) sleep_mock.assert_called_with(5)
def test_single_mnp_job(self, args, expected, capsys, boto3_stubber, test_datadir, shared_datadir): response_parent = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_single_mnp_job.json") ) response_children = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_single_mnp_job_children.json") ) boto3_stubber( "batch", [ MockedBoto3Request( method="describe_jobs", response=response_parent, expected_params={"jobs": ["6abf3ecd-07a8-4faa-8a65-79e7404eb50f"]}, ), MockedBoto3Request( method="describe_jobs", response=response_children, expected_params={ "jobs": ["6abf3ecd-07a8-4faa-8a65-79e7404eb50f#0", "6abf3ecd-07a8-4faa-8a65-79e7404eb50f#1"] }, ), ], ) awsbstat.main(["-c", "cluster"] + args) assert capsys.readouterr().out == read_text(test_datadir / expected)
def test_retry_on_boto3_throttling(boto3_stubber, mocker): @AWSExceptionHandler.retry_on_boto3_throttling def describe_stack_resources(client): client.describe_stack_resources(StackName=FAKE_NAME) sleep_mock = mocker.patch("pcluster.utils.time.sleep") mocked_requests = [ MockedBoto3Request( method="describe_stack_resources", response="Error", expected_params={"StackName": FAKE_NAME}, generate_error=True, error_code="Throttling", ), MockedBoto3Request( method="describe_stack_resources", response="Error", expected_params={"StackName": FAKE_NAME}, generate_error=True, error_code="Throttling", ), MockedBoto3Request(method="describe_stack_resources", response={}, expected_params={"StackName": FAKE_NAME}), ] client = boto3_stubber("cloudformation", mocked_requests) describe_stack_resources(client) sleep_mock.assert_called_with(5)
def test_default_ordering_by_id(self, args, expected, capsys, boto3_stubber, test_datadir, shared_datadir): parent_jobs_response = {"jobs": []} for file in [ "batch_describe-jobs_single_mnp_job.json", "batch_describe-jobs_single_array_job.json", "batch_describe-jobs_single_job.json", ]: parent_jobs_response["jobs"].extend( json.loads(read_text(shared_datadir / "aws_api_responses/{0}".format(file)))["jobs"] ) children_jobs_response = {"jobs": []} for file in [ "batch_describe-jobs_single_mnp_job_children.json", "batch_describe-jobs_single_array_job_children.json", ]: children_jobs_response["jobs"].extend( json.loads(read_text(shared_datadir / "aws_api_responses/{0}".format(file)))["jobs"] ) boto3_stubber( "batch", [ MockedBoto3Request( method="describe_jobs", response=parent_jobs_response, expected_params={ "jobs": [ "3286a19c-68a9-47c9-8000-427d23ffc7ca", "ab2cd019-1d84-43c7-a016-9772dd963f3b", "6abf3ecd-07a8-4faa-8a65-79e7404eb50f", ] }, ), MockedBoto3Request( method="describe_jobs", response=children_jobs_response, expected_params={ "jobs": [ "6abf3ecd-07a8-4faa-8a65-79e7404eb50f#0", "6abf3ecd-07a8-4faa-8a65-79e7404eb50f#1", "3286a19c-68a9-47c9-8000-427d23ffc7ca:0", "3286a19c-68a9-47c9-8000-427d23ffc7ca:1", ] }, ), ], ) awsbstat.main(["-c", "cluster"] + args) assert capsys.readouterr().out == read_text(test_datadir / expected)
def test_all_status_detailed(self, capsys, boto3_stubber, test_datadir, shared_datadir): mocked_requests = [] jobs_ids = [] describe_jobs_response = {"jobs": []} for status in ALL_JOB_STATUS: list_jobs_response = json.loads( read_text(shared_datadir / "aws_api_responses/batch_list-jobs_{0}.json".format(status)) ) describe_jobs_response["jobs"].extend( json.loads(read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_{0}.json".format(status)))[ "jobs" ] ) jobs_ids.extend([job["jobId"] for job in list_jobs_response["jobSummaryList"]]) mocked_requests.append( MockedBoto3Request( method="list_jobs", response=list_jobs_response, expected_params={ "jobQueue": DEFAULT_AWSBATCHCLICONFIG_MOCK_CONFIG["job_queue"], "jobStatus": status, "nextToken": "", }, ) ) mocked_requests.append( MockedBoto3Request( method="describe_jobs", response=describe_jobs_response, expected_params={"jobs": jobs_ids} ) ) boto3_stubber("batch", mocked_requests) awsbstat.main(["-c", "cluster", "-s", "ALL", "-d"]) # describe-jobs api validation made by the Stubber requires startedAt to be always present. # Removing it from output when value is default (1970-01-01T00:00:00+00:00) since this is the # behavior for not stubbed calls. output = capsys.readouterr().out.replace("1970-01-01T00:00:00+00:00", "-") expcted_jobs_count_by_status = { "SUBMITTED": 2, "PENDING": 1, "RUNNABLE": 2, "STARTING": 2, "RUNNING": 2, "SUCCEEDED": 3, "FAILED": 3, } for status, count in expcted_jobs_count_by_status.items(): assert output.count(status) == count assert output.count("jobId") == 15 assert output == read_text(test_datadir / "expected_output.txt")
def test_get_default_instance(boto3_stubber, region, free_tier_instance_type, default_instance_type, stub_boto3): os_lib.environ["AWS_DEFAULT_REGION"] = region if free_tier_instance_type: response = { "InstanceTypes": [{ "InstanceType": free_tier_instance_type }] } else: response = {"InstanceTypes": []} if stub_boto3: mocked_requests = [ MockedBoto3Request( method="describe_instance_types", response=response, expected_params={ "Filters": [ { "Name": "free-tier-eligible", "Values": ["true"] }, { "Name": "current-generation", "Values": ["true"] }, ] }, ) ] boto3_stubber("ec2", mocked_requests) assert_that(Ec2Client().get_default_instance_type()).is_equal_to( default_instance_type)
def test_get_imagebuilder_stacks(self, set_env, boto3_stubber, next_token, describe_stacks_response, expected_stacks): set_env("AWS_DEFAULT_REGION", "us-east-1") expected_describe_stacks_params = {} if not next_token else { "NextToken": next_token } generate_error = isinstance(describe_stacks_response, Exception) mocked_requests = [ MockedBoto3Request( method="describe_stacks", response=describe_stacks_response if not generate_error else "error", expected_params=expected_describe_stacks_params, generate_error=generate_error, error_code="error" if generate_error else None, ) ] boto3_stubber("cloudformation", mocked_requests) if not generate_error: stacks, next_token = CfnClient().get_imagebuilder_stacks( next_token=next_token) assert_that(next_token).is_equal_to( describe_stacks_response.get("NextToken")) assert_that({s["StackName"] for s in stacks}).is_equal_to(expected_stacks) else: with pytest.raises(AWSClientError) as e: CfnClient().list_pcluster_stacks(next_token=next_token) assert_that(e.value.error_code).is_equal_to("error")
def test_get_instance_profile(boto3_stubber): os_lib.environ["AWS_DEFAULT_REGION"] = "us-east-1" instance_profile_name = "mocked_instance_profile_name" response = { "InstanceProfile": { "InstanceProfileName": instance_profile_name, "Path": "/", "InstanceProfileId": "SomeIdOfLengthAtLeastSixteen", "Arn": f"arn:aws:iam:::instance-profile/{instance_profile_name}", "CreateDate": "2021-07-28", "Roles": [ { "Arn": f"arn:aws:iam:::role/{instance_profile_name}", "Path": "/", "RoleName": instance_profile_name, "RoleId": "AnotherIdOfLengthAtLeastSixteen", "CreateDate": "2021-07-28", } ], } } mocked_requests = [ MockedBoto3Request( method="get_instance_profile", response=response, expected_params={"InstanceProfileName": instance_profile_name}, ) ] boto3_stubber("iam", mocked_requests) assert_that(IamClient().get_instance_profile(instance_profile_name)).is_equal_to(response)
def test_get_ebs_snapshot_info(boto3_stubber, snapshot_id, error_message): """Verify that get_snapshot_info makes the expected API call.""" response = { "Description": "This is my snapshot", "Encrypted": False, "VolumeId": "vol-049df61146c4d7901", "State": "completed", "VolumeSize": 120, "StartTime": "2014-02-28T21:28:32.000Z", "Progress": "100%", "OwnerId": "012345678910", "SnapshotId": "snap-1234567890abcdef0", } describe_snapshots_response = {"Snapshots": [response]} mocked_requests = [ MockedBoto3Request( method="describe_snapshots", response=describe_snapshots_response if error_message is None else error_message, expected_params={"SnapshotIds": ["snap-1234567890abcdef0"]}, generate_error=error_message is not None, ) ] boto3_stubber("ec2", mocked_requests) if error_message is None: assert_that(Ec2Client().get_ebs_snapshot_info( snapshot_id)).is_equal_to(response) elif error_message: with pytest.raises(AWSClientError, match=error_message) as clienterror: Ec2Client().get_ebs_snapshot_info(snapshot_id) assert_that(clienterror.value.code).is_not_equal_to(0)
def test_get_cce_emsg_containing_supported_instance_types_client_error( boto3_stubber): """Verify CreateComputeEnvironment call to get error message with supported instance types behaves as expected.""" dummy_error_message = "dummy message" mocked_requests = [ MockedBoto3Request( method="create_compute_environment", expected_params={ "computeEnvironmentName": "dummy", "type": "MANAGED", "computeResources": { "type": "EC2", "minvCpus": 0, "maxvCpus": 0, "instanceTypes": ["p8.84xlarge"], "subnets": ["subnet-12345"], "securityGroupIds": ["sg-12345"], "instanceRole": "ecsInstanceRole", }, "serviceRole": "AWSBatchServiceRole", }, response=dummy_error_message, generate_error=True, ) ] boto3_stubber("batch", mocked_requests) return_value = AWSApi.instance( ).batch._get_cce_emsg_containing_supported_instance_types() assert_that(return_value).is_equal_to(dummy_error_message)
def test_get_stack_events_retry(self, boto3_stubber, mocker): sleep_mock = mocker.patch("pcluster.aws.common.time.sleep") expected_events = [_generate_stack_event()] mocked_requests = [ MockedBoto3Request( method="describe_stack_events", response="Error", expected_params={"StackName": FAKE_NAME}, generate_error=True, error_code="Throttling", ), MockedBoto3Request( method="describe_stack_events", response={"StackEvents": expected_events}, expected_params={"StackName": FAKE_NAME}, ), ] boto3_stubber("cloudformation", mocked_requests) assert_that(CfnClient().get_stack_events(FAKE_NAME) ["StackEvents"]).is_equal_to(expected_events) sleep_mock.assert_called_with(5)
def test_single_job_detailed(self, capsys, boto3_stubber, test_datadir, shared_datadir): response = json.loads(read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_single_job.json")) boto3_stubber( "batch", MockedBoto3Request( method="describe_jobs", response=response, expected_params={"jobs": ["ab2cd019-1d84-43c7-a016-9772dd963f3b"]}, ), ) awsbstat.main(["-c", "cluster", "ab2cd019-1d84-43c7-a016-9772dd963f3b"]) assert capsys.readouterr().out == read_text(test_datadir / "expected_output.txt")
def _append_mocked_describe_sg_request(ip_perm, ip_perm_egress, sec_group): describe_security_groups_response = { "SecurityGroups": [{ "IpPermissionsEgress": ip_perm_egress, "Description": "My security group", "IpPermissions": ip_perm, "GroupName": "MySecurityGroup", "OwnerId": "123456789012", "GroupId": sec_group, }] } return MockedBoto3Request( method="describe_security_groups", response=describe_security_groups_response, expected_params={"GroupIds": [security_group]}, )
def test_succeeded_status(self, capsys, boto3_stubber, test_datadir, shared_datadir): response = json.loads(read_text(shared_datadir / "aws_api_responses/batch_list-jobs_SUCCEEDED.json")) boto3_stubber( "batch", MockedBoto3Request( method="list_jobs", response=response, expected_params={ "jobQueue": DEFAULT_AWSBATCHCLICONFIG_MOCK_CONFIG["job_queue"], "jobStatus": "SUCCEEDED", "nextToken": "", }, ), ) awsbstat.main(["-c", "cluster", "-s", "SUCCEEDED"]) assert capsys.readouterr().out == read_text(test_datadir / "expected_output.txt")
def test_run_instances_dryrun(boto3_stubber, error_code, raise_exception): """Verify that if run_instance doesn't generate exception if the error code is DryRunOperation.""" error_message = "fake error message" mocked_requests = [ MockedBoto3Request( method="run_instances", response=error_message, expected_params=None, generate_error=True, error_code=error_code, ) ] boto3_stubber("ec2", mocked_requests) kwargs = {"MaxCount": 10, "MinCount": 0, "DryRun": True} if raise_exception: with pytest.raises(AWSClientError, match=error_message) as clienterror: Ec2Client().run_instances(**kwargs) assert_that(clienterror.value.code).is_not_equal_to(0) else: Ec2Client().run_instances(**kwargs)
def test_no_jobs_all_status(self, capsys, boto3_stubber, test_datadir): empty_response = {"jobSummaryList": []} mocked_requests = [] for status in ALL_JOB_STATUS: mocked_requests.append( MockedBoto3Request( method="list_jobs", response=empty_response, expected_params={ "jobQueue": DEFAULT_AWSBATCHCLICONFIG_MOCK_CONFIG["job_queue"], "jobStatus": status, "nextToken": "", }, ) ) boto3_stubber("batch", mocked_requests) awsbstat.main(["-c", "cluster", "-s", "ALL"]) assert capsys.readouterr().out == read_text(test_datadir / "expected_output.txt")
def test_children_by_ids(self, args, expected, capsys, boto3_stubber, test_datadir, shared_datadir): boto3_stubber( "batch", MockedBoto3Request( method="describe_jobs", response=json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_children_jobs.json") ), expected_params={ "jobs": [ "3286a19c-68a9-47c9-8000-427d23ffc7ca:0", "ab2cd019-1d84-43c7-a016-9772dd963f3b", "6abf3ecd-07a8-4faa-8a65-79e7404eb50f#1", ] }, ), ) awsbstat.main(["-c", "cluster"] + args) assert capsys.readouterr().out == read_text(test_datadir / expected)
def test_all_status(self, capsys, boto3_stubber, test_datadir, shared_datadir): mocked_requests = [] for status in ALL_JOB_STATUS: response = json.loads( read_text(shared_datadir / "aws_api_responses/batch_list-jobs_{0}.json".format(status)) ) mocked_requests.append( MockedBoto3Request( method="list_jobs", response=response, expected_params={ "jobQueue": DEFAULT_AWSBATCHCLICONFIG_MOCK_CONFIG["job_queue"], "jobStatus": status, "nextToken": "", }, ) ) boto3_stubber("batch", mocked_requests) awsbstat.main(["-c", "cluster", "-s", "ALL"]) assert capsys.readouterr().out == read_text(test_datadir / "expected_output.txt")
def test_get_official_images(boto3_stubber, os, architecture, boto3_response, expected_response, error_message): filter_version = get_installed_version() filter_os = OS_TO_IMAGE_NAME_PART_MAP[os] if os else "*" filter_arch = architecture or "*" expected_params = { "Filters": [ { "Name": "name", "Values": [ f"aws-parallelcluster-{filter_version}-{filter_os}-{filter_arch}*" ] }, ], "ImageIds": [], "Owners": ["amazon"], } mocked_requests = [ MockedBoto3Request( method="describe_images", expected_params=expected_params, response=str(boto3_response) if isinstance(boto3_response, Exception) else boto3_response, generate_error=isinstance(boto3_response, Exception), ) ] boto3_stubber("ec2", mocked_requests) if error_message: with pytest.raises(AWSClientError, match=error_message): Ec2Client().get_official_images(os, architecture) else: response = Ec2Client().get_official_images(os, architecture) with soft_assertions(): assert_that(len(response)).is_equal_to(len(expected_response)) for i in range(len(response)): assert_that(response[i].name).is_equal_to( expected_response[i].name)
def test_get_policy(boto3_stubber): os_lib.environ["AWS_DEFAULT_REGION"] = "us-east-1" policy_name = "mocked_policy_name" policy_arn = f"arn:aws:iam:::policy/{policy_name}" response = { "Policy": { "PolicyName": policy_name, "Path": "/", "PolicyId": "SomeIdOfLengthAtLeastSixteen", "Arn": policy_arn, "CreateDate": "2021-07-28", } } mocked_requests = [ MockedBoto3Request( method="get_policy", response=response, expected_params={"PolicyArn": policy_arn}, ) ] boto3_stubber("iam", mocked_requests) assert_that(IamClient().get_policy(policy_arn)).is_equal_to(response)
def test_list_instance_types(boto3_stubber, generate_error): """Verify that list_instance_types behaves as expected.""" dummy_message = "dummy error message" dummy_instance_types = ["c5.xlarge", "m6g.xlarge"] mocked_requests = [ MockedBoto3Request( method="describe_instance_type_offerings", expected_params={}, response=dummy_message if generate_error else { "InstanceTypeOfferings": [{ "InstanceType": instance_type } for instance_type in dummy_instance_types] }, generate_error=generate_error, ) ] boto3_stubber("ec2", mocked_requests) if generate_error: with pytest.raises(AWSClientError, match=dummy_message): Ec2Client().list_instance_types() else: return_value = Ec2Client().list_instance_types() assert_that(return_value).is_equal_to(dummy_instance_types)
def test_get_official_image_id(boto3_stubber, os, architecture, filters, boto3_response, error_message): expected_ami_id = "ami-00e87074e52e6" expected_params = { "Filters": [ { "Name": "name", "Values": [ f"aws-parallelcluster-{get_installed_version()}-amzn2-hvm-{architecture}*" ] }, ], "Owners": [filters.owner if filters and filters.owner else "amazon"], } if filters and filters.tags: expected_params["Filters"].extend([{ "Name": f"tag:{tag.key}", "Values": [tag.value] } for tag in filters.tags]) mocked_requests = [ MockedBoto3Request( method="describe_images", expected_params=expected_params, response=str(boto3_response) if isinstance(boto3_response, Exception) else boto3_response, generate_error=isinstance(boto3_response, Exception), ) ] boto3_stubber("ec2", mocked_requests) if error_message: with pytest.raises(AWSClientError, match=error_message): Ec2Client().get_official_image_id(os, architecture, filters) else: ami_id = Ec2Client().get_official_image_id(os, architecture, filters) assert_that(ami_id).is_equal_to(expected_ami_id)
def test_expanded_children(self, capsys, boto3_stubber, test_datadir, shared_datadir): mocked_requests = [] # Mock all list-jobs requests for status in ALL_JOB_STATUS: list_jobs_response = json.loads( read_text(shared_datadir / "aws_api_responses/batch_list-jobs_{0}.json".format(status)) ) mocked_requests.append( MockedBoto3Request( method="list_jobs", response=list_jobs_response, expected_params={ "jobQueue": DEFAULT_AWSBATCHCLICONFIG_MOCK_CONFIG["job_queue"], "jobStatus": status, "nextToken": "", }, ) ) # Mock describe-jobs on parents describe_parent_jobs_response = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_ALL_parents.json") ) jobs_with_children_ids = [] for job in describe_parent_jobs_response["jobs"]: jobs_with_children_ids.append(job["jobId"]) mocked_requests.append( MockedBoto3Request( method="describe_jobs", response=describe_parent_jobs_response, expected_params={"jobs": jobs_with_children_ids}, ) ) # Mock describe-jobs on children describe_children_jobs_response = json.loads( read_text(shared_datadir / "aws_api_responses/batch_describe-jobs_ALL_children.json") ) mocked_requests.append( MockedBoto3Request( method="describe_jobs", response=describe_children_jobs_response, expected_params={ "jobs": [ "3c6ee190-9121-464e-a0ac-62e4084e6bf1#0", "3c6ee190-9121-464e-a0ac-62e4084e6bf1#1", "11aa9096-1e98-4a7c-a44b-5ac3442df177:0", "11aa9096-1e98-4a7c-a44b-5ac3442df177:1", "77712b12-71eb-4007-a865-85f05de13a71#0", "77712b12-71eb-4007-a865-85f05de13a71#1", "bbbbbcbc-2647-4d8b-a1ef-da65bffe0dd0#0", "bbbbbcbc-2647-4d8b-a1ef-da65bffe0dd0#1", "qwerfcbc-2647-4d8b-a1ef-da65bffe0dd0#0", "qwerfcbc-2647-4d8b-a1ef-da65bffe0dd0#1", "3286a19c-68a9-47c9-8000-427d23ffc7ca:0", "3286a19c-68a9-47c9-8000-427d23ffc7ca:1", "3ec00225-8b85-48ba-a321-f61d005bec46#0", "3ec00225-8b85-48ba-a321-f61d005bec46#1", "44db07a9-f8a2-48d9-8d67-dcb04ceca54c:0", "44db07a9-f8a2-48d9-8d67-dcb04ceca54c:1", "7a712b12-71eb-4007-a865-85f05de13a71#0", "7a712b12-71eb-4007-a865-85f05de13a71#1", ] }, ) ) boto3_stubber("batch", mocked_requests) awsbstat.main(["-c", "cluster", "-s", "ALL", "-e"]) # describe-jobs api validation made by the Stubber requires startedAt to be always present. # Removing it from output when value is default (1970-01-01T00:00:00+00:00) since this is the # behavior for not stubbed calls. output = capsys.readouterr().out.replace("1970-01-01T00:00:00+00:00", "- ") assert output == read_text(test_datadir / "expected_output.txt")
def test_fsx_network_validator(boto3_stubber, fsx_vpc, ip_permissions, network_interfaces, expected_message): describe_file_systems_response = { "FileSystems": [{ "VpcId": fsx_vpc, "NetworkInterfaceIds": network_interfaces, "SubnetIds": ["subnet-12345678"], "FileSystemType": "LUSTRE", "CreationTime": 1567636453.038, "ResourceARN": "arn:aws:fsx:us-west-2:111122223333:file-system/fs-0ff8da96d57f3b4e3", "StorageCapacity": 3600, "LustreConfiguration": { "WeeklyMaintenanceStartTime": "4:07:00" }, "FileSystemId": "fs-0ff8da96d57f3b4e3", "DNSName": "fs-0ff8da96d57f3b4e3.fsx.us-west-2.amazonaws.com", "OwnerId": "059623208481", "Lifecycle": "AVAILABLE", }] } fsx_mocked_requests = [ MockedBoto3Request( method="describe_file_systems", response=describe_file_systems_response, expected_params={"FileSystemIds": ["fs-0ff8da96d57f3b4e3"]}, ) ] boto3_stubber("fsx", fsx_mocked_requests) describe_subnets_response = { "Subnets": [{ "AvailabilityZone": "us-east-2c", "AvailabilityZoneId": "use2-az3", "AvailableIpAddressCount": 248, "CidrBlock": "10.0.1.0/24", "DefaultForAz": False, "MapPublicIpOnLaunch": False, "State": "available", "SubnetId": "subnet-12345678", "VpcId": "vpc-06e4ab6c6cEXAMPLE", "OwnerId": "111122223333", "AssignIpv6AddressOnCreation": False, "Ipv6CidrBlockAssociationSet": [], "Tags": [{ "Key": "Name", "Value": "MySubnet" }], "SubnetArn": "arn:aws:ec2:us-east-2:111122223333:subnet/subnet-12345678", }] } ec2_mocked_requests = [ MockedBoto3Request( method="describe_subnets", response=describe_subnets_response, expected_params={"SubnetIds": ["subnet-12345678"]}, ) ] if network_interfaces: network_interfaces_in_response = [] for network_interface in network_interfaces: network_interfaces_in_response.append({ "Association": { "AllocationId": "eipalloc-01564b674a1a88a47", "AssociationId": "eipassoc-02726ee370e175cea", "IpOwnerId": "111122223333", "PublicDnsName": "ec2-34-248-114-123.eu-west-1.compute.amazonaws.com", "PublicIp": "34.248.114.123", }, "Attachment": { "AttachmentId": "ela-attach-0cf98331", "DeleteOnTermination": False, "DeviceIndex": 1, "InstanceOwnerId": "amazon-aws", "Status": "attached", }, "AvailabilityZone": "eu-west-1a", "Description": "Interface for NAT Gateway nat-0a8b0e0d28266841f", "Groups": [{ "GroupName": "default", "GroupId": "sg-12345678" }], "InterfaceType": "nat_gateway", "Ipv6Addresses": [], "MacAddress": "0a:e5:8a:82:fd:24", "NetworkInterfaceId": network_interface, "OwnerId": "111122223333", "PrivateDnsName": "ip-10-0-124-85.eu-west-1.compute.internal", "PrivateIpAddress": "10.0.124.85", "PrivateIpAddresses": [{ "Association": { "AllocationId": "eipalloc-01564b674a1a88a47", "AssociationId": "eipassoc-02726ee370e175cea", "IpOwnerId": "111122223333", "PublicDnsName": "ec2-34-248-114-123.eu-west-1.compute.amazonaws.com", "PublicIp": "34.248.114.123", }, "Primary": True, "PrivateDnsName": "ip-10-0-124-85.eu-west-1.compute.internal", "PrivateIpAddress": "10.0.124.85", }], "RequesterId": "036872051663", "RequesterManaged": True, "SourceDestCheck": False, "Status": "in-use", "SubnetId": "subnet-12345678", "TagSet": [], "VpcId": fsx_vpc, }) describe_network_interfaces_response = { "NetworkInterfaces": network_interfaces_in_response } ec2_mocked_requests.append( MockedBoto3Request( method="describe_network_interfaces", response=describe_network_interfaces_response, expected_params={"NetworkInterfaceIds": network_interfaces}, )) if fsx_vpc == "vpc-06e4ab6c6cEXAMPLE": # the describe security group is performed only if the VPC of the network interface is the same of the FSX describe_security_groups_response = { "SecurityGroups": [{ "IpPermissionsEgress": ip_permissions, "Description": "My security group", "IpPermissions": ip_permissions, "GroupName": "MySecurityGroup", "OwnerId": "123456789012", "GroupId": "sg-12345678", }] } ec2_mocked_requests.append( MockedBoto3Request( method="describe_security_groups", response=describe_security_groups_response, expected_params={"GroupIds": ["sg-12345678"]}, )) boto3_stubber("ec2", ec2_mocked_requests) actual_failures = FsxNetworkingValidator().execute("fs-0ff8da96d57f3b4e3", "subnet-12345678") assert_failure_messages(actual_failures, expected_message)