def test_register_configs_for_all_packs(self): # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = {"dummy_pack_1": PACK_PATH} packs_base_paths = content_utils.get_packs_base_paths() registrar.register_configs_for_all_packs(base_dirs=packs_base_paths) # Verify pack and schema have been registered pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 1) self.assertEqual(len(config_dbs), 1) config_db = config_dbs[0] self.assertEqual(config_db.values["api_key"], "{{user.api_key}}") self.assertEqual(config_db.values["api_secret"], "{{user.api_secret}}") self.assertEqual(config_db.values["region"], "us-west-1")
def _register_config_for_pack(self, pack, config_path): content = {} values = self._meta_loader.load(config_path) content['pack'] = pack content['values'] = values config_api = ConfigAPI(**content) config_api.validate(validate_against_schema=self._validate_configs) config_db = ConfigAPI.to_model(config_api) try: config_db.id = Config.get_by_pack(config_api.pack).id except StackStormDBObjectNotFoundError: LOG.debug('Config for pack "%s" not found. Creating new entry.', pack) try: config_db = Config.add_or_update(config_db) extra = {'config_db': config_db} LOG.audit('Config for pack "%s" is updated.', config_db.pack, extra=extra) except Exception: LOG.exception('Failed to config for pack %s.', pack) raise return config_db
def test_get_config_default_value_from_config_schema_is_used(self): # No value is provided for "region" in the config, default value from config schema # should be used loader = ContentPackConfigLoader(pack_name='dummy_pack_5') config = loader.get_config() self.assertEqual(config['region'], 'default-region-value') # Here a default value is specified in schema but an explicit value is provided in the # config loader = ContentPackConfigLoader(pack_name='dummy_pack_1') config = loader.get_config() self.assertEqual(config['region'], 'us-west-1') # Config item attribute has required: false # Value is provided in the config - it should be used as provided pack_name = 'dummy_pack_5' loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config['non_required_with_default_value'], 'config value') config_db = Config.get_by_pack(pack_name) del config_db['values']['non_required_with_default_value'] Config.add_or_update(config_db) # No value in the config - default value should be used config_db = Config.get_by_pack(pack_name) config_db.delete() # No config exists for that pack - default value should be used loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config['non_required_with_default_value'], 'some default value')
def test_register_configs_for_all_packs(self): # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = {'dummy_pack_1': PACK_1_PATH} packs_base_paths = content_utils.get_packs_base_paths() registrar.register_from_packs(base_dirs=packs_base_paths) # Verify pack and schema have been registered pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 1) self.assertEqual(len(config_dbs), 1) config_db = config_dbs[0] self.assertEqual(config_db.values['api_key'], '{{st2kv.user.api_key}}') self.assertEqual(config_db.values['api_secret'], SUPER_SECRET_PARAMETER) self.assertEqual(config_db.values['region'], 'us-west-1')
def test_run(self): pack = 'dummy_pack_1' # Verify all the resources are there pack_dbs = Pack.query(ref=pack) action_dbs = Action.query(pack=pack) alias_dbs = ActionAlias.query(pack=pack) rule_dbs = Rule.query(pack=pack) sensor_dbs = Sensor.query(pack=pack) trigger_type_dbs = TriggerType.query(pack=pack) policy_dbs = Policy.query(pack=pack) config_schema_dbs = ConfigSchema.query(pack=pack) config_dbs = Config.query(pack=pack) self.assertEqual(len(pack_dbs), 1) self.assertEqual(len(action_dbs), 1) self.assertEqual(len(alias_dbs), 2) self.assertEqual(len(rule_dbs), 1) self.assertEqual(len(sensor_dbs), 3) self.assertEqual(len(trigger_type_dbs), 4) self.assertEqual(len(policy_dbs), 2) self.assertEqual(len(config_schema_dbs), 1) self.assertEqual(len(config_dbs), 1) # Run action action = self.get_action_instance() action.run(packs=[pack]) # Make sure all resources have been removed from the db pack_dbs = Pack.query(ref=pack) action_dbs = Action.query(pack=pack) alias_dbs = ActionAlias.query(pack=pack) rule_dbs = Rule.query(pack=pack) sensor_dbs = Sensor.query(pack=pack) trigger_type_dbs = TriggerType.query(pack=pack) policy_dbs = Policy.query(pack=pack) config_schema_dbs = ConfigSchema.query(pack=pack) config_dbs = Config.query(pack=pack) self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(action_dbs), 0) self.assertEqual(len(alias_dbs), 0) self.assertEqual(len(rule_dbs), 0) self.assertEqual(len(sensor_dbs), 0) self.assertEqual(len(trigger_type_dbs), 0) self.assertEqual(len(policy_dbs), 0) self.assertEqual(len(config_schema_dbs), 0) self.assertEqual(len(config_dbs), 0)
def test_default_values_from_schema_are_used_when_no_config_exists(self): pack_name = 'dummy_pack_5' config_db = Config.get_by_pack(pack_name) # Delete the existing config loaded in setUp config_db = Config.get_by_pack(pack_name) config_db.delete() # Verify config has been deleted from the database self.assertRaises(StackStormDBObjectNotFoundError, Config.get_by_pack, pack_name) loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config['region'], 'default-region-value')
def test_get_config_dynamic_config_item_render_fails_user_friendly_exception_is_thrown(self): pack_name = 'dummy_pack_schema_with_nested_object_5' loader = ContentPackConfigLoader(pack_name=pack_name) # Render fails on top-level item values = { 'level0_key': '{{st2kvXX.invalid}}' } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key "level0_key" with ' 'value "{{st2kvXX.invalid}}" for pack ".*?" config: ' '\'st2kvXX\' is undefined') self.assertRaisesRegexp(Exception, expected_msg, loader.get_config) config_db.delete() # Renders fails on fist level item values = { 'level0_object': { 'level1_key': '{{st2kvXX.invalid}}' } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.level1_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: \'st2kvXX\' is undefined') self.assertRaisesRegexp(Exception, expected_msg, loader.get_config) config_db.delete() # Renders fails on second level item values = { 'level0_object': { 'level1_object': { 'level2_key': '{{st2kvXX.invalid}}' } } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.level1_object.level2_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: \'st2kvXX\' is undefined') self.assertRaisesRegexp(Exception, expected_msg, loader.get_config) config_db.delete()
def get_config(self): result = {} # 1. Retrieve values from pack local config.yaml file config = self._config_parser.get_config() if config: config = config.config or {} result.update(config) # Retrieve corresponding ConfigDB and ConfigSchemaDB object # Note: ConfigSchemaDB is optional right now. If it doesn't exist, we assume every value # is of a type string try: config_db = Config.get_by_pack(value=self.pack_name) except StackStormDBObjectNotFoundError: # Corresponding pack config doesn't exist, return early return result try: config_schema_db = ConfigSchema.get_by_pack(value=self.pack_name) except StackStormDBObjectNotFoundError: config_schema_db = None # 2. Retrieve values from "global" pack config file (if available) and resolve them if # necessary config = self._get_values_for_config(config_schema_db=config_schema_db, config_db=config_db) result.update(config) return result
def test_register_all_configs_with_config_schema_validation_validation_failure_1(self): # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False, fail_on_failure=True, validate_configs=True) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = {'dummy_pack_6': PACK_6_PATH} # Register ConfigSchema for pack registrar._register_pack_db = mock.Mock() registrar._register_pack(pack_name='dummy_pack_5', pack_dir=PACK_6_PATH) packs_base_paths = content_utils.get_packs_base_paths() if six.PY3: expected_msg = ('Failed validating attribute "regions" in config for pack ' '"dummy_pack_6" (.*?): 1000 is not of type \'array\'') else: expected_msg = ('Failed validating attribute "regions" in config for pack ' '"dummy_pack_6" (.*?): 1000 is not of type u\'array\'') self.assertRaisesRegexp(ValueError, expected_msg, registrar.register_from_packs, base_dirs=packs_base_paths)
def test_get_config_dynamic_config_item_list(self): pack_name = 'dummy_pack_schema_with_nested_object_7' loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name='k0', value='v0')) KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) #################### # values in list values = { 'level0_key': [ 'a', '{{st2kv.system.k0}}', 'b', '{{st2kv.system.k1}}', ] } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEquals(config_rendered, { 'level0_key': [ 'a', 'v0', 'b', 'v1' ] }) config_db.delete()
def get_config(self): result = {} # Retrieve corresponding ConfigDB and ConfigSchemaDB object # Note: ConfigSchemaDB is optional right now. If it doesn't exist, we assume every value # is of a type string try: config_db = Config.get_by_pack(value=self.pack_name) except StackStormDBObjectNotFoundError: # Corresponding pack config doesn't exist. We set config_db to an empty config so # that the default values from config schema are still correctly applied even if # pack doesn't contain a config. config_db = ConfigDB(pack=self.pack_name, values={}) try: config_schema_db = ConfigSchema.get_by_pack(value=self.pack_name) except StackStormDBObjectNotFoundError: config_schema_db = None # 2. Retrieve values from "global" pack config file (if available) and resolve them if # necessary config = self._get_values_for_config(config_schema_db=config_schema_db, config_db=config_db) result.update(config) return result
def test_empty_config_object_in_the_database(self): pack_name = 'dummy_pack_empty_config' config_db = ConfigDB(pack=pack_name) config_db = Config.add_or_update(config_db) loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config, {})
def save_model(config_api): pack = config_api.pack config_db = ConfigAPI.to_model(config_api) try: config_db.id = Config.get_by_pack(pack).id except StackStormDBObjectNotFoundError: LOG.debug('Config for pack "%s" not found. Creating new entry.', pack) try: config_db = Config.add_or_update(config_db) extra = {'config_db': config_db} LOG.audit('Config for pack "%s" is updated.', config_db.pack, extra=extra) except Exception: LOG.exception('Failed to save config for pack %s.', pack) raise return config_db
def test_get_config_dynamic_config_item_nested_list(self): pack_name = 'dummy_pack_schema_with_nested_object_8' loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name='k0', value='v0')) KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) KeyValuePair.add_or_update(KeyValuePairDB(name='k2', value='v2')) #################### # values in objects embedded in lists and nested lists values = { 'level0_key': [ { 'level1_key0': '{{st2kv.system.k0}}' }, '{{st2kv.system.k1}}', [ '{{st2kv.system.k0}}', '{{st2kv.system.k1}}', '{{st2kv.system.k2}}', ], { 'level1_key2': [ '{{st2kv.system.k2}}', ] } ] } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEquals(config_rendered, { 'level0_key': [ { 'level1_key0': 'v0' }, 'v1', [ 'v0', 'v1', 'v2', ], { 'level1_key2': [ 'v2', ] } ] }) config_db.delete()
def test_register_all_configs_invalid_config_no_config_schema(self): # verify_ configs is on, but ConfigSchema for the pack doesn't exist so # validation should proceed normally # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False, validate_configs=False) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = {'dummy_pack_6': PACK_6_PATH} packs_base_paths = content_utils.get_packs_base_paths() registrar.register_from_packs(base_dirs=packs_base_paths) # Verify pack and schema have been registered pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 1) self.assertEqual(len(config_dbs), 1)
def test_get_config_dynamic_config_item_nested_list(self): pack_name = 'dummy_pack_schema_with_nested_object_8' loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name='k0', value='v0')) KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) KeyValuePair.add_or_update(KeyValuePairDB(name='k2', value='v2')) #################### # values in objects embedded in lists and nested lists values = { 'level0_key': [{ 'level1_key0': '{{st2kv.system.k0}}' }, '{{st2kv.system.k1}}', [ '{{st2kv.system.k0}}', '{{st2kv.system.k1}}', '{{st2kv.system.k2}}', ], { 'level1_key2': [ '{{st2kv.system.k2}}', ] }] } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEqual( config_rendered, { 'level0_key': [{ 'level1_key0': 'v0' }, 'v1', [ 'v0', 'v1', 'v2', ], { 'level1_key2': [ 'v2', ] }] }) config_db.delete()
def test_get_config_dynamic_config_item(self): pack_name = 'dummy_pack_schema_with_nested_object_6' loader = ContentPackConfigLoader(pack_name=pack_name) #################### # value in top level item KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) values = { 'level0_key': '{{st2kv.system.k1}}' } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEquals(config_rendered, {'level0_key': 'v1'}) config_db.delete()
def test_get_config_dynamic_config_item(self): pack_name = 'dummy_pack_schema_with_nested_object_6' loader = ContentPackConfigLoader(pack_name=pack_name) #################### # value in top level item KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) values = { 'level0_key': '{{st2kv.system.k1}}' } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEquals(config_rendered, {'level0_key': 'v1'}) config_db.delete()
def setUp(self): super(UnloadActionTestCase, self).setUp() # Register mock pack # Verify DB is empty pack_dbs = Pack.get_all() config_schema_dbs = ConfigSchema.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_schema_dbs), 0) self.assertEqual(len(config_dbs), 0) # Register the pack with all the content # TODO: Don't use pack cache cfg.CONF.set_override(name='all', override=True, group='register') cfg.CONF.set_override(name='pack', override=PACK_PATH_1, group='register') cfg.CONF.set_override(name='no_fail_on_failure', override=True, group='register') register_content()
def setUp(self): super(UnloadActionTestCase, self).setUp() # Register mock pack # Verify DB is empty pack_dbs = Pack.get_all() config_schema_dbs = ConfigSchema.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_schema_dbs), 0) self.assertEqual(len(config_dbs), 0) # Register the pack with all the content # TODO: Don't use pack cache cfg.CONF.set_override(name='all', override=True, group='register') cfg.CONF.set_override(name='pack', override=PACK_PATH_1, group='register') cfg.CONF.set_override(name='no_fail_on_failure', override=True, group='register') register_content()
def test_default_values_are_used_when_default_values_are_falsey(self): pack_name = 'dummy_pack_17' loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() # 1. Default values are used self.assertEqual(config['key_with_default_falsy_value_1'], False) self.assertEqual(config['key_with_default_falsy_value_2'], None) self.assertEqual(config['key_with_default_falsy_value_3'], {}) self.assertEqual(config['key_with_default_falsy_value_4'], '') self.assertEqual(config['key_with_default_falsy_value_5'], 0) self.assertEqual(config['key_with_default_falsy_value_6']['key_1'], False) self.assertEqual(config['key_with_default_falsy_value_6']['key_2'], 0) # 2. Default values are overwrriten with config values which are also falsey values = { 'key_with_default_falsy_value_1': 0, 'key_with_default_falsy_value_2': '', 'key_with_default_falsy_value_3': False, 'key_with_default_falsy_value_4': None, 'key_with_default_falsy_value_5': {}, 'key_with_default_falsy_value_6': { 'key_2': False } } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config['key_with_default_falsy_value_1'], 0) self.assertEqual(config['key_with_default_falsy_value_2'], '') self.assertEqual(config['key_with_default_falsy_value_3'], False) self.assertEqual(config['key_with_default_falsy_value_4'], None) self.assertEqual(config['key_with_default_falsy_value_5'], {}) self.assertEqual(config['key_with_default_falsy_value_6']['key_1'], False) self.assertEqual(config['key_with_default_falsy_value_6']['key_2'], False)
def test_default_values_are_used_when_default_values_are_falsey(self): pack_name = "dummy_pack_17" loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() # 1. Default values are used self.assertEqual(config["key_with_default_falsy_value_1"], False) self.assertEqual(config["key_with_default_falsy_value_2"], None) self.assertEqual(config["key_with_default_falsy_value_3"], {}) self.assertEqual(config["key_with_default_falsy_value_4"], "") self.assertEqual(config["key_with_default_falsy_value_5"], 0) self.assertEqual(config["key_with_default_falsy_value_6"]["key_1"], False) self.assertEqual(config["key_with_default_falsy_value_6"]["key_2"], 0) # 2. Default values are overwrriten with config values which are also falsey values = { "key_with_default_falsy_value_1": 0, "key_with_default_falsy_value_2": "", "key_with_default_falsy_value_3": False, "key_with_default_falsy_value_4": None, "key_with_default_falsy_value_5": {}, "key_with_default_falsy_value_6": { "key_2": False }, } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config["key_with_default_falsy_value_1"], 0) self.assertEqual(config["key_with_default_falsy_value_2"], "") self.assertEqual(config["key_with_default_falsy_value_3"], False) self.assertEqual(config["key_with_default_falsy_value_4"], None) self.assertEqual(config["key_with_default_falsy_value_5"], {}) self.assertEqual(config["key_with_default_falsy_value_6"]["key_1"], False) self.assertEqual(config["key_with_default_falsy_value_6"]["key_2"], False)
def test_register_all_configs_with_config_schema_validation_validation_failure_2( self, ): # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False, fail_on_failure=True, validate_configs=True) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = { "dummy_pack_19": PACK_19_PATH } # Register ConfigSchema for pack registrar._register_pack_db = mock.Mock() registrar._register_pack(pack_name="dummy_pack_19", pack_dir=PACK_19_PATH) packs_base_paths = content_utils.get_packs_base_paths() if six.PY3: expected_msg = ( 'Failed validating attribute "instances.0.alias" in config for pack ' "\"dummy_pack_19\" (.*?): {'not': 'string'} is not of type " "'string'") else: expected_msg = ( 'Failed validating attribute "instances.0.alias" in config for pack ' "\"dummy_pack_19\" (.*?): {'not': 'string'} is not of type " "u'string'") self.assertRaisesRegexp( ValueError, expected_msg, registrar.register_from_packs, base_dirs=packs_base_paths, )
def test_default_values_are_used_when_default_values_are_falsey(self): pack_name = 'dummy_pack_17' loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() # 1. Default values are used self.assertEqual(config['key_with_default_falsy_value_1'], False) self.assertEqual(config['key_with_default_falsy_value_2'], None) self.assertEqual(config['key_with_default_falsy_value_3'], {}) self.assertEqual(config['key_with_default_falsy_value_4'], '') self.assertEqual(config['key_with_default_falsy_value_5'], 0) self.assertEqual(config['key_with_default_falsy_value_6']['key_1'], False) self.assertEqual(config['key_with_default_falsy_value_6']['key_2'], 0) # 2. Default values are overwrriten with config values which are also falsey values = { 'key_with_default_falsy_value_1': 0, 'key_with_default_falsy_value_2': '', 'key_with_default_falsy_value_3': False, 'key_with_default_falsy_value_4': None, 'key_with_default_falsy_value_5': {}, 'key_with_default_falsy_value_6': { 'key_2': False } } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) loader = ContentPackConfigLoader(pack_name=pack_name) config = loader.get_config() self.assertEqual(config['key_with_default_falsy_value_1'], 0) self.assertEqual(config['key_with_default_falsy_value_2'], '') self.assertEqual(config['key_with_default_falsy_value_3'], False) self.assertEqual(config['key_with_default_falsy_value_4'], None) self.assertEqual(config['key_with_default_falsy_value_5'], {}) self.assertEqual(config['key_with_default_falsy_value_6']['key_1'], False) self.assertEqual(config['key_with_default_falsy_value_6']['key_2'], False)
def test_get_config_dynamic_config_item_nested_dict(self): pack_name = "dummy_pack_schema_with_nested_object_7" loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name="k0", value="v0")) KeyValuePair.add_or_update(KeyValuePairDB(name="k1", value="v1")) KeyValuePair.add_or_update(KeyValuePairDB(name="k2", value="v2")) #################### # values nested dictionaries values = { "level0_key": "{{st2kv.system.k0}}", "level0_object": { "level1_key": "{{st2kv.system.k1}}", "level1_object": { "level2_key": "{{st2kv.system.k2}}" }, }, } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEqual( config_rendered, { "level0_key": "v0", "level0_object": { "level1_key": "v1", "level1_object": { "level2_key": "v2" }, }, }, ) config_db.delete()
def test_register_all_configs_with_config_schema_validation_validation_failure_4( self, ): # This test checks for default values containing "decrypt_kv" jinja filter for # keys which have "secret: True" set. # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False, fail_on_failure=True, validate_configs=True) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = { "dummy_pack_22": PACK_22_PATH } # Register ConfigSchema for pack registrar._register_pack_db = mock.Mock() registrar._register_pack(pack_name="dummy_pack_22", pack_dir=PACK_22_PATH) packs_base_paths = content_utils.get_packs_base_paths() expected_msg = ( 'Values specified as "secret: True" in config schema are automatically ' 'decrypted by default. Use of "decrypt_kv" jinja filter is not allowed ' "for such values. Please check the specified values in the config or " "the default values in the schema.") self.assertRaisesRegexp( ValueError, expected_msg, registrar.register_from_packs, base_dirs=packs_base_paths, )
def test_get_config_dynamic_config_item_nested_dict(self): pack_name = 'dummy_pack_schema_with_nested_object_7' loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name='k0', value='v0')) KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) KeyValuePair.add_or_update(KeyValuePairDB(name='k2', value='v2')) #################### # values nested dictionaries values = { 'level0_key': '{{st2kv.system.k0}}', 'level0_object': { 'level1_key': '{{st2kv.system.k1}}', 'level1_object': { 'level2_key': '{{st2kv.system.k2}}' } } } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEquals(config_rendered, { 'level0_key': 'v0', 'level0_object': { 'level1_key': 'v1', 'level1_object': { 'level2_key': 'v2' } } }) config_db.delete()
def test_register_all_configs_with_config_schema_validation_validation_failure_1( self): # Verify DB is empty pack_dbs = Pack.get_all() config_dbs = Config.get_all() self.assertEqual(len(pack_dbs), 0) self.assertEqual(len(config_dbs), 0) registrar = ConfigsRegistrar(use_pack_cache=False, fail_on_failure=True, validate_configs=True) registrar._pack_loader.get_packs = mock.Mock() registrar._pack_loader.get_packs.return_value = { 'dummy_pack_6': PACK_6_PATH } # Register ConfigSchema for pack registrar._register_pack_db = mock.Mock() registrar._register_pack(pack_name='dummy_pack_5', pack_dir=PACK_6_PATH) packs_base_paths = content_utils.get_packs_base_paths() if six.PY3: expected_msg = ( 'Failed validating attribute "regions" in config for pack ' '"dummy_pack_6" (.*?): 1000 is not of type \'array\'') else: expected_msg = ( 'Failed validating attribute "regions" in config for pack ' '"dummy_pack_6" (.*?): 1000 is not of type u\'array\'') self.assertRaisesRegexp(ValueError, expected_msg, registrar.register_from_packs, base_dirs=packs_base_paths)
def test_get_config_dynamic_config_item_nested_dict(self): pack_name = 'dummy_pack_schema_with_nested_object_7' loader = ContentPackConfigLoader(pack_name=pack_name) KeyValuePair.add_or_update(KeyValuePairDB(name='k0', value='v0')) KeyValuePair.add_or_update(KeyValuePairDB(name='k1', value='v1')) KeyValuePair.add_or_update(KeyValuePairDB(name='k2', value='v2')) #################### # values nested dictionaries values = { 'level0_key': '{{st2kv.system.k0}}', 'level0_object': { 'level1_key': '{{st2kv.system.k1}}', 'level1_object': { 'level2_key': '{{st2kv.system.k2}}' } } } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) config_rendered = loader.get_config() self.assertEqual( config_rendered, { 'level0_key': 'v0', 'level0_object': { 'level1_key': 'v1', 'level1_object': { 'level2_key': 'v2' } } }) config_db.delete()
def test_get_config_dynamic_config_item_render_fails_user_friendly_exception_is_thrown(self): pack_name = 'dummy_pack_schema_with_nested_object_5' loader = ContentPackConfigLoader(pack_name=pack_name) # Render fails on top-level item values = { 'level0_key': '{{st2kvXX.invalid}}' } config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key "level0_key" with ' 'value "{{st2kvXX.invalid}}" for pack ".*?" config: ' '<class \'jinja2.exceptions.UndefinedError\'> ' '\'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on fist level item values = { 'level0_object': { 'level1_key': '{{st2kvXX.invalid}}' } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.level1_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on second level item values = { 'level0_object': { 'level1_object': { 'level2_key': '{{st2kvXX.invalid}}' } } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.level1_object.level2_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on list item values = { 'level0_object': [ 'abc', '{{st2kvXX.invalid}}' ] } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.1" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on nested object in list item values = { 'level0_object': [ {'level2_key': '{{st2kvXX.invalid}}'} ] } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_object.0.level2_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on invalid syntax values = { 'level0_key': '{{ this is some invalid Jinja }}' } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ('Failed to render dynamic configuration value for key ' '"level0_key" with value "{{ this is some invalid Jinja }}"' ' for pack ".*?" config: <class \'jinja2.exceptions.TemplateSyntaxError\'>' ' expected token \'end of print statement\', got \'Jinja\'') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete()
def test_get_config_dynamic_config_item_render_fails_user_friendly_exception_is_thrown( self, ): pack_name = "dummy_pack_schema_with_nested_object_5" loader = ContentPackConfigLoader(pack_name=pack_name) # Render fails on top-level item values = {"level0_key": "{{st2kvXX.invalid}}"} config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key "level0_key" with ' 'value "{{st2kvXX.invalid}}" for pack ".*?" config: ' "<class 'jinja2.exceptions.UndefinedError'> " "'st2kvXX' is undefined") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on fist level item values = {"level0_object": {"level1_key": "{{st2kvXX.invalid}}"}} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( "Failed to render dynamic configuration value for key " '"level0_object.level1_key" with value "{{st2kvXX.invalid}}"' " for pack \".*?\" config: <class 'jinja2.exceptions.UndefinedError'>" " 'st2kvXX' is undefined") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on second level item values = { "level0_object": { "level1_object": { "level2_key": "{{st2kvXX.invalid}}" } } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( "Failed to render dynamic configuration value for key " '"level0_object.level1_object.level2_key" with value "{{st2kvXX.invalid}}"' " for pack \".*?\" config: <class 'jinja2.exceptions.UndefinedError'>" " 'st2kvXX' is undefined") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on list item values = {"level0_object": ["abc", "{{st2kvXX.invalid}}"]} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( "Failed to render dynamic configuration value for key " '"level0_object.1" with value "{{st2kvXX.invalid}}"' " for pack \".*?\" config: <class 'jinja2.exceptions.UndefinedError'>" " 'st2kvXX' is undefined") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on nested object in list item values = {"level0_object": [{"level2_key": "{{st2kvXX.invalid}}"}]} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( "Failed to render dynamic configuration value for key " '"level0_object.0.level2_key" with value "{{st2kvXX.invalid}}"' " for pack \".*?\" config: <class 'jinja2.exceptions.UndefinedError'>" " 'st2kvXX' is undefined") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on invalid syntax values = {"level0_key": "{{ this is some invalid Jinja }}"} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( "Failed to render dynamic configuration value for key " '"level0_key" with value "{{ this is some invalid Jinja }}"' " for pack \".*?\" config: <class 'jinja2.exceptions.TemplateSyntaxError'>" " expected token 'end of print statement', got 'Jinja'") self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete()
def test_get_config_dynamic_config_item_render_fails_user_friendly_exception_is_thrown( self): pack_name = 'dummy_pack_schema_with_nested_object_5' loader = ContentPackConfigLoader(pack_name=pack_name) # Render fails on top-level item values = {'level0_key': '{{st2kvXX.invalid}}'} config_db = ConfigDB(pack=pack_name, values=values) config_db = Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key "level0_key" with ' 'value "{{st2kvXX.invalid}}" for pack ".*?" config: ' '<class \'jinja2.exceptions.UndefinedError\'> ' '\'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on fist level item values = {'level0_object': {'level1_key': '{{st2kvXX.invalid}}'}} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key ' '"level0_object.level1_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on second level item values = { 'level0_object': { 'level1_object': { 'level2_key': '{{st2kvXX.invalid}}' } } } config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key ' '"level0_object.level1_object.level2_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on list item values = {'level0_object': ['abc', '{{st2kvXX.invalid}}']} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key ' '"level0_object.1" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on nested object in list item values = {'level0_object': [{'level2_key': '{{st2kvXX.invalid}}'}]} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key ' '"level0_object.0.level2_key" with value "{{st2kvXX.invalid}}"' ' for pack ".*?" config: <class \'jinja2.exceptions.UndefinedError\'>' ' \'st2kvXX\' is undefined') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete() # Renders fails on invalid syntax values = {'level0_key': '{{ this is some invalid Jinja }}'} config_db = ConfigDB(pack=pack_name, values=values) Config.add_or_update(config_db) expected_msg = ( 'Failed to render dynamic configuration value for key ' '"level0_key" with value "{{ this is some invalid Jinja }}"' ' for pack ".*?" config: <class \'jinja2.exceptions.TemplateSyntaxError\'>' ' expected token \'end of print statement\', got \'Jinja\'') self.assertRaisesRegexp(RuntimeError, expected_msg, loader.get_config) config_db.delete()