in packages/cdk-graph/src/core/compute.ts [332:440]
function resolveReference(
store: Graph.Store,
unresolved: SerializedGraph.SGUnresolvedReference
): Graph.Reference | undefined {
const source = store.getNode(unresolved.source);
if (source.stack == null) {
console.warn(String(source), source);
throw new Error(`Node ${source} is not within stack`);
}
let target: Graph.Node;
switch (unresolved.referenceType) {
case ReferenceTypeEnum.REF: {
// ref logicalId is only unique in the stack
target = store.findNodeByLogicalId(source.stack, unresolved.target);
return new Graph.Reference({
store,
uuid: generateConsistentUUID(unresolved, Graph.Reference.PREFIX),
referenceType: ReferenceTypeEnum.REF,
source,
target,
});
}
case ReferenceTypeEnum.IMPORT: {
// imports already contain the stack id (stack:logicalId)
target = store.findNodeByLogicalUniversalId(
unresolved.target as LOGICAL_UNIVERSAL_ID
);
return new Graph.ImportReference({
store,
uuid: generateConsistentUUID(unresolved, Graph.ImportReference.PREFIX),
source,
target,
});
}
case ReferenceTypeEnum.IMPORT_ARN: {
const resolvedImportArnNode = store.findNodeByImportArn(
unresolved.target
);
if (!resolvedImportArnNode) {
// ImportArn tokens are not direct matches, so we can safely ignore misses.
// We only care about resources directly imported into the CDK app.
return undefined;
}
return new Graph.ImportReference({
store,
uuid: generateConsistentUUID(unresolved, Graph.ImportReference.PREFIX),
source,
target: resolvedImportArnNode,
});
}
case ReferenceTypeEnum.ATTRIBUTE: {
const attribute = unresolved.value as string;
if (attribute && attribute.startsWith("Outputs.")) {
// Stack output reference
const stacksToSearch = source.rootStack?.stage?.stacks || store.stacks;
const potentialRefStacks = Object.values(stacksToSearch).filter(
(_stack) => _stack.logicalId === unresolved.target
);
if (potentialRefStacks.length === 1) {
const refStack = potentialRefStacks[0];
target = refStack.findOutput(attribute.replace("Outputs.", ""));
} else {
console.warn(
"Failed to find logical id from attribute reference:",
unresolved.target
);
if (potentialRefStacks.length) {
console.warn(
"Found multiple matching stacks:",
Object.values(potentialRefStacks).map(
(stack) => `${String(stack)}:${stack.logicalId || "ROOT"}`
)
);
} else {
console.warn(
"Available stacks:",
Object.values(store.stacks).map(
(stack) => `${String(stack)}:${stack.logicalId || "ROOT"}`
)
);
}
throw new Error(
`Failed to find Fn::GetAtt stack for output reference "${unresolved.target}": ${potentialRefStacks.length}`
);
}
} else {
target = store.findNodeByLogicalId(source.stack, unresolved.target);
}
if (target) {
return new Graph.AttributeReference({
store,
uuid: generateConsistentUUID(
unresolved,
Graph.AttributeReference.PREFIX
),
source,
target,
value: attribute,
});
}
}
}
throw new Error(`Failed to resolve reference: ${JSON.stringify(unresolved)}`);
}