Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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'])
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
    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'])
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
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)