def test_check_config_bool(self): """ Test check_config for bool. """ checker = PluginConfigChecker([{'name': 'use_auth', 'type': 'bool'}]) checker.check_config({'use_auth': True}) with self.assertRaises(PluginException) as ctx: checker.check_config({'use_auth': 234543}) self.assertTrue('bool' in ctx.exception.message)
def test_check_config_int(self): """ Test check_config for int. """ checker = PluginConfigChecker([{'name': 'port', 'type': 'int'}]) checker.check_config({'port': 123}) with self.assertRaises(PluginException) as ctx: checker.check_config({'port': "123"}) self.assertTrue('int' in ctx.exception.message)
def test_simple(self): """ Test a simple valid configuration. """ _ = self checker = PluginConfigChecker([ {'name': 'log_inputs', 'type': 'bool', 'description': 'Log the input data.'}, {'name': 'log_outputs', 'type': 'bool', 'description': 'Log the output data.'} ]) checker.check_config({'log_inputs': True, 'log_outputs': False})
def test_check_config_str(self): """ Test check_config for str. """ checker = PluginConfigChecker([{'name': 'hostname', 'type': 'str'}]) checker.check_config({'hostname': 'cloud.openmotics.com'}) with self.assertRaises(PluginException) as ctx: checker.check_config({'hostname': 123}) self.assertTrue('str' in ctx.exception.message)
def test_check_config_password(self): """ Test check_config for bool. """ checker = PluginConfigChecker([{'name': 'password', 'type': 'password'}]) checker.check_config({'password': '******'}) with self.assertRaises(PluginException) as ctx: checker.check_config({'password': 123}) self.assertTrue('str' in ctx.exception.message)
def __init__(self, webinterface, gateway_logger): self.setup_logging(log_function=gateway_logger) super(HelloWorldPlugin, self).__init__(webinterface, logger) logger.info('Starting %s plugin %s ...', self.name, self.version) # set config on default config and instantiate a validator self._config = self.default_config self._config_checker = PluginConfigChecker(self.config_description) logger.info("%s plugin started", self.name)
def test_check_config_error(self): """ Test check_config with an invalid data type """ checker = PluginConfigChecker([{'name': 'hostname', 'type': 'str'}]) with self.assertRaises(PluginException) as ctx: checker.check_config('string') self.assertTrue('dict' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({}) self.assertTrue('hostname' in ctx.exception.message)
def test_constructor_str(self): """ Test for the constructor for str. """ PluginConfigChecker([{ 'name': 'hostname', 'type': 'str', 'description': 'The hostname of the server.' }]) PluginConfigChecker([{'name': 'hostname', 'type': 'str'}]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'type': 'str'}]) self.assertTrue('name' in ctx.exception.message)
def test_constructor_int(self): """ Test for the constructor for int. """ PluginConfigChecker([{ 'name': 'port', 'type': 'int', 'description': 'Port on the server.' }]) PluginConfigChecker([{'name': 'port', 'type': 'int'}]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'type': 'int'}]) self.assertTrue('name' in ctx.exception.message)
def test_constructor_password(self): """ Test for the constructor for bool. """ PluginConfigChecker([{ 'name': 'password', 'type': 'password', 'description': 'A password.' }]) PluginConfigChecker([{'name': 'password', 'type': 'password'}]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'type': 'password'}]) self.assertTrue('name' in ctx.exception.message)
def test_simple(self): """ Test a simple valid configuration. """ _ = self checker = PluginConfigChecker([{ 'name': 'log_inputs', 'type': 'bool', 'description': 'Log the input data.' }, { 'name': 'log_outputs', 'type': 'bool', 'description': 'Log the output data.' }]) checker.check_config({'log_inputs': True, 'log_outputs': False})
def test_constructor_bool(self): """ Test for the constructor for bool. """ PluginConfigChecker([{ 'name': 'use_auth', 'type': 'bool', 'description': 'Use authentication while connecting.' }]) PluginConfigChecker([{'name': 'use_auth', 'type': 'bool'}]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'type': 'bool'}]) self.assertTrue('name' in ctx.exception.message)
def test_constructor_enum(self): """ Test for the constructor for enum. """ PluginConfigChecker([{ 'name': 'enumtest', 'type': 'enum', 'description': 'Test for enum', 'choices': ['First', 'Second'] }]) PluginConfigChecker([{ 'name': 'enumtest', 'type': 'enum', 'choices': ['First', 'Second'] }]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'enumtest', 'type': 'enum', 'choices': 'First' }]) self.assertTrue('choices' in ctx.exception.message and 'list' in ctx.exception.message)
def test_check_config_password(self): """ Test check_config for bool. """ checker = PluginConfigChecker([{ 'name': 'password', 'type': 'password' }]) checker.check_config({'password': '******'}) with self.assertRaises(PluginException) as ctx: checker.check_config({'password': 123}) self.assertTrue('str' in ctx.exception.message)
def test_constructor_error(self): """ Test with an invalid data type """ with self.assertRaises(PluginException) as ctx: PluginConfigChecker({'test': 123}) self.assertTrue('list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'test': 123}]) self.assertTrue('name' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'name': 123}]) self.assertTrue('name' in ctx.exception.message and 'string' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'name': 'test'}]) self.assertTrue('type' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'name': 'test', 'type': 123}]) self.assertTrue('type' in ctx.exception.message and 'string' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{'name': 'test', 'type': 'something_else'}]) self.assertTrue('type' in ctx.exception.message and 'something_else' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'test', 'type': 'str', 'description': [] }]) self.assertTrue('description' in ctx.exception.message and 'string' in ctx.exception.message)
def test_constructor(self): """ Test for the constructor. """ _ = self PluginConfigChecker(FULL_DESCR)
class HelloWorldPlugin(OMPluginBase): """ Hello world plugin to demonstrate minimal requirements of a plugin """ name = 'HelloWorldPlugin' version = '1.0.3' interfaces = [('config', '1.0')] # configuration config_description = [{ 'type': 'str', 'description': 'Give your first name', 'name': 'first_name' }] default_config = { 'first_name': "my_test_name" } # optional default arguments def __init__(self, webinterface, gateway_logger): self.setup_logging(log_function=gateway_logger) super(HelloWorldPlugin, self).__init__(webinterface, logger) logger.info('Starting %s plugin %s ...', self.name, self.version) # set config on default config and instantiate a validator self._config = self.default_config self._config_checker = PluginConfigChecker(self.config_description) logger.info("%s plugin started", self.name) @staticmethod def setup_logging(log_function): # type: (Callable) -> None logger.setLevel(logging.INFO) log_handler = PluginLogHandler(log_function=log_function) formatter = logging.Formatter( '%(threadName)s - %(levelname)s - %(message)s') log_handler.setFormatter(formatter) logger.addHandler(log_handler) @om_expose def get_config_description(self): """ Returns the config_description. Used to render the structure in the gateway portal. """ return json.dumps(self.config_description) @om_expose def get_config(self): """ Returns the (filled in) config currently loaded. When this is the first time, this will be the default config. Otherwise, the adapted version in the portal configuration will be retrieved """ return json.dumps(self._config) @om_expose def set_config(self, config): """ Reads and validates config values from portal and sets new config. """ # read and validate config = json.loads(config) self._config_checker.check_config(config) # validation succeeded: set config and write out to file self._config = config self.write_config(config) # run the hello world as part of the config, just for demo purposes self.say_hello() return json.dumps({'success': True}) def say_hello(self): name = self._config['first_name'] logger.info(f" welcome {name}")
def test_constructor_section(self): """ Test for the constructor for section. """ PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'repeat': True, 'min': 1, 'content': [{ 'name': 'output', 'type': 'int' }] }]) PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'repeat': False, 'content': [{ 'name': 'output', 'type': 'int' }] }]) PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'content': [{ 'name': 'output', 'type': 'int' }] }]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'repeat': 'hello', 'content': [{ 'name': 'output', 'type': 'int' }] }]) self.assertTrue('repeat' in ctx.exception.message and 'bool' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'min': 1, 'content': [{ 'name': 'output', 'type': 'int' }] }]) self.assertTrue('min' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'content': 'error' }]) self.assertTrue('content' in ctx.exception.message and 'list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'content': [{ 'name': 123 }] }]) self.assertTrue('content' in ctx.exception.message and 'name' in ctx.exception.message and 'string' in ctx.exception.message)
def test_check_config_nested_enum(self): """ Test check_config for nested_enum. """ checker = PluginConfigChecker([{'name': 'network', 'type': 'nested_enum', 'choices': [ {'value': 'Facebook', 'content': [{'name': 'likes', 'type': 'int'}]}, {'value': 'Twitter', 'content': [{'name': 'followers', 'type': 'int'}]} ]}]) checker.check_config({'network': ['Twitter', {'followers': 3}]}) checker.check_config({'network': ['Facebook', {'likes': 3}]}) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': 'test'}) self.assertTrue('list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': []}) self.assertTrue('list' in ctx.exception.message and '2' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': ['something else', {}]}) self.assertTrue('choices' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': ['Twitter', {}]}) self.assertTrue('nested_enum dict' in ctx.exception.message and 'followers' in ctx.exception.message)
def test_check_config_section(self): """ Test check_config for section. """ checker = PluginConfigChecker([{'name': 'outputs', 'type': 'section', 'repeat': True, 'min': 1, 'content': [{'name': 'output', 'type': 'int'}]}]) checker.check_config({'outputs': []}) checker.check_config({'outputs': [{'output': 2}]}) checker.check_config({'outputs': [{'output': 2}, {'output': 4}]}) with self.assertRaises(PluginException) as ctx: checker.check_config({'outputs': 'test'}) self.assertTrue('list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'outputs': [{'test': 123}]}) self.assertTrue('section' in ctx.exception.message and 'output' in ctx.exception.message)
def test_constructor_nested_enum(self): """ Test for constructor for nested enum. """ PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 'Facebook', 'content': [{ 'name': 'likes', 'type': 'int' }] }, { 'value': 'Twitter', 'content': [{ 'name': 'followers', 'type': 'int' }] }] }]) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': 'test' }]) self.assertTrue('choices' in ctx.exception.message and 'list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': ['test'] }]) self.assertTrue('choices' in ctx.exception.message and 'dict' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{}] }]) self.assertTrue('choices' in ctx.exception.message and 'value' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 123 }] }]) self.assertTrue('choices' in ctx.exception.message and 'network' in ctx.exception.message and 'content' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 'test' }] }]) self.assertTrue('choices' in ctx.exception.message and 'content' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 'test', 'content': 'test' }] }]) self.assertTrue('choices' in ctx.exception.message and 'content' in ctx.exception.message and 'list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 'test', 'content': [{}] }] }]) self.assertTrue('choices' in ctx.exception.message and 'content' in ctx.exception.message and 'name' in ctx.exception.message)
def test_check_config_section(self): """ Test check_config for section. """ checker = PluginConfigChecker([{ 'name': 'outputs', 'type': 'section', 'repeat': True, 'min': 1, 'content': [{ 'name': 'output', 'type': 'int' }] }]) checker.check_config({'outputs': []}) checker.check_config({'outputs': [{'output': 2}]}) checker.check_config({'outputs': [{'output': 2}, {'output': 4}]}) with self.assertRaises(PluginException) as ctx: checker.check_config({'outputs': 'test'}) self.assertTrue('list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'outputs': [{'test': 123}]}) self.assertTrue('section' in ctx.exception.message and 'output' in ctx.exception.message)
def test_check_config_nested_enum(self): """ Test check_config for nested_enum. """ checker = PluginConfigChecker([{ 'name': 'network', 'type': 'nested_enum', 'choices': [{ 'value': 'Facebook', 'content': [{ 'name': 'likes', 'type': 'int' }] }, { 'value': 'Twitter', 'content': [{ 'name': 'followers', 'type': 'int' }] }] }]) checker.check_config({'network': ['Twitter', {'followers': 3}]}) checker.check_config({'network': ['Facebook', {'likes': 3}]}) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': 'test'}) self.assertTrue('list' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': []}) self.assertTrue('list' in ctx.exception.message and '2' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': ['something else', {}]}) self.assertTrue('choices' in ctx.exception.message) with self.assertRaises(PluginException) as ctx: checker.check_config({'network': ['Twitter', {}]}) self.assertTrue('nested_enum dict' in ctx.exception.message and 'followers' in ctx.exception.message)