def test_set_config(self): self.setup_existing_params() differences = [[ 'change', 'DUMMY_VAR12', ('dummy_values_12', 'test_change') ], [ 'add', '', [('DUMMY_VAR20', 'test_add_20'), ('DUMMY_VAR21', 'test_add_21')] ], [ 'remove', '', [('DUMMY_VAR13', 'dummy_values_13'), ('DUMMY_VAR10', 'dummy_values_10')] ]] store_object = ParameterStore('test-service', 'dummy-staging') store_object.set_config(differences) response = store_object.get_existing_config() assert response == { u'DUMMY_VAR12': u'test_change', u'DUMMY_VAR11': u'dummy_values_11', u'DUMMY_VAR8': u'dummy_values_8', u'DUMMY_VAR9': u'dummy_values_9', u'DUMMY_VAR0': u'dummy_values_0', u'DUMMY_VAR1': u'dummy_values_1', u'DUMMY_VAR2': u'dummy_values_2', u'DUMMY_VAR3': u'dummy_values_3', u'DUMMY_VAR4': u'dummy_values_4', u'DUMMY_VAR5': u'dummy_values_5', u'DUMMY_VAR6': u'dummy_values_6', u'DUMMY_VAR7': u'dummy_values_7', u'DUMMY_VAR20': u'test_add_20', u'DUMMY_VAR21': u'test_add_21' }
def test_set_config_validation(self, capsys): self.setup_environment_config() self.setup_existing_params() invalid_differences = [[ 'change', 'DUMMY_VAR12', ('dummy_values_12', '') ], ['add', '', [('DUMMY_VAR22', ''), ('DUMMY_VAR*', 'valid_value')]]] store_object = ParameterStore('test-service', 'dummy-staging') with pytest.raises(SystemExit) as pytest_wrapped_e: store_object.set_config(invalid_differences) captured = capsys.readouterr() assert captured.out == "'' is not a valid value for key 'DUMMY_VAR12'\n'' is not a valid value for key 'DUMMY_VAR22'\n'DUMMY_VAR*' is not a valid key.\n" assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.value.code == 1 response = store_object.get_existing_config() assert response == { u'DUMMY_VAR12': u'dummy_values_12', u'DUMMY_VAR11': u'dummy_values_11', u'DUMMY_VAR8': u'dummy_values_8', u'DUMMY_VAR9': u'dummy_values_9', u'DUMMY_VAR0': u'dummy_values_0', u'DUMMY_VAR1': u'dummy_values_1', u'DUMMY_VAR2': u'dummy_values_2', u'DUMMY_VAR3': u'dummy_values_3', u'DUMMY_VAR4': u'dummy_values_4', u'DUMMY_VAR5': u'dummy_values_5', u'DUMMY_VAR6': u'dummy_values_6', u'DUMMY_VAR7': u'dummy_values_7', u'DUMMY_VAR13': u'dummy_values_13', u'DUMMY_VAR10': u'dummy_values_10' }
def test_get_existing_config(self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client mock_client.get_parameters_by_path.return_value = { 'Parameters': [{ 'Name': '/staging/test-service/DUMMY_VAR{}'.format(i), 'Value': 'dummy_values_{}'.format(i) } for i in range(0, 4)] } store_object = ParameterStore('test-service', 'staging') env_configs, sidecar_configs = store_object.get_existing_config() assert env_configs == { u'DUMMY_VAR0': u'dummy_values_0', u'DUMMY_VAR1': u'dummy_values_1', u'DUMMY_VAR2': u'dummy_values_2', u'DUMMY_VAR3': u'dummy_values_3' } assert sidecar_configs == {} mock_client.get_parameters_by_path.assert_called_with( Path='/staging/test-service/', Recursive=True, WithDecryption=True, MaxResults=10)
def test_get_existing_config_as_string_for_sidecars( self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client mock_client.get_parameters_by_path.return_value = { 'Parameters': [ { 'Name': '/staging/test-service/DUMMY_VAR0', 'Value': 'dummy_values_0' }, { 'Name': '/staging/test-service/sidecars/redis/KEY1', 'Value': 'value1' }, { 'Name': '/staging/test-service/sidecars/redis/KEY2', 'Value': 'value2' }, { 'Name': '/staging/test-service/sidecars/nginx/WORKER_COUNT', 'Value': '2' }, ] } store_object = ParameterStore('test-service', 'staging') assert store_object.get_existing_config_as_string( 'redis') == """KEY1=value1 KEY2=value2""" assert store_object.get_existing_config_as_string( 'nginx') == "WORKER_COUNT=2"
def test_get_existing_config_as_string(self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client mock_client.get_parameters_by_path.return_value = { 'Parameters': [{ 'Name': '/staging/test-service/DUMMY_VAR{}'.format(i), 'Value': 'dummy_values_{}'.format(i) } for i in range(0, 4)] } store_object = ParameterStore('test-service', 'staging') env_configs = store_object.get_existing_config_as_string() assert env_configs == """DUMMY_VAR0=dummy_values_0
def test_get_existing_config_with_sidecars(self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client mock_client.get_parameters_by_path.return_value = { 'Parameters': [ { 'Name': '/staging/test-service/DUMMY_VAR0', 'Value': 'dummy_values_0' }, { 'Name': '/staging/test-service/sidecars/redis/KEY1', 'Value': 'value1' }, { 'Name': '/staging/test-service/sidecars/redis/KEY2', 'Value': 'value2' }, { 'Name': '/staging/test-service/sidecars/nginx/WORKER_COUNT', 'Value': '2' }, ] } store_object = ParameterStore('test-service', 'staging') env_config, sidecars_config = store_object.get_existing_config() assert env_config == {u'DUMMY_VAR0': u'dummy_values_0'} assert sidecars_config == { 'redis': { 'KEY1': 'value1', 'KEY2': 'value2' }, 'nginx': { 'WORKER_COUNT': '2' }, } mock_client.get_parameters_by_path.assert_called_with( Path='/staging/test-service/', Recursive=True, WithDecryption=True, MaxResults=10)
def _get_parameter_store_config(service_name, env_name): try: environment_config, _ = ParameterStore( service_name, env_name).get_existing_config_paths() except Exception as err: log_intent(str(err)) ex_msg = f"Cannot find the configuration in parameter store [env: ${env_name} | service: ${service_name}]." raise UnrecoverableException(ex_msg) return environment_config
def test_initialization(self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client store_object = ParameterStore('test-service', 'staging') mock_get_client_for.assert_called_with('ssm', 'staging') assert store_object.environment == 'staging' assert store_object.service_name == 'test-service' assert store_object.path_prefix == '/staging/test-service/'
def edit_config(name, environment): parameter_store = ParameterStore(name, environment) env_config_strings = parameter_store.get_existing_config_as_string() edited_config_content = click.edit(str(env_config_strings)) if edited_config_content is None: log_warning("No changes made, exiting.") return differences = list( dictdiffer.diff(read_config(env_config_strings), read_config(edited_config_content))) if not differences: log_warning("No changes made, exiting.") else: print_parameter_changes(differences) if click.confirm('Do you want update the config?'): parameter_store.set_config(differences) else: log_warning("Changes aborted.")
def test_set_config_for_sidecars(self, mock_get_client_for): mock_client = MagicMock() mock_get_client_for.return_value = mock_client differences = [[ 'change', 'DUMMY_VAR12', ('dummy_values_12', 'test_change') ], [ 'add', '', [('DUMMY_VAR20', 'test_add_20'), ('DUMMY_VAR21', 'test_add_21')] ], [ 'remove', '', [('DUMMY_VAR13', 'dummy_values_13'), ('DUMMY_VAR10', 'dummy_values_10')] ]] store_object = ParameterStore('test-service', 'dummy-staging') store_object.set_config(differences, 'nginx') mock_client.put_parameter.assert_has_calls([ call(Name='/dummy-staging/test-service/sidecars/nginx/DUMMY_VAR12', Value='test_change', Type='SecureString', KeyId='alias/aws/ssm', Overwrite=True), call(Name='/dummy-staging/test-service/sidecars/nginx/DUMMY_VAR20', Value='test_add_20', Type='SecureString', KeyId='alias/aws/ssm', Overwrite=False), call(Name='/dummy-staging/test-service/sidecars/nginx/DUMMY_VAR21', Value='test_add_21', Type='SecureString', KeyId='alias/aws/ssm', Overwrite=False), ]) mock_client.delete_parameters.assert_called_with(Names=[ '/dummy-staging/test-service/sidecars/nginx/DUMMY_VAR13', '/dummy-staging/test-service/sidecars/nginx/DUMMY_VAR10' ])
def test_get_existing_config(self): self.setup_existing_params() store_object = ParameterStore('test-service', 'dummy-staging') response = store_object.get_existing_config() assert response == { u'DUMMY_VAR12': u'dummy_values_12', u'DUMMY_VAR13': u'dummy_values_13', u'DUMMY_VAR10': u'dummy_values_10', u'DUMMY_VAR11': u'dummy_values_11', u'DUMMY_VAR8': u'dummy_values_8', u'DUMMY_VAR9': u'dummy_values_9', u'DUMMY_VAR0': u'dummy_values_0', u'DUMMY_VAR1': u'dummy_values_1', u'DUMMY_VAR2': u'dummy_values_2', u'DUMMY_VAR3': u'dummy_values_3', u'DUMMY_VAR4': u'dummy_values_4', u'DUMMY_VAR5': u'dummy_values_5', u'DUMMY_VAR6': u'dummy_values_6', u'DUMMY_VAR7': u'dummy_values_7' }
def test_set_config_validation(self, mock_get_client_for, mock_log_err): mock_client = MagicMock() mock_get_client_for.return_value = mock_client invalid_differences = [[ 'change', 'DUMMY_VAR12', ('dummy_values_12', '') ], ['add', '', [('DUMMY_VAR22', ''), ('DUMMY_VAR*', 'valid_value')]]] store_object = ParameterStore('test-service', 'dummy-staging') with pytest.raises(UnrecoverableException) as pytest_wrapped_e: store_object.set_config(invalid_differences) mock_log_err.assert_called_with("'DUMMY_VAR*' is not a valid key.") assert pytest_wrapped_e.type == UnrecoverableException assert str( pytest_wrapped_e.value ) == "'Environment variables validation failed with above errors.'" with pytest.raises(UnrecoverableException) as pytest_wrapped_e: store_object.set_config(invalid_differences, sidecar_name='nginx') mock_log_err.assert_called_with("'DUMMY_VAR*' is not a valid key.") assert pytest_wrapped_e.type == UnrecoverableException assert str( pytest_wrapped_e.value ) == "'Environment variables validation failed with above errors.'"
def build_config(env_name, service_name, sample_env_file_path): service_config = read_config(open(sample_env_file_path).read()) try: environment_config = ParameterStore(service_name, env_name).get_existing_config() except Exception as err: log_intent(str(err)) raise UnrecoverableException( "Cannot find the configuration in parameter store \ [env: %s | service: %s]." % (env_name, service_name)) missing_env_config = set(service_config) - set(environment_config) if missing_env_config: raise UnrecoverableException('There is no config value for the keys ' + str(missing_env_config)) missing_env_sample_config = set(environment_config) - set(service_config) if missing_env_sample_config: raise UnrecoverableException( 'There is no config value for the keys in env.sample file ' + str(missing_env_sample_config)) return make_container_defn_env_conf(service_config, environment_config)
def edit_config(name, environment, sidecar_name, no_editor=False, values=None, confirm=False): if values is None: values = {} parameter_store = ParameterStore(name, environment) env_config_strings = parameter_store.get_existing_config_as_string(sidecar_name) if no_editor: differences = list() split_env_configs = list(map(lambda x: x.split('='), env_config_strings.split('\n'))) for key, value in values.items(): existing = next(d for d in split_env_configs if d[0] == key) if existing: differences.append(('change', key, (existing[1], value))) else: differences.append(('add', '', [(key, value)])) print_parameter_changes(differences) if confirm or click.confirm('Do you want update the config?'): parameter_store.set_config(differences, sidecar_name) else: log_warning("Changes aborted.") else: edited_config_content = click.edit(str(env_config_strings), extension=".properties") if edited_config_content is None: log_warning("No changes made, exiting.") return differences = list(dictdiffer.diff( read_config(env_config_strings), read_config(edited_config_content) )) if not differences: log_warning("No changes made, exiting.") else: print_parameter_changes(differences) if click.confirm('Do you want update the config?'): parameter_store.set_config(differences, sidecar_name) else: log_warning("Changes aborted.")
def test_initialization(self): store_object = ParameterStore('test-service', 'dummy-staging') assert store_object.environment == 'dummy-staging' assert store_object.service_name == 'test-service' assert store_object.path_prefix == '/dummy-staging/test-service/'
def test_get_existing_config_as_string(self): self.setup_existing_params() store_object = ParameterStore('test-service', 'dummy-staging') response = store_object.get_existing_config_as_string() assert response == 'DUMMY_VAR0=dummy_values_0\nDUMMY_VAR1=dummy_values_1\nDUMMY_VAR10=dummy_values_10\nDUMMY_VAR11=dummy_values_11\nDUMMY_VAR12=dummy_values_12\nDUMMY_VAR13=dummy_values_13\nDUMMY_VAR2=dummy_values_2\nDUMMY_VAR3=dummy_values_3\nDUMMY_VAR4=dummy_values_4\nDUMMY_VAR5=dummy_values_5\nDUMMY_VAR6=dummy_values_6\nDUMMY_VAR7=dummy_values_7\nDUMMY_VAR8=dummy_values_8\nDUMMY_VAR9=dummy_values_9'