aws / aws/aws-cdk

aws_cdk: custom Synthesizer doesn't show how/when to bind

Open
#35,865 3 comments 0 reactions 0 assignees View on GitHub
documentation effort/small p2 package/tools
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
1d 19h
Merged PRs (30d)
74

Description

### Describe the issue

https://docs.aws.amazon.com/cdk/v2/guide/configure-synth.html

> If the default CDK synthesis behavior doesn’t suit your needs, you can customize CDK synthesis. To do this, you modify DefaultStackSynthesizer, use other available built-in synthesizers, or create your own synthesizer. For instructions, see [Customize CDK stack synthesis](https://docs.aws.amazon.com/cdk/v2/guide/customize-synth.html).

https://docs.aws.amazon.com/cdk/v2/guide/customize-synth.html

> One way to customize CDK stack synthesis, is by modifying the [DefaultStackSynthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html). You can customize this synthesizer for a single CDK stack using the synthesizer property of your Stack instance.
>
> ```python
> MyStack(self, "MyStack",
> synthesizer=DefaultStackSynthesizer(
> qualifier="MYQUALIFIER"
> ))
> ```

If I try to implement this:
```python
class CustomStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, synthesizer=DefaultStackSynthesizer(), **kwargs)
logger.error("Initialized CustomStack: %s", construct_id)
logger.error("Bound stack: %r", self.synthesizer._bound_stack)
```
when I `cdk synth` it results in an error:
```
Initialized CustomStack: MyStack
[jsii/kernel] WARNING: referenced object aws-cdk-lib.DefaultStackSynthesizer@10693 does not have the Symbol($__jsii__interfaces__$) property!
jsii.errors.JavaScriptError:
@jsii/kernel.RuntimeError: ValidationError: The StackSynthesizer must be bound to a Stack first before boundStack() can be called
at Kernel._Kernel_ensureSync (/private/var/folders/ts/8kph5_654z18cy46hmzl59lr0000gn/T/tmpksl0cnpw/lib/program.js:928:23)
at Kernel.get (/private/var/folders/ts/8kph5_654z18cy46hmzl59lr0000gn/T/tmpksl0cnpw/lib/program.js:265:104)
at KernelHost.processRequest (/private/var/folders/ts/8kph5_654z18cy46hmzl59lr0000gn/T/tmpksl0cnpw/lib/program.js:15482:36)
at KernelHost.run (/private/var/folders/ts/8kph5_654z18cy46hmzl59lr0000gn/T/tmpksl0cnpw/lib/program.js:15442:22)
at Immediate._onImmediate (/private/var/folders/ts/8kph5_654z18cy46hmzl59lr0000gn/T/tmpksl0cnpw/lib/program.js:15443:45)
at process.processImmediate (node:internal/timers:485:21)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "", line 198, in _run_module_as_main
File "", line 88, in _run_code
File "/Users/anentropic/dev/myproject/infra/app.py", line 110, in
MyStage(
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_runtime.py", line 118, in __call__
inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/infra/stage.py", line 25, in __init__
MyStack(
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_runtime.py", line 118, in __call__
inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/infra/stacks.py", line 39, in __init__
super().__init__(
File "/Users/anentropic/dev/myproject/infra/constructs/synthesizer.py", line 35, in __init__
logger.error("Bound stack: %r", self.synthesizer._bound_stack)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/aws_cdk/__init__.py", line 25153, in _bound_stack
return typing.cast(Stack, jsii.get(self, "boundStack"))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_kernel/__init__.py", line 149, in wrapped
return _recursize_dereference(kernel, fn(kernel, *args, **kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_kernel/__init__.py", line 360, in get
response = self.provider.get(
^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 368, in get
return self._process.send(request, GetResponse)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/anentropic/dev/myproject/.venv/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 342, in send
raise RuntimeError(resp.error) from JavaScriptError(resp.stack)
RuntimeError: ValidationError: The StackSynthesizer must be bound to a Stack first before boundStack() can be called
```

If I omit the `synthesizer=DefaultStackSynthesizer()` arg then synth succeeds (and I see my `Bound stack: ...` logging output).

This is puzzling, because it appears here https://github.com/aws/aws-cdk/blob/a7a6b406fb5869bbd063a56f1c1f4d6449586bf1/packages/aws-cdk-lib/core/lib/stack.ts#L526-L533 that the synthesizer gets bound as part of the stack constructor. So after calling `super().__init__(..)` in the Stack it should be bound.

Either it's a bug or the docs have omitted some important details about implementing a custom synthesizer.

### Links

https://docs.aws.amazon.com/cdk/v2/guide/customize-synth.html

Contributor guide

Open the contributing guide

Research direction

Start with the linked Customize CDK stack synthesis documentation and the Stack constructor code at packages/aws-cdk-lib/core/lib/stack.ts#L526-L533. Reproduce the Python custom Stack example with and without DefaultStackSynthesizer, then document when binding occurs and clarify the supported custom synthesizer usage or the discrepancy shown by the error.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, python, typescript
Domain
documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.