Example #1
0
    def test_get_config_some_values_overriden_in_datastore(self):
        # Test a scenario where some values are overriden in datastore via pack
        # flobal config
        kvp_db = set_datastore_value_for_config_key(pack_name='dummy_pack_5',
                                                    key_name='api_secret',
                                                    value='some_api_secret',
                                                    secret=True,
                                                    user='******')

        # This is a secret so a value should be encrypted
        self.assertTrue(kvp_db.value != 'some_api_secret')
        self.assertTrue(len(kvp_db.value) > len('some_api_secret') * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(pack_name='dummy_pack_5',
                                                    key_name='private_key_path',
                                                    value='some_private_key')
        self.assertEqual(kvp_db.value, 'some_private_key')
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name='dummy_pack_5', user='******')
        config = loader.get_config()

        # regions is provided in the pack global config
        # api_secret is dynamically loaded from the datastore for a particular user
        expected_config = {
            'api_key': 'some_api_key',
            'api_secret': 'some_api_secret',
            'regions': ['us-west-1'],
            'region': 'default-region-value',
            'private_key_path': 'some_private_key'
        }

        self.assertEqual(config, expected_config)
Example #2
0
    def _get_action_instance(self):
        try:
            actions_cls = action_loader.register_plugin(Action, self._file_path)
        except Exception as e:
            tb_msg = traceback.format_exc()
            msg = ('Failed to load action class from file "%s" (action file most likely doesn\'t '
                   'exist or contains invalid syntax): %s' % (self._file_path, str(e)))
            msg += '\n\n' + tb_msg
            exc_cls = type(e)
            raise exc_cls(msg)

        action_cls = actions_cls[0] if actions_cls and len(actions_cls) > 0 else None

        if not action_cls:
            raise Exception('File "%s" has no action class or the file doesn\'t exist.' %
                            (self._file_path))

        self._class_name = action_cls.__class__.__name__

        config_loader = ContentPackConfigLoader(pack_name=self._pack, user=self._user)
        config = config_loader.get_config()

        if config:
            LOG.info('Found config for action "%s"' % (self._file_path))
        else:
            LOG.info('No config found for action "%s"' % (self._file_path))
            config = None

        action_service = ActionService(action_wrapper=self)
        action_instance = get_action_class_instance(action_cls=action_cls,
                                                    config=config,
                                                    action_service=action_service)
        return action_instance
Example #3
0
    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()
Example #4
0
    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, {})
Example #5
0
    def test_ensure_local_pack_config_feature_removed(self):
        # Test a scenario where all the values are loaded from pack local
        # config and pack global config (pack name.yaml) doesn't exist.
        # Test a scenario where no values are overridden in the datastore
        loader = ContentPackConfigLoader(pack_name='dummy_pack_4')
        config = loader.get_config()
        expected_config = {}

        self.assertDictEqual(config, expected_config)
Example #6
0
    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, {})
Example #7
0
    def test_ensure_local_pack_config_feature_removed(self):
        # Test a scenario where all the values are loaded from pack local
        # config and pack global config (pack name.yaml) doesn't exist.
        # Test a scenario where no values are overridden in the datastore
        loader = ContentPackConfigLoader(pack_name='dummy_pack_4')
        config = loader.get_config()
        expected_config = {}

        self.assertDictEqual(config, expected_config)
Example #8
0
    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()
Example #9
0
    def _get_sensor_config(self):
        config_loader = ContentPackConfigLoader(pack_name=self._pack)
        config = config_loader.get_config()

        if config:
            self._logger.info('Found config for sensor "%s"' % (self._class_name))
        else:
            self._logger.info('No config found for sensor "%s"' % (self._class_name))

        return config
Example #10
0
    def _get_sensor_config(self):
        config_loader = ContentPackConfigLoader(pack_name=self._pack)
        config = config_loader.get_config()

        if config:
            self._logger.info('Found config for sensor "%s"' % (self._class_name))
        else:
            self._logger.info('No config found for sensor "%s"' % (self._class_name))

        return config
Example #11
0
    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()
Example #12
0
    def test_get_config_dynamic_config_item_under_additional_properties(self):
        pack_name = "dummy_pack_schema_with_additional_properties_1"
        loader = ContentPackConfigLoader(pack_name=pack_name)

        encrypted_value = crypto.symmetric_encrypt(KeyValuePairAPI.crypto_key,
                                                   "v1_encrypted")
        KeyValuePair.add_or_update(
            KeyValuePairDB(name="k1_encrypted",
                           value=encrypted_value,
                           secret=True))

        ####################
        # values in objects under an object with additionalProperties
        values = {
            "profiles": {
                "dev": {
                    # no host or port to test default value
                    "token": "hard-coded-secret",
                },
                "prod": {
                    "host": "127.1.2.7",
                    "port": 8282,
                    # encrypted in datastore
                    "token": "{{st2kv.system.k1_encrypted}}",
                    # schema declares `secret: true` which triggers auto-decryption.
                    # If this were not encrypted, it would try to decrypt it and fail.
                },
            }
        }
        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,
            {
                "region": "us-east-1",
                "profiles": {
                    "dev": {
                        "host": "127.0.0.3",
                        "port": 8080,
                        "token": "hard-coded-secret",
                    },
                    "prod": {
                        "host": "127.1.2.7",
                        "port": 8282,
                        "token": "v1_encrypted",
                    },
                },
            },
        )

        config_db.delete()
Example #13
0
    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()
Example #14
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')
Example #15
0
    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')
Example #16
0
    def test_get_config_all_values_are_loaded_from_local_config(self):
        # Test a scenario where all the values are loaded from pack local config and pack global
        # config (pack name.yaml) doesn't exist
        # Test a scenario where no values are overridden in the datastore
        loader = ContentPackConfigLoader(pack_name='dummy_pack_4')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'private_key_path': None
        }
        self.assertEqual(config, expected_config)
Example #17
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')
Example #18
0
    def test_get_config_all_values_are_loaded_from_local_config(self):
        # Test a scenario where all the values are loaded from pack local config and pack global
        # config (pack name.yaml) doesn't exist
        # Test a scenario where no values are overridden in the datastore
        loader = ContentPackConfigLoader(pack_name='dummy_pack_4')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'private_key_path': None
        }
        self.assertEqual(config, expected_config)
Example #19
0
    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.assertEqual(config_rendered, {"level0_key": "v1"})

        config_db.delete()
Example #20
0
    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.assertEqual(config_rendered, {'level0_key': 'v1'})

        config_db.delete()
Example #21
0
    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()
Example #22
0
    def _get_action_instance(self):
        actions_cls = action_loader.register_plugin(Action, self._file_path)
        action_cls = actions_cls[0] if actions_cls and len(actions_cls) > 0 else None

        if not action_cls:
            raise Exception('File "%s" has no action or the file doesn\'t exist.' % (self._file_path))

        config_loader = ContentPackConfigLoader(pack_name=self._pack, user=self._user)
        config = config_loader.get_config()

        if config:
            LOG.info('Found config for action "%s"' % (self._file_path))
        else:
            LOG.info('No config found for action "%s"' % (self._file_path))
            config = None

        action_service = ActionService(action_wrapper=self)
        action_instance = get_action_class_instance(action_cls=action_cls, config=config, action_service=action_service)
        return action_instance
Example #23
0
    def _get_runner(self, runnertype_db, action_db, liveaction_db):
        resolved_entry_point = self._get_entry_point_abs_path(
            action_db.pack, action_db.entry_point)
        context = getattr(liveaction_db, 'context', dict())
        user = context.get('user', cfg.CONF.system_user.user)

        # Note: Right now configs are only supported by the Python runner actions
        if runnertype_db.runner_module == 'python_runner':
            LOG.debug('Loading config for pack')

            config_loader = ContentPackConfigLoader(pack_name=action_db.pack,
                                                    user=user)
            config = config_loader.get_config()
        else:
            config = None

        runner = get_runner(package_name=runnertype_db.runner_package,
                            module_name=runnertype_db.runner_module,
                            config=config)

        # TODO: Pass those arguments to the constructor instead of late
        # assignment, late assignment is awful
        runner.runner_type_db = runnertype_db
        runner.action = action_db
        runner.action_name = action_db.name
        runner.liveaction = liveaction_db
        runner.liveaction_id = str(liveaction_db.id)
        runner.execution = ActionExecution.get(
            liveaction__id=runner.liveaction_id)
        runner.execution_id = str(runner.execution.id)
        runner.entry_point = resolved_entry_point
        runner.context = context
        runner.callback = getattr(liveaction_db, 'callback', dict())
        runner.libs_dir_path = self._get_action_libs_abs_path(
            action_db.pack, action_db.entry_point)

        # For re-run, get the ActionExecutionDB in which the re-run is based on.
        rerun_ref_id = runner.context.get('re-run', {}).get('ref')
        runner.rerun_ex_ref = ActionExecution.get(
            id=rerun_ref_id) if rerun_ref_id else None

        return runner
Example #24
0
    def _get_action_instance(self):
        try:
            actions_cls = action_loader.register_plugin(
                Action, self._file_path)
        except Exception as e:
            tb_msg = traceback.format_exc()
            msg = (
                'Failed to load action class from file "%s" (action file most likely doesn\'t '
                'exist or contains invalid syntax): %s' %
                (self._file_path, str(e)))
            msg += '\n\n' + tb_msg
            exc_cls = type(e)
            raise exc_cls(msg)

        action_cls = actions_cls[0] if actions_cls and len(
            actions_cls) > 0 else None

        if not action_cls:
            raise Exception(
                'File "%s" has no action class or the file doesn\'t exist.' %
                (self._file_path))

        self._class_name = action_cls.__class__.__name__

        config_loader = ContentPackConfigLoader(pack_name=self._pack,
                                                user=self._user)
        config = config_loader.get_config()

        if config:
            LOG.info('Found config for action "%s"' % (self._file_path))
        else:
            LOG.info('No config found for action "%s"' % (self._file_path))
            config = None

        action_service = ActionService(action_wrapper=self)
        action_instance = get_action_class_instance(
            action_cls=action_cls,
            config=config,
            action_service=action_service)
        return action_instance
Example #25
0
    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)
Example #26
0
    def _get_action_instance(self):
        actions_cls = action_loader.register_plugin(Action, self._file_path)
        action_cls = actions_cls[0] if actions_cls and len(actions_cls) > 0 else None

        if not action_cls:
            raise Exception('File "%s" has no action or the file doesn\'t exist.' %
                            (self._file_path))

        config_loader = ContentPackConfigLoader(pack_name=self._pack, user=self._user)
        config = config_loader.get_config()

        if config:
            LOG.info('Found config for action "%s"' % (self._file_path))
        else:
            LOG.info('No config found for action "%s"' % (self._file_path))
            config = None

        action_service = ActionService(action_wrapper=self)
        action_instance = get_action_class_instance(action_cls=action_cls,
                                                    config=config,
                                                    action_service=action_service)
        return action_instance
Example #27
0
    def _get_runner(self, runner_type_db, action_db, liveaction_db):
        resolved_entry_point = self._get_entry_point_abs_path(
            action_db.pack, action_db.entry_point)
        context = getattr(liveaction_db, "context", dict())
        user = context.get("user", cfg.CONF.system_user.user)
        config = None

        # Note: Right now configs are only supported by the Python runner actions
        if (runner_type_db.name == "python-script"
                or runner_type_db.runner_module == "python_runner"):
            LOG.debug("Loading config from pack for python runner.")
            config_loader = ContentPackConfigLoader(pack_name=action_db.pack,
                                                    user=user)
            config = config_loader.get_config()

        runner = get_runner(name=runner_type_db.name, config=config)

        # TODO: Pass those arguments to the constructor instead of late
        # assignment, late assignment is awful
        runner.runner_type = runner_type_db
        runner.action = action_db
        runner.action_name = action_db.name
        runner.liveaction = liveaction_db
        runner.liveaction_id = str(liveaction_db.id)
        runner.execution = ActionExecution.get(
            liveaction__id=runner.liveaction_id)
        runner.execution_id = str(runner.execution.id)
        runner.entry_point = resolved_entry_point
        runner.context = context
        runner.callback = getattr(liveaction_db, "callback", dict())
        runner.libs_dir_path = self._get_action_libs_abs_path(
            action_db.pack, action_db.entry_point)

        # For re-run, get the ActionExecutionDB in which the re-run is based on.
        rerun_ref_id = runner.context.get("re-run", {}).get("ref")
        runner.rerun_ex_ref = (ActionExecution.get(
            id=rerun_ref_id) if rerun_ref_id else None)

        return runner
Example #28
0
    def test_get_config_some_values_overriden_in_datastore(self):
        # Test a scenario where some values are overriden in datastore via pack
        # global config
        kvp_db = set_datastore_value_for_config_key(
            pack_name="dummy_pack_5",
            key_name="api_secret",
            value="some_api_secret",
            secret=True,
            user="******",
        )

        # This is a secret so a value should be encrypted
        self.assertTrue(kvp_db.value != "some_api_secret")
        self.assertTrue(len(kvp_db.value) > len("some_api_secret") * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(
            pack_name="dummy_pack_5",
            key_name="private_key_path",
            value="some_private_key",
        )
        self.assertEqual(kvp_db.value, "some_private_key")
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name="dummy_pack_5", user="******")
        config = loader.get_config()

        # regions is provided in the pack global config
        # api_secret is dynamically loaded from the datastore for a particular user
        expected_config = {
            "api_key": "some_api_key",
            "api_secret": "some_api_secret",
            "regions": ["us-west-1"],
            "region": "default-region-value",
            "private_key_path": "some_private_key",
            "non_required_with_default_value": "config value",
        }

        self.assertEqual(config, expected_config)
Example #29
0
    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()
Example #30
0
File: base.py Project: nzlosh/st2
    def _get_runner(self, runner_type_db, action_db, liveaction_db):
        resolved_entry_point = self._get_entry_point_abs_path(action_db.pack, action_db.entry_point)
        context = getattr(liveaction_db, 'context', dict())
        user = context.get('user', cfg.CONF.system_user.user)
        config = None

        # Note: Right now configs are only supported by the Python runner actions
        if (runner_type_db.name == 'python-script' or
                runner_type_db.runner_module == 'python_runner'):
            LOG.debug('Loading config from pack for python runner.')
            config_loader = ContentPackConfigLoader(pack_name=action_db.pack, user=user)
            config = config_loader.get_config()

        runner = get_runner(
            name=runner_type_db.name,
            config=config)

        # TODO: Pass those arguments to the constructor instead of late
        # assignment, late assignment is awful
        runner.runner_type = runner_type_db
        runner.action = action_db
        runner.action_name = action_db.name
        runner.liveaction = liveaction_db
        runner.liveaction_id = str(liveaction_db.id)
        runner.execution = ActionExecution.get(liveaction__id=runner.liveaction_id)
        runner.execution_id = str(runner.execution.id)
        runner.entry_point = resolved_entry_point
        runner.context = context
        runner.callback = getattr(liveaction_db, 'callback', dict())
        runner.libs_dir_path = self._get_action_libs_abs_path(action_db.pack,
                                                              action_db.entry_point)

        # For re-run, get the ActionExecutionDB in which the re-run is based on.
        rerun_ref_id = runner.context.get('re-run', {}).get('ref')
        runner.rerun_ex_ref = ActionExecution.get(id=rerun_ref_id) if rerun_ref_id else None

        return runner
Example #31
0
    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()
Example #32
0
    def test_get_config_some_values_overriden_in_datastore(self):
        # Test a scenario where some values are overriden in datastore via pack
        # flobal config
        kvp_db = set_datastore_value_for_config_key(pack_name='dummy_pack_5',
                                                    key_name='api_secret',
                                                    value='some_api_secret',
                                                    secret=True,
                                                    user='******')

        # This is a secret so a value should be encrypted
        self.assertTrue(kvp_db.value != 'some_api_secret')
        self.assertTrue(len(kvp_db.value) > len('some_api_secret') * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(
            pack_name='dummy_pack_5',
            key_name='private_key_path',
            value='some_private_key')
        self.assertEqual(kvp_db.value, 'some_private_key')
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name='dummy_pack_5', user='******')
        config = loader.get_config()

        # regions is provided in the pack global config
        # api_secret is dynamically loaded from the datastore for a particular user
        expected_config = {
            'api_key': 'some_api_key',
            'api_secret': 'some_api_secret',
            'regions': ['us-west-1'],
            'region': 'default-region-value',
            'private_key_path': 'some_private_key',
            'non_required_with_default_value': 'config value'
        }

        self.assertEqual(config, expected_config)
Example #33
0
    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()
Example #34
0
    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()
Example #35
0
    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')
Example #36
0
    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)
Example #37
0
    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)
Example #38
0
    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()
Example #39
0
    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')
Example #40
0
    def test_get_config_nested_schema_default_values_from_config_schema_are_used(
            self):
        # Special case for more complex config schemas with attributes ntesting.
        # Validate that the default values are also used for one level nested object properties.
        pack_name = "dummy_pack_schema_with_nested_object_1"

        # 1. None of the nested object values are provided
        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            "api_key": "",
            "api_secret": "",
            "regions": ["us-west-1", "us-east-1"],
            "auth_settings": {
                "host": "127.0.0.3",
                "port": 8080,
                "device_uids": ["a", "b", "c"],
            },
        }
        self.assertEqual(config, expected_config)

        # 2. Some of the nested object values are provided (host, port)
        pack_name = "dummy_pack_schema_with_nested_object_2"

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            "api_key": "",
            "api_secret": "",
            "regions": ["us-west-1", "us-east-1"],
            "auth_settings": {
                "host": "127.0.0.6",
                "port": 9090,
                "device_uids": ["a", "b", "c"],
            },
        }
        self.assertEqual(config, expected_config)

        # 3. Nested attribute (auth_settings.token) references a non-secret datastore value
        pack_name = "dummy_pack_schema_with_nested_object_3"

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name="auth_settings_token",
            value="some_auth_settings_token",
        )
        self.assertEqual(kvp_db.value, "some_auth_settings_token")
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            "api_key": "",
            "api_secret": "",
            "regions": ["us-west-1", "us-east-1"],
            "auth_settings": {
                "host": "127.0.0.10",
                "port": 8080,
                "device_uids": ["a", "b", "c"],
                "token": "some_auth_settings_token",
            },
        }
        self.assertEqual(config, expected_config)

        # 4. Nested attribute (auth_settings.token) references a secret datastore value
        pack_name = "dummy_pack_schema_with_nested_object_4"

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name="auth_settings_token",
            value="joe_token_secret",
            secret=True,
            user="******",
        )
        self.assertTrue(kvp_db.value != "joe_token_secret")
        self.assertTrue(len(kvp_db.value) > len("joe_token_secret") * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name="auth_settings_token",
            value="alice_token_secret",
            secret=True,
            user="******",
        )
        self.assertTrue(kvp_db.value != "alice_token_secret")
        self.assertTrue(len(kvp_db.value) > len("alice_token_secret") * 2)
        self.assertTrue(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name, user="******")
        config = loader.get_config()

        expected_config = {
            "api_key": "",
            "api_secret": "",
            "regions": ["us-west-1", "us-east-1"],
            "auth_settings": {
                "host": "127.0.0.11",
                "port": 8080,
                "device_uids": ["a", "b", "c"],
                "token": "joe_token_secret",
            },
        }
        self.assertEqual(config, expected_config)

        loader = ContentPackConfigLoader(pack_name=pack_name, user="******")
        config = loader.get_config()

        expected_config = {
            "api_key": "",
            "api_secret": "",
            "regions": ["us-west-1", "us-east-1"],
            "auth_settings": {
                "host": "127.0.0.11",
                "port": 8080,
                "device_uids": ["a", "b", "c"],
                "token": "alice_token_secret",
            },
        }
        self.assertEqual(config, expected_config)
Example #41
0
    def test_get_config_nested_schema_default_values_from_config_schema_are_used(
            self):
        # Special case for more complex config schemas with attributes ntesting.
        # Validate that the default values are also used for one level nested object properties.
        pack_name = 'dummy_pack_schema_with_nested_object_1'

        # 1. None of the nested object values are provided
        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.3',
                'port': 8080,
                'device_uids': ['a', 'b', 'c']
            }
        }
        self.assertEqual(config, expected_config)

        # 2. Some of the nested object values are provided (host, port)
        pack_name = 'dummy_pack_schema_with_nested_object_2'

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.6',
                'port': 9090,
                'device_uids': ['a', 'b', 'c']
            }
        }
        self.assertEqual(config, expected_config)

        # 3. Nested attribute (auth_settings.token) references a non-secret datastore value
        pack_name = 'dummy_pack_schema_with_nested_object_3'

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name='auth_settings_token',
            value='some_auth_settings_token')
        self.assertEqual(kvp_db.value, 'some_auth_settings_token')
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.10',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'some_auth_settings_token'
            }
        }
        self.assertEqual(config, expected_config)

        # 4. Nested attribute (auth_settings.token) references a secret datastore value
        pack_name = 'dummy_pack_schema_with_nested_object_4'

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name='auth_settings_token',
            value='joe_token_secret',
            secret=True,
            user='******')
        self.assertTrue(kvp_db.value != 'joe_token_secret')
        self.assertTrue(len(kvp_db.value) > len('joe_token_secret') * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(
            pack_name=pack_name,
            key_name='auth_settings_token',
            value='alice_token_secret',
            secret=True,
            user='******')
        self.assertTrue(kvp_db.value != 'alice_token_secret')
        self.assertTrue(len(kvp_db.value) > len('alice_token_secret') * 2)
        self.assertTrue(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name, user='******')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.11',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'joe_token_secret'
            }
        }
        self.assertEqual(config, expected_config)

        loader = ContentPackConfigLoader(pack_name=pack_name, user='******')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.11',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'alice_token_secret'
            }
        }
        self.assertEqual(config, expected_config)
Example #42
0
    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()
Example #43
0
    def test_get_config_nested_schema_default_values_from_config_schema_are_used(self):
        # Special case for more complex config schemas with attributes ntesting.
        # Validate that the default values are also used for one level nested object properties.
        pack_name = 'dummy_pack_schema_with_nested_object_1'

        # 1. None of the nested object values are provided
        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.3',
                'port': 8080,
                'device_uids': ['a', 'b', 'c']
            }
        }
        self.assertEqual(config, expected_config)

        # 2. Some of the nested object values are provided (host, port)
        pack_name = 'dummy_pack_schema_with_nested_object_2'

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.6',
                'port': 9090,
                'device_uids': ['a', 'b', 'c']
            }
        }
        self.assertEqual(config, expected_config)

        # 3. Nested attribute (auth_settings.token) references a non-secret datastore value
        pack_name = 'dummy_pack_schema_with_nested_object_3'

        kvp_db = set_datastore_value_for_config_key(pack_name=pack_name,
                                                    key_name='auth_settings_token',
                                                    value='some_auth_settings_token')
        self.assertEqual(kvp_db.value, 'some_auth_settings_token')
        self.assertFalse(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name)
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.10',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'some_auth_settings_token'
            }
        }
        self.assertEqual(config, expected_config)

        # 4. Nested attribute (auth_settings.token) references a secret datastore value
        pack_name = 'dummy_pack_schema_with_nested_object_4'

        kvp_db = set_datastore_value_for_config_key(pack_name=pack_name,
                                                    key_name='auth_settings_token',
                                                    value='joe_token_secret',
                                                    secret=True,
                                                    user='******')
        self.assertTrue(kvp_db.value != 'joe_token_secret')
        self.assertTrue(len(kvp_db.value) > len('joe_token_secret') * 2)
        self.assertTrue(kvp_db.secret)

        kvp_db = set_datastore_value_for_config_key(pack_name=pack_name,
                                                    key_name='auth_settings_token',
                                                    value='alice_token_secret',
                                                    secret=True,
                                                    user='******')
        self.assertTrue(kvp_db.value != 'alice_token_secret')
        self.assertTrue(len(kvp_db.value) > len('alice_token_secret') * 2)
        self.assertTrue(kvp_db.secret)

        loader = ContentPackConfigLoader(pack_name=pack_name, user='******')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.11',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'joe_token_secret'
            }
        }
        self.assertEqual(config, expected_config)

        loader = ContentPackConfigLoader(pack_name=pack_name, user='******')
        config = loader.get_config()

        expected_config = {
            'api_key': '',
            'api_secret': '',
            'regions': ['us-west-1', 'us-east-1'],
            'auth_settings': {
                'host': '127.0.0.11',
                'port': 8080,
                'device_uids': ['a', 'b', 'c'],
                'token': 'alice_token_secret'
            }
        }
        self.assertEqual(config, expected_config)