# Google Cloud Credentials / Service Account / Bucket para armazenar o Terraform State
export GOOGLE_CREDENTIALS_FILE="${HOME}/trash/credentials.json"
if [ -e "${GOOGLE_CREDENTIALS_FILE}" ]; then
if which jq > /dev/null; then
GOOGLE_PROJECT=$(jq .project_id ${GOOGLE_CREDENTIALS_FILE} -r)
else
GOOGLE_PROJECT="$(grep project_id ${GOOGLE_CREDENTIALS_FILE} | awk -F '"' '{ print $4 }')"
fi
export GOOGLE_PROJECT
else
echo "File doesn't exists: ${GOOGLE_CREDENTIALS_FILE}"
exit 1
fi
export GOOGLE_CREDENTIALS=$(cat "${GOOGLE_CREDENTIALS_FILE}" | tr -d "\n")
export GOOGLE_BACKEND_CREDENTIALS="${GOOGLE_CREDENTIALS}"
export GOOGLE_BUCKET="silvios-wasp-foundation-k9z"
export GOOGLE_PREFIX="terraform"
export GOOGLE_CREDENTIALS_BASE64=$( echo "${GOOGLE_CREDENTIALS}" | base64 | tr -d "\n")
export GOOGLE_BACKEND_CREDENTIALS_BASE64=$(echo "${GOOGLE_BACKEND_CREDENTIALS}" | base64 | tr -d "\n")
# Empacotando o Projeto de Exemplo
git clone https://github.com/smsilva/terraform-packager.git
cd terraform-packager
export STACK_INSTANCE_NAME=wasp-files
# Build
env DEBUG=2 scripts/stackbuild examples/google-bucket
# Run
env DEBUG=1 scripts/stackrun google-bucket:edge plan
env DEBUG=1 scripts/stackrun google-bucket:edge apply
env DEBUG=0 scripts/stackrun google-bucket:edge outputTerraform Packager é uma coleção de scripts e templates para empacotar código Terrraform.
O objetivo é criar um artefato que seja autosuficiente e personalizável.
Uma imagem criada usa o conceito de Stacks e contém essencialmente:
- Terraform: binário em uma versão específica do Terraform
- HCL Code: Código Terraform usado para criar recursos
- Providers: Os Terraform Providers serão baixados somente durante o build da imagem.
Esse conceito procura seguir a fisolofia de "build once", ou seja, o build do artefato ocorre apenas uma vez e o mesmo artefato pode ser usado para criar várias instâncias da Stack usando diferentes credenciais.
- Você precisará instalar o
yqutilitário para leitura de arquivos yaml. - Docker
- Estes comandos foram testados no
Ubuntu 20.04.
Se preferir ver um vídeo curto: Terraform Packager: empacotando código Terraform
Para empacotar um código Terraform com o terraform-packager você precisa garantir que o diretório root do seu Módulo Terraform possua um arquivo stack.yaml com as seguintes variáveis:
name: azure-nome-do-seu-modulo
version: 0.1.0
terraform:
version: 1.0.9
backend: azurermO exemplo usado considera que você possua variáveis de ambiente do Azure Resource Manager configuradas:
ARM_SUBSCRIPTION_ID................: ID_DE_UMA_SUBSCRIPTION_NA_AZURE
ARM_TENANT_ID......................: ID_DO_TENANT_DA_SUBSCRIPTION
ARM_CLIENT_ID......................: ID_DE_UMA_SERVICE_PRINCIPAL_CRIADA_PARA_USO_COM_TERRAFORM
ARM_CLIENT_SECRET..................: SECRET_DA_SERVICE_PRINCIPAL_ACIMA
ARM_STORAGE_ACCOUNT_NAME...........: NOME_DO_STORAGE_ACCOUNT_QUE_SERA_USADO_PARA_ARMAZENAR_O_TFSTATE
ARM_STORAGE_ACCOUNT_CONTAINER_NAME.: NOME_DO_STORAGE_ACCOUNT_CONTAINER
ARM_SAS_TOKEN......................: UM_TOKEN_TEMPORARIO_USADO_PARA_ACESSAR_A_STORAGE_ACCOUNTSscripts/stackbuild "examples/azure-null-resource"scripts/stackrun azure-null-resource:latest planscripts/stackrun azure-null-resource:latest applyEmbora não recomendável por ferir o princípio de que um artefato deveria sempre produzir o mesmo resultado, é possível passar um arquivo tfvars através de um volume para o container e usá-lo nos comandos Terraform.
export LOCAL_TERRAFORM_VARIABLES_DIRECTORY="${PWD}/examples/docker/custom-image"
scripts/stackrun azure-null-resource:latest plan -var-file=/opt/variables/terraform.tfvarsscripts/stackrun azure-null-resource:latest apply -var-file=/opt/variables/terraform.tfvars -auto-approvescripts/stackbuild examples/azure-null-resource
docker build \
--rm \
--tag mystack:latest "examples/docker/custom-image"scripts/stackrun mystack:latest planscripts/stackrun mystack:latest applyname: azure-null-resource
terraform:
version: 1.8.5
backend: local5.2. Por padrão o state será gerado no diretório configurado na variável de ambiente LOCAL_TERRAFORM_OUTPUT_DIRECTORY:
export LOCAL_TERRAFORM_OUTPUT_DIRECTORY="$(mktemp -d -t terraform-XXXXXXXXXX)"
echo "Terraform output directory: ${LOCAL_TERRAFORM_OUTPUT_DIRECTORY}"env DEBUG=2 scripts/stackbuild examples/azure-null-resourceexport TERRAFORM_STATE_FILE="azure-null-resource/terraform.state.json"env DEBUG=2 scripts/stackrun azure-null-resource plan
env DEBUG=2 scripts/stackrun azure-null-resource applyfind "${LOCAL_TERRAFORM_OUTPUT_DIRECTORY?}" -type fExemplo de saída:
/tmp/terraform-Q72cCQBbWz/terraform.state
/tmp/terraform-Q72cCQBbWz/azure-null-resource/terraform.state.json
/tmp/terraform-Q72cCQBbWz/terraform.plan.json
/tmp/terraform-Q72cCQBbWz/terraform.plan
/tmp/terraform-Q72cCQBbWz/plan_detailed_exitcode
/tmp/terraform-Q72cCQBbWz/terraform.plan.txtcat /tmp/terraform-Q72cCQBbWz/azure-null-resource/terraform.state.jsonSe você precisar executar scripts durante a fase de build, você pode criar um diretório .tfp/scripts/build na raiz do seu repositório.
.
├── .tfp
│ └── scripts
│ └── build
│ └── install-az-cli
├── README.md
├── cz.yaml -> ../../cz.yaml
├── src
│ ├── main.tf
│ └── provider.tf
└── stack.yamlExemplo para o script install-az-cli:
#!/bin/bash
apk add py3-pip
apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo make
pip install --upgrade pip
pip install azure-cli
az versionSe você precisar executar scripts durante runtime, você pode criar um diretório .tfp/scripts/runtime na raiz do seu repositório.
.
├── .tfp
│ └── scripts
│ └── runtime
│ ├── after-apply
│ ├── after-destroy
│ ├── after-init
│ ├── after-plan
│ ├── before-apply
│ ├── before-destroy
│ ├── before-init
│ └── before-plan
├── README.md
├── cz.yaml -> ../../cz.yaml
├── src
│ ├── main.tf
│ └── provider.tf
└── stack.yamlO script stackrun' vai montar os arquivos de credenciais do Azure CLI no container caso os arquivos existam e a variável de ambiente ARM_CLIENT_ID` esteja vazia.
Caso necessite, você pode alterar as variáveis que identificam os arquivos de credenciais do Azure CLI:
# Abaixo as variáveis usadas pelo terraform-packager para identificar os arquivos de credenciais do Azure CLI com seus respectivos valores padrão
export TF_PACKAGER_AZURE_ACCESS_TOKEN_FILE="${HOME}/.azure/access_token.json"
export TF_PACKAGER_AZURE_PROFILE_FILE="${HOME}/.azure/azureProfile.json"
export TF_PACKAGER_AZURE_MSAL_TOKEN_CACHE_FILE="${HOME}/.azure/msal_token_cache.json"ATENÇÃO: Antes de executar
stackbuildoustackrun, certifique-se de ter obtido um token de acesso usando o comando:
export TF_PACKAGER_AZURE_ACCESS_TOKEN_FILE="${HOME}/.azure/access_token.json"
export TF_PACKAGER_AZURE_PROFILE_FILE="${HOME}/.azure/azureProfile.json"
export TF_PACKAGER_AZURE_MSAL_TOKEN_CACHE_FILE="${HOME}/.azure/msal_token_cache.json"
az account get-access-token > "${TF_PACKAGER_AZURE_ACCESS_TOKEN_FILE?}"
stackrun azure-cli-auth-example:latest planSe você precisar configurar chaves SSH para acessar repositórios privados, você pode criar um arquivo ${HOME}./ssh/config seguindo exemplo abaixo:
# GitHub
Host github.com
HostName github.com
IdentityFile ~/.ssh/id_ed25519
# Azure DevOps
Host ssh.dev.azure.com
HostName ssh.dev.azure.com
IdentityFile ~/.ssh/id_rsa
# Global
Host *
User git
PubkeyAcceptedAlgorithms +ssh-rsa
HostkeyAlgorithms +ssh-rsa
StrictHostKeyChecking no| Variável de Ambiente | Descrição | Exemplo |
|---|---|---|
DEBUG |
Nível de depuração | DEBUG=2 |
LOCAL_TERRAFORM_OUTPUT_DIRECTORY |
Diretório onde o Terraform irá armazenar os arquivos de saída | LOCAL_TERRAFORM_OUTPUT_DIRECTORY="$(mktemp -d -t terraform-XXXXXXXXXX)" |
LOCAL_TERRAFORM_VARIABLES_DIRECTORY_EXTRA |
Todos os arquivos do diretórios serão volumados em /opt/src |
LOCAL_TERRAFORM_VARIABLES_DIRECTORY_EXTRA="${PWD}/examples/custom-image" |
LOCAL_TERRAFORM_VARIABLES_DIRECTORY |
Diretório local que será volumado em /opt/variables |
LOCAL_TERRAFORM_VARIABLES_DIRECTORY="${PWD}/examples/custom-image/tfvars-files" |
TERRAFORM_STATE_FILE |
Nome do arquivo de state | TERRAFORM_STATE_FILE="azure-null-resource/terraform.state.json" |
TF_PACKAGER_AZURE_ACCESS_TOKEN_FILE |
Arquivo de token de acesso do Azure CLI | TF_PACKAGER_AZURE_ACCESS_TOKEN_FILE="${HOME}/.azure/access_token.json" |
TF_PACKAGER_AZURE_MSAL_TOKEN_CACHE_FILE |
Arquivo de cache de token MSAL do Azure CLI | TF_PACKAGER_AZURE_MSAL_TOKEN_CACHE_FILE="${HOME}/.azure/msal_token_cache.json" |
TF_PACKAGER_AZURE_PROFILE_FILE |
Arquivo de perfil do Azure CLI | TF_PACKAGER_AZURE_PROFILE_FILE="${HOME}/.azure/azureProfile.json" |
TF_PACKAGER_DOCKER_PROGRESS |
Definie como exibir p progresso do build do container Docker | TF_PACKAGER_DOCKER_PROGRESS=plain (auto, plain, tty, rawjson) |
TF_PACKAGER_TEMPORARY_BUILD_CONTEXT_DIRECTORY |
Diretório temporário para o build do container Docker | TF_PACKAGER_TEMPORARY_BUILD_CONTEXT_DIRECTORY="$(mktemp -d -t terraform-XXXXXXXXXX)" |
env DEBUG=1 scripts/stackrun google-bucket:edge plan \
| sed \
-e '/You may now begin working with Terraform/,/commands will detect it and remind you to do so if necessary./d' \
-e '/Terraform used the selected providers/,/Resource actions are indicated with the following symbols:/d' \
-e '/Successfully configured the backend/,/unless the backend configuration changes./d' \
-e '/To perform exactly these actions/,/terraform apply "\/opt\/output\/terraform.plan\"/d'