Aws-cdk: Automatic token exports can not be arrays

Created on 21 Jan 2020  ยท  6Comments  ยท  Source: aws/aws-cdk

Reproduction Steps

Add the following to your stack:

Fn.select(0, vpcEndpoint.vpcEndpointDnsEntries)

It generates the following which is incorrect since DnsEntries are a string

"ExportsOutputFnGetAttVPCVpcCloudAuthVpcEndpointA6A0016BDnsEntries65E2739D": {
  "Value": {
    "Fn::GetAtt": [
      "VPCVpcCloudAuthVpcEndpointA6A0016B",
      "DnsEntries"
    ]
  },
  "Export": {
    "Name": "Vpc:ExportsOutputFnGetAttVPCVpcCloudAuthVpcEndpointA6A0016BDnsEntries65E2739D"
  }
}

Error Log

Vpc: creating CloudFormation changeset...

 โŒ  Vpc failed: Error [ValidationError]: Template format error: The Value field of every Outputs member must evaluate to a String.
    at Request.extractError (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:685:12)
    at Request.callListeners (/home/linuxbrew/.linuxbrew/Cellar/aws-cdk/1.20.0/libexec/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  message: 'Template format error: The Value field of every Outputs member must evaluate to a String.',
  code: 'ValidationError',
  time: 2020-01-19T23:30:22.007Z,
  requestId: '43c10843-42a8-4439-a770-a77ec7859f46',
  statusCode: 400,
  retryable: false,
  retryDelay: 109.59137506513541
}
Template format error: The Value field of every Outputs member must evaluate to a String.

Environment

  • CLI Version :
  • Framework Version:
  • OS :
  • Language :

Other


This is :bug: Bug Report

@aws-cdcore bug efformedium p2

Most helpful comment

I have experience the same issue had had to create my own way around it (not ideal :P)

@SomayaB and @rix0rrr you asked about example code, here it is (https://github.com/timpur/aws-cdk-issue-5897/blob/master/cdk.out/Stack1.template.json#L18).

Very basic stack but produces the issue. Seems the select happens in the consumer which is fine bout the generated output doesnt account for refs that are arrays of strings ....

I imagine is something to do with this line (https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/core/lib/private/refs.ts#L183)

Thanks. Hopes this helps

All 6 comments

Hi @nunezro2, thanks for submitting an issue. In order to have a better understanding of what the problem is we need a bit more information. Could you edit the original post and fill out the template as much as possible. Thanks!

Looks like the bug report is that Fn.select() doesn't actually output a { Fn::Select } intrinsic, which I can hardly imagine.

Closing until we get a repro.

I can report the same issue with InterfaceVpcEndpoint

in one stack I have:

this.endpointDNS = Fn.select(0, this.endpointService.vpcEndpointDnsEntries);

Then the output of that stack is:

"Outputs": {
    "ExportsOutputFnGetAttsapgatewayvpcendpoint99C0B197DnsEntriesC7F2A387": {
      "Value": {
        "Fn::GetAtt": [
          "sapgatewayvpcendpoint99C0B197",
          "DnsEntries"
        ]
      },
      "Export": {
        "Name": "SAPGatewayProxyEndpointClient:ExportsOutputFnGetAttsapgatewayvpcendpoint99C0B197DnsEntriesC7F2A387"
      }
    }
  }

And then Fn::Split happens at the "consumption" stack

``json { "Name":"HOST", "Value":{ "Fn::Join":[ "", [ { "Fn::Select":[ 0, { "Fn::ImportValue":"SAPGatewayProxyEndpointClient:ExportsOutputFnGetAttsapgatewayvpcendpoint99C0B197DnsEntriesC7F2A387" } ] }, "}:443" ] ] } },

I have experience the same issue had had to create my own way around it (not ideal :P)

@SomayaB and @rix0rrr you asked about example code, here it is (https://github.com/timpur/aws-cdk-issue-5897/blob/master/cdk.out/Stack1.template.json#L18).

Very basic stack but produces the issue. Seems the select happens in the consumer which is fine bout the generated output doesnt account for refs that are arrays of strings ....

I imagine is something to do with this line (https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/core/lib/private/refs.ts#L183)

Thanks. Hopes this helps

Oh yes I see what's going on now. You do the select in the other stack. Overlooked it the first time around, sorry.

Not even sure if we have enough information at runtime to properly encode this, but we can see.


The solution will have to look like:

  • Whenever array tokens are exported, we should export a { Fn::Join } expression, and on import they should be imported as { Fn::Split: { Fn:: ImportValue }}.

Question is, do we have enough information to detect the token type when this link is being established?

I've just found this same error when passing a VPC object as parameter between two stacks: if an InterfaceEndpoint is defined in the VPC one output (with DnsEntries) is created and the failure appears.

Was this page helpful?
0 / 5 - 0 ratings