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'
Exemple #2
0
    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)
Exemple #3
0
    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()
Exemple #4
0
    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)
        ])
Exemple #5
0
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'
Exemple #6
0
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"
Exemple #7
0
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'
Exemple #8
0
    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'
Exemple #9
0
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)