How does `stack.resolve(thingy)` work behinds the ...
# help
d
How does
stack.resolve(thingy)
work behinds the scenes? It seems to prevent any future changes to thingy using L2 methods?
We have the following code …
Copy code
const cfDistribution = this.cfDistribution.node.defaultChild as cf.CfnDistribution
    const config = stack.resolve(cfDistribution.distributionConfig)

    const origins = config.origins.map((origin: cf.OriginProps) =>
      origin?.originPath === `/${this.deployId}`
        ? {
            ...origin,
            originCustomHeaders: [
              {
                headerName: 'X-Site-Root-Key',
                headerValue: this.deployId,
              },
            ],
          }
        : origin,
    )

    cfDistribution.distributionConfig = {
      ...cfDistribution.distributionConfig,
      webAclId: settings.WAF,
      origins,
    }
and I tried to run this code on the next line and it fails….
Copy code
if (props.httpApi) {
      const { httpApi } = props
      const apiDomain = `${httpApi.httpApiId}.execute-api.${region}.<http://amazonaws.com|amazonaws.com>`
      this.cfDistribution.addBehavior('/api', new cfOrigins.HttpOrigin(apiDomain), {
        allowedMethods: cf.AllowedMethods.ALLOW_ALL,
        viewerProtocolPolicy: cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        cachePolicy: cf.CachePolicy.CACHING_DISABLED,
        compress: false,
      })
    }
saying that an origin is missing. What seems to have happened is the behavior is added that references an origin that doesn’t exist, since the
resolve
seems to have sealed any edits to that cfDistribution.
Changing the order fixed the issue in our case BUT, this seems to speak to a larger risk with using it as a construct author. IF you build a construct that uses
resolve
it then prevents you from exposing that underlining thing. Eg.
StaticSite.cfDistribution.addBehavior()
wouldn’t work if StaticSite internally resolved ``cfDistribution`` . Is any of this correct? How else can we accomplish our above code is not to resolve?
f
Hey @Dan Van Brunt, haven’t used it.. it seems CDK does a best try to resolve any token values? https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/core/lib/private/resolve.ts#L103
Looking at the test, it seems obviously there are tokens that cannot be resolved at build time https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/core/test/stack.test.ts#L602
See this test https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/core/test/stack.test.ts#L973, if region is specific,
azs
would know how many zones there are in the region. But if region is not known at build time,
.resolve()
won’t be able to resolve it.
d
I don’t think “build time” vs “deploy time” is our issue though.
I can get the details we need from resolve. But it seems to lock the resource after running it.
In order for us to filter the origins in our construct to find the one that contains the deployId… I first need to resolve. (I think) which locks that resource so that when I try to add a behavior after the resolve It does not work.