def test_get_env(mock_env_dir, mock_env_branch, mock_git_repo): """Test runway.commands.runway_command.get_env.""" mock_repo = MagicMock() mock_repo.active_branch.name = 'git_branch' mock_git_repo.return_value = mock_repo mock_env_dir.return_value = 'dir_value' mock_env_branch.return_value = 'branch_value' with environ({}): os.environ.pop('DEPLOY_ENVIRONMENT', None) # ensure not in env assert get_env('/', prompt_if_unexpected=True) == 'branch_value' mock_env_branch.assert_called_once_with('git_branch', True) # cases resulting in get_env_from_directory assert get_env('path', ignore_git_branch=True) == 'dir_value' mock_git_repo.side_effect = InvalidGitRepositoryError assert get_env('path') == 'dir_value' mock_env_dir.assert_has_calls([call('path'), call('path')]) # handle TypeError mock_git_repo.side_effect = TypeError with pytest.raises(SystemExit): assert not get_env('path') mock_git_repo.side_effect = None with environ({'DEPLOY_ENVIRONMENT': 'test'}): assert get_env('path') == 'test'
def deploy(self, force=False, sys_path=None): """Run the CFNgin deploy action. Args: force (bool): Explicitly enable the action even if an environment file is not found. syspath (Optional[str]): Explicitly define a path to work in. If not provided, ``self.sys_path`` is used. """ if self.should_skip(force): return if not sys_path: sys_path = self.sys_path config_files = self.find_config_files(sys_path=sys_path) with environ(self.__ctx.env_vars): for config in config_files: ctx = self.load(config) LOGGER.info('%s: deploying...', os.path.basename(config)) action = build.Action( context=ctx, provider_builder=self._get_provider_builder( ctx.config.service_role ) ) action.execute(concurrency=self.concurrency, tail=self.tail)
def plan(self, force=False, sys_path=None): """Run the CFNgin plan action. Args: force (bool): Explicitly enable the action even if an environment file is not found. syspath (Optional[str]): Explicitly define a path to work in. If not provided, ``self.sys_path`` is used. """ if self.should_skip(force): return if not sys_path: sys_path = self.sys_path config_files = self.find_config_files(sys_path=sys_path) with environ(self.__ctx.env_vars): for config in config_files: ctx = self.load(config) LOGGER.info('%s: generating change sets...', os.path.basename(config)) with argv('stacker', 'diff', ctx.config_path): action = diff.Action( context=ctx, provider_builder=self._get_provider_builder( ctx.config.service_role ) ) action.execute()
def test_run(self, monkeypatch): """Test run method.""" # TODO test _process_deployments instead of mocking it out deployments = [{'modules': ['test'], 'regions': 'us-east-1'}] test_config = Config(deployments=deployments, tests=[]) get_env = MagicMock(return_value='test') monkeypatch.setattr(MODULE_PATH + '.select_modules_to_run', lambda a, b, c, d, e: a) monkeypatch.setattr(MODULE_PATH + '.get_env', get_env) monkeypatch.setattr(Config, 'find_config_file', MagicMock(return_value=os.getcwd() + 'runway.yml')) monkeypatch.setattr(ModulesCommand, 'runway_config', test_config) monkeypatch.setattr(ModulesCommand, '_process_deployments', lambda obj, y, x: None) obj = ModulesCommand(cli_arguments={}) with environ({}): os.environ.pop('CI', None) assert not obj.run(test_config.deployments, command='plan') os.environ['CI'] = '1' assert not obj.run(test_config.deployments, command='plan') get_env.assert_has_calls([ call(os.getcwd(), False, prompt_if_unexpected=True), call(os.getcwd(), False, prompt_if_unexpected=False) ])
def test_environ(): """Test environ.""" orig_expected = {'TEST_PARAM': 'initial value'} override = {'TEST_PARAM': 'override', 'new_param': 'value'} assert os.environ == orig_expected, 'validate original value' with environ(override): assert os.environ == override, 'validate override' assert os.environ == orig_expected, 'validate value returned to original'
def test_environ(): """Test environ.""" orig_expected = dict(os.environ) override = {"TEST_PARAM": "override", "new_param": "value"} override_expected = dict(orig_expected) override_expected.update(override) assert os.environ == orig_expected, "validate original value" with environ(override): assert os.environ == override_expected, "validate override" assert os.environ.pop("new_param") == "value" assert os.environ == orig_expected, "validate value returned to original"
def test_environ(): """Test environ.""" orig_expected = dict(os.environ) override = {'TEST_PARAM': 'override', 'new_param': 'value'} override_expected = dict(orig_expected) override_expected.update(override) assert os.environ == orig_expected, 'validate original value' with environ(override): assert os.environ == override_expected, 'validate override' assert os.environ.pop('new_param') == 'value' assert os.environ == orig_expected, 'validate value returned to original'
def test_init(self, tmp_path): """Test init process.""" env_name = 'test' env_region = 'us-east-1' env_root = str(tmp_path) config_file = tmp_path / 'config' config_file.write_text(u'[profile test]\n' 'aws_access_key_id = bar\n' 'aws_secret_access_key = foo') with environ(dict(AWS_PROFILE='test', **TEST_CREDENTIALS)): env_vars = os.environ.copy() env_vars['DEPLOY_ENVIRONMENT'] = env_name ctx = Context(env_name, env_region, env_root) assert not ctx.command assert not ctx.debug assert ctx.env_name == env_name assert ctx.env_region == env_region assert ctx.env_root == env_root assert sorted(ctx.env_vars) == sorted(env_vars) with environ({ 'AWS_PROFILE': 'test', 'AWS_CONFIG_FILE': str(config_file) }): os.environ.pop('AWS_ACCESS_KEY_ID', None) os.environ.pop('AWS_SECRET_ACCESS_KEY', None) os.environ.pop('AWS_SESSION_TOKEN', None) env_vars = os.environ.copy() env_vars['DEPLOY_ENVIRONMENT'] = env_name ctx = Context(env_name, env_region, env_root) assert ctx.env_vars != os.environ assert ctx.env_vars['AWS_ACCESS_KEY_ID'] == 'bar' assert ctx.env_vars['AWS_SECRET_ACCESS_KEY'] == 'foo'
def test_load_object_from_string(): """Test load object from string.""" tests = (("string.Template", string.Template), ("os.path.basename", os.path.basename), ("string.ascii_letters", string.ascii_letters)) for test in tests: assert load_object_from_string(test[0]) is test[1] obj_path = 'tests.fixtures.mock_hooks.GLOBAL_VALUE' # check value from os.environ assert load_object_from_string(obj_path, try_reload=True) == 'us-east-1' with environ({'AWS_DEFAULT_REGION': 'us-west-2'}): # check value from os.environ after changing it to ensure reload assert load_object_from_string(obj_path, try_reload=True) == 'us-west-2'
def _build(self): """Execute and assert initial build. Explicitly spawning with a tty here to ensure output (e.g. from pip) includes color """ with environ({**os.environ, **{'DEPLOY_ENVIRONMENT': 'dev'}}): with tempfile.TemporaryFile() as pty_output: def read_pty(fds): """Append tty output to file descriptor.""" data = os.read(fds, 1024) pty_output.write(data) return data spawn_result = pty.spawn(['runway', 'deploy'], read_pty) assert spawn_result == 0, 'exit code should be zero' pty_output.seek(0) combined_output = pty_output.read().decode() assert '\x1b[31mERROR: ' not in combined_output, ( 'no red ERROR should be present' )
def test_run(self, mock_context, mock_get_env, mock_select_modules_to_run, config, command, cli_args, mock_input, fx_config, monkeypatch): """Test run.""" config = fx_config.load(config) config.future.strict_environments = True mock_get_env.return_value = 'test' mock_context.return_value = mock_context mock_context.is_interactive = bool(mock_input) mock_context.is_noninteractive = not bool(mock_input) # True if None mock_context.env_vars = {} monkeypatch.setattr(MODULE + '.input', mock_input) monkeypatch.setattr(ModulesCommand, 'reverse_deployments', MagicMock(return_value=['reversed-deployments'])) monkeypatch.setattr(ModulesCommand, 'runway_config', config) monkeypatch.setattr(ModulesCommand, 'select_deployment_to_run', MagicMock(return_value=['deployment'])) monkeypatch.setattr(ModulesCommand, '_process_deployments', MagicMock()) if command == 'destroy' and mock_input and mock_input.return_value != 'y': with pytest.raises(SystemExit) as excinfo: ModulesCommand(cli_args).run(command=command) mock_input.assert_called_once_with('Proceed?: ') assert excinfo.value.code == 0 return # end here since a lot of the rest will be skipped env_vars = {} if not mock_input: env_vars['CI'] = '1' with environ(env_vars): ModulesCommand(cli_args).run(command=command) mock_get_env.assert_called_once_with( os.getcwd(), config.ignore_git_branch, prompt_if_unexpected=bool(mock_input)) mock_context.assert_called_once_with(env_name='test', env_region=None, env_root=os.getcwd(), env_vars=os.environ, command=command) assert mock_context.env_vars['RUNWAYCONFIG'] == './runway.yml' if command == 'destroy' and mock_input: mock_input.assert_called_once_with('Proceed?: ') ModulesCommand.reverse_deployments.assert_called_once() if mock_context.is_noninteractive or cli_args.get('--tag'): mock_select_modules_to_run.assert_called() else: ModulesCommand.select_deployment_to_run.assert_called_once_with( config.deployments, command) mock_select_modules_to_run.assert_called_once_with( 'deployment', cli_args.get('--tag'), command, mock_context.is_noninteractive, mock_context.env_name) # pylint: disable=no-member ModulesCommand._process_deployments.assert_called_once_with( ANY, mock_context)