Example #1
0
    def test_handle_provider_exception(self, mock_should_use, exception,
                                       default, caplog):
        """Test handle provider raise exception."""
        caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
        mock_should_use.return_value = True
        mock_provider = MagicMock(region="us-east-1")
        mock_provider.get_output.side_effect = exception
        raw_query = "test-stack.output1"

        if default:
            assert (CfnLookup.handle(
                raw_query + "::default=" + default,
                context=None,
                provider=mock_provider,
            ) == default)
            mock_should_use.assert_called_once_with({"default": default},
                                                    mock_provider)
            assert ("unable to resolve lookup for CloudFormation Stack output "
                    '"{}"; using default'.format(raw_query)) in caplog.messages
        else:
            if isinstance(exception, (ClientError, StackDoesNotExist)):
                with pytest.raises(exception.__class__):
                    assert not CfnLookup.handle(
                        raw_query, context=None, provider=mock_provider)
            else:
                with pytest.raises(OutputDoesNotExist) as excinfo:
                    assert not CfnLookup.handle(
                        raw_query, context=None, provider=mock_provider)
                assert excinfo.value.stack_name == "test-stack"
                assert excinfo.value.output == "output1"
            mock_should_use.assert_called_once_with({}, mock_provider)
        mock_provider.get_output.assert_called_once_with(
            "test-stack", "output1")
Example #2
0
    def test_handle_exception(self, mock_should_use, exception, default,
                              caplog, monkeypatch):
        """Test handle cls.get_stack_output raise exception."""
        caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
        mock_context = MagicMock(name="context")
        mock_session = MagicMock(name="session")
        mock_context.get_session.return_value = mock_session
        mock_session.client.return_value = mock_session
        mock_should_use.return_value = False
        monkeypatch.setattr(CfnLookup, "get_stack_output", MagicMock())
        CfnLookup.get_stack_output.side_effect = exception

        raw_query = "test-stack.output1"
        query = OutputQuery(*raw_query.split("."))

        if default:
            assert (CfnLookup.handle(raw_query + "::default=" + default,
                                     mock_context) == default)
            mock_should_use.assert_called_once_with({"default": default}, None)
            assert ("unable to resolve lookup for CloudFormation Stack output "
                    '"{}"; using default'.format(raw_query)) in caplog.messages
        else:
            if isinstance(exception, (ClientError, StackDoesNotExist)):
                with pytest.raises(exception.__class__):
                    assert not CfnLookup.handle(raw_query, mock_context)
            else:
                with pytest.raises(OutputDoesNotExist) as excinfo:
                    assert not CfnLookup.handle(raw_query, mock_context)
                assert excinfo.value.stack_name == "test-stack"
                assert excinfo.value.output == "output1"
            mock_should_use.assert_called_once_with({}, None)

        mock_context.get_session.assert_called_once()
        mock_session.client.assert_called_once_with("cloudformation")
        CfnLookup.get_stack_output.assert_called_once_with(mock_session, query)
Example #3
0
    def test_handle(self, mocker: MockerFixture) -> None:
        """Test handle."""
        mock_format_results = mocker.patch.object(CfnLookup,
                                                  "format_results",
                                                  return_value="success")
        mock_get_stack_output = mocker.patch.object(CfnLookup,
                                                    "get_stack_output",
                                                    return_value="cls.success")
        mock_should_use = mocker.patch.object(CfnLookup,
                                              "should_use_provider",
                                              side_effect=[True, False])
        mock_context = MagicMock(name="context")
        mock_session = MagicMock(name="session")
        mock_context.get_session.return_value = mock_session
        mock_session.client.return_value = mock_session
        mock_provider = MagicMock(name="provider")
        mock_provider.get_output.return_value = "provider.success"

        raw_query = "test-stack.output1"
        query = OutputQuery(*raw_query.split("."))
        region = "us-west-2"
        args = "::region={region}".format(region=region)
        value = raw_query + args
        mock_parse = mocker.patch.object(CfnLookup,
                                         "parse",
                                         return_value=(raw_query, {
                                             "region": region
                                         }))

        # test happy path when used from CFNgin (provider)
        assert (CfnLookup.handle(value,
                                 context=mock_context,
                                 provider=mock_provider) == "success")
        mock_parse.assert_called_once_with(value)
        mock_provider.get_output.assert_called_once_with(*query)
        mock_should_use.assert_called_once_with({"region": region},
                                                mock_provider)
        mock_format_results.assert_called_once_with("provider.success",
                                                    region=region)
        mock_context.get_session.assert_not_called()
        mock_get_stack_output.assert_not_called()

        # test happy path when use from runway (no provider)
        assert CfnLookup.handle(value, context=mock_context) == "success"
        mock_should_use.assert_called_with({"region": region}, None)
        mock_context.get_session.assert_called_once_with(region=region)
        mock_session.client.assert_called_once_with("cloudformation")
        mock_get_stack_output.assert_called_once_with(mock_session, query)
        mock_format_results.assert_called_with("cls.success", region=region)
Example #4
0
 def test_handle_valueerror(self,
                            runway_context: MockRunwayContext) -> None:
     """Test handle raising ValueError."""
     with pytest.raises(ValueError) as excinfo:
         assert CfnLookup.handle("something", runway_context)
     assert (str(excinfo.value) ==
             'query must be <stack-name>.<output-name>; got "something"')
Example #5
0
 def test_should_use_provider_falsy(self, args, provider, caplog):
     """Test should_use_provider with falsy cases."""
     caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
     assert not CfnLookup.should_use_provider(args, provider)
     if provider:
         assert ("not using provider; requested region does not match"
                 in caplog.messages)
         assert "using provider" not in caplog.messages
Example #6
0
 def test_should_use_provider_truthy(
     self,
     args: Dict[str, Any],
     caplog: LogCaptureFixture,
     provider: Optional[Provider],
 ) -> None:
     """Test should_use_provider with truthy cases."""
     caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
     assert CfnLookup.should_use_provider(args, provider)
     assert "using provider" in caplog.messages
Example #7
0
 def test_should_use_provider_falsy(
     self,
     args: Dict[str, Any],
     caplog: LogCaptureFixture,
     provider: Optional[Provider],
 ) -> None:
     """Test should_use_provider with falsy cases."""
     caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
     assert not CfnLookup.should_use_provider(args, provider)
     if provider:
         assert ("not using provider; requested region does not match"
                 in caplog.messages)
         assert "using provider" not in caplog.messages
Example #8
0
    def test_get_stack_output_clienterror(self, caplog):
        """Test get_stack_output raising ClientError."""
        caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
        client, stubber = setup_cfn_client()
        stack_name = "test-stack"
        query = OutputQuery(stack_name, "output1")

        stubber.add_client_error(
            "describe_stacks",
            service_error_code="ValidationError",
            service_message="Stack %s does not exist" % stack_name,
            expected_params={"StackName": stack_name},
        )

        with stubber, pytest.raises(ClientError):
            assert CfnLookup.get_stack_output(client, query)

        stubber.assert_no_pending_responses()
        assert "describing stack: %s" % stack_name in caplog.messages
Example #9
0
    def test_get_stack_output(self, caplog: LogCaptureFixture) -> None:
        """Test get_stack_output."""
        caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
        client, stubber = setup_cfn_client()
        stack_name = "test-stack"
        outputs = {"output1": "val1", "output2": "val2"}
        query = OutputQuery(stack_name, "output1")

        stubber.add_response(
            "describe_stacks",
            {"Stacks": [generate_describe_stacks_stack(stack_name, outputs)]},
            {"StackName": stack_name},
        )

        with stubber:
            assert CfnLookup.get_stack_output(client, query) == "val1"

        stubber.assert_no_pending_responses()
        assert "describing stack: %s" % stack_name in caplog.messages
        assert ("{} stack outputs: {}".format(stack_name, json.dumps(outputs))
                in caplog.messages)
Example #10
0
 def test_should_use_provider_truthy(self, args, provider, caplog):
     """Test should_use_provider with truthy cases."""
     caplog.set_level(logging.DEBUG, logger="runway.lookups.handlers.cfn")
     assert CfnLookup.should_use_provider(args, provider)
     assert "using provider" in caplog.messages
Example #11
0
 def test_handle_valueerror(self):
     """Test handle raising ValueError."""
     with pytest.raises(ValueError) as excinfo:
         assert CfnLookup.handle("something", None)
     assert (str(excinfo.value) ==
             'query must be <stack-name>.<output-name>; got "something"')