Hello everyone I'm currently working with `acm` ...
# typescript
a
Hello everyone I'm currently working with
acm
to generate some certificates so that I can store them on SSM and then reference them on my application code
serverless framework
. I exported the required values as outputs so that I could take a look at them but to my surprise they are `null`and empty (
[]
). The funny thing is that everything was created correctly on
AWS
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const stack = pulumi.getStack();

const certificate = new aws.acm.Certificate("core-certificate", {
  domainName: `api.${stack}.<http://app.example.io|app.example.io>`,
  validationMethod: "DNS",
  subjectAlternativeNames: [`*.api.${stack}.<http://app.example.io|app.example.io>`],
  // default
  keyAlgorithm: "RSA_2048",
  // stick to serverless conventions
  tags: {
    STAGE: stack,
  },
});

const zone = aws.route53.getZone({
  name: `${stack}.<http://app.example.io|app.example.io>`,
  privateZone: false,
});

const certificationRecords: aws.route53.Record[] = [];

certificate.domainValidationOptions.apply((domainValidationOptions) => {
  for (const [index, dvo] of Object.entries(domainValidationOptions)) {
    certificationRecords.push(
      new aws.route53.Record(`certification-validation-record-${index}`, {
        name: dvo.resourceRecordName,
        zoneId: zone.then((zone) => zone.zoneId),
        records: [dvo.resourceRecordValue],
        type: dvo.resourceRecordType,
        allowOverwrite: true,
        ttl: 10,
      })
    );
  }
});

const certificateValidation = new aws.acm.CertificateValidation(
  "certificate-validation",
  {
    certificateArn: certificate.arn,
    validationRecordFqdns: certificationRecords.map((record) => record.fqdn),
  }
);

export const records = certificationRecords;
export const validation = certificateValidation.validationRecordFqdns;
my outputs
Copy code
{
  "records": [],
  "validation": null
}
I'm wondering if it has to do something on pulumi's internals đŸ€”
any insights would be appreciated
thanks
l
Sort of. You have built records in an apply, so it will always be empty at runtime. And because it's always empty, the call to map will do nothing, so the fqdns is empty too. Instead of building records in an apply and exporting them, you need to build an array of Output<Record> outside of an apply. That will export correctly.
a
but how will I access the properties dynamically that are required from
domainValidationOptions
?
nvm, I think I understand your point
this did the trick
Copy code
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const stack = pulumi.getStack();

const certificate = new aws.acm.Certificate("core-certificate", {
  domainName: `api.${stack}.<http://app.example.io|app.example.io>`,
  validationMethod: "DNS",
  subjectAlternativeNames: [`*.api.${stack}.<http://app.example.io|app.example.io>`],
  // default
  keyAlgorithm: "RSA_2048",
  // stick to serverless conventions
  tags: {
    STAGE: stack,
  },
});

const zone = aws.route53.getZone({
  name: `${stack}.<http://app.example.io|app.example.io>`,
  privateZone: false,
});

const certificationRecords = certificate.domainValidationOptions.apply(
  (domainValidationOptions) => {
    return Object.entries(domainValidationOptions).map(([index, dvo]) => {
      return new aws.route53.Record(
        `certification-validation-record-${index}`,
        {
          name: dvo.resourceRecordName,
          zoneId: zone.then((zone) => zone.zoneId),
          records: [dvo.resourceRecordValue],
          type: dvo.resourceRecordType,
          allowOverwrite: true,
          ttl: 10,
        }
      );
    });
  }
);

const certificateValidation = new aws.acm.CertificateValidation(
  "certificate-validation",
  {
    certificateArn: certificate.arn,
    validationRecordFqdns: certificationRecords.apply((records) =>
      records.map((record) => record.fqdn)
    ),
  }
);

export const certificateOutput = certificate;
export const recordsOutput = certificationRecords;
export const validationOutput = certificateValidation;
thanksÂȘ
l
You don't need to get at the actual values when you're passing them to resource constructors. You can use the Outputs from other resources as if they were unwrapped. Pulumi unwraps them at deployment time.
Yes that looks fine. I think you can use fewer calls to apply if you change where the looping happens, but that's probably excessive optimization. Working is all you need :)
a
left it as this
Copy code
const certificationRecords = certificate.domainValidationOptions.apply(
  (domainValidationOptions) =>
    Object.entries(domainValidationOptions).map(
      ([index, dvo]) =>
        new aws.route53.Record(`certification-validation-record-${index}`, {
          name: dvo.resourceRecordName,
          zoneId: zone.then((zone) => zone.zoneId),
          records: [dvo.resourceRecordValue],
          type: dvo.resourceRecordType,
          allowOverwrite: true,
          ttl: 10,
        })
    )
);
thanks again!!