hashicorp / terraform-cdk

Define infrastructure resources using programming constructs and provision them using HashiCorp Terraform
https://www.terraform.io/cdktf
Mozilla Public License 2.0
4.79k stars 441 forks source link

PYTHON: Depends on node.js installation #3620

Open srgoni opened 1 month ago

srgoni commented 1 month ago

Expected Behavior

When executing a cdktf stack script written in Python directly, it should run without requiring any dependencies besides the cdktf Python modules and precompiled providers.

Actual Behavior

The script fails with a FileNotFoundError: [Errno 2] No such file or directory: 'node' error, indicating that the Python modules will always try to spawn an external Node.js interpreter.

Steps to Reproduce

  1. Create a basic Python cdktf script:
    # main.py
    from cdktf import App, TerraformStack
    app = App()
    TerraformStack(app, "test")
    app.synth()
  2. Install dependencies:
    pipenv install cdktf=0.20.7
  3. Execute the cdktf script to generate Terraform:
    pipenv run python main.py
  4. Run Terraform on the resulting output:
    terraform apply

Versions

language: Python 3.11 cdktf-cli: N/A node: N/A cdktf: 0.20.7 constructs: 10.3.0 jsii: 1.98.0 terraform: 1.5.7 arch: amd64 os: Debian trixie

Providers

N/A, problem occurs without any providers.

Gist

https://gist.github.com/srgoni/3f1882ad95b2587c41b1e85ac0c65809

Possible Solutions

No response

Workarounds

No response

Anything Else?

I believe that this scenario used to work with previous cdktf versions, but I don't have a reproducible setup at hand.

Full stack trace:

Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from cdktf import App, TerraformStack
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/cdktf/__init__.py", line 35, in <module>
    from ._jsii import *
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/cdktf/_jsii/__init__.py", line 13, in <module>
    import constructs._jsii
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/constructs/__init__.py", line 43, in <module>
    from ._jsii import *
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/constructs/_jsii/__init__.py", line 13, in <module>
    __jsii_assembly__ = jsii.JSIIAssembly.load(
                        ^^^^^^^^^^^^^^^^^^^^^^^
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_runtime.py", line 55, in load
    _kernel.load(assembly.name, assembly.version, os.fspath(assembly_path))
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/__init__.py", line 299, in load
    self.provider.load(LoadRequest(name=name, version=version, tarball=tarball))
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 354, in load
    return self._process.send(request, LoadResponse)
           ^^^^^^^^^^^^^
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_utils.py", line 23, in wrapped
    stored.append(fgetter(self))
                  ^^^^^^^^^^^^^
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 349, in _process
    process.start()
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 260, in start
    self._process = subprocess.Popen(
                    ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.11/subprocess.py", line 1955, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'node'
Exception ignored in: <function _NodeProcess.__del__ at 0x7fdfde7f5440>
Traceback (most recent call last):
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 228, in __del__
    self.stop()
  File "~/.local/share/virtualenvs/test/lib/python3.11/site-packages/jsii/_kernel/providers/process.py", line 291, in stop
    assert self._process.stdin is not None
           ^^^^^^^^^^^^^
AttributeError: '_NodeProcess' object has no attribute '_process'

References

No response

Help Wanted

Community Note

nbaju1 commented 1 month ago

Node is a prerequisite for CDKTF whichever language you are writing in, as stated in the docs.

srgoni commented 1 month ago

Interesting. I assumed that the language-specific libraries were all 100% transpiled and didn't require pulling in another language ecosystem (which I'd like to avoid if possible).

It's clear that the cdktf CLI tool requires Node, but I'm not using that.

nbaju1 commented 1 month ago

The cdktf python library utilizes the jsii library when you run app.synth(), which requires node to be available. See jsii docs.