typescriptterraformcommand-line-interfaceterraform-cdk

how to install terraform on node.js/typescript based cli tool


I am developing a typescript/node.js based cli tool, in which I want to include terraform in such a way that when users use the tool, they will not need to install terraform on their own machine, and that the tool can run soemthing like terraform --help (by running a shell command within the typescript code) successfully. However, I have not been able to figure out how to do this, and I am seeking help on how to successfully install terraform inside a typescript/node.js based cli tool. As far as I am aware, there is no node-based binary for terraform that I can reference inside the node_modules directory, and from my research it doesn't seem that I can use docker within a cli tool (correct me if I'm wrong). Would anyone know how to install terraform? (the ultimate goal is to use cdktf to deploy cloud infrastructure within the typescript code, but for this cdktf needs terraform)


Solution

  • The general problem of installing external software over the network is to find some way to determine:

    Terraform in particular is distributed as a native code executable and so there is a separate distribution package for each target platform. A target platform is something like linux_amd64, or darwin_arm64 (for macOS on Apple Silicon), etc. Therefore there is an extra step of detecting which platform your Node program is currently running on so it can download the appropriate package.

    NodeJS uses different identifiers for operating systems and architectures than Terraform does, but that information is available via properties of the process module:

    (NOTE: The possible values listed above are those from Node v18.11.0; this set of possible operating systems and architectures is likely to differ in other versions of Node.)

    In your own program then you can define a data structure which maps from the OS and architecture names that Node uses to the source URLs and checksums for the Terraform distribution, which you can find on releases.hashicorp.com.

    For example:

    let terraformPackages = {
      'win32': {
        'x64': {
          url: 'https://releases.hashicorp.com/terraform/1.3.2/terraform_1.3.2_windows_amd64.zip',
          sha256sum: '6b0e47fff3392352ecc1264fd5b348fd17b2f2dff1a8dca9933e9bb033fdb498',
        },
      },
      'linux': {
        'x64': {
          url: 'https://releases.hashicorp.com/terraform/1.3.2/terraform_1.3.2_linux_amd64.zip',
          sha256sum: '6372e02a7f04bef9dac4a7a12f4580a0ad96a37b5997e80738e070be330cb11c',
        },
        'arm64': {
          url: 'https://releases.hashicorp.com/terraform/1.3.2/terraform_1.3.2_linux_arm64.zip',
          sha256sum: 'ce1a8770aaf27736a3352c5c31e95fb10d0944729b9d81013bf6848f8657da5f',
        },
      },
      'darwin': {
        'x64': {
          url: 'https://releases.hashicorp.com/terraform/1.3.2/terraform_1.3.2_darwin_amd64.zip',
          sha256sum: 'edaed5a7c4057f1f2a3826922f3e594c45e24c1e22605b94de9c097b683c38bd',
        },
        'arm64': {
          url: 'https://releases.hashicorp.com/terraform/1.3.2/terraform_1.3.2_darwin_arm64.zip',
          sha256sum: 'ff92cd79b01d39a890314c2df91355c0b6d6815fbc069ccaee9da5d8b9ff8580',
        },
      },
      // ...
    };
    

    When your program wants to download Terraform, it can consult terraformPackages[process.platform][process.arch] (taking care to handle the situation where there is no available Terraform package for a particular platform) to learn both where to download it from and what checksum to expect.

    You can use the crypto module to calculate the SHA256 hash of the package you've downloaded and compare it against the sha256sum property to make sure you've downloaded the expected file. If (and only if) the checksum matches, you can extract the zip file to a suitable location and execute it from there.

    For cdktf in particular, you can set the TERRAFORM_BINARY_NAME environment variable to refer to the terraform command inside the directory where you extracted the zip file so that the cdktf tool will find and use the executable you placed in that location.