def setUp(self): """ Create params/groups for each test """ names = ["my_param", "my_grouped_param"] self._create_params(names) self.cache = SSMParameter("my_param") self.group = SSMParameterGroup() self.grouped_param = self.group.parameter("my_grouped_param")
def test_hierarchy(self): """ Test group hierarchy """ group = SSMParameterGroup() params = group.parameters(self.HIERARCHY_PREPATH) self.assertEqual(len(group), self.GROUP_SIZE) for parameter in params: self.assertEqual(parameter.value, self.PARAM_VALUE) self.assertTrue(self.HIERARCHY_PREPATH in parameter.name)
def test_hierarchy_root(self): """ Test group hierarchy root """ group = SSMParameterGroup() params = group.parameters(self.HIERARCHY_ROOT) self.assertEqual(len(params), self.GROUP_SIZE * 2) self.assertEqual(len(group), self.GROUP_SIZE * 2) for parameter in params: self.assertTrue(self.HIERARCHY_ROOT in parameter.name)
def test_hierarchy_prefix_single(self): """ Test group hierarchy prefix with single parameter """ group = SSMParameterGroup(base_path=self.HIERARCHY_ROOT) param = group.parameter("%s/my_param_1" % self.HIERARCHY_PREPATH_SIMPLE) self.assertEqual(len(group), 1) self.assertTrue(self.HIERARCHY_PREPATH in param.name) self.assertTrue(self.HIERARCHY_ROOT in param.name) self.assertEqual(param.value, self.PARAM_VALUE)
def test_hierarchy_with_lists(self): """ Test group hierarchy with lists """ group = SSMParameterGroup() params = group.parameters(self.HIERARCHY_PREPATH_LIST) self.assertEqual(len(group), self.GROUP_SIZE) for parameter in params: self.assertIsInstance(parameter.value, list) for value in parameter.value: self.assertEqual(value, self.PARAM_VALUE) self.assertTrue(self.HIERARCHY_PREPATH_LIST in parameter.name)
def test_hierarchy_prefix_mixed(self): """ Test group hierarchy prefix with mixed parameters """ group = SSMParameterGroup(base_path=self.HIERARCHY_ROOT) param = group.parameter("%s/my_param_1" % self.HIERARCHY_PREPATH_SIMPLE) params_1 = group.parameters(self.HIERARCHY_PREPATH_SIMPLE) params_2 = group.parameters(self.HIERARCHY_PREPATH_LIST_SIMPLE) self.assertIsInstance(param, SSMParameter) self.assertEqual(len(params_1), self.GROUP_SIZE) self.assertEqual(len(params_2), self.GROUP_SIZE) self.assertEqual(len(group), self.GROUP_SIZE * 2)
def test_with_valid_client(self): """ Test invalid client (without required methods) """ # pylint: disable=unused-argument,no-self-use class MyValidClient(object): """ This client has all the required methods """ def get_parameters(self, *args, **kwargs): """ Mock method """ return { 'InvalidParameters': [], 'Parameters': [ { "Type": "String", "Name": "my_param", "Value": "abc123", "Version": 1 }, ], } def get_parameters_by_path(self, *args, **kwargs): """ Mock method """ return { "Parameters": [ { "Type": "String", "Name": "/foo/bar/1", "Value": "abc123", "Version": 1 }, { "Type": "String", "Name": "/foo/bar/2", "Value": "abc123", "Version": 1 }, ] } client = MyValidClient() SSMParameter.set_ssm_client(client) param = SSMParameter("my_param") self.assertEqual(param.value, self.PARAM_VALUE) group = SSMParameterGroup() param = group.parameter("my_param") self.assertEqual(param.value, self.PARAM_VALUE) params = group.parameters("/foo/bar/") self.assertEqual(len(params), 2) for param in params: self.assertEqual(param.value, self.PARAM_VALUE)
def test_main_with_param_group(self): group = SSMParameterGroup() param_1 = group.parameter("my_param_1") param_2 = group.parameter("my_param_2") param_3 = group.parameter("my_param_3") # one by one my_value_1 = param_1.value my_value_2 = param_2.value my_value_3 = param_3.value self.assertEqual(my_value_1, self.PARAM_VALUE) self.assertEqual(my_value_2, self.PARAM_VALUE) self.assertEqual(my_value_3, self.PARAM_VALUE)
def test_hierarchy_multiple_overlap(self): """ Test group hierarchy multiple overlapping calls """ group = SSMParameterGroup() params_1 = group.parameters(self.HIERARCHY_PREPATH) params_all = group.parameters(self.HIERARCHY_ROOT) self.assertEqual(len(params_1), self.GROUP_SIZE) self.assertEqual(len(params_all), self.GROUP_SIZE * 2) self.assertEqual(len(group), self.GROUP_SIZE * 2) for parameter in params_1: self.assertTrue(self.HIERARCHY_PREPATH in parameter.name) self.assertTrue(self.HIERARCHY_ROOT in parameter.name) for parameter in params_all: self.assertTrue(self.HIERARCHY_ROOT in parameter.name)
def test_hierarchy_prefix_errors(self): """ Test group hierarchy prefix errors """ with self.assertRaises(InvalidPathError): _ = SSMParameterGroup(base_path="InvalidPrefix") group = SSMParameterGroup(base_path=self.HIERARCHY_ROOT) # note: this raises only because the group has a base path with self.assertRaises(InvalidPathError): _ = group.parameter("InvalidPath") with self.assertRaises(InvalidPathError): _ = group.parameters("InvalidPath")
def test_group_string_list(self): """ Test StringList expiration """ group = SSMParameterGroup() my_param = group.parameter("my_param_1") self.assertEqual(my_param.value, self.PARAM_VALUE) my_params_list = group.parameter("my_params_list") values = my_params_list.value self.assertTrue(isinstance(values, list)) self.assertEqual(len(values), self.PARAM_LIST_COUNT) for value in values: self.assertEqual(value, self.PARAM_VALUE)
def test_hierarchy_recursive(self): """ Test group hierarchy prefix (recursive) """ names = [ "/PrefixRecursive/Foo/Baz/1", "/PrefixRecursive/Foo/Baz/2", "/PrefixRecursive/Foo/Baz/Taz/1", "/PrefixRecursive/Foo/Baz/Taz/2", ] self._create_params(names) group = SSMParameterGroup(base_path="/PrefixRecursive/Foo") baz_params = group.parameters("/Baz") self.assertEqual(len(baz_params), 4) self.assertEqual(len(group), 4)
def test_creation(self): # single string cache = SSMParameter("my_param") self.assertTrue(cache._with_decryption) self.assertIsNone(cache._max_age) self.assertIsNone(cache._last_refresh_time) # invalid params with self.assertRaises(TypeError): SSMParameter() with self.assertRaises(ValueError): SSMParameter(None) group = SSMParameterGroup() parameter = group.parameter("my_param") with self.assertRaises(TypeError): group.parameter()
def test_creation(self): """ Test regular creation """ # single string param = SSMParameter("my_param") self.assertTrue(param._with_decryption) self.assertIsNone(param._max_age) self.assertIsNone(param._last_refresh_time) # invalid params with self.assertRaises(TypeError): SSMParameter() # pylint: disable=no-value-for-parameter with self.assertRaises(ValueError): SSMParameter(None) group = SSMParameterGroup() param = group.parameter("my_param") with self.assertRaises(TypeError): group.parameter() # pylint: disable=no-value-for-parameter
def test_hierarchy_prefix_complex(self): """ Test group hierarchy prefix (complex) """ names = [ "/PrefixComplex/Foo/Bar", "/PrefixComplex/Foo/Baz/1", "/PrefixComplex/Foo/Baz/2", "/PrefixComplex/Foo/Taz/1", "/PrefixComplex/Foo/Taz/2", ] self._create_params(names) group = SSMParameterGroup(base_path="/PrefixComplex/Foo") bar_param = group.parameter("/Bar") baz_params = group.parameters("/Baz") taz_params = group.parameters("/Taz") self.assertIsInstance(bar_param, SSMParameter) self.assertEqual(len(baz_params), 2) self.assertEqual(len(taz_params), 2) self.assertEqual(len(group), 5)
def test_hierarchy_multiple(self): """ Test group hierarchy multiple calls """ group = SSMParameterGroup() params_1 = group.parameters(self.HIERARCHY_PREPATH) params_2 = group.parameters(self.HIERARCHY_PREPATH_LIST) self.assertEqual(len(params_1), self.GROUP_SIZE) self.assertEqual(len(params_2), self.GROUP_SIZE) self.assertEqual(len(group), self.GROUP_SIZE * 2) for parameter in params_1: self.assertTrue(self.HIERARCHY_PREPATH in parameter.name) self.assertTrue(self.HIERARCHY_ROOT in parameter.name) self.assertTrue(parameter.name.startswith(self.HIERARCHY_PREPATH)) for parameter in params_2: self.assertTrue(self.HIERARCHY_PREPATH_LIST in parameter.name) self.assertTrue(self.HIERARCHY_ROOT in parameter.name) self.assertTrue( parameter.name.startswith(self.HIERARCHY_PREPATH_LIST))
def test_hierarchy_prefix(self): """ Test group hierarchy prefix with multiple parameters """ group = SSMParameterGroup(base_path=self.HIERARCHY_ROOT) params_1 = group.parameters(self.HIERARCHY_PREPATH_SIMPLE) params_2 = group.parameters(self.HIERARCHY_PREPATH_LIST_SIMPLE) self.assertEqual(len(params_1), self.GROUP_SIZE) self.assertEqual(len(params_2), self.GROUP_SIZE) self.assertEqual(len(group), self.GROUP_SIZE * 2) for parameter in params_1: self.assertTrue(self.HIERARCHY_PREPATH in parameter.name) self.assertTrue(self.HIERARCHY_ROOT in parameter.name) self.assertTrue(parameter.name.startswith(self.HIERARCHY_PREPATH)) for parameter in params_2: self.assertTrue(self.HIERARCHY_PREPATH_LIST in parameter.name) self.assertTrue(self.HIERARCHY_ROOT in parameter.name) self.assertTrue( parameter.name.startswith(self.HIERARCHY_PREPATH_LIST))
def test_versions_group_select(self): """ Test version selection in a group """ method_name = sys._getframe().f_code.co_name self._setUp(method_name) name = method_name self._create_or_update_param(name) # this will update the value and create version 2 self._create_or_update_param(name, self.PARAM_VALUE_V2) group = SSMParameterGroup() param = group.parameter("%s:1" % name) self.assertEqual(param.version, 1) self.assertEqual(param.value, self.PARAM_VALUE) self._delete_param(name)
def test_unexisting_in_group(self): """ Test unexisting parameter in group case """ group = SSMParameterGroup() _ = group.secret("my_secret_1") __ = group.secret("my_secret_unexisting") with self.assertRaises(InvalidParameterError): group.refresh()
def test_main_with_explicit_refresh_of_group_param(self): group = SSMParameterGroup() # will not expire param_1 = group.parameter("my_param_1") param_2 = group.parameter("my_param_2") class InvalidCredentials(Exception): pass def do_something(): my_value = param_1.value if my_value == self.PARAM_VALUE: raise InvalidCredentials() try: do_something() except InvalidCredentials: # manually update value NEW_VALUE = "new_value" self._create_params(["my_param_1", "my_param_2"], NEW_VALUE) param_1.refresh() # force refresh do_something() # won't fail anymore self.assertEqual(param_2.value, NEW_VALUE)
def test_versions_group(self): """ Test version update in a group """ method_name = sys._getframe().f_code.co_name self._setUp(method_name) name = method_name self._create_or_update_param(name) group = SSMParameterGroup() param = group.parameter(name) self.assertEqual(param.version, 1) self.assertEqual(param.value, self.PARAM_VALUE) # this will update the value and create version 2 self._create_or_update_param(name, self.PARAM_VALUE_V2) group.refresh() # refreshing should give you version 2 self.assertEqual(param.version, 2) self.assertEqual(param.value, self.PARAM_VALUE_V2) self._delete_param(name)
def test_explicit_refresh_param(self): """ Test group refresh on param case """ group = SSMParameterGroup() # will not expire param_1 = group.parameter("my_param_1") param_2 = group.parameter("my_param_2") class InvalidCredentials(Exception): """ Mock exception class """ def do_something(): """ Raise an exception until the value has changed """ my_value = param_1.value if my_value == self.PARAM_VALUE: raise InvalidCredentials() try: do_something() except InvalidCredentials: # manually update value new_value = "new_value" self._create_params(["my_param_1", "my_param_2"], new_value) param_1.refresh() # force refresh do_something() # won't fail anymore self.assertEqual(param_2.value, new_value)
def test_main_with_expiration_group(self): """ Test group case with expiration """ group = SSMParameterGroup(max_age=300) param_1 = group.parameter("my_param_1") param_2 = group.parameter("my_param_2") param_3 = group.parameter("my_param_3") # individual params don't share max_age internally (for now) for param in (param_1, param_2, param_3): self.assertEqual(param._max_age, None) # force fetch group.refresh() # pretend time has passed (for the group) group._last_refresh_time = datetime.utcnow() - timedelta(seconds=301) self.assertTrue(group._should_refresh()) self.assertTrue(param_1._should_refresh()) self.assertTrue(param_2._should_refresh()) self.assertTrue(param_3._should_refresh())
def test_creation(self): """ Test regular creation """ # single string param = SecretsManagerParameter("my_secret") self.assertTrue(param._with_decryption) self.assertIsNone(param._max_age) self.assertIsNone(param._last_refresh_time) self.assertTrue(param._name.startswith(SecretsManagerParameter.PREFIX)) # invalid params with self.assertRaises(TypeError): SecretsManagerParameter() # pylint: disable=no-value-for-parameter with self.assertRaises(ValueError): SecretsManagerParameter(None) with self.assertRaises(InvalidParameterError): SecretsManagerParameter("/my_secret") group = SSMParameterGroup() secret = group.secret("my_secret") with self.assertRaises(TypeError): group.secret() # pylint: disable=no-value-for-parameter with self.assertRaises(InvalidParameterError): group.secret("/my_secret")
def get_param(self, name): group = SSMParameterGroup(base_path=self.path) return group.parameter("/{}".format(name))
def get_params(self): group = SSMParameterGroup(base_path=self.path) for ssm_param in group.parameters("/"): yield Param(ssm_param)
def get_stages(project): project_path = (Path("/") / project).as_posix() group = SSMParameterGroup(base_path=project_path) param_paths = [Path(x.full_name) for x in group.parameters("/")] stage_names = set(p.parts[2] for p in param_paths) return [Stage(project, x) for x in stage_names]
from ssm_cache import SSMParameterGroup app_envs = SSMParameterGroup(base_path="/scenario_6/app", max_age=300) SECRET_KEY = app_envs.parameter('/SECRET_KEY').value AWS_STORAGE_BUCKET_NAME = app_envs.parameter('/AWS_STORAGE_BUCKET_NAME').value CLOUDFRONT_URL = app_envs.parameter('/CLOUDFRONT_URL').value CLOUDFRONT_PRIVATE_KEY = app_envs.parameter('/CLOUDFRONT_PRIVATE_KEY').value CLOUDFRONT_KEY_PAIR_ID = app_envs.parameter('/CLOUDFRONT_KEY_PAIR_ID').value DB_NAME = app_envs.parameter('/DB_NAME').value DB_USER = app_envs.parameter('/DB_USER').value DB_PASSWORD = app_envs.parameter('/DB_PASSWORD').value DB_HOST = app_envs.parameter('/DB_HOST').value DB_PORT = app_envs.parameter('/DB_PORT').value
def setUp(self): names = ["my_param", "my_grouped_param"] self._create_params(names) self.cache = SSMParameter("my_param") self.group = SSMParameterGroup() self.grouped_param = self.group.parameter("my_grouped_param")
class TestSSMCacheDecorator(TestBase): def setUp(self): names = ["my_param", "my_grouped_param"] self._create_params(names) self.cache = SSMParameter("my_param") self.group = SSMParameterGroup() self.grouped_param = self.group.parameter("my_grouped_param") def test_decorator_simple(self): @self.cache.refresh_on_error() def my_function(is_retry=False): if not is_retry: raise Exception("raising an error") else: return "OK" self.assertEqual("OK", my_function()) def test_decorator_grouped_simple(self): @self.group.refresh_on_error() def my_function(is_retry=False): if not is_retry: raise Exception("raising an error") else: return "OK" self.assertEqual("OK", my_function()) def test_decorator_error_class(self): """ Special error is handled, if given """ @self.cache.refresh_on_error(MySpecialError) def my_function(is_retry=False): if not is_retry: raise MySpecialError("raising a special error") else: return "OK" self.assertEqual("OK", my_function()) def test_decorator_error_class_raise(self): """ Generic errors are not handled, if error_class is given """ @self.cache.refresh_on_error(MySpecialError) def my_function(is_retry=False): if not is_retry: raise Exception("raising a regular error") else: return "OK" with self.assertRaises(Exception): my_function() def test_decorator_callback(self): """ Callback is invoked on error, if provided """ callback = mock.Mock() @self.cache.refresh_on_error(Exception, callback) def my_function(is_retry=False): if not is_retry: raise Exception("raising a regular error") else: return "OK" self.assertEqual("OK", my_function()) self.assertEqual(1, callback.call_count) def test_decorator_callback_invalid(self): """ Error if non-collable callback """ with self.assertRaises(TypeError): @self.cache.refresh_on_error(Exception, "invalid_callable") def my_function(is_retry=False): pass def test_decorator_retry_argument(self): """ Retry argument can be customized """ @self.cache.refresh_on_error(retry_argument='my_retry_name') def my_function(my_retry_name=False): if not my_retry_name: raise Exception("raising a regular error") else: return "OK" self.assertEqual("OK", my_function()) def test_decorator_recursion(self): """ Only the first exception is handled """ @self.cache.refresh_on_error() def my_function(is_retry=False): raise Exception("%s" % is_retry) with self.assertRaises(Exception) as cm: my_function() self.assertEqual(str(cm.exception), "True") def test_decorator_all_together(self): """ All the decorator features should work together """ data = { "result": "KO", } def callback(): data['result'] = "OK" @self.cache.refresh_on_error(MySpecialError, callback, retry_argument="my_retry_name") def my_function(my_retry_name=False): if not my_retry_name: raise MySpecialError("raising a special error") else: return data['result'] self.assertEqual("OK", my_function())