Introducción a Cloud Foundation Toolkit

1. Introducción a CFT 101

ea557448aaa1fffc.png

Última actualización: 3 de marzo de 2020

¿Qué es Cloud Foundation Toolkit?

En términos simples, CFT proporciona plantillas de prácticas recomendadas para dar los primeros pasos en Google Cloud Platform. En este instructivo, aprenderás a contribuir a Cloud Foundation Toolkit.

Requisitos

  • Una cuenta de GitHub
  • Docker instalado en tu máquina ( Instalación en Mac, Instalación en Windows)
  • Editor de código para editar código (ejemplo: Visual Studio Code)
  • Conocimientos básicos sobre Git y GitHub
  • Algo de experiencia con Terraform y la infraestructura como código
  • Permiso para otorgar el rol de Creador del proyecto a una cuenta de servicio

Qué compilarás

En este codelab, aprenderás a contribuir a Cloud Foundation Toolkit (CFT).

Harás lo siguiente:

  • Configura un entorno de desarrollo para contribuir a CFT
  • Agrega una función a un módulo de CFT
  • Cómo agregar pruebas para la función agregada
  • Ejecuta pruebas de integración en CFT
  • Cómo ejecutar pruebas de lint
  • Confirma el código en GitHub y envía una solicitud de extracción (PR)

Para ejecutar todos los pasos anteriores, agregará una nueva función al módulo CFT de Google Cloud Storage. Agregarás una etiqueta llamada "silly_label", que se agregará automáticamente a todos los buckets creados a través del módulo de CFT de GCS. También podrás escribir pruebas para validar tu función y garantizar la integración de extremo a extremo.

2. Configura el entorno de desarrollo

Si lo deseas, puedes usar Cloud Shell para tus tareas de desarrollo. Si no quieres usar Cloud Shell para contribuir a CFT, puedes configurar el entorno de desarrollo en tu máquina.

Configura Git

GitHub se basa en un sistema de control de versión (VCS) de código abierto llamado Git. Git es responsable de todo lo que ocurre en relación con GitHub de manera local en tu máquina o en Cloud Shell.

  1. Cuando usas Cloud Shell, no necesitas instalar Git, ya que está preinstalado.
$ git --version
# This will display the git version on the Cloud Shell.

Si quieres configurar el entorno de desarrollo en tu máquina, debes instalar Git.

Cómo configurar tu nombre de usuario y correo electrónico en Git

Git usa un nombre de usuario para asociar confirmaciones con una identidad. El nombre de usuario de Git no es el mismo que tu nombre de usuario de GitHub.

Puedes cambiar el nombre asociado con tus confirmaciones de Git con el comando git config. Cambiar el nombre asociado a tus confirmaciones de Git con git config solo afectará las confirmaciones futuras y no cambiará el nombre que se usa para las confirmaciones anteriores.

Configuraste Git correctamente. Deberías poder bifurcar, crear y clonar ramas. Usaremos Git de forma exhaustiva en este codelab.

3. Repositorio de GCS de Fork CFT

Bifurca un repositorio de CFT

Configuraste Git en tu máquina local o en Cloud Shell en el paso anterior. Ahora, debes bifurcar el repo de CFT de Google Cloud Storage para comenzar a contribuir.

Una bifurcación es una copia de un repositorio. La bifurcación de un repositorio te permite experimentar libremente con los cambios sin afectar el proyecto original.

Por lo general, los tenedores se utilizan para proponer cambios en el proyecto de otra persona o para usar el proyecto de otra persona como punto de partida para tu propia idea.

Por ejemplo, puedes usar bifurcaciones para proponer cambios relacionados con la corrección de un error. Para corregir un error, puedes hacer lo siguiente:

  • Bifurca el repositorio.
  • Corrige los errores.
  • Envía una solicitud de extracción al propietario del proyecto.

Pasos para bifurcar un repositorio de CFT:

  1. Abre tu navegador web y navega al repositorio terraform-google-modules/terraform-google-cloud-storage. Usaremos este repositorio para todo el codelab.
  2. En la esquina superior derecha de la página, haz clic en Bifurcar (Fork).

e3894c6de6a732b4.png

  1. Verás una opción para saber dónde quieres colocar la bifurcación, elegir tu perfil y se bifurcará el repo.

Clona la bifurcación de forma local

La bifurcación que creaste es una copia del repositorio del módulo de GCS. Ahora clonarás este repositorio en tu entorno local para agregar el atributo nuevo.

Sigue estos pasos para clonar la bifurcación:

  1. Abre tu navegador web y navega a la bifurcación en terraform-google-modules/terraform-google-cloud-storage.
  2. En la esquina superior derecha, encontrarás el botón “Clonar o descargar” (Clone or download). haz clic en él.

3bfa87b9f7f01f61.png

  1. Después de hacer clic en el botón “Clonar o descargar” haz clic en el botón "Bloc de notas" para copiar la URL de la bifurcación. Usarás esta URL para clonar la bifurcación en tu entorno local.

dbf3682d004e0ee0.png

  1. Ve a una terminal en VSCode o a tu máquina y clona la bifurcación.
$ git clone <url>
# This command will clone your fork locally.
# Paste the copied URL from the previous step.
  1. Ahora que clonaste la bifurcación de forma local, debes ir a tu repositorio, crear una rama nueva a partir de la bifurcación y realizar cambios en el código a la rama temporal.

Por convención, puedes nombrar tu rama de la siguiente manera:

  • Para solicitudes de funciones: feature/feature-name
  • Para realizar actualizaciones internas, internal/change-name
  • Para correcciones de errores: bugfix/issue-name

Dado que estás agregando una función nueva, puedes llamar a tu rama temporal feature/silly_label

$ cd terraform-google-cloud-storage
# This command takes you into the cloned directory on your local machine.

$ git branch
# This command tells your current branch
# When you run this for the first time after you have cloned, your 
# output should say "master", that is your fork.

$ git checkout -b feature/silly_label
# This command creates a new branch on your fork and switches your 
# branch to the newly created branch.

$ git branch
# This command will confirm your current branch to be "feature/silly_label"

Ya está todo listo para comenzar a trabajar en Cloud Foundation Toolkit.

4. Cómo crear un entorno de pruebas

El proceso de desarrollo estándar de CFT se basa en el uso de un proyecto de prueba aislado para pruebas. Este paso te guiará en la creación del proyecto de prueba (basado en una configuración estándar) a través de una cuenta de servicio.

0. Instala Docker Engine

Si utilizas tu máquina con fines de desarrollo, debes instalar Docker Engine.

1. Instala el SDK de Google Cloud

No es necesario que instales el SDK de Google Cloud si usas Cloud Shell en GCP.

Ve al SDK de Google Cloud y descarga el instalador interactivo para tu plataforma.

2. Establece la configuración

Para crear un entorno de prueba, necesitarás una organización de Google Cloud, una carpeta de prueba y una cuenta de facturación. Estos valores deben establecerse a través de variables de entorno:

export TF_VAR_org_id="your_org_id"
export TF_VAR_folder_id="your_folder_id"
export TF_VAR_billing_account="your_billing_account_id"

3 Configura tu cuenta de servicio

Antes de crear un entorno de pruebas, debes descargar una clave de cuenta de servicio a tu entorno de pruebas. Esta cuenta de servicio necesitará los roles de Creador de proyecto, Usuario de cuenta de facturación y Visualizador de la organización. Estos pasos te ayudarán a crear una cuenta de servicio nueva, pero también puedes reutilizar una existente.

3.1 Crea o selecciona un proyecto de GCP de origen

Antes de crear tu cuenta de servicio, debes seleccionar un proyecto para alojarla. También puedes crear un proyecto nuevo.

gcloud config set core/project YOUR_PROJECT_ID

3.2 Habilitar las APIs de Google Cloud

Habilita las siguientes APIs de Google Cloud en tu proyecto de origen:

gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable iam.googleapis.com
gcloud services enable cloudbilling.googleapis.com

3.3 Crea una cuenta de servicio

Crea una cuenta de servicio nueva para administrar el entorno de pruebas:

# Creating a service account for CFT.
gcloud iam service-accounts create cft-onboarding \
  --description="CFT Onboarding Terraform Service Account" \
  --display-name="CFT Onboarding"

# Assign SERVICE_ACCOUNT environment variable for later steps
export SERVICE_ACCOUNT=cft-onboarding@$(gcloud config get-value core/project).iam.gserviceaccount.com

Verifica que se haya creado la cuenta de servicio:

gcloud iam service-accounts list --filter="EMAIL=${SERVICE_ACCOUNT}"

3.4 Otorga los roles Creador de proyectos, Usuario de la cuenta de facturación y Visualizador de la organización a la cuenta de servicio:

gcloud resource-manager folders add-iam-policy-binding ${TF_VAR_folder_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/resourcemanager.projectCreator"
gcloud organizations add-iam-policy-binding ${TF_VAR_org_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/billing.user"
gcloud organizations add-iam-policy-binding ${TF_VAR_org_id} \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/resourcemanager.organizationViewer"

Ahora tienes una cuenta de servicio que puede usarse para administrar el entorno de pruebas.

4. Asigna el rol Usuario de cuentas de facturación en el recurso de cuenta de facturación

4.1 Recupera la política de IAM de la cuenta de facturación

Descarga las vinculaciones de políticas de IAM existentes en la cuenta de facturación

gcloud beta billing accounts get-iam-policy ${TF_VAR_billing_account} | tee policy.yml

4.2 Actualiza la política para incluir la cuenta de servicio

Actualiza el archivo policy.yml para agregar una nueva vinculación para la cuenta de servicio con el rol roles/billing.user

bindings:
- members:
  - serviceAccount:cft-onboarding@<YOUR_PROJECT_ID>.iam.gserviceaccount.com
  role: roles/billing.user

4.3 Actualiza la política de la cuenta de facturación

Aplica los cambios en la cuenta de facturación

gcloud beta billing accounts set-iam-policy ${TF_VAR_billing_account} policy.yml

5. Prepara la credencial de Terraform

Para crear el entorno de pruebas, debes descargar la clave de la cuenta de servicio en tu shell.

5.1 Clave de cuenta de servicio

Crea y descarga una clave de cuenta de servicio para Terraform

gcloud iam service-accounts keys create cft.json --iam-account=${SERVICE_ACCOUNT}

5.2 Configura la credencial de Terraform

Proporciona la clave a Terraform con la variable de entorno SERVICE_ACCOUNT_JSON y configura el valor según el contenido de la clave de tu cuenta de servicio.

export SERVICE_ACCOUNT_JSON=$(< cft.json)

6. Crea un proyecto de prueba para las implementaciones de Terraform

Ahora que todo está preparado, puedes crear el proyecto de prueba con un solo comando. Ejecuta este comando desde la raíz del directorio terraform-google-cloud-storage:

make docker_test_prepare

Verás el siguiente resultado cuando ejecutes make docker_test_prepare. Al final, recibirás el project_id de prueba que se creó, en el que implementarás y probarás tu módulo de Cloud Storage con la función nueva.

macbookpro3:terraform-google-cloud-storage user$ make docker_test_prepare
docker run --rm -it \
                -e SERVICE_ACCOUNT_JSON \
                -e TF_VAR_org_id \
                -e TF_VAR_folder_id \
                -e TF_VAR_billing_account \
                -v /Users/cft/terraform-google-cloud-storage:/workspace \
                gcr.io/cloud-foundation-cicd/cft/developer-tools:0.8.0 \
                /usr/local/bin/execute_with_credentials.sh prepare_environment
Activated service account credentials for: [cft-onboarding@<project_id>.iam.gserviceaccount.com]
Activated service account credentials for: [cft-onboarding@<project_id>.iam.gserviceaccount.com]
Initializing modules...

Initializing the backend...

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.google-beta: version = "~> 3.9"
* provider.null: version = "~> 2.1"
* provider.random: version = "~> 2.2"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
module.project.module.project-factory.null_resource.preconditions: Refreshing state... [id=8723188031607443970]
module.project.module.project-factory.null_resource.shared_vpc_subnet_invalid_name[0]: Refreshing state... [id=5109975723938185892]
module.project.module.gsuite_group.data.google_organization.org[0]: Refreshing state...
module.project.module.project-factory.random_id.random_project_id_suffix: Refreshing state... [id=rnk]
module.project.module.project-factory.google_project.main: Refreshing state... [id=<project-id>]
module.project.module.project-factory.google_project_service.project_services[0]: Refreshing state... [id=<project-id>/storage-api.googleapis.com]
module.project.module.project-factory.google_project_service.project_services[1]: Refreshing state... [id=<project-id>/cloudresourcemanager.googleapis.com]
module.project.module.project-factory.google_project_service.project_services[2]: Refreshing state... [id=<project-id>/compute.googleapis.com]
module.project.module.project-factory.data.null_data_source.default_service_account: Refreshing state...
module.project.module.project-factory.google_service_account.default_service_account: Refreshing state... [id=projects/ci-cloud-storage-ae79/serviceAccounts/project-service-account@<project-id>.iam.gserv
iceaccount.com]
module.project.module.project-factory.google_project_service.project_services[3]: Refreshing state... [id=<project-id>/serviceusage.googleapis.com]
module.project.module.project-factory.null_resource.delete_default_compute_service_account[0]: Refreshing state... [id=3576396874950891283]
google_service_account.int_test: Refreshing state... [id=projects/<project-id>/serviceAccounts/cft-onboarding@<project-id>.iam.gserviceaccount.com]
google_service_account_key.int_test: Refreshing state... [id=projects/<project-id>/serviceAccounts/cft-onboarding@<project-id>.iam.gserviceaccount.com/keys/351009a1e011e88049ab2097994d1c627a61
6961]
google_project_iam_member.int_test[1]: Refreshing state... [id=<project-id>/roles/iam.serviceAccountUser/serviceaccount:cft-onboarding@<project-id>.iam.gserviceaccount.com]
google_project_iam_member.int_test[0]: Refreshing state... [id=<project-id>/roles/storage.admin/serviceaccount:cft-onboarding@<project-id>.iam.gserviceaccount.com]

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

Outputs:

project_id = <test-project-id>
sa_key = <sensitive>
Found test/setup/make_source.sh. Using it for additional explicit environment configuration.

Ya creaste un proyecto de prueba al que hace referencia project_id, como se puede ver en el resultado de la consola. Se configuró tu entorno de desarrollo y pruebas.

5. Agrega una función nueva al módulo de CFT

Ahora que tu entorno de desarrollo y prueba está configurado, comencemos a agregar tu "silly_label" en el módulo de CFT google-cloud-storage.

Asegúrate de estar en terraform-google-cloud-storage y abre el archivo main.tf como se muestra a continuación en la estructura de carpetas.

17f2d3b9893be853.png

Desde "silly_label" es una etiqueta, agregarás el atributo en la línea 27 en la variable "labels" en main.tf, como se muestra a continuación:

terraform-google-cloud-storage/main.tf

resource "google_storage_bucket" "buckets" {
 <...>
 storage_class = var.storage_class
 // CODELAB:Add silly label in labels variable
 labels        = merge(var.labels, { name = replace("${local.prefix}${lower(element(var.names, count.index))}", ".", "-") }, { "silly" = var.silly_label })
 force_destroy = lookup(
 <...>
}

Ahora, agregarás la variable silly_label en variables.tf que ves en la estructura de carpetas anterior.

Copia y pega el siguiente código y agrégalo a la línea 29 en variables.tf. Asegúrate de tener un nuevo carácter de línea arriba y abajo del bloque de variables que agregaste.

terraform-google-cloud-storage/variables.tf

variable "names" {
 description = "Bucket name suffixes."
 type        = list(string)
}

// CODELAB: Add "silly_label" variable to variables.tf between "names" and "location"
variable "silly_label" {
 description = "Sample label for bucket."
 type        = string
}

variable "location" {
 description = "Bucket location."
 default     = "EU"
}

6. Agregar un atributo nuevo al ejemplo del bucket de almacenamiento

Agregaste la función al archivo main.tf del módulo y, ahora, la probarás con un ejemplo.

La "silly_label" debe agregarse a la claseexamples/multiple-buckets/main.tf.

Un dispositivo utilizará este ejemplo en el siguiente paso para realizar pruebas de integración.

Copia y pega la siguiente línea de variable silly_label en la línea 27 de main.tf en terraform-google-cloud-storage/examples/multiple-buckets/, como se ve en la estructura de carpetas:

408cb1365b2a0793.png

terraform-google-cloud-storage/examples/multiple-buckets/main.tf

module "cloud_storage" {
 <...>
 // CODELAB: Add "silly_label" as an example to main.tf.
 silly_label        = "awesome"

 <..>
}

7. Escribe una prueba de Inspec para verificar la función

Agregaste la función al archivo main.tf del módulo y, luego, la agregaste al ejemplo de multiple_buckets para probarla en el dispositivo. Debes probar la función mediante una prueba de integración de InSpec escrita en Ruby.

Agregarás tus pruebas nuevas en el archivo gsutil.rb que se encuentra en la siguiente estructura de carpetas:

b2bfeb203477e0c8.png

Agregaste “silly_label” en todos los buckets que se crearon con el módulo multiple_buckets y, ahora, debes escribir pruebas para probar la nueva función.

En el siguiente código, obtienes la etiqueta de cada bucket a través del comando gsutil y, luego, verificas el resultado que muestra el comando.

terraform-google-cloud-storage/test/integration/multiple-buckets/controls/gsutil.rb

control "gsutil" do
 <..>

# CODELAB: Copy paste the below test in gsutil.rb to test silly_label feature.

# command to get the labels for bucket_1
describe command("gsutil label get gs://#{attribute("names_list")[0]}") do
   //check if the command gave a valid response
   its(:exit_status) { should eq 0 }
   its(:stderr) { should eq "" }

   //parse the command's output into JSON
   let!(:data) do
     if subject.exit_status == 0
         JSON.parse(subject.stdout)
     else
         {}
     end
   end

   # check if bucket_1 has the new "silly" label with the value "awesome"
   describe "bucket_1" do
   it "has label" do
       data.each do |bucket|
           expect(data["silly"]).to include("awesome")
       end
     end
   end
 end

8. Ejecuta pruebas de integración en CFT

Pruebas de integración

Las pruebas de integración se usan para verificar el comportamiento del módulo raíz, los submódulos y los módulos de ejemplo. Las incorporaciones, los cambios y las correcciones deben ir acompañadas de pruebas.

Las pruebas de integración se ejecutan con Kitchen, Kitchen-Terraform y, además, InSpec. Estas herramientas están empaquetadas dentro de una imagen de Docker para mayor comodidad.

La estrategia general para estas pruebas es verificar el comportamiento de los módulos de ejemplo y, así, garantizar que el módulo raíz, los submódulos y los módulos de ejemplo sean correctos en cuanto a funcionalidad.

En la ejecución interactiva, cada paso se realiza mediante varios comandos.

  1. Ejecuta make docker_run para iniciar el contenedor de Docker de prueba en modo interactivo.

Make es una herramienta de automatización de compilación que compila automáticamente programas ejecutables y bibliotecas a partir del código fuente mediante la lectura de archivos llamados Makefiles que especifican cómo derivar el programa de destino. Cuando realizas cambios en los archivos, el contenedor de Docker se debe actualizar automáticamente.

Cuando ejecutes make docker_run, crearás un lugar de trabajo en tu contenedor de Docker y activarás las credenciales para tu cuenta de servicio. El lugar de trabajo se usará en los siguientes pasos para ejecutar pruebas.

Verás el siguiente resultado en tu terminal:

Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
  1. Ejecuta kitchen_do list para enumerar todas las instancias de tu lugar de trabajo que contienen pruebas de integración.
     You will see the below output in your terminal.
    
[root@<CONTAINER_ID> workspace]# kitchen_do list
Automatically setting inputs from outputs of test/setup
Found test/source.sh. Using it for additional explicit environment configuration.
Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
Instance                  Driver     Provisioner  Verifier   Transport  Last Action  Last Error
multiple-buckets-default  Terraform  Terraform    Terraform  Ssh        Verified     <None>
  1. Ejecuta kitchen_do create <EXAMPLE_NAME> para inicializar el directorio de trabajo para un módulo de ejemplo.

En este paso, se inicializa cocina y se inicializa Terraform en el espacio de trabajo.

Verás el siguiente resultado en tu terminal.

[root@<CONTAINER_ID> workspace]# kitchen_do create multiple-buckets-default
Automatically setting inputs from outputs of test/setup
Found test/source.sh. Using it for additional explicit environment configuration.
Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
-----> Starting Kitchen (v1.24.0)
-----> Creating <multiple-buckets-default>...
       Terraform v0.12.12
       + provider.google v3.10.0
       
       Your version of Terraform is out of date! The latest version
       is 0.12.21. You can update by downloading from www.terraform.io/downloads.html
$$$$$$ Running command `terraform init -input=false -lock=true -lock-timeout=0s  -upgrade -force-copy -backend=true  -get=true -get-plugins=true -verify-plugins=true` in directory /workspace/test/fi
xtures/multiple_buckets
       Upgrading modules...
       - example in ../../../examples/multiple_buckets
       - example.cloud_storage in ../../..
       
       Initializing the backend...
       
       Initializing provider plugins...
       - Checking for available provider plugins...
       - Downloading plugin for provider "google" (hashicorp/google) 2.18.1...
       - Downloading plugin for provider "random" (hashicorp/random) 2.2.1...
       
       Terraform has been successfully initialized!
$$$$$$ Running command `terraform workspace select kitchen-terraform-multiple-buckets-default` in directory /workspace/test/fixtures/multiple_buckets
       Finished creating <multiple-buckets-default> (0m11.01s).
-----> Kitchen is finished. (0m12.62s)
  1. Ejecuta kitchen_do converge <EXAMPLE_NAME> para aplicar el módulo de ejemplo.

En este paso, se aplica el espacio de trabajo de Terraform que se creó en el paso anterior al proyecto de GCP que se creó anteriormente en el codelab.

Verás el siguiente resultado en tu terminal.

[root@<CONTAINER_ID> workspace]# kitchen_do converge multiple-buckets-default
Automatically setting inputs from outputs of test/setup
Found test/source.sh. Using it for additional explicit environment configuration.
Activated service account credentials for: [cft@<YOUR_PROJECT_ID>.iam.gserviceaccount.com]
-----> Starting Kitchen (v1.24.0)
-----> Converging <multiple-buckets-default>...
       Terraform v0.12.20
       + provider.google v3.9.0
       
       Your version of Terraform is out of date! The latest version
       is 0.12.21. You can update by downloading from https://www.terraform.io/downloads.html
$$$$$$ Running command `terraform workspace select kitchen-terraform-multiple-buckets-default` in directory /workspace/test/fixtures/multiple_buckets
$$$$$$ Running command `terraform get -update` in directory /workspace/test/fixtures/multiple_buckets
       - example in ../../../examples/multiple_buckets
       - example.cloud_storage in ../../..
$$$$$$ Running command `terraform validate   ` in directory /workspace/test/fixtures/multiple_buckets
       Success! The configuration is valid.
       
$$$$$$ Running command `terraform apply -lock=true -lock-timeout=0s -input=false -auto-approve=true  -parallelism=10 -refresh=true  ` in directory /workspace/test/fixtures/multiple_buckets
       random_pet.main: Creating...
       random_pet.main: Creation complete after 0s [id=<BUCKET-ID>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[0]: Creating...
       module.example.module.cloud_storage.google_storage_bucket.buckets[1]: Creating...
       module.example.module.cloud_storage.google_storage_bucket.buckets[1]: Creation complete after 3s [id=<BUCKET-ID-01>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[0]: Creation complete after 3s [id=<BUCKET-ID-02>]
       
       Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
       
       Outputs:
       
       names = {
         "one" = "<BUCKET-ID-01>"
         "two" = "<BUCKET-ID-02>"
       }
       names_list = [
         "<BUCKET-NAME-01>",
         "<BUCKET-NAME-02>",
       ]
       project_id = ci-cloud-storage-ae79
       Finished converging <multiple-buckets-default> (0m7.17s).
-----> Kitchen is finished. (0m8.77s)
  1. Ejecuta kitchen_do verify <EXAMPLE_NAME> para probar el módulo de ejemplo.

Este paso se ejecutará a través del archivo gsutils.rb, que contiene pruebas para el módulo multiple_buckets. Cada prueba tiene un comando gsutil que se ejecutará en el proyecto de prueba que creaste anteriormente con la configuración de credenciales de la cuenta de servicio.

Si recibes algún error, verás lo que se esperaba y lo que recibió el comando para la prueba.

Verás el siguiente resultado en tu terminal.

multiple_buckets local: Verifying

Profile: multiple_buckets
Version: (not specified)
Target:  local://

  ✔  gsutil: gsutil
     ✔  Command: `gsutil ls -p <PROJECT_ID>` exit_status should eq 0
     ✔  Command: `gsutil ls -p <PROJECT_ID>` stderr should eq ""
     ✔  Command: `gsutil ls -p <PROJECT_ID>` stdout should include "multiple-buckets-mzgy-eu-one"
     ✔  Command: `gsutil ls -p <PROJECT_ID>` stdout should include "<BUCKET-ID-01>"
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-01>` exit_status should eq 0
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-01>` stderr should eq ""
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-01>` stdout should include "Enabled: True"
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-02>` exit_status should eq 0
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-02>` stderr should eq ""
     ✔  Command: `gsutil bucketpolicyonly get gs://<BUCKET-ID-02>` stdout should include "Enabled: False"
     ✔  Command: `gsutil label get gs://<BUCKET-ID-01>` exit_status should eq 0
     ✔  Command: `gsutil label get gs://<BUCKET-ID-01>` stderr should eq ""
     ✔  Command: `gsutil label get gs://<BUCKET-ID-01>` bucket_1 has label
     ✔  Command: `gsutil label get gs://<BUCKET-ID-02>` exit_status should eq 0
     ✔  Command: `gsutil label get gs://<BUCKET-ID-02>` stderr should eq ""
     ✔  Command: `gsutil label get gs://<BUCKET-ID-02>` bucket_2 has label
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` should eq "NEARLINE"
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` should eq "SetStorageClass"
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` should eq 10
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` should eq false
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` should eq ["MULTI_REGIONAL", "STANDARD", "DURABLE_REDUCED_AVAILABILITY"]
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` exit_status should eq 0
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-01>` stderr should eq ""
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` should eq "NEARLINE"
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` should eq "SetStorageClass"
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` should eq 10
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` should eq false
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` should eq ["MULTI_REGIONAL", "STANDARD", "DURABLE_REDUCED_AVAILABILITY"]
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` exit_status should eq 0
     ✔  Command: `gsutil lifecycle get gs://<BUCKET-ID-02>` stderr should eq ""


Profile Summary: 1 successful control, 0 control failures, 0 controls skipped
Test Summary: 30 successful, 0 failures, 0 skipped
       Finished verifying <multiple-buckets-default> (0m8.83s).
-----> Kitchen is finished. (0m16.61s)
  1. Ejecuta kitchen_do destroy <EXAMPLE_NAME> para destruir el estado del módulo de ejemplo.

En este paso, se destruye el lugar de trabajo que creaste en los pasos anteriores. En este paso, también se destruirán los buckets de GCS que se crearon en el proyecto, junto con la etiqueta que agregaste al módulo de GCS.

Puedes ver el siguiente resultado en tu terminal.

[root@<CONTAINER_ID> workspace]# kitchen_do destroy multiple-buckets-default
Automatically setting inputs from outputs of test/setup
Found test/source.sh. Using it for additional explicit environment configuration.
Activated service account credentials for: [ci-cloud-storage@ci-cloud-storage-54ab.iam.gserviceaccount.com]
-----> Starting Kitchen (v1.24.0)
-----> Destroying <multiple-buckets-default>...
       Terraform v0.12.12
       + provider.google v3.10.0
       
       Your version of Terraform is out of date! The latest version
       is 0.12.21. You can update by downloading from www.terraform.io/downloads.html
$$$$$$ Running command `terraform init -input=false -lock=true -lock-timeout=0s  -force-copy -backend=true  -get=true -get-plugins=true -verify-plugins=true` in directory /workspace/test/fixtures/mu
ltiple_buckets
       Initializing modules...
       
       Initializing the backend...
       
       Initializing provider plugins...
       
       Terraform has been successfully initialized!
$$$$$$ Running command `terraform workspace select kitchen-terraform-multiple-buckets-default` in directory /workspace/test/fixtures/multiple_buckets
$$$$$$ Running command `terraform destroy -auto-approve -lock=true -lock-timeout=0s -input=false  -parallelism=10 -refresh=true  ` in directory /workspace/test/fixtures/multiple_buckets
       random_string.prefix: Refreshing state... [id=mzgy]
       module.example.module.cloud_storage.google_storage_bucket.buckets[0]: Refreshing state... [id=<BUCKET-ID-01>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[1]: Refreshing state... [id=<BUCKET-ID-02>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[0]: Destroying... [id=<BUCKET-ID-01>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[1]: Destroying... [id=<BUCKET-ID-02>]
       module.example.module.cloud_storage.google_storage_bucket.buckets[0]: Destruction complete after 1s
       module.example.module.cloud_storage.google_storage_bucket.buckets[1]: Destruction complete after 2s
       random_string.prefix: Destroying... [id=mzgy]
       random_string.prefix: Destruction complete after 0s
       
       Destroy complete! Resources: 3 destroyed.
$$$$$$ Running command `terraform workspace select default` in directory /workspace/test/fixtures/multiple_buckets
       Switched to workspace "default".
$$$$$$ Running command `terraform workspace delete kitchen-terraform-multiple-buckets-default` in directory /workspace/test/fixtures/multiple_buckets
       Deleted workspace "kitchen-terraform-multiple-buckets-default"!
       Finished destroying <multiple-buckets-default> (0m6.49s).
-----> Kitchen is finished. (0m8.10s)

9. Generar documentación para entradas y salidas

Las tablas de entrada y salida de los archivos README del módulo raíz, los submódulos y los módulos de ejemplo se generan automáticamente en función de variables y outputs de los módulos respectivos. Estas tablas se deben actualizar si se cambian las interfaces del módulo.

Ejecuta:

make generate_docs
# This will generate new Inputs and Outputs tables

10. Cómo ejecutar pruebas de lint en CFT

Un linter es una herramienta que analiza el código fuente para marcar errores de programación y estilo, y construcciones sospechosas.

Se puede analizar con lint o formatear muchos de los archivos del repositorio para mantener un estándar de calidad. Para garantizar la calidad en CFT, usarás una prueba de lint.

Ejecuta:

make docker_test_lint
# This will run all lint tests on your repo

11. Cómo enviar una solicitud de extracción en GitHub

Ahora que cambiaste el código de forma local y lo probaste a través de las pruebas de integración, deberías publicar este código en el repositorio principal.

Para que tu código esté disponible en el repositorio principal, deberás confirmar los cambios de código realizados en tu rama y enviarlo al repositorio principal. Para que tu código se agregue al repositorio principal que bifurcaste al comienzo del codelab, generarás una solicitud de extracción (PR) en el repositorio principal después de confirmar el código en tu repositorio.

Si envías una solicitud de extracción, el administrador del repositorio recibirá una notificación para que revise los cambios propuestos al código. Además, puedes agregar a otros usuarios como revisores para recibir comentarios sobre los cambios realizados en el código. El PR activará una Cloud Build que ejecutará pruebas en el repositorio.

En función de los cambios que realices en el código, los revisores proporcionarán comentarios sobre el código y solicitarán modificaciones si es necesario cambiar algo en función de las prácticas recomendadas y la documentación. El administrador revisará los cambios en el código, se asegurará de que cumpla con el repositorio y podría volver a solicitarte que realices algunos cambios antes de combinarlo con el repositorio principal.

Ejecuta los siguientes pasos para confirmar el código en la rama bifurcada y enviarlo a la rama bifurcada:

  1. El primer paso es agregar los archivos modificados al repositorio local.
$ git add main.tf
$ git add README.md
$ git add variables.tf
$ git add examples/multiple-buckets/main.tf
$ git add test/integration/multiple-buckets/controls/gsutil.rb
# The ‘git add' command adds the file in the local repository and 
# stages the file for commit. To unstage a file, use git reset HEAD YOUR-FILE
  1. Tus archivos ya están en etapa de pruebas. A continuación, confirmarás los cambios.
$ git commit -m "First CFT commit"
# This will commit the staged changes and prepares them to be pushed 
# to a remote repository. To remove this commit and modify the file, 
# use 'git reset --soft HEAD~1' and commit and add the file again.
  1. Envía los cambios confirmados en tu repositorio local a GitHub para crear una solicitud de extracción (PR).
$ git push -u origin master
# Pushes the changes in your local repository up to the remote
# repository you specified as the origin

Los cambios en tu código ya están listos para una solicitud de extracción.

Ejecuta los siguientes pasos para plantear un PR al repositorio terraform-google-modules/terraform-google-cloud-storage :

  1. En el navegador web, ve a la página principal del repositorio.
  2. En el menú Branch, elige la bifurcación que contiene tus confirmaciones.
  3. A la derecha de la “Rama” haz clic en “Nueva solicitud de extracción”.

40087ce52ee5ed35.png

  1. Usar la base "base" menú desplegable para seleccionar la rama con la que deseas fusionar los cambios; por lo general, esta es la "principal" ya que confirmaste cambios de código en tu bifurcación.
  2. Ingresa un título y una descripción para tu solicitud de extracción para describir los cambios en tu código. Sé lo más específico posible y conciso.
  3. Si deseas crear una solicitud de extracción lista para su revisión, haz clic en “Crear solicitud de extracción”.

a9e70a2ec9653cd7.png

  1. Verás los activadores de Cloud Build en ejecución que se activan debido a la solicitud de extracción.

Enviaste correctamente tu primer cambio de código a la rama bifurcada y elevaste tu primer PR de CFT a la rama principal.

12. Felicitaciones

¡Felicitaciones! Agregaste correctamente una función a un módulo de CFT y enviaste un formulario de RR.PP. para su revisión.

Agregaste una función a un módulo de CFT, la probaste de forma local con un ejemplo y realizaste pruebas antes de confirmar el código en GitHub. Por último, presentaste un formulario de Relaciones Públicas para su revisión y la fusión final con CFT.

Ahora conoces los pasos importantes para comenzar a usar Cloud Foundation Toolkit.