-
Notifications
You must be signed in to change notification settings - Fork 205
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
988c598
commit bb045e6
Showing
9 changed files
with
505 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file | ||
# Put files here that you don't want copied into your bundle's invocation image | ||
.gitignore | ||
Dockerfile.tmpl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Dockerfile | ||
cnab/ | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
# Using Porter with Azure and Terraform | ||
|
||
This bundle provides an example of how you can use Porter to build Terraform-based bundles. The example provided here will create Azure CosmosDB and Azure EventHubs objects using Terraform configurations and the [porter-terraform](https://github.com/deislabs/porter-terraform/) mixin. This sample also shows how the Terraform mixin can be used with other mixins, in this case the Azure mixin. The Azure mixin is first used to create an Azure storage account that will be used to configure the Terraform `azurerm` backend. It is possible to build bundles using just the [porter-terraform](https://github.com/deislabs/porter-terraform) mixin, but this example shows you how to use outputs between steps as well. | ||
|
||
## Setup | ||
|
||
This bundle will create resources in Azure. In order to do this, you'll first need to [create an Azure account](https://azure.microsoft.com/en-us/free/) if you don't already have one. | ||
|
||
The bundle will use an Azure [Service Principal](https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) in order to authenticate with Azure. Once you have an account, create a Service Principal for use with the bundle. You can do this via the Azure portal, or via the Azure CLI: | ||
|
||
1. Create a service principal with the Azure CLI: | ||
```console | ||
az ad sp create-for-rbac --name porterform -o table | ||
``` | ||
1. Save the values from the command output in environment variables: | ||
|
||
**Bash** | ||
```console | ||
export AZURE_TENANT_ID=<Tenant> | ||
export AZURE_CLIENT_ID=<AppId> | ||
export AZURE_CLIENT_SECRET=<Password> | ||
``` | ||
|
||
**PowerShell** | ||
```console | ||
$env:AZURE_TENANT_ID = "<Tenant>" | ||
$env:AZURE_CLIENT_ID = "<AppId>" | ||
$env:AZURE_CLIENT_SECRET = "<Password>" | ||
``` | ||
|
||
You will also need to have [Porter](https://porter.sh/install/) and [Docker](https://docs.docker.com/v17.12/install/) installed before you proceed. | ||
|
||
## Overview | ||
|
||
If you examine the contents of this example, you will see a `porter.yaml` file and a `terraform` directory. The `porter.yaml` is the bundle definition that will be used to build and run the bundle. Please see the [porter.yaml](porter.yaml) for the contents of the file. In this file, you will find a few credential definitions: | ||
|
||
```yaml | ||
credentials: | ||
- name: subscription_id | ||
env: AZURE_SUBSCRIPTION_ID | ||
|
||
- name: tenant_id | ||
env: AZURE_TENANT_ID | ||
|
||
- name: client_id | ||
env: AZURE_CLIENT_ID | ||
|
||
- name: client_secret | ||
env: AZURE_CLIENT_SECRET | ||
``` | ||
|
||
These credentials will correspond to the Azure Service Principal you created above. You'll also notice some parameter definitions: | ||
|
||
```yaml | ||
parameters: | ||
- name: location | ||
type: string | ||
default: "EastUS" | ||
|
||
- name: resource_group_name | ||
type: string | ||
default: "porter-terraform" | ||
|
||
- name: storage_account_name | ||
type: string | ||
default: "porterstorage" | ||
|
||
- name: storage_container_name | ||
type: string | ||
default: "portertf" | ||
|
||
- name: storage_rg | ||
type: string | ||
default: "porter-storage" | ||
|
||
- name: database-name | ||
type: string | ||
default: "porter-terraform" | ||
``` | ||
These represent the values that can be provided at runtime when installing the bundle. | ||
Finally, please note how the `porter-terraform` mixin is used: | ||
|
||
```yaml | ||
- terraform: | ||
description: "Create Azure CosmosDB and Event Hubs" | ||
autoApprove: true | ||
input: false | ||
backendConfig: | ||
key: "{{ bundle.name }}.tfstate" | ||
storage_account_name: "{{ bundle.parameters.storage_account_name }}" | ||
container_name: "{{ bundle.parameters.storage_container_name }}" | ||
access_key: "{{ bundle.outputs.STORAGE_ACCOUNT_KEY }}" | ||
vars: | ||
subscription_id: "{{bundle.credentials.subscription_id}}" | ||
tenant_id: "{{bundle.credentials.tenant_id}}" | ||
client_id: "{{bundle.credentials.client_id}}" | ||
client_secret: "{{bundle.credentials.client_secret}}" | ||
database_name: "{{bundle.parameters.database-name}}" | ||
resource_group_name: "{{bundle.parameters.resource_group_name}}" | ||
resource_group_location: "{{bundle.parameters.location}}" | ||
outputs: | ||
- name: cosmos-db-uri | ||
- name: eventhubs_connection_string | ||
``` | ||
|
||
This mixin step uses both parameters and credentials, defined above, and declares two output values. The source of these output files is defined in the Terraform configuration. | ||
|
||
The `terraform` directory contains the Terraform configuration files that will be used by the `porter-terraform` mixin: | ||
|
||
```bash | ||
ls -l terraform/ | ||
total 40 | ||
-rw-r--r-- 1 jeremyrickard staff 1023 Jul 2 08:32 cosmos-db.tf | ||
-rw-r--r-- 1 jeremyrickard staff 622 Jul 2 08:30 eventhubs.tf | ||
-rw-r--r-- 1 jeremyrickard staff 290 Jul 3 10:43 main.tf | ||
-rw-r--r-- 1 jeremyrickard staff 286 Jul 3 17:09 outputs.tf | ||
-rw-r--r-- 1 jeremyrickard staff 325 Jul 2 08:11 variables.tf | ||
``` | ||
|
||
The `main.tf` file configures the `azurerm` provider, while the `outputs.tf` defines the outputs we will capture from the Terraform step. `cosmos-db.tf` and `eventhubs.tf` contain the declarations for the infrastructure we will create. Finally, `variables.tf` defines a set of variables used throughout the files. These correspond to the parameters in our `porter.yaml` above. | ||
|
||
## Building The Bundle | ||
|
||
In order to use this bundle, you'll first need to build it. This is done with the `porter` command line tool. Ensure that your working directory is set to this example directory before proceeding, then run the following command: | ||
|
||
``` | ||
porter build | ||
``` | ||
|
||
Once this command has finished, you will see some additional resources in your working directory: a `Dockerfile` and a `.cnab` directory. The `Dockerfile` was generated by Porter and the `porter-terraform` mixin: | ||
|
||
```bash | ||
$ more Dockerfile | ||
FROM quay.io/deis/lightweight-docker-go:v0.2.0 | ||
FROM debian:stretch | ||
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt | ||
COPY . /cnab/app | ||
RUN mv /cnab/app/cnab/app/* /cnab/app && rm -r /cnab/app/cnab | ||
# exec mixin has no buildtime dependencies | ||
ENV TERRAFORM_VERSION=0.11.11 | ||
RUN apt-get update && apt-get install -y wget unzip && \ | ||
wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ | ||
unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /usr/bin | ||
WORKDIR /cnab/app | ||
CMD ["/cnab/app/run"] | ||
``` | ||
|
||
The Dockerfile contains the necessary instructions to install Terraform within our bundle's invocation image. | ||
|
||
## Generate a Credential Set | ||
|
||
Before you can install the bundle, you'll need to generate a credential set. This credential set will map your local service principal environment variables into the destinations defined in the `porter.yaml`. You can generate the credential set by running `porter credentials generate`. This will prompt you for the source for each credential defined in the bundle: | ||
|
||
```bash | ||
$ porter credentials generate | ||
Generating new credential porter-terraform-example from bundle porter-terraform-example | ||
==> 4 credentials required for bundle porter-terraform-example | ||
? How would you like to set credential "client_id" [Use arrows to move, space to select, type to filter] | ||
specific value | ||
> environment variable | ||
file path | ||
shell command | ||
``` | ||
|
||
For each of the credentials, provide the corresponding environment variable that you set above. For example, for `client_id`, select `environment variable` and provide the value `AZURE_CLIENT_ID`. | ||
|
||
```bash | ||
$ porter credentials generate | ||
Generating new credential porter-terraform-example from bundle porter-terraform-example | ||
==> 4 credentials required for bundle porter-terraform-example | ||
? How would you like to set credential "client_id" environment variable | ||
? Enter the environment variable that will be used to set credential "client_id" AZURE_CLIENT_ID | ||
? How would you like to set credential "client_secret" environment variable | ||
? Enter the environment variable that will be used to set credential "client_secret" AZURE_CLIENT_SECRET | ||
? How would you like to set credential "subscription_id" environment variable | ||
? Enter the environment variable that will be used to set credential "subscription_id" AZURE_SUBSCRIPTION_ID | ||
? How would you like to set credential "tenant_id" environment variable | ||
? Enter the environment variable that will be used to set credential "tenant_id" AZURE_TENANT_ID | ||
Saving credential to /Users/jeremyrickard/.porter/credentials/porter-terraform-example.yaml | ||
``` | ||
|
||
## Installing the Bundle | ||
|
||
Once you have built the bundle and generated a credential set, you're ready to install the bundle! To do that, you'll use the `porter install` command: | ||
|
||
```bash | ||
$ porter install -c porter-terraform-example | ||
installing porter-terraform-example... | ||
executing porter install configuration from /cnab/app/porter.yaml | ||
Create an Azure Storage Account | ||
Starting deployment operations... | ||
Finished deployment operations... | ||
Emit the key in base64 encoded form | ||
Here is a the storage account key (base64 encoded) ==> %%A KEY%% | ||
Create Azure CosmosDB and Event Hubs | ||
Initializing Terraform... | ||
/usr/bin/terraform terraform init -backend=true -backend-config=access_key=******* -backend-config=container_name=portertf -backend-config=key=porter-terraform-example.tfstate -backend-config=storage_account_name=porterstorage -reconfigure | ||
Initializing the backend... | ||
Successfully configured the backend "azurerm"! Terraform will automatically | ||
use this backend unless the backend configuration changes. | ||
Initializing provider plugins... | ||
- Checking for available provider plugins on https://releases.hashicorp.com... | ||
- Downloading plugin for provider "azurerm" (1.31.0)... | ||
< OUTPUT TRUNCATED> | ||
``` | ||
|
||
Installing the bundle will take some amount of time. As it is running you should see an output line like this: | ||
|
||
``` | ||
Here is a the storage account key (base64 encoded) ==> <SOME STRING> | ||
``` | ||
|
||
This is the account key that you'll need to later uninstall the bundle. It will be base64 encoded, so you'll need to decode it before using it to uninstall the bundle: | ||
|
||
```bash | ||
$ echo <SOMESTRING> | base64 -D | ||
``` | ||
|
||
You can also obtain the value from the Azure portal. | ||
|
||
## Uninstalling the Bundle | ||
|
||
When you're ready to uninstall the bundle, simply run the `porter uninstall` command and provide the storage account key: | ||
|
||
```bash | ||
$ porter uninstall -c porter-terraform-example --param tf_storage_account_key=%%YOUR KEY VALUE%% | ||
uninstalling porter-terraform-example... | ||
executing porter uninstall configuration from /cnab/app/porter.yaml | ||
Remove Azure CosmosDB and Event Hubs | ||
Initializing Terraform... | ||
/usr/bin/terraform terraform init -backend=true -backend-config=access_key=<A GENERATED KEY> -backend-config=container_name=portertf -backend-config=key=porter-terraform-example.tfstate -backend-config=storage_account_name=porterstorage -reconfigure | ||
Initializing the backend... | ||
Successfully configured the backend "azurerm"! Terraform will automatically | ||
use this backend unless the backend configuration changes. | ||
Initializing provider plugins... | ||
- Checking for available provider plugins on https://releases.hashicorp.com... | ||
- Downloading plugin for provider "azurerm" (1.31.0)... | ||
< OUTPUT TRUNCATED> | ||
``` | ||
|
||
This will take a number of minutes to finish, but when complete the resources will be removed from your account. |
Oops, something went wrong.