Operating Your Terraform Blueprints with Zeet
Terraform is a powerful declarative engine for your cloud infrastructure. With great power comes great responsibility: why not let Zeet take some of that responsiblity off your plate?
Requirements for Terraform Modules (!)
ATTENTION: GCP Provider and GCS Backend Support is currently under development
Zeet can operate your terraform modules, but there's a few restrictions to keep in mind:
- Modules can only use a single cloud provider, either AWS or GCP
- this means you can use 1 AWS account or 1 GCP account within a module
- the module must only rely on the "default" provider
- Only the AWS S3 Bucket and GCP GCS Bucket state backends are supported
Deploying Your Terraform Module via GraphQL
The first step to deploying your Terraform module is to declare your module as a Zeet Blueprint:
Define Your Blueprint
First, issue a createBlueprint
mutation request.
createBlueprint(input:
{
userID: "uuid-abc-123",
slug: "my-blueprint",
displayName: "My Team's Great Blueprint",
published: true,
type: TERRAFORM,
configuration: {
terraform: {
githubSource: "github.com/example-co/example-repo",
}
},
variables: [
{name: "my_string_input", type: STRING, required: true},
{name: "optional_boolean", type: BOOLEAN, required: false}
]
}
) {...}
This mutation requires the following parameters:
- userID: your team's user ID
- slug: a short url-safe string used to programmatically reference your blueprint
- displayName: a human-readable name for your blueprint (can include spaces and special characters)
- published: whether the blueprint should be visible to your team members
- type: the type of blueprint you are defining, in this case, it should be
TERRAFORM
- configuration: the type-specific configuration for your blueprint (see below)
- variables: the variables accepted by each instance of the blueprint (see below)
Configuration
For a Terraform module, we'll need to declare the source of the module. Zeet supports two sources:
- githubSource: a module defined in github, see the Terraform Docs
- if it's in a private github repository, you can include a
gitIntegration
that will supply authentication for the repository.
- if it's in a private github repository, you can include a
- registrySource: a module served by a Terraform Registry
- registrySource supports the additional
moduleVersionConstraint
argument: see the Terraform Docs
- registrySource supports the additional
Variables
Terraform modules support Input Variables and Zeet helps you manage those variables.
When defining your Blueprint, you will declare a variable for each Terraform Input Variable you wish to accept (Terraform variables with defaults don't need to be declared in Zeet, you can omit them in this step if you wish):
- The Zeet Variable
name
must exactly match the Terraform Input Variable name - The
type
must match Terraform Input Variable type- use the JSON type in Zeet for Terraform maps and arrays
- The
required
parameter for each variable should match the expected behavior in Terraform: if the Terraform Input Variable has a default, you can mark it optional in Zeet (or omit it from this mutation entirely).
Create Your Project
Now that you've defined the Blueprint in Zeet, you and your teammates can instantiate any number of Projects using the module.
createProjectV3(input: {
blueprintID: $blueprintID,
projectName: "api-server",
environmentName: "production",
name: "terraform-module-deployment-abc",
variables: [
{
variableSpecID: "variable-uuid-1",
value: "my-variable-value"
}
],
terraformConfiguration: {
stateBackend: {
s3Bucket: {
awsAccountID: "uuid-account-xyz",
region: "us-region-1",
bucketName: "example-co-terraform-state-bucket"
}
}
}
}
) {id, name, blueprintID}
For the createProjectV3
mutation, you'll need to supply:
- The blueprintID (as returned by the
createBlueprint
call) - A projectName or projectID (now called groups), and environmentName or environmentID (now called sub-groups): to organize your Project into a group and sub-group
- A name, to identify your Project
- Since this is a Terraform Resource, the name will need to be a valid Terraform module identifier
- The values for each variable
- You'll need to specify at least the required variables (as defined by the Blueprint)
- The terraformConfiguration for this module instance:
- For a Terraform module, this will be the Terraform state backend, i.e. an S3 bucket name and region, and the AWS Account to own the bucket (connected via Zeet)
- Zeet will create the bucket (S3 or GCS) if it does not already exist
- For a Terraform module, this will be the Terraform state backend, i.e. an S3 bucket name and region, and the AWS Account to own the bucket (connected via Zeet)
Plan and Apply your Terraform Module
Once your Project exists, you can now manage its lifecycle completely via Zeet. We do this using the Terraform Blueprint Driver.
Terraform Plan
To invoke the Blueprint Driver, we use the executeBlueprintDriverAction
mutation:
executeBlueprintDriverAction(input: {
projectID: "uuid-resource-123",
action: PLAN,
driver: TERRAFORM,
parameters: {
cloudProvider: {
awsAccountID: "aws-provider-zeet-uuid",
region: "us-region-9"
}
}
}) {
__typename
... on BlueprintDriverActionResult {
execution {
id,
jobRun {
id,
},
}
}
}
- Include the projectID (from the previous step)
- We will use the
PLAN
action - Using the
TERRAFORM
driver - And in the parameters, we specify the cloud provider to inject into our module:
- Either an AWS account and region, or a GCP account and region
- See the Terraform Docs on Providers for more info
The PLAN
action will return a "job" instance, which is executing your Terraform Plan asynchronously, and you can follow the progress of that job accordingly.
Terraform Apply
Once you've generated a Terraform Plan, you can then Apply that plan, again using the executeBlueprintDriverAction
mutation:
executeBlueprintDriverAction(input: {
projectID: "uuid-resource-123",
action: APPLY,
driver: TERRAFORM,
parameters: {
planID: "actionResult-execution-id-from-previous-step"
}
}) {
... on BlueprintDriverActionResult {
execution {
id
jobRun {
id
}
}
}
}
- Again specify the projectID
- Use the
APPLY
action - Again using the
TERRAFORM
driver - The parameters for the
APPLY
action only requires theplanID
- The
planID
is the execution id from the previous step:BlueprintDriverActionResult.execution.id
- The
This will run terraform apply
using the exact plan that was generated by the previous step.