Beispiel #1
0
    def test_destroy_raise_client_error(self, cfngin_context, monkeypatch):
        """Test destory with ClientError raised."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        def build_client_error(msg):
            """Raise a ClientError."""
            return ClientError({'Error': {'Message': msg}}, 'test')

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'destroy_stack', lambda wait: None)

        def raise_stack_not_exist(_records):
            """Raise ClientError mimicing stack not existing."""
            raise build_client_error('Stack with id {} does not exist'.format(
                cert.stack.fqn))

        def raise_other(_records):
            """Raise other ClientError."""
            raise build_client_error('something')

        monkeypatch.setattr(cert, 'remove_validation_records',
                            raise_stack_not_exist)
        assert cert.destroy()

        monkeypatch.setattr(cert, 'remove_validation_records', raise_other)
        with pytest.raises(ClientError) as excinfo:
            cert.destroy()
        assert 'something' in str(excinfo.value)
Beispiel #2
0
    def test_update_record_set(self, cfngin_context):
        """Test update_record_set."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        r53_stubber = cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        r53_stubber.add_response(
            "change_resource_record_sets",
            gen_change_resource_record_sets(),
            {
                "HostedZoneId": cert.args.hosted_zone_id,
                "ChangeBatch": gen_change_batch(
                    changes=[
                        gen_change(
                            action="UPSERT",
                            record_set=gen_record_set(
                                use_resource_record=True, TTL=cert.args.ttl
                            ),
                        )
                    ]
                ),
            },
        )

        with r53_stubber:
            assert not cert.update_record_set(gen_record_set())
        r53_stubber.assert_no_pending_responses()
Beispiel #3
0
    def test_deploy_recreate(self, cfngin_context, monkeypatch):
        """Test deploy with stack recreation."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'domain_changed', lambda: False)
        monkeypatch.setattr(cert, 'deploy_stack', lambda: STATUS.recreate)
        monkeypatch.setattr(cert, 'get_certificate',
                            MagicMock(side_effect=['old', cert_arn]))
        monkeypatch.setattr(cert, '_wait_for_stack',
                            MagicMock(side_effect=[STATUS.new, None]))
        monkeypatch.setattr(
            cert, 'get_validation_record', lambda x: 'get_validation_record'
            if x == cert_arn else ValueError)
        monkeypatch.setattr(
            cert, 'put_record_set', lambda x: None
            if x == 'get_validation_record' else ValueError)

        assert cert.deploy() == expected
Beispiel #4
0
    def test_deploy_update(self, cfngin_context, monkeypatch):
        """Test deploy update stack."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'domain_changed', lambda: False)
        monkeypatch.setattr(cert, 'deploy_stack', lambda: STATUS.update)
        monkeypatch.setattr(cert, 'get_certificate', lambda: cert_arn)
        monkeypatch.setattr(
            cert, 'get_validation_record',
            lambda x, status: 'get_validation_record'
            if x == cert_arn and status == 'SUCCESS' else ValueError)
        monkeypatch.setattr(
            cert, 'update_record_set', lambda x: None
            if x == 'get_validation_record' else ValueError)
        monkeypatch.setattr(cert, '_wait_for_stack',
                            lambda x, last_status: None)

        assert cert.deploy() == expected
Beispiel #5
0
    def test_put_record_set(self, cfngin_context: MockCFNginContext) -> None:
        """Test put_record."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        r53_stubber = cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        r53_stubber.add_response(
            "change_resource_record_sets",
            gen_change_resource_record_sets(),
            {
                "HostedZoneId":
                cert.args.hosted_zone_id,
                "ChangeBatch":
                gen_change_batch(changes=[
                    gen_change(record_set=cast(
                        "ResourceRecordSetTypeDef",
                        gen_record_set(use_resource_record=True,
                                       TTL=cert.args.ttl),
                    ))
                ]),
            },
        )

        with r53_stubber:
            assert not cert.put_record_set(
                cast("ResourceRecordTypeDef", gen_record_set()))
        r53_stubber.assert_no_pending_responses()
Beispiel #6
0
    def test_get_validation_record_status_missmatch(
            self, cfngin_context: MockCFNginContext, check: str,
            found: str) -> None:
        """Test get get_validation_record with a missmatched record status."""
        # setup context
        acm_stubber = cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected_request = {"CertificateArn": cert_arn}

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        acm_stubber.add_response(
            "describe_certificate",
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(ValidationStatus=found)
                ],
            ),
            expected_request,
        )

        with acm_stubber, pytest.raises(ValueError) as excinfo:
            cert.get_validation_record(cert_arn=cert_arn, status=check)

        assert "No validations with status" in str(excinfo.value)
        acm_stubber.assert_no_pending_responses()
Beispiel #7
0
    def test_destory_aws_errors(self, cfngin_context: MockCFNginContext,
                                monkeypatch: MonkeyPatch) -> None:
        """Test destory with errors from AWS."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        monkeypatch.setattr(
            cert,
            "remove_validation_records",
            MagicMock(side_effect=[
                cert.r53_client.exceptions.InvalidChangeBatch({}, ""),
                cert.r53_client.exceptions.NoSuchHostedZone({}, ""),
                cert.acm_client.exceptions.ResourceNotFoundException({}, ""),
            ]),
        )
        monkeypatch.setattr(cert, "destroy_stack", lambda wait: None)

        assert cert.destroy()
        assert cert.destroy()
        assert cert.destroy()
Beispiel #8
0
    def test_get_validation_record_status_missmatch(self, cfngin_context,
                                                    check, found):
        """Test get get_validation_record with a missmatched record status."""
        # setup context
        acm_stubber = cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected_request = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')

        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(ValidationStatus=found)
                ]), expected_request)

        with acm_stubber, pytest.raises(ValueError) as excinfo:
            cert.get_validation_record(cert_arn=cert_arn, status=check)

        assert 'No validations with status' in str(excinfo.value)
        acm_stubber.assert_no_pending_responses()
Beispiel #9
0
    def test_get_validation_record_gt_one(self, cfngin_context):
        """Test get get_validation_record more than one result."""
        # setup context
        acm_stubber = cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected_request = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')

        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(CertificateArn=cert_arn,
                            DomainValidationOptions=[
                                gen_domain_validation_option(),
                                gen_domain_validation_option()
                            ]), expected_request)

        with acm_stubber, pytest.raises(ValueError) as excinfo:
            cert.get_validation_record(cert_arn=cert_arn)

        assert 'only one option is supported' in str(excinfo.value)
        acm_stubber.assert_no_pending_responses()
Beispiel #10
0
    def test_deploy_update(self, cfngin_context: MockCFNginContext,
                           monkeypatch: MonkeyPatch) -> None:
        """Test deploy update stack."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected = {"CertificateArn": cert_arn}

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "domain_changed", lambda: False)
        monkeypatch.setattr(cert, "deploy_stack", lambda: STATUS.update)
        monkeypatch.setattr(cert, "get_certificate", lambda: cert_arn)
        monkeypatch.setattr(
            cert,
            "get_validation_record",
            lambda x, status: "get_validation_record"
            if x == cert_arn and status == "SUCCESS" else ValueError,
        )
        monkeypatch.setattr(
            cert,
            "update_record_set",
            lambda x: None if x == "get_validation_record" else ValueError,
        )
        monkeypatch.setattr(cert, "_wait_for_stack",
                            lambda x, last_status: None)

        assert cert.deploy() == expected
Beispiel #11
0
    def test_get_certificate(self, cfngin_context, patch_time):
        """Test get_certificate."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        provider = MagicMock(cloudformation=boto3.client('cloudformation'))
        cfn_stubber = Stubber(provider.cloudformation)

        cert = Certificate(context=cfngin_context,
                           provider=provider,
                           domain='example.com',
                           hosted_zone_id='test')

        expected_request = {
            'StackName': 'test-example-com',
            'LogicalResourceId': 'Certificate'
        }

        cfn_stubber.add_response('describe_stack_resources',
                                 {'StackResources': []}, expected_request)
        cfn_stubber.add_response('describe_stack_resources',
                                 {'StackResources': [gen_stack_resource()]},
                                 expected_request)
        cfn_stubber.add_response('describe_stack_resources', {
            'StackResources':
            [gen_stack_resource(PhysicalResourceId='success')]
        }, expected_request)

        with cfn_stubber:
            assert cert.get_certificate() == 'success'

        cfn_stubber.assert_no_pending_responses()
Beispiel #12
0
    def test_get_validation_record_gt_one(
            self, cfngin_context: MockCFNginContext) -> None:
        """Test get get_validation_record more than one result."""
        # setup context
        acm_stubber = cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected_request = {"CertificateArn": cert_arn}

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        acm_stubber.add_response(
            "describe_certificate",
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(),
                    gen_domain_validation_option(),
                ],
            ),
            expected_request,
        )

        with acm_stubber, pytest.raises(ValueError) as excinfo:
            cert.get_validation_record(cert_arn=cert_arn)

        assert "only one option is supported" in str(excinfo.value)
        acm_stubber.assert_no_pending_responses()
Beispiel #13
0
    def test_update_record_set(self, cfngin_context):
        """Test update_record_set."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        r53_stubber = cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')

        r53_stubber.add_response(
            'change_resource_record_sets', gen_change_resource_record_sets(), {
                'HostedZoneId':
                cert.args.hosted_zone_id,
                'ChangeBatch':
                gen_change_batch(changes=[
                    gen_change(
                        action='UPSERT',
                        record_set=gen_record_set(use_resource_record=True,
                                                  TTL=cert.args.ttl))
                ])
            })

        with r53_stubber:
            assert not cert.update_record_set(gen_record_set())
        r53_stubber.assert_no_pending_responses()
Beispiel #14
0
    def test_get_validation_record(
        self,
        cfngin_context: MockCFNginContext,
        monkeypatch: MonkeyPatch,
        patch_time: None,
        status: str,
    ) -> None:
        """Test get_validation_record."""
        # setup context
        acm_stubber = cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected_request = {"CertificateArn": cert_arn}
        validate_option_missing_record = gen_domain_validation_option(
            ValidationStatus=status)
        del validate_option_missing_record["ResourceRecord"]

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "get_certificate", lambda: cert_arn)

        acm_stubber.add_response(
            "describe_certificate",
            gen_certificate(CertificateArn=cert_arn),
            expected_request,
        )
        acm_stubber.add_response(
            "describe_certificate",
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[validate_option_missing_record],
            ),
            expected_request,
        )
        acm_stubber.add_response(
            "describe_certificate",
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(ValidationStatus=status)
                ],
            ),
            expected_request,
        )

        with acm_stubber:
            assert (cert.get_validation_record(status=status) ==
                    gen_domain_validation_option()["ResourceRecord"])
        acm_stubber.assert_no_pending_responses()
Beispiel #15
0
    def test_remove_validation_records(self, cfngin_context, monkeypatch):
        """Test remove_validation_records."""
        # setup context
        acm_stubber = cfngin_context.add_stubber('acm', 'us-east-1')
        r53_stubber = cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected_cert_request = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'get_certificate', lambda: cert_arn)

        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[gen_domain_validation_option()]),
            expected_cert_request)
        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(ValidationMethod='EMAIL')
                ]), expected_cert_request)

        r53_stubber.add_response(
            'change_resource_record_sets', gen_change_resource_record_sets(), {
                'HostedZoneId':
                cert.args.hosted_zone_id,
                'ChangeBatch':
                gen_change_batch(changes=[
                    gen_change(action='DELETE',
                               record_set=gen_record_set(
                                   use_resource_record=True,
                                   TTL=cert.args.ttl,
                                   **gen_domain_validation_option()
                                   ['ResourceRecord']))
                ])
            })

        with acm_stubber, r53_stubber, pytest.raises(ValueError) as excinfo:
            assert not cert.remove_validation_records()
            cert.remove_validation_records()

        acm_stubber.assert_no_pending_responses()
        r53_stubber.assert_no_pending_responses()
        assert str(excinfo.value) == 'Must provide one of more record sets'
Beispiel #16
0
    def test_attributes(self, cfngin_context: MockCFNginContext) -> None:
        """Test attributes set during __init__."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        result = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            alt_names=["example.net"],
            domain="example.com",
            hosted_zone_id="test",
            stack_name="stack-name",
            ttl=13,
        )

        assert result.stack_name == "stack-name"
        assert result.properties["DomainName"] == "example.com"
        assert result.properties["SubjectAlternativeNames"] == ["example.net"]
        # value tested in base class; just ensure its not None
        assert result.properties["Tags"]
        assert result.properties["ValidationMethod"] == "DNS"

        # blueprint attributes
        assert result.blueprint.VARIABLES["DomainName"]
        assert result.blueprint.VARIABLES["ValidateRecordTTL"]

        # template attributes
        template = result.blueprint.template
        assert template.description == result.get_template_description()
        assert not template.metadata
        assert not template.conditions
        assert not template.mappings
        assert template.outputs["DomainName"].Value.to_dict() == {
            "Ref": "DomainName"
        }
        assert template.outputs["ValidateRecordTTL"].Value.to_dict() == {
            "Ref": "ValidateRecordTTL"
        }
        assert not template.parameters
        assert isinstance(template.resources["Certificate"],
                          CertificateResource)
        assert not template.rules
        assert template.version == "2010-09-09"
        assert not template.transform

        # stack attributes
        assert result.stack.fqn == "test-stack-name"
        assert result.stack._blueprint == result.blueprint
Beispiel #17
0
    def test_deploy_domain_changed(self, cfngin_context, monkeypatch):
        """Test deploy domain changed."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'domain_changed', lambda: True)

        assert not cert.deploy()
Beispiel #18
0
    def test_deploy_error_destroy(self, cfngin_context: MockCFNginContext,
                                  monkeypatch: MonkeyPatch) -> None:
        """Test deploy with errors that result in destroy being called."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )

        monkeypatch.setattr(cert, "domain_changed", lambda: False)
        monkeypatch.setattr(cert, "deploy_stack",
                            lambda: STATUS.new)  # type: ignore
        monkeypatch.setattr(cert, "get_certificate", lambda: cert_arn)
        monkeypatch.setattr(
            cert,
            "get_validation_record",
            lambda x: "get_validation_record" if x == cert_arn else ValueError,
        )
        monkeypatch.setattr(
            cert,
            "put_record_set",
            MagicMock(side_effect=[
                cert.r53_client.exceptions.InvalidChangeBatch({}, ""),
                cert.r53_client.exceptions.NoSuchHostedZone({}, ""),
                None,
            ]),
        )
        monkeypatch.setattr(
            cert, "destroy",
            lambda records, skip_r53: check_bool_is_true(skip_r53))
        monkeypatch.setattr(cert, "_wait_for_stack",
                            MagicMock(side_effect=StackFailed("test")))

        assert not cert.deploy(
        )  # cert.r53_client.exceptions.InvalidChangeBatch
        assert not cert.deploy()  # cert.r53_client.exceptions.NoSuchHostedZone

        monkeypatch.setattr(
            cert, "destroy",
            lambda records, skip_r53: check_bool_is_false(skip_r53))
        assert not cert.deploy()  # StackFailed
Beispiel #19
0
    def test_deploy_domain_changed(self, cfngin_context, monkeypatch):
        """Test deploy domain changed."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "domain_changed", lambda: True)

        assert not cert.deploy()
Beispiel #20
0
    def test_stage_methods(
        self,
        cfngin_context: MockCFNginContext,
        monkeypatch: MonkeyPatch,
        stage: str,
        expected: str,
    ) -> None:
        """Test stage methods.

        All of these call a different method that is being tested separately
        so this test just ensures each stage is mapped to the correct method
        on the backend.

        """
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "deploy", lambda: "deploy")
        monkeypatch.setattr(cert, "destroy", lambda: "destroy")

        assert getattr(cert, stage)() == expected
Beispiel #21
0
    def test_attributes(self, cfngin_context):
        """Test attributes set during __init__."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        result = Certificate(context=cfngin_context,
                             provider=MagicMock(),
                             alt_names=['example.net'],
                             domain='example.com',
                             hosted_zone_id='test',
                             stack_name='stack-name',
                             ttl=13)

        assert result.stack_name == 'stack-name'
        assert result.properties.DomainName == 'example.com'
        assert result.properties.SubjectAlternativeNames == ['example.net']
        # value tested in base class; just ensure its not None
        assert result.properties.Tags
        assert result.properties.ValidationMethod == 'DNS'

        # blueprint attributes
        assert result.blueprint.VARIABLES['DomainName']
        assert result.blueprint.VARIABLES['ValidateRecordTTL']

        # template attributes
        template = result.blueprint.template
        assert template.description == result.get_template_description()
        assert not template.metadata
        assert not template.conditions
        assert not template.mappings
        assert template.outputs['DomainName'].Value.to_dict() == \
            {'Ref': 'DomainName'}
        assert template.outputs['ValidateRecordTTL'].Value.to_dict() == \
            {'Ref': 'ValidateRecordTTL'}
        assert not template.parameters
        assert isinstance(template.resources['Certificate'],
                          CertificateResource)
        assert not template.rules
        assert template.version == '2010-09-09'
        assert not template.transform

        # stack attributes
        assert result.stack.fqn == 'test-stack-name'
        assert result.stack._blueprint == result.blueprint
Beispiel #22
0
    def test_deploy_error_no_destroy(self, cfngin_context, monkeypatch):
        """Test deploy with errors that don't result in destroy being called."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'domain_changed', lambda: False)
        monkeypatch.setattr(
            cert, 'deploy_stack',
            MagicMock(
                side_effect=StackUpdateBadStatus('test', 'test', 'test')))

        assert not cert.deploy()
Beispiel #23
0
    def test_deploy_no_change(self, cfngin_context, monkeypatch):
        """Test deploy no change."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected = {'CertificateArn': cert_arn}

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'domain_changed', lambda: False)
        monkeypatch.setattr(cert, 'deploy_stack', lambda: STATUS.no)
        monkeypatch.setattr(cert, 'get_certificate', lambda: cert_arn)

        assert cert.deploy() == expected
Beispiel #24
0
    def test_destory(self, cfngin_context, monkeypatch):
        """Test destory."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        # should only be called once
        monkeypatch.setattr(cert, 'remove_validation_records',
                            MagicMock(return_value=None))
        monkeypatch.setattr(cert, 'destroy_stack', lambda wait: None)

        assert cert.destroy()
        assert cert.destroy(skip_r53=True)
        assert cert.remove_validation_records.call_count == 1  # pylint: disable=no-member
Beispiel #25
0
    def test_get_certificate(self, cfngin_context: MockCFNginContext,
                             patch_time: None) -> None:
        """Test get_certificate."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        provider = MagicMock(cloudformation=boto3.client("cloudformation"))
        cfn_stubber = Stubber(provider.cloudformation)

        cert = Certificate(
            context=cfngin_context,
            provider=provider,
            domain="example.com",
            hosted_zone_id="test",
        )

        expected_request = {
            "StackName": "test-example-com",
            "LogicalResourceId": "Certificate",
        }

        cfn_stubber.add_response("describe_stack_resources",
                                 {"StackResources": []}, expected_request)
        cfn_stubber.add_response(
            "describe_stack_resources",
            {"StackResources": [gen_stack_resource()]},
            expected_request,
        )
        cfn_stubber.add_response(
            "describe_stack_resources",
            {
                "StackResources":
                [gen_stack_resource(PhysicalResourceId="success")]
            },
            expected_request,
        )

        with cfn_stubber:
            assert cert.get_certificate() == "success"

        cfn_stubber.assert_no_pending_responses()
Beispiel #26
0
    def test_get_validation_record(self, cfngin_context, monkeypatch,
                                   patch_time, status):
        """Test get_validation_record."""
        # setup context
        acm_stubber = cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'
        expected_request = {'CertificateArn': cert_arn}
        validate_option_missing_record = gen_domain_validation_option(
            ValidationStatus=status)
        del validate_option_missing_record['ResourceRecord']

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')
        monkeypatch.setattr(cert, 'get_certificate', lambda: cert_arn)

        acm_stubber.add_response('describe_certificate',
                                 gen_certificate(CertificateArn=cert_arn),
                                 expected_request)
        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[validate_option_missing_record]),
            expected_request)
        acm_stubber.add_response(
            'describe_certificate',
            gen_certificate(
                CertificateArn=cert_arn,
                DomainValidationOptions=[
                    gen_domain_validation_option(ValidationStatus=status)
                ]), expected_request)

        with acm_stubber:
            assert cert.get_validation_record(status=status) == \
                gen_domain_validation_option()['ResourceRecord']
        acm_stubber.assert_no_pending_responses()
Beispiel #27
0
    def test_deploy_error_no_destroy(self, cfngin_context, monkeypatch):
        """Test deploy with errors that don't result in destroy being called."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "domain_changed", lambda: False)
        monkeypatch.setattr(
            cert,
            "deploy_stack",
            MagicMock(side_effect=StackUpdateBadStatus("test", "test", "test")),
        )

        assert not cert.deploy()
Beispiel #28
0
    def test_deploy_no_change(self, cfngin_context, monkeypatch):
        """Test deploy no change."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected = {"CertificateArn": cert_arn}

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "domain_changed", lambda: False)
        monkeypatch.setattr(cert, "deploy_stack", lambda: STATUS.no)
        monkeypatch.setattr(cert, "get_certificate", lambda: cert_arn)

        assert cert.deploy() == expected
Beispiel #29
0
    def test_deploy_error_destroy(self, cfngin_context, monkeypatch):
        """Test deploy with errors that result in destroy being called."""
        # setup context
        cfngin_context.add_stubber('acm', 'us-east-1')
        cfngin_context.add_stubber('route53', 'us-east-1')
        cfngin_context.config.namespace = 'test'

        cert_arn = 'arn:aws:acm:us-east-1:012345678901:certificate/test'

        cert = Certificate(context=cfngin_context,
                           provider=MagicMock(),
                           domain='example.com',
                           hosted_zone_id='test')

        monkeypatch.setattr(cert, 'domain_changed', lambda: False)
        monkeypatch.setattr(cert, 'deploy_stack', lambda: STATUS.new)
        monkeypatch.setattr(cert, 'get_certificate', lambda: cert_arn)
        monkeypatch.setattr(
            cert, 'get_validation_record', lambda x: 'get_validation_record'
            if x == cert_arn else ValueError)
        monkeypatch.setattr(
            cert, 'put_record_set',
            MagicMock(side_effect=[
                cert.r53_client.exceptions.InvalidChangeBatch({}, ''),
                cert.r53_client.exceptions.NoSuchHostedZone({}, ''), None
            ]))
        monkeypatch.setattr(
            cert, 'destroy',
            lambda records, skip_r53: check_bool_is_true(skip_r53))
        monkeypatch.setattr(cert, '_wait_for_stack',
                            MagicMock(side_effect=StackFailed('test')))

        assert not cert.deploy(
        )  # cert.r53_client.exceptions.InvalidChangeBatch
        assert not cert.deploy()  # cert.r53_client.exceptions.NoSuchHostedZone

        monkeypatch.setattr(
            cert, 'destroy',
            lambda records, skip_r53: check_bool_is_false(skip_r53))
        assert not cert.deploy()  # StackFailed
Beispiel #30
0
    def test_deploy_recreate(self, cfngin_context: MockCFNginContext,
                             monkeypatch: MonkeyPatch):
        """Test deploy with stack recreation."""
        # setup context
        cfngin_context.add_stubber("acm", "us-east-1")
        cfngin_context.add_stubber("route53", "us-east-1")
        cfngin_context.config.namespace = "test"

        cert_arn = "arn:aws:acm:us-east-1:012345678901:certificate/test"
        expected = {"CertificateArn": cert_arn}

        cert = Certificate(
            context=cfngin_context,
            provider=MagicMock(),
            domain="example.com",
            hosted_zone_id="test",
        )
        monkeypatch.setattr(cert, "domain_changed", lambda: False)
        monkeypatch.setattr(cert, "deploy_stack",
                            lambda: STATUS.recreate)  # type: ignore
        monkeypatch.setattr(cert, "get_certificate",
                            MagicMock(side_effect=["old", cert_arn]))
        monkeypatch.setattr(
            cert,
            "_wait_for_stack",
            MagicMock(side_effect=[STATUS.new, None])  # type: ignore
        )
        monkeypatch.setattr(
            cert,
            "get_validation_record",
            lambda x: "get_validation_record" if x == cert_arn else ValueError,
        )
        monkeypatch.setattr(
            cert,
            "put_record_set",
            lambda x: None if x == "get_validation_record" else ValueError,
        )

        assert cert.deploy() == expected