Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline Usage of Prebuilt Providers #331

Merged
merged 12 commits into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Choose a language:
## Documentation

* Install and run a quick start tutorial at [HashiCorp Learn](https://learn.hashicorp.com/terraform/cdktf/cdktf-install)
* Using CDK for Terraform CLI for importing Terraform [modules and providers](./docs/working-with-cdk-for-terraform/importing-providers-and-modules.md).
* Using CDK for Terraform CLI for importing Terraform [modules and providers](./docs/working-with-cdk-for-terraform/using-providers-and-modules.md).
* Explore the CDK for Terraform [CLI](./docs/cli-commands.md).
* Defining Terraform [outputs](./docs/working-with-cdk-for-terraform/terraform-outputs.md).
* Using Terraform [remote backend](./docs/working-with-cdk-for-terraform/remote-backend.md).
Expand Down
145 changes: 145 additions & 0 deletions docs/working-with-cdk-for-terraform/cdktf-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# cdktf.json Configuration File

With the `cdktf.json` in your project root directory you can configure the behaviour of the Terraform CDK CLI:

## Specification

```ts
export enum Language {
TYPESCRIPT = 'typescript',
PYTHON = 'python',
DOTNET = 'dotnet', // not yet supported
JAVA = 'java', // not yet supported
}

export interface Config {
readonly app?: string; // The command to run in order to synthesize the code to Terraform compatible JSON
readonly language?: Language; // Target language for building provider or module bindings. Currently supported: `typescript` or `python`
readonly output: string; // Default: 'cdktf.out'. Where the synthesized JSON should go. Also will be the working directory for Terraform operations
readonly codeMakerOutput: string; // Default: '.gen'. Path where generated provider bindings will be rendered to.
readonly terraformProviders?: string[]; // Terraform Providers to build
readonly terraformModules?: string[]; // Terraform Modules to build
}
```

### Terraform Providers and Modules

The [following specifications](https://www.terraform.io/docs/configuration/provider-requirements.html#requiring-providers) schema should be followed for providers and modules

[source](https://www.terraform.io/docs/configuration/provider-requirements.html#source-addresses)@[version](https://www.terraform.io/docs/configuration/provider-requirements.html#version-constraints)

#### For HashiCorp maintained providers

Official HashiCorp [maintained providers](https://registry.terraform.io/browse/providers?tier=official) (e.g. `aws`, `google` or `azurerm`) can be specified in a short version like this: `"aws@~> 2.0"`

#### 3rd Party Providers

Community providers have to provide a fully qualified name, e.g. to define the Docker provider: `terraform-providers/docker@~> 2.0`

#### Modules

Similar to 3rd Party providers, the full registry namespace should be provided. Please note that only modules from the registry are supported at this point.

## Examples

### Minimal Configuration

A minimal configuration would define `app` only. This is useful, when planning to use [prebuilt providers](https://github.com/terraform-cdk-providers) and therefore no provider or modules bindings should be generated.

```json
{
"app": "npm run --silent compile && node main.js"
}
```

### Changing Code Output Directories

This will synthesize JSON into `my-workdir` and all Terraform operations - such as `deploy` or `destroy` - will be performed in this directory.

```json
{
"app": "npm run --silent compile && node main.js",
"output": "my-workdir",
}
```

### Building Providers
skorfmann marked this conversation as resolved.
Show resolved Hide resolved

With this `terraformProviders` configuration, a `cdktf get` will build the latest AWS provider within the 2.X version range. The generated code will be saved into `.gen` by default. This can be adjusted with `codeMakerOutput`, see other examples below.

```json
{
"language": "typescript",
"app": "npm run --silent compile && node main.js",
"terraformProviders": [
"aws@~> 2.0"
]
}
```

### Building Modules

With this `terraformModules` configuration, a `cdktf get` will build the latest `terraform-aws-modules/vpc/aws` module from the Terraform Registry. The generated code will be saved into `.gen` by default. This can be adjusted with `codeMakerOutput` - see other examples below.

```json
{
"language": "typescript",
"app": "npm run --silent compile && node main.js",
"terraformModules": [
"terraform-aws-modules/vpc/aws"
]
}
```

### Building Providers & Modules

This combines examples above, a `cdktf get` will build both the AWS provider and the latest `terraform-aws-modules/vpc/aws` module from the Terraform Registry.

```json
{
"language": "typescript",
skorfmann marked this conversation as resolved.
Show resolved Hide resolved
"app": "npm run --silent compile && node main.js",
"terraformModules": [
"terraform-aws-modules/vpc/aws"
],
"terraformProviders": [
"aws@~> 2.0"
]
}
```

### Building Multiple Providers

It's possible to build multiple providers or modules as well.

```json
{
"language": "typescript",
"app": "npm run --silent compile && node main.js",
"terraformProviders": [
"null",
"aws",
"google",
"azurerm",
"kubernetes",
"consul",
"vault",
"nomad",
]
}
```

### Building Providers in Custom Directory

This will generate the `aws` provider bindings in the folder `./imports`. This is used in the Python template, to make it easier to reference the generated classes.

```json
{
"language": "python",
"app": "pipenv run ./main.py",
"terraformProviders": [
"aws@~> 2.0"
],
"codeMakerOutput": "imports"
}
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
# Importing Providers and Modules
# Using Providers and Modules

## Prebuilt Providers

To improve the general user experience around provider imports and to allow building further abstractions on top of the Terraform provider bindings, a few popular providers are offered as prebuilt packages. At the moment the following providers are built and published to NPM / PyPi on a regular basis automatically.

- [AWS Provider](https://github.com/terraform-cdk-providers/cdktf-provider-aws)
- [Google Provider](https://github.com/terraform-cdk-providers/cdktf-provider-google)
- [Azure Provider](https://github.com/terraform-cdk-providers/cdktf-provider-azurerm)
- [Kubernetes Provider](https://github.com/terraform-cdk-providers/cdktf-provider-kubernetes)
- [Docker Provider](https://github.com/terraform-cdk-providers/cdktf-provider-docker)
- [Github Provider](https://github.com/terraform-cdk-providers/cdktf-provider-github)
- [Null Provider](https://github.com/terraform-cdk-providers/cdktf-provider-null)

Please check the [Terraform CDK Providers](https://github.com/terraform-cdk-providers) organization as well for an up to date list. As these are normal NPM / PyPI packages, they can be used as any other dependency.

e.g. in Typescript / Node:

```
anubhavmishra marked this conversation as resolved.
Show resolved Hide resolved
npm install -a @cdktf/provider-aws
```

## Importing Providers and Modules

CDK for Terraform allows you to import Terraform [providers](https://www.terraform.io/docs/providers/index.html) and [modules](https://www.terraform.io/docs/modules/index.html) to your project
using this workflow.
Expand Down Expand Up @@ -31,7 +53,7 @@ new MyStack(app, 'hello-terraform');
app.synth();
```

The project also has the `cdktf.json` file that defines what providers and modules are being used by the project.
The project also has the [cdktf.json](./cdktf-json.md) file that defines what providers and modules are being used by the project.

```bash
vim cdktf.json
Expand Down Expand Up @@ -183,4 +205,4 @@ cdktf synth --json
}
}

```
```
4 changes: 4 additions & 0 deletions examples/typescript/aws-prebuilt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.gen
cdktf.out
terraform.tfstate*
!tsconfig.json
15 changes: 15 additions & 0 deletions examples/typescript/aws-prebuilt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Typescript AWS with Prebuilt Provider

A CDK for Terraform application in TypeScript using the prebuilt [AWS provider](https://github.com/terraform-cdk-providers/cdktf-provider-aws).

## Usage

Install project dependencies:

```shell
yarn install
```

You can now edit the [main.ts](./main.ts) file if you want to modify any code.

Perform a `cdktf diff` to get a plan of what would be deployed.
3 changes: 3 additions & 0 deletions examples/typescript/aws-prebuilt/cdktf.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "npm run --silent compile && node main.js"
}
49 changes: 49 additions & 0 deletions examples/typescript/aws-prebuilt/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Construct } from 'constructs';
import { App, TerraformStack, TerraformOutput } from 'cdktf';
import { DataAwsRegion, AwsProvider, DynamodbTable, SnsTopic } from '@cdktf/provider-aws'

export class HelloTerra extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);

new AwsProvider(this, 'aws', {
region: 'eu-central-1'
})

const region = new DataAwsRegion(this, 'region')

const table = new DynamodbTable(this, 'Hello', {
name: `my-first-table-${region.name}`,
hashKey: 'temp',
attribute: [
{ name: 'id', type: 'S' },
],
billingMode: "PAY_PER_REQUEST"
});

table.addOverride('hash_key', 'id')
// table.addOverride('hash_key', 'foo')
table.addOverride('lifecycle', { create_before_destroy: true })

const topicCount = 1
const topics = [...Array(topicCount).keys()].map((i) => {
return new SnsTopic(this, `Topic${i}`, {
displayName: `my-first-sns-topic${i}`
});
})

new TerraformOutput(this, 'table_name', {
value: table.name
})

topics.forEach((topic, i) => {
new TerraformOutput(this, `sns_topic${i}`, {
value: topic.name
})
})
}
}

const app = new App();
new HelloTerra(app, 'hello-terra');
app.synth();
21 changes: 21 additions & 0 deletions examples/typescript/aws-prebuilt/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@examples/typescript-aws-prebuilt",
"version": "0.0.0",
"main": "index.js",
"license": "MPL-2.0",
"scripts": {
"build": "tsc",
"compile": "tsc --pretty",
"synth": "cdktf synth"
},
"devDependencies": {
"@types/node": "^14.0.26",
"cdktf-cli": "0.0.0",
"typescript": "^3.9.7"
},
"dependencies": {
"@cdktf/provider-aws": "^0.0.19",
"cdktf": "0.0.0",
"constructs": "^3.0.0"
}
}
33 changes: 33 additions & 0 deletions examples/typescript/aws-prebuilt/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"compilerOptions": {
"alwaysStrict": true,
"charset": "utf8",
"declaration": true,
"experimentalDecorators": true,
"inlineSourceMap": true,
"inlineSources": true,
"lib": [
"es2018"
],
"module": "CommonJS",
"noEmitOnError": true,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"strict": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"stripInternal": true,
"target": "ES2018"
},
"include": [
"**/*.ts"
],
"exclude": [
"node_modules"
]
}
18 changes: 18 additions & 0 deletions examples/typescript/aws-prebuilt/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@types/node@^13.1.1":
version "13.1.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.4.tgz#4cfd90175a200ee9b02bd6b1cd19bc349741607e"
integrity sha512-Lue/mlp2egZJoHXZr4LndxDAd7i/7SQYhV0EjWfb/a4/OZ6tuVwMCVPiwkU5nsEipxEf7hmkSU7Em5VQ8P5NGA==

constructs@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/constructs/-/constructs-2.0.1.tgz#274d6b8ce6a698813495c444466b0c745349ddb5"
integrity sha512-edR85YFGI9TBT9byAo5vAfI0PRi+jFGzinwN3RAJwKfv6Yc9x9kALYfoEmgotp95qT7/k/iUQWHrH9BMJeqpdg==

typescript@^3.7.4:
version "3.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19"
integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==
2 changes: 1 addition & 1 deletion packages/cdktf-cli/bin/cmds/synth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Command implements yargs.CommandModule {
const outdir = argv.output;
const jsonOutput = argv.json;

if (!await fs.pathExists(config.codeMakerOutput)) {
if (config.checkCodeMakerOutput && !await fs.pathExists(config.codeMakerOutput)) {
console.error(`ERROR: synthesis failed, run "cdktf get" to generate providers in ${config.codeMakerOutput}`);
process.exit(1);
}
Expand Down
6 changes: 6 additions & 0 deletions packages/cdktf-cli/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const DEFAULTS = {
codeMakerOutput: '.gen'
}

function isPresent(input: string[] | undefined): boolean {
return Array.isArray(input) && input.length > 0
}

export interface Config {
readonly app?: string;
Expand All @@ -16,6 +19,7 @@ export interface Config {
readonly codeMakerOutput: string;
readonly terraformProviders?: string[];
readonly terraformModules?: string[];
checkCodeMakerOutput?: boolean;
}

export function readConfigSync(): Config {
Expand All @@ -28,5 +32,7 @@ export function readConfigSync(): Config {
};
}

config.checkCodeMakerOutput = isPresent(config.terraformModules) || isPresent(config.terraformProviders)

return config;
}
Loading