I need to create an AWS ACM certificate with pulumi for multiple wildcard SubjectAlternativeNames, e.g.
*.mydomain.tld*.subdomain01.mydomain.tld*.subdomain02.mydomain.tld
Using export as a dev helper, I managed to display the contents of the domain_validation_options certificate attribute:
from pulumi import export
from pulumi_aws import acm
cert = acm.Certificate('cert',
domain_name='mydomain.tld',
subject_alternative_names=[
'*.mydomain.tld',
'*.subdomain01.mydomain.tld',
'*.subdomain02.mydomain.tld'
],
validation_method="DNS")
export('domain_validation_options', cert.domain_validation_options)
which upon pulumi up displays something like
Outputs:
+ domain_validation_options : [
+ [0]: {
+ domain_name : "*.subdomain01.mydomain.tld"
+ resource_record_name : "_a55 ... 935.subdomain01.mydomain.tld."
+ resource_record_type : "CNAME"
+ resource_record_value: "_1ba ... 7d6.npyrrzfbbp.acm-validations.aws."
}
+ [1]: {
+ domain_name : "*.subdomain02.mydomain.tld"
+ resource_record_name : "_be5 ... cd3.subdomain02.mydomain.tld."
+ resource_record_type : "CNAME"
+ resource_record_value: "_7b0 ... 5f3.hcnplcfwms.acm-validations.aws."
}
+ [2]: {
+ domain_name : "mydomain.tld"
+ resource_record_name : "_691 ... 20f.mydomain.tld."
+ resource_record_type : "CNAME"
+ resource_record_value: "_566 ... 582.hrrssmwwfk.acm-validations.aws."
}
+ [3]: {
+ domain_name : "*.mydomain.tld"
+ resource_record_name : "_691 ... 20f.mydomain.tld."
+ resource_record_type : "CNAME"
+ resource_record_value: "_566 ... 582.hrrssmwwfk.acm-validations.aws."
}
]
My problem: I need to create AWS Route 53 records to validate the certificate (using DNS), but as I have more than mydomain.tld and *.mydomain.tld, I can not just take the first entry in the domain validation options list (domain_validation_options[0] in the pulumi example code).
Moreover, as the creation of AWS Route 53 records is part of a larger code base that creates all kinds of records, I can not take the route shown in the Referencing domain_validation_options With for_each Based Resources pulumi sample code (or at least what I think that sample code does - I have a real hard time understanding it...)
As domain_validation_options is a pulumi output, I managed to figure out that I need to use apply() to select the correct entry for the record being created.
So, with a name variable in my code with a value of e.g. *.api.focussheet.dev, how can I look up the correct entry ?
In "regular" python code, this seems fairly easy, e.g.
from pulumi_aws import route53
name = '*.api.focussheet.dev'
for dvo in cert.domain_validation_options:
if name == dvo['domain_name']:
args = {
'name': dvo.resource_record_name,
'records': [dvo.resource_record_value],
'type': dvo.resource_record_type
}
new_record = route53.Record(name, **args)
break
but that code fails with TypeError: 'Output' object is not iterable, consider iterating the underlying value inside an 'apply'.
I tried to come up with some apply code that uses a lambda and I also tried creating a function to pass to apply, but I just can't seem to get the syntax and the arguments right.
Can anybody help me ? How do I use pulumi's apply() to select the domain_validation_options entry with a domain_name attribute that is equal to a name variable / argument ?
The trick here is understanding what an
applyis.The reason your code is throwing
TypeError: 'Output' object is not iterable, consider iterating the underlying value inside an 'apply'is because you are trying to loop over a value that the python interpreter hasn't resolved correctly yet. There's a hint in the error message,consider iterating the underlying value inside an 'apply'.So in practice, we need to do this:
Here, we create a method to create the route53 validation record for a list of dvos. Then, we just need to use an apply to make sure those values are available to iterate correctly:
All of that together, looks like this