npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@c6fc/sonnetry

v3.1.3

Published

AWS + Terraform + Jsonnet in perfect harmony.

Downloads

118

Readme

AWS + Terraform + Jsonnet in perfect harmony

Sonnetry extends Jsonnet with the power of the AWS SDK for Node, and empowers its use with Terraform. All in a simple, easy-to-use way.

Installation

Quick-start a Sonnetry project using npm-init:

$ npm init sonnetry my_sonnetry_project

To specify the terraform version to use, update your package.json to include a tf_version config element.

"config": {
  "tf_version": "1.25.0"
}

Jsonnet extended by the AWS SDK

One of the greatest features of Sonnetry is the ability to consume the AWS SDK for JavaScript directly within Jsonnet. Consider the following Jsonnet file:

local aws = import 'aws-sdk';  // Import the AWS SDK

{
  'demo.tf.json': {
    output: {
      whoami: {
      	// Prepare an API caller
        value: aws.api(		

            // Using a client for the 'STS' service	
            aws.client('STS'),

            // To call 'getCallerIdentity'
            'getCallerIdentity'

        // Then retrieve the 'Arn' property from the result.
        ).Arn
      }
    }
  }
}

When evaluated, you'll see the following in ./render/demo.tf.json:

{
  "output": {
    "whoami": {
      "value": "arn:aws:iam::123456789012:user/you"
    }
  }
}

Wait, It called sts:getCallerIdentity, then injected the Identity ARN into the Terraform configuration? How is this possible?!

Sonnetry accomplishes this through two very simple native functions added to Jsonnet:

  1. aws.client( <service_code>, [{ ...params }])
  2. aws.api( <aws_client>, <sdk_method>, [{ ...params }])

These perfectly translate to the service codes and methods exposed by the AWS SDK for JavaScript. For example, if we wanted to call ec2:DescribeVpcs in us-west-2, we could do this:

local ec2client = aws.client('EC2', { region: "us-west-2" }),
vpcs: aws.api(ec2client, 'describeVpcs')

or, as a one-liner:

vpcs: aws.api(aws.client('EC2', { region: "us-west-2" }), 'describeVpcs')

If you don't need to specify any parameters to the API client, you can also just use aws.call():

identity: aws.call('STS', 'getCallerIdentity')

It's that easy! If you want to see more examples, check out the sonnetry-examples repo on github!

Project-based state management in S3

Terraform's remote state is critical for long-lived infrastructure or circumstances where multiple individuals are contributing to the architecture. Sonnetry makes it easy to bootstrap a project into a new remote state, and for that state to be used consistently across accounts or security contexts.

This is accomplished through Sonnetry's 'bootstrap()' function:

local aws = import 'aws-sdk';        // Import the AWS SDK
local sonnetry = import 'sonnetry';  // Import sonnetry

// Create the s3 backend and return
// a terraform s3 backend configuration
local backend = sonnetry.bootstrap('my-persistent-project');

{
  // Save the backend in the project
  'backend.tf.json': backend

  // Access a property of the backend configuration
  backendBucket:: backend.terraform.backend.s3.bucket
}

If the account doesn't have a Sonnetry state bucket, it will be created when the file is evaluated. The bucket is created with the format of sonnetry-<random_characters>-<unix_timestamp>, and is automatically configured to block public access and enable versioning.

Applying the configuration will render the following in 'backend.tf.json':

{
    "terraform": {
        "backend": {
            "s3": {
                "bucket": "sonnetry-oszghfzdrx-1637718050",
                "key": "sonnetry/my-persistent-project/terraform.tfstate",
                "region": "us-east-1"
            }
        }
    }
}

Sonnetry will always use the same bucket for all projects within an account. As a result, it's important to ensure that different projects use distinct project names.

Using the command line utility

Sonnetry bundles the sonnetry command line utility for ease of use. It can be run depending on how you chose to install it:

$ npx sonnetry   # Project-local
$ sonnetry       # Global

Use the sonnetry generate command to parse a Jsonnet file and render the results into .render in the local directory. This is great for validating the results before invoking terraform, or if you want to run terraform manually.

$ npx sonnetry apply terraform.jsonnet
[+] Evaluating terraform.jsonnet into ./render/
./render/demo.tf.json

The sonnetry apply command starts out the same as generate, with the added step of running terraform against the generated configurations in ./render/.

$ npx sonnetry apply terraform.jsonnet
[+] Evaluating terraform.jsonnet into ./render/
./render/demo.tf.json

[...]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

whoami_short = "arn:aws:iam::123456789012:user/you"
[+] Successfully applied

Using the library

If you need more control over your IaC, you can easily import and use the library in your own project.

const { Sonnet } = require('@c6fc/sonnetry');

const sonnetry = new Sonnet({
  // The folder to write the configurations into
  renderPath: './render',

  // Whether to delete the *.tf.json files from the renderPath before rendering		
  cleanBeforeRender: true
});

// Render the Jsonnet file, returning a raw object.
const json = await sonnetry.render('terraform.jsonnet');

// Save the most recent render to the renderPath.
sonnetry.write();

// Run `terraform apply` on the rendered files.
sonnetry.apply();

Authenticating to AWS

Authenticating to AWS is a common challenge when working with Terraform, and Sonnetry addresses this beautifully. Sonnetry will always use the same credentials that the AWS CLI would in a given context, automatically determining the AWS credentials to be used in the following order:

  1. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN environment variables
  2. EC2 instance profile
  3. AWS_PROFILE environment variable

It also natively supports assumerole profile entries, and will prompt for MFA as appropriate.

$ export AWS_PROFILE=assumerole_profile_with_mfa
$ npx sonnetry apply terraform.jsonnet
Enter MFA code for arn:aws:iam::123456789012:mfa/you: ******
[+] Successfully assumed role [arn:aws:iam::210987654321:role/Deployment]
[...]