def run(self, event, context=None, handler=None, event_source=None, debug=False): if context is None: context = FlexerContext() if context.state is None: context.state = FlexerLocalState() logger.info('Running handler "%s"', handler) try: module_name, func_name = self._parse_handler(handler) if module_name not in self.modules: self.modules[module_name] = self._import_module(module_name) func = self._get_handler_from_module(module_name, func_name) except FlexerException as e: return FlexerResult(value=None, logs=e.stack_trace, error=e.to_dict()) value, error, stdout = None, None, '' headers = {} f = sys.stderr if debug else StringIO() try: with RedirectStdStreams(stdout=f, stderr=f): try: value = func(event, context) headers = context.response_headers # if a cmp object type is returned, # encode result and add header if hasattr(value, "cmp_response"): headers['x-cmp-response'] = type(value).__name__ value = value.cmp_response() except BaseException: del func error = self._format_exception_info(sys.exc_info()) if not debug: stdout = f.getvalue() finally: if not debug: f.close() logger.info('Handler completed "%s"', handler) if error: stdout += error['stack_trace'] return FlexerResult(value=value, logs=stdout, error=error, headers=headers)
def test_run_with_invalid_db_secret(self): """Run a method that tries to use an invalid secret for an Nflex DB """ handler = 'module_with_db.test' expected = { 'exc_message': 'The mydb secret is not a valid MongoDB connection string', # noqa 'exc_type': 'Exception', } context = FlexerContext() secrets = [ "test", "mongodb://", "mongodb://a", "mongodb://*****:*****@", "mongodb://*****:*****@c", "mongodb://*****:*****@c/", ] for s in secrets: context.secrets = {"_nflexdb_mydb": s} result = self.runner.run(event={}, context=context, handler=handler) actual = json.loads(result) self.assertEqual(None, actual['value']) error = actual['error'] self.assertEqual(expected['exc_message'], error['exc_message']) self.assertEqual(expected['exc_type'], error['exc_type']) self.assertIn('Exception', error['stack_trace'])
def run(handler, event, config, secrets, cmp_client): event = json.loads(event) handler = "main.%s" % handler context = FlexerContext(cmp_client=cmp_client) if config is not None: context.config = json.loads(config) if secrets is not None: context.secrets = json.loads(secrets) result = Flexer().run(event=event, context=context, handler=handler, debug=True) return json.loads(result)
def test_run_with_valid_db_secret(self): """Run a method that tries to use a valid secret for an Nflex DB """ handler = 'module_with_db.test' context = FlexerContext() context.secrets = {"_nflexdb_mydb": "mongodb://*****:*****@c/mydb"} with mock.patch('pymongo.MongoClient', return_value=mock.MagicMock()): result = self.runner.run(event={}, context=context, handler=handler) actual = json.loads(result) self.assertTrue('error' in actual) self.assertTrue('value' in actual) self.assertEqual(None, actual['error']) self.assertTrue('result' in actual['value'])
def setUpClass(cls): # The rule to evaluate number as boolean is inspired by C++11 implementation # All numbers but 0 and True or true will be evaluated as True cls.logging = re.search(r'^-?[1-9][0-9]*$|^[Tt]rue$', os.getenv("LOG_TO_STDOUT", "False")) != None path = os.getenv("CONFIG_YAML", DEFAULT_CONFIG_YAML) cls.account = read_yaml_file(path) cls.account["credentials"] = (lookup_values( cls.account.get("credentials_keys"))) if "resources" in cls.account: cls.resource_data = cls.account.get("resources") else: cls.resource_data = [{ "resource": cls.account.get("resource"), "expected_metrics": cls.account.get("expected_metrics") }] cls.runner = Flexer() cfg = load_config(cfg_file=CONFIG_FILE)["regions"]["default"] client = CmpClient(url=cfg["cmp_url"], auth=(cfg['cmp_api_key'], cfg['cmp_api_secret'])) cls.context = FlexerContext(cmp_client=client) secrets = (lookup_values(cls.account.get("secrets_keys"))) cls.context.secrets = secrets
def setUpClass(cls): path = os.getenv("CONFIG_YAML", DEFAULT_CONFIG_YAML) cls.account = read_yaml_file(path) cls.account["credentials"] = (lookup_credentials( cls.account.get("credentials_keys"))) cls.runner = Flexer() cfg = load_config(cfg_file=CONFIG_FILE)["regions"]["default"] client = CmpClient(url=cfg["cmp_url"], auth=(cfg['cmp_api_key'], cfg['cmp_api_secret'])) cls.context = FlexerContext(cmp_client=client)
def test_tasks(self, mock): auth = ('username', 'password') cmp_client = CmpClient(url='http://localhost', auth=auth, access_token='foo') task_id = 'task-1' context = FlexerContext(cmp_client=cmp_client) # Should do nothing set_task_percentage(context, None, 100) mock.post('http://localhost/tasks/task-1/update', text='null') set_task_percentage(context, task_id, 100) mock.post('http://localhost/tasks/task-1/update', text='"Oops"', status_code=500) with pytest.raises(Exception) as e: set_task_percentage(context, task_id, 100) assert 'Got bad response from tasks API' in str(e)
def run(self, event, context=None, handler=None, event_source=None, debug=False): if context is None: context = FlexerContext() if context.state is None: context.state = FlexerLocalState() logger.info('Running handler "%s"', handler) try: module_name, func_name = self._parse_handler(handler) if module_name not in self.modules: self.modules[module_name] = self._import_module(module_name) func = self._get_handler_from_module(module_name, func_name) except FlexerException as e: return FlexerResult(value=None, logs=e.stack_trace, error=e.to_dict()) value, error, stdout = None, None, '' headers = {} f = sys.stderr if debug else StringIO.StringIO() try: with RedirectStdStreams(stdout=f, stderr=f): try: value = func(event, context) headers = context.response_headers # if a cmp object type is returned, # encode result and add header if hasattr(value, "cmp_response"): headers['x-cmp-response'] = type(value).__name__ value = value.cmp_response() except: del func error = self._format_exception_info(sys.exc_info()) if not debug: stdout = f.getvalue() finally: if not debug: f.close() logger.info('Handler completed "%s"', handler) if error: stdout += error['stack_trace'] else: schema = self._get_validation_schema(event_source, handler) if schema: validator = Draft4Validator(schema) errors = [] for e in sorted(validator.iter_errors(value), key=str): errors.append(e.message + ' in ' + str(list(e.path))) if errors: error = { 'exc_message': json.dumps(errors), 'exc_type': 'ValidationError' } stdout += json.dumps(errors) return FlexerResult(value=value, logs=stdout, error=error, headers=headers)
def run(handler, event, cmp_client): event = json.loads(event) handler = "main.%s" % handler context = FlexerContext(cmp_client=cmp_client) runner = Flexer() return runner.run(event=event, context=context, handler=handler)