Пример #1
0
    def test_tar_file_exists_in_specified_bin_dir___correct_file_is_posted(
            self):
        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            bin_dir = os.path.join(d, 'alt_bin_dir')
            os.mkdir(bin_dir)
            Path(os.path.join(bin_dir, TAR_FILE)).touch()

            rsps.add(responses.POST,
                     url='http://localhost:8001/exposure',
                     body=json.dumps({
                         'exposures': [{
                             'location': 'exposure_location'
                         }]
                     }).encode())

            client = OasisAPIClient('http://localhost:8001')
            client.upload_inputs_from_directory(d, bin_directory=bin_dir)

            self.assertEqual(1, len(rsps.calls))

            request = rsps.calls[0].request
            self.assertEqual(request.url, 'http://localhost:8001/exposure')

            multipart_data = request.body.fields['file']
            self.assertEqual('inputs.tar.gz', multipart_data[0])
            self.assertEqual(os.path.join(bin_dir, TAR_FILE),
                             multipart_data[1].name)
            self.assertEqual('text/plain', multipart_data[2])
Пример #2
0
    def test_request_response_is_ok___response_location_is_returned(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(responses.POST, 'http://localhost:8001/analysis/foo', status=200, body=b'{"location": "output-location"}')

            self.assertEqual('output-location', client.run_analysis({'analysis': 'data'}, 'foo'))
Пример #3
0
    def test_no_errors_are_raised___completed_is_incremented(
            self, input_dir, output_dir, settings, do_il, do_ri,
            initial_complete, initial_failed):
        client = OasisAPIClient('http://localhost:8001')
        client.upload_inputs_from_directory = Mock(
            return_value='input_location')
        client.run_analysis_and_poll = Mock()

        counter = Counter({
            'completed': initial_complete,
            'failed': initial_failed,
        })

        TestModelApiCmd().run_analysis(
            (client, input_dir, output_dir, settings, do_il, do_ri, counter,
             [], 1))

        self.assertEqual(initial_complete + 1, counter['completed'])
        self.assertEqual(initial_failed, counter['failed'])
        client.upload_inputs_from_directory.assert_called_once_with(
            input_dir,
            bin_directory=ANY,
            do_il=do_il,
            do_ri=do_ri,
            do_build=True)
        client.run_analysis_and_poll.assert_called_once_with(
            settings, 'input_location', output_dir)
Пример #4
0
    def test_delete_resource_is_called_with_the_correct_parameters(self):
        client = OasisAPIClient('http://localhost:8001')
        client.delete_resource = Mock()

        client.delete_exposure('foo')

        client.delete_resource.assert_called_once_with('/exposure/foo')
Пример #5
0
    def test_response_is_ok___file_is_created_with_correct_content(self):
        client = OasisAPIClient('http://localhost:8001')
        client.DOWNLOAD_CHUCK_SIZE_IN_BYTES = 10

        expected_content = ''.join(
            choice(string.ascii_letters)
            for i in range(2 * client.DOWNLOAD_CHUCK_SIZE_IN_BYTES)).encode()

        with NamedTemporaryFile('w') as f:
            local_filename = f.name

        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET,
                     'http://localhost:8001/foo',
                     status=200,
                     body=expected_content)

            client.download_resource('foo', local_filename)

            self.assertTrue(os.path.exists(local_filename))

            with io.open(local_filename, 'rb') as f:
                dld_content = f.read()

            os.remove(local_filename)
            self.assertEqual(expected_content, dld_content)
Пример #6
0
    def test_download_resource_is_called_with_the_correct_parameters(self):
        client = OasisAPIClient('http://localhost:8001')
        client.download_resource = Mock()

        client.download_outputs('foo', 'local_filename')

        client.download_resource.assert_called_once_with('/outputs/foo', 'local_filename')
Пример #7
0
    def test_do_build_is_truebin_dir_is_supplied___bin_building_functions_are_called_with_correct_args(
            self, check_mock, check_tools_mock, create_bin_mock,
            create_tar_mock):
        create_tar_mock.side_effect = fake_build_tar_fn

        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            bin_dir = os.path.join(d, 'alt_bin_dir')
            os.mkdir(bin_dir)

            rsps.add(responses.POST,
                     url='http://localhost:8001/exposure',
                     body=json.dumps({
                         'exposures': [{
                             'location': 'exposure_location'
                         }]
                     }).encode())

            client = OasisAPIClient('http://localhost:8001')
            client.upload_inputs_from_directory(d,
                                                bin_directory=bin_dir,
                                                do_build=True)

            check_mock.assert_called_once_with(d, do_il=False)
            check_tools_mock.assert_called_once_with(do_il=False)
            create_bin_mock.assert_called_once_with(d, bin_dir, do_il=False)
            create_tar_mock.assert_called_once_with(bin_dir)
Пример #8
0
    def test_request_is_not_ok___exception_is_raised(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET, 'http://localhost:8001/analysis_status/foo', status=400)

            with self.assertRaises(OasisException):
                client.get_analysis_status('foo')
Пример #9
0
    def test_response_is_ok___info_is_logged(self):
        client = OasisAPIClient('http://localhost:8001', Mock())

        with responses.RequestsMock() as rsps:
            rsps.add(responses.DELETE, 'http://localhost:8001/foo', status=200)

            client.delete_resource('foo')

            client._logger.info.assert_called_with('Deleted http://localhost:8001/foo')
Пример #10
0
    def test_response_is_not_ok___warning_is_logged(self):
        client = OasisAPIClient('http://localhost:8001', Mock())

        with responses.RequestsMock() as rsps:
            rsps.add(responses.DELETE, 'http://localhost:8001/foo', status=400)

            client.delete_resource('foo')

            client._logger.warning.assert_called_with("DELETE http://localhost:8001/foo failed: 400")
Пример #11
0
    def test_tar_file_exists___exposure_location_from_result_is_returned(self):
        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            Path(os.path.join(d, TAR_FILE)).touch()

            rsps.add(responses.POST, url='http://localhost:8001/exposure', body=json.dumps({'exposures': [{'location': 'exposure_location'}]}).encode())

            client = OasisAPIClient('http://localhost:8001')
            result = client.upload_inputs_from_directory(d)

            self.assertEqual('exposure_location', result)
Пример #12
0
    def test_do_clean_is_true___clean_bin_directory_is_called_on_the_correct_directory(self, clean_mock):
        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            Path(os.path.join(d, TAR_FILE)).touch()

            rsps.add(responses.POST, url='http://localhost:8001/exposure', body=json.dumps({'exposures': [{'location': 'exposure_location'}]}).encode())

            client = OasisAPIClient('http://localhost:8001')
            client.upload_inputs_from_directory(d, do_clean=True)

            clean_mock.assert_called_once_with(d)
Пример #13
0
    def test_response_from_server_is_not_ok___oasis_error_is_raised(self):
        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            Path(os.path.join(d, TAR_FILE)).touch()

            rsps.add(responses.POST, status=400, url='http://localhost:8001/exposure', body=json.dumps({'exposures': [{'location': 'exposure_location'}]}).encode())

            client = OasisAPIClient('http://localhost:8001')

            with self.assertRaises(OasisException):
                client.upload_inputs_from_directory(d)
Пример #14
0
    def test_heath_check_returns_200___result_is_true(self):
        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET, 'http://localhost:8001/healthcheck', status=200)

            client = OasisAPIClient('http://localhost:8001')

            result = client.health_check()

            self.assertTrue(result)
            self.assertEqual(1, len(rsps.calls))
            self.assertEqual('http://localhost:8001/healthcheck', rsps.calls[0].request.url)
Пример #15
0
    def test_local_file_already_exists___exception_is_raised_and_file_is_unchanged(self):
        client = OasisAPIClient('http://localhost:8001')

        with NamedTemporaryFile('w+') as f:
            f.write('foobarboo')
            f.flush()

            with self.assertRaises(OasisException):
                client.download_resource('foo', f.name)

            f.seek(0)
            self.assertEqual('foobarboo', f.read())
Пример #16
0
    def test_request_response_is_not_ok___exception_is_raised(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(responses.POST, 'http://localhost:8001/analysis/foo', status=400)

            with self.assertRaises(OasisException):
                client.run_analysis({'analysis': 'data'}, 'foo')

            self.assertEqual(1, len(rsps.calls))
            self.assertEqual('http://localhost:8001/analysis/foo', rsps.calls[0].request.url)
            self.assertEqual({'analysis': 'data'}, json.loads(rsps.calls[0].request.body.decode()))
Пример #17
0
    def test_do_build_is_false___bin_building_functions_are_not_called(self, check_mock, check_tools_mock, create_bin_mock, create_tar_mock):
        with TemporaryDirectory() as d, responses.RequestsMock() as rsps:
            Path(os.path.join(d, TAR_FILE)).touch()
            rsps.add(responses.POST, url='http://localhost:8001/exposure', body=json.dumps({'exposures': [{'location': 'exposure_location'}]}).encode())

            client = OasisAPIClient('http://localhost:8001')
            client.upload_inputs_from_directory(d, do_build=False)

            check_mock.assert_not_called()
            check_tools_mock.assert_not_called()
            create_bin_mock.assert_not_called()
            create_tar_mock.assert_not_called()
Пример #18
0
    def test_request_status_is_failure___exception_is_raised(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                'http://localhost:8001/analysis_status/foo',
                status=200,
                body=json.dumps({'status': STATUS_FAILURE, 'message': 'oops'}).encode()
            )

            with self.assertRaises(OasisException):
                client.get_analysis_status('foo')
Пример #19
0
    def test_response_is_not_ok___exception_is_raised_and_file_is_not_created(self):
        client = OasisAPIClient('http://localhost:8001')

        with NamedTemporaryFile('w') as f:
            local_filename = f.name

        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET, 'http://localhost:8001/foo', status=400)

            with self.assertRaises(OasisException):
                client.download_resource('foo', local_filename)

            self.assertFalse(os.path.exists(local_filename))
Пример #20
0
    def test_heath_check_raise_an_exception_on_each_call___result_is_false(self, max_attempts):
        with patch('requests.get', Mock(side_effect=RequestException())) as get_mock:
            client = OasisAPIClient('http://localhost:8001')

            result = client.health_check(max_attempts, retry_delay=0)

            self.assertFalse(result)
            self.assertEqual(max_attempts, get_mock.call_count)
            call_urls = [args[0] for args in get_mock.call_args_list]
            self.assertEqual(
                [('http://localhost:8001/healthcheck',) for i in range(max_attempts)],
                call_urls,
            )
Пример #21
0
    def test_heath_check_returns_non_200_on_each_call___result_is_false(self, max_attempts):
        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET, 'http://localhost:8001/healthcheck', status=404)

            client = OasisAPIClient('http://localhost:8001')

            result = client.health_check(max_attempts, retry_delay=0)

            self.assertFalse(result)
            self.assertEqual(max_attempts, len(rsps.calls))
            self.assertEqual(
                ['http://localhost:8001/healthcheck' for i in range(max_attempts)],
                [call.request.url for call in rsps.calls],
            )
Пример #22
0
    def test_run_and_poll_raises_an_error___failed_counter_is_incremented(self, input_dir, output_dir, settings, do_il, initial_complete, initial_failed):
        client = OasisAPIClient('http://localhost:8001')
        client.upload_inputs_from_directory = Mock()
        client.run_analysis_and_poll = Mock(side_effect=OasisException())

        counter = Counter({
            'completed': initial_complete,
            'failed': initial_failed,
        })

        TestModelApiCmd().run_analysis((client, input_dir, output_dir, settings, do_il, counter))

        self.assertEqual(initial_complete, counter['completed'])
        self.assertEqual(initial_failed + 1, counter['failed'])
Пример #23
0
    def test_request_status_is_pending___result_status_is_pending_location_is_empty(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                'http://localhost:8001/analysis_status/foo',
                status=200,
                body=json.dumps({'status': STATUS_PENDING}).encode()
            )

            status, outputs_location = client.get_analysis_status('foo')

            self.assertEqual(status, STATUS_PENDING)
            self.assertEqual(outputs_location, '')
Пример #24
0
    def test_request_status_is_success___result_status_is_success_location_is_from_response_body(self):
        client = OasisAPIClient('http://localhost:8001')

        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                'http://localhost:8001/analysis_status/foo',
                status=200,
                body=json.dumps({'status': STATUS_SUCCESS, 'outputs_location': 'outputs-location'}).encode()
            )

            status, outputs_location = client.get_analysis_status('foo')

            self.assertEqual(status, STATUS_SUCCESS)
            self.assertEqual(outputs_location, 'outputs-location')
Пример #25
0
 def get_mocked_client(self):
     client = OasisAPIClient('http://localhost:8001')
     client.run_analysis = Mock(return_value=self.analysis_status_location)
     client.get_analysis_status = Mock(return_value=(STATUS_SUCCESS, self.analysis_output_location))
     client.download_outputs = Mock()
     client.delete_exposure = Mock()
     client.delete_outputs = Mock()
     return client
def run_analysis(c):
    try:

        upload_directory = os.path.join("upload", str(uuid.uuid1()))

        shutil.copytree(os.path.join(input_data_directory, "csv"),
                        upload_directory)

        client = OasisAPIClient(api_url, logging.getLogger())
        input_location = client.upload_inputs_from_directory(
            upload_directory, do_il, do_validation=False)
        client.run_analysis(analysis_settings,
                            input_location,
                            output_data_directory,
                            do_clean=False)
        c.increment_num_completed()

    except Exception:
        logging.exception("API test failed")
        c.increment_num_failed()
Пример #27
0
def do_run_prog_oasis(processrunid):
    '''
    Run a programme model combination.
    '''

    element_run_ids = list()
    element_run_id = -1

    flamingo_db_utils.update_process_run_status(processrunid, "In Progress")

    try:
        base_url = flamingo_db_utils.get_base_url(processrunid)
        element_run_ids = \
            flamingo_db_utils.get_element_run_ids(processrunid)

        upload_directory = generate_summary_files(processrunid)
        logging.getLogger().debug(
            "Upload_directory: {}".format(upload_directory))

        analysis_settings_json = get_analysis_settings_json(processrunid)
        logging.getLogger().debug(analysis_settings_json)

        if 'il_output' in analysis_settings_json['analysis_settings']:
            create_il_bins = analysis_settings_json['analysis_settings'][
                'il_output']
        else:
            create_il_bins = False
        analysis_poll_interval_in_seconds = 5
        client = OasisAPIClient(base_url, logging.getLogger())

        element_run_id = element_run_ids[0][0]
        input_location = client.upload_inputs_from_directory(
            upload_directory,
            do_il=create_il_bins,
            do_build=True,
            do_clean=True)
        logging.getLogger().info("Input location: {}".format(input_location))

        flamingo_db_utils.log_element_run_to_db(
            element_run_id, "Success",
            "Exposure files location: {}".format(input_location))

        element_run_id = element_run_ids[1][0]
        analysis_status_location = client.run_analysis(analysis_settings_json,
                                                       input_location)

        flamingo_db_utils.log_element_run_to_db(element_run_id, "Success",
                                                "Started analysis")

        element_run_id = element_run_ids[2][0]
        outputs_location = ""
        while True:
            logging.getLogger().debug("Polling analysis status for: {}".format(
                analysis_status_location))
            (status, outputs_location) = \
                client.get_analysis_status(analysis_status_location)
            flamingo_db_utils.log_element_run_to_db(element_run_id, status,
                                                    "In Progress")

            if status == status_code.STATUS_SUCCESS:
                if outputs_location is None:
                    raise Exception("Complete but no outputs location")
                flamingo_db_utils.log_element_run_to_db(
                    element_run_id, status, "Analysis Completed")
                break
            elif status == status_code.STATUS_FAILURE:
                error_message = "Analysis failed: {}".format(message)
                logging.getLogger().error(error_message)
                raise Exception(error_message)
            time.sleep(analysis_poll_interval_in_seconds)
        element_run_id = element_run_ids[3][0]

        # download outputs and cleanup
        outputs_file = os.path.join(upload_directory,
                                    outputs_location + ".tar.gz")
        client.download_outputs(outputs_location, outputs_file)
        client.delete_exposure(input_location)
        client.delete_outputs(outputs_location)
        flamingo_db_utils.log_element_run_to_db(
            element_run_id, 'Success', 'Downloaded output files successfully')

        extract_tarball(
            os.path.join(upload_directory, outputs_location + ".tar.gz"),
            upload_directory)

        output_file_list = ','.join(
            map(str, os.listdir(os.path.join(upload_directory, "output"))))
        logging.getLogger().debug(
            "Output_file_list: {}".format(output_file_list))
        db.execute(
            "exec dbo.linkOutputFileToProcessRun @ProcessRunId = ?, @OutputFiles = ?",
            processrunid, output_file_list)
        flamingo_db_utils.update_process_run_status(processrunid, 'Completed')

        # append summary id meanings to output files
        output_file_details = flamingo_db_utils.get_output_file_details(
            processrunid)
        logging.getLogger().debug(
            "output_file_details: {}".format(output_file_details))
        columns = [
            "FileName", "FileDesc", "PerspectiveName", "OutputID", "LECFlag",
            "AnalysisFileNameStub", "SummaryLevelName"
        ]
        df_output_file_details = pd.DataFrame(columns=columns)
        recs = map(lambda tup: dict(zip(columns, list(tup))),
                   output_file_details)
        df_output_file_details = df_output_file_details.append(recs)
        logging.getLogger().debug(
            "df_output_file_details:\n{}".format(df_output_file_details))

        prog_oasis_location = flamingo_db_utils.get_prog_oasis_location(
            processrunid)
        itemdict = prog_oasis_location + '/ItemDict.csv'
        fmdict = prog_oasis_location + '/FMDict.csv'
        df_itemdict = pd.read_csv(itemdict)
        df_fmdict = pd.read_csv(fmdict)
        df_fmdict["policy_layer"] = df_fmdict["policy_name"].map(
            str) + '--' + df_fmdict["layer_name"].map(str)

        for index, row in df_output_file_details.iterrows():
            output = upload_directory + '/output/' + row['FileName']
            logging.getLogger().debug("FileName: {}".format(output))
            output_tmp = output + '.tmp'
            SummaryLevelName = row['SummaryLevelName']
            df_output = pd.read_csv(output)
            SummaryLevelId = SummaryLevelName.lower() + '_id'
            SummaryLevelDesc = SummaryLevelName.lower() + '_desc'
            logging.getLogger().debug(
                "SummaryLevelName: {}".format(SummaryLevelName))
            if SummaryLevelName != "Portfolio":
                if SummaryLevelName == "Policy":
                    # join fmdict to file
                    df_summarydict = df_fmdict[['agg_id', 'policy_layer']]
                    logging.getLogger().debug(
                        "df_summarydict: {}".format(df_summarydict))
                    df_summarydict_distinct = df_summarydict.drop_duplicates()
                    df_output_temp = df_output.join(
                        df_summarydict_distinct.set_index('agg_id'),
                        on='summary_id')
                else:
                    # join itemdict to file
                    df_summarydict = df_itemdict[[
                        SummaryLevelId, SummaryLevelDesc
                    ]]
                    df_summarydict_distinct = df_summarydict.drop_duplicates()
                    df_output_temp = df_output.join(
                        df_summarydict_distinct.set_index(SummaryLevelId),
                        on='summary_id')
                    logging.getLogger().debug(
                        "df_summarydict_distinct: {}".format(
                            df_summarydict_distinct))
                df_output_temp.to_csv(output, encoding='utf-8', index=False)

    except Exception as e:
        flamingo_db_utils.update_process_run_status(processrunid, "Failed")
        if element_run_id != -1:
            flamingo_db_utils.log_element_run_to_db(element_run_id, 'Failed: ',
                                                    str(e))
        logging.getLogger().exception(
            "Failed to run prog oasis: {}".format(processrunid))