Hey all! :slightly_smiling_face: I'm attempting to...
# automation-api
l
Hey all! ๐Ÿ™‚ I'm attempting to create and validate a certificate in route53 for a new hosted zone, but I'm getting a little lost and confused with Outputs and apply and how that relates to lists. I've used apply successfully elsewhere, but basically I'm trying to figure out how I can get the
domain_validation_options
from the creation of my certificate and then loop through them, creating a record for each. I'll share my python in a comment. I'm a newbie all around so it's very probably I've just done something that won't work period ๐Ÿ˜‚
Here's what I have that failing ๐Ÿ˜•
Copy code
def create_route53_zone(org_id):
    return aws.route53.Zone(f'shared-hosted-zone-{org_id}', name=f'{org_id}.<http://getbuildbot.com|getbuildbot.com>')


def create_certificate(org_id):
    return aws_acm.Certificate(f'shared-certificate-{org_id}',
                               domain_name=f'{org_id}.<http://getbuildbot.com|getbuildbot.com>',
                               subject_alternative_names=f'*.{org_id}.<http://getbuildbot.com|getbuildbot.com>',
                               tags={
                                   "deployed_by": "Pulumi",
                                   "Name": {org_id},
                               },
                               validation_method="DNS")


def create_records(org_id, domain_validation_options, zone_id):
    validation_record_fqdns = []
    i = 0
    for dvo in domain_validation_options:
        cert_validation = aws.route53.Record(f'{org_id}-record-{i}',
                                             name=dvo['resourceRecordName'],
                                             records=[dvo['resourceRecordValue']],
                                             ttl=300,
                                             type=dvo['resourceRecordType'],
                                             zone_id=zone_id,
                                             opts=pulumi.ResourceOptions(delete_before_replace=True))
        i += 1
        validation_record_fqdns.append(cert_validation.fqdn)
    return validation_record_fqdns


def validate_certificate(org_id, certificate, fqdns):
    return aws_acm.CertificateValidation(f'{org_id}-validation',
                                         certificate_arn=certificate,
                                         validation_record_fqdns=fqdns)


def create_and_validate_hosted_zone(org_id):
    hosted_zone = create_route53_zone(org_id=org_id)
    certificate = create_certificate(org_id=org_id)
    fqdns = certificate.domain_validation_options.apply(lambda domain_validation_options: create_records(org_id=org_id,
                                                                                                         domain_validation_options=domain_validation_options,
                                                                                                         zone_id=hosted_zone.zone_id))

    validate_certificate(org_id=org_id, certificate=certificate.arn, fqdns=fqdns)
    return {
        "hosted_zone": hosted_zone,
        "certificate_arn": certificate.arn
    }
l
Can you avoid iterating? I know how many domain validation options are in my certificate, and Pulumi lifts all the values out fine, so I can create my records without looping.
In typescript, I can use this logic; hopefully it translates to python.
Copy code
new aws.route53.Record(name, {
      zoneId: zoneId,
      name: this.certificate.domainValidationOptions[1].resourceRecordName,
      type: aws.route53.RecordType.CNAME,
      ttl: 300,
      records: [this.certificate.domainValidationOptions[1].resourceRecordValue]
    });
That creates the record for the 2nd DVO. Change the index for the different DVOs.
I'm not sure if you can get the count of DVOs back from the certificate, since it's an
Output<outputs.acm.CertificateDomainValidationOption[]>
, meaning the size of the array won't be known at runtime.
In theory, the number of DVOs should equal 1 + the number of subject alternative names.
l
Ooo. Great idea! Yes, I definition no how many options there are ahead of time. Let me try this out and see if it works!
That isn't working either:
ValueError: unexpected input of type set
. But I can't figure out where I'm passing in a set... I've tried separating out the records and just creating them singly instead of iterating, but no luck!
Copy code
def create_and_validate_hosted_zone(org_id):
    hosted_zone = create_route53_zone(org_id=org_id)
    certificate = create_certificate(org_id=org_id)
    fqdns = []
    fqdn1_record = aws.route53.Record(f'{org_id}-record-1',
                                      name=certificate.domain_validation_options[0].resource_record_name,
                                      records=[certificate.domain_validation_options[0].resource_record_value],
                                      ttl=300,
                                      type=certificate.domain_validation_options[0].resource_record_type,
                                      zone_id=hosted_zone.zone_id,
                                      opts=pulumi.ResourceOptions(delete_before_replace=True))
    fqdn2_record = aws.route53.Record(f'{org_id}-record-1',
                                      name=certificate.domain_validation_options[1].resource_record_name,
                                      records=[certificate.domain_validation_options[1].resource_record_value],
                                      ttl=300,
                                      type=certificate.domain_validation_options[1].resource_record_type,
                                      zone_id=hosted_zone.zone_id,
                                      opts=pulumi.ResourceOptions(delete_before_replace=True))

    fqdns.append(fqdn1_record.fqdn)
    fqdns.append(fqdn2_record.fqdn)
    validate_certificate(org_id=org_id, certificate=certificate.arn, fqdns=fqdns)
    return {
        "hosted_zone": hosted_zone,
        "certificate_arn": certificate.arn
    }
r
Huh that error is indeed confusing. Is that the whole error?
l
@red-match-15116 Well, the only part that's intelligible for me. ๐Ÿ˜‚
r
Hah yeah thatโ€™s fair, that error trace could definitely use some clearing up. I canโ€™t say I can tell just from a quick glance what the issue is, I agree I donโ€™t see any sets! Can you try commenting out just the
validate_certificate
bit and see if that works? I have a hunch it might have something to do with fqdns
l
Can you inspect/log the values of
certificate.domain_validation_options[0].resource_record_type
(and [1])? I didn't get a good value back for those so I hard-coded CNAME..
๐Ÿ‘†๐Ÿฝ 1
l
@little-cartoon-10569 @red-match-15116 Shucks! Didn't work ๐Ÿ˜• Same error. I know it's related though because if I remove the function that creates all of this, the stack deploys fine.
I figured it out, just for others that might have this issue! Turns out you can't have tags The docs say you can (and show an example...?) but the minute I isolated it to the creation of the certificate, I went line by line and removed parameters, and when I removed the tags it deployed successfully! Whoo-hoo!! I'm thinking the docs should be updated and/or there is a bug there somewhere ๐Ÿ™‚
Copy code
def create_certificate(org_id):
    return aws.acm.Certificate(f'shared-certificate-{org_id}',
                               domain_name=f'{org_id}.<http://getbuildbot.com|getbuildbot.com>',
                               subject_alternative_names=[f'*.{org_id}.<http://getbuildbot.com|getbuildbot.com>'],
                               validation_method="DNS")
r
Oh! I think it might be because of the Name tag being passed in as
{org_id}
(which is a set containing the item
org_id
) - can you try it without the curly braces?
l
Thanks! I'll try that too! And actually, the stack launched successfully (no more errors at least!) but when I added back the validate certificate resource, it started hanging on the validation of the certificate. Do you happen to have any experience with that / and/or how long it's supposed to take to validate? I remember when I used terraform I eventually just gave up and did it manually ๐Ÿ˜‚ But maybe I'm missing something in my code somewhere?
r
Hmm that I do not know! You might be able to get more specific help from the #aws channel in that regard.
l
thanks @red-match-15116! You've been awesome!
โค๏ธ 1
l
Validation happens really fast for me.. under a second.