Poradnik Cloud Foundation Toolkit

1. Wprowadzenie do CFT 101

ea557448aaa1fffc.png

Ostatnia aktualizacja: 3.03.2020

Co to jest Cloud Foundation Toolkit?

Mówiąc w skrócie, CFT zawiera szablony ze sprawdzonymi metodami, które pozwalają szybko rozpocząć pracę w Google Cloud Platform. Z tego samouczka dowiesz się, jak wziąć udział w Cloud Foundation Toolkit.

Czego potrzebujesz

  • konto GitHub.
  • Docker zainstalowany na komputerze ( zainstaluj na Macu, zainstaluj Windows)
  • Edytor kodu do edycji kodu (np. Visual Studio Code)
  • Podstawowa znajomość usług Git i GitHub
  • Pewne doświadczenie z Terraform i infrastrukturą jako kodem
  • Uprawnienie do przypisania roli twórcy projektów do konta usługi

Co utworzysz

W ramach tego ćwiczenia w Codelabs dowiesz się, jak wnosić wkład w Cloud Foundation Toolkit (CFT).

W ramach ćwiczenia:

  • Skonfiguruj środowisko programistyczne do wykorzystania w CFT
  • Dodawanie funkcji do modułu CFT
  • Dodaj testy dodanej funkcji
  • Przeprowadzaj testy integracji w CFT
  • Przeprowadzanie testów lintowania
  • Zatwierdź kod w GitHubie i prześlij żądanie pull (PR)

Wszystkie powyższe czynności możesz wykonać, dodając nową funkcję do modułu CFT w Google Cloud Storage. Dodasz etykietę "silly_label", która będzie automatycznie dodawana do wszystkich zasobników utworzonych za pomocą modułu GCS CFT. Będziesz też mieć możliwość napisania testów, aby sprawdzić działanie funkcji i zapewnić kompleksową integrację.

2. Skonfiguruj środowisko programistyczne

Jeśli chcesz, możesz wykorzystać Cloud Shell na potrzeby programowania. Jeśli nie chcesz używać Cloud Shell do współtworzenia CFT, możesz skonfigurować na swoim komputerze środowisko programistyczne.

Skonfiguruj Git

Serwis GitHub opiera się na systemie kontroli wersji typu open source (VCS) o nazwie Git. Git jest odpowiedzialny za wszystko, co związane z GitHubem, co dzieje się lokalnie na Twojej maszynie lub w Cloud Shell.

  1. Jeśli używasz Cloud Shell, nie musisz instalować git, bo jest on zainstalowany fabrycznie.
$ git --version
# This will display the git version on the Cloud Shell.

Jeśli konfigurujesz środowisko programistyczne na komputerze, musisz zainstalować Git.

Ustawianie nazwy użytkownika i adresu e-mail w Git

Git używa nazwy użytkownika, aby powiązać zatwierdzenia z tożsamością. Nazwa użytkownika Git różni się od Twojej nazwy użytkownika GitHuba.

Nazwę powiązaną z zatwierdzeniami Git możesz zmienić za pomocą polecenia git config. Zmiana nazwy powiązanej z Twoimi zatwierdzeniami Git za pomocą git config będzie miała wpływ tylko na przyszłe zatwierdzenia i nie zmieni nazwy używanej w poprzednich zatwierdzeniach.

Udało Ci się skonfigurować Git i powinno być możliwe rozwidlenie, tworzenie i klonowanie gałęzi. W tym ćwiczeniu z programowania będziemy intensywnie korzystać z Git.

3. Oddziel repozytorium GCS CFT

Tworzenie rozwidlenia repozytorium CFT

Konfigurujesz Git na maszynie lokalnej lub w Cloud Shell w poprzednim kroku. Aby zacząć współtworzyć, musisz teraz utworzyć rozwidlenie repozytorium CFT Google Cloud Storage.

Fork to kopia repozytorium. Rozwinięcie repozytorium umożliwia swobodne eksperymentowanie ze zmianami bez wpływu na pierwotny projekt.

Najczęściej używa się ich do proponowania zmian do cudzego projektu lub do wykorzystywania projektu innej osoby jako punktu wyjścia dla własnego pomysłu.

Możesz na przykład użyć rozwidlenia, aby zaproponować zmiany związane z naprawą błędu. Aby naprawić błąd:

  • Utwórz rozwidlenie repozytorium.
  • Wprowadź poprawki.
  • Prześlij prośbę o pull do właściciela projektu.

Instrukcje tworzenia repozytorium CFT:

  1. Otwórz przeglądarkę i przejdź do repozytorium terraform-google-modules/terraform-google-cloud-storage. Będziemy używać tego repozytorium w całych ćwiczeniach z programowania.
  2. W prawym górnym rogu strony kliknij rozwidlenie.

e3894c6de6a732b4.png

  1. Pojawi się opcja wyboru miejsca, w którym chcesz umieścić widelec, wybierz swój profil, a repozytorium zostanie rozwidlone.

Lokalne sklonowanie rozwidlenia

Utworzony przez Ciebie rozwidlenie jest kopią repozytorium modułu GCS. Aby dodać nową funkcję, sklonujesz to repozytorium do środowiska lokalnego.

Procedura sklonowania widelec:

  1. Otwórz przeglądarkę i przejdź do swojego rozwidlenia na stronie terraform-google-modules/terraform-google-cloud-storage.
  2. W prawym górnym rogu zobaczysz przycisk „Klonuj lub pobierz”. kliknij go.

3bfa87b9f7f01f61.png

  1. Po kliknięciu przycisku „Klonuj lub pobierz” kliknij „Notatnik”. aby skopiować adres URL rozwidlenia. Użyjesz tego adresu, aby sklonować swój widelec do środowiska lokalnego.

dbf3682d004e0ee0.png

  1. Przejdź do terminala w VSCode lub na komputerze i skopiuj rozwidlenie.
$ git clone <url>
# This command will clone your fork locally.
# Paste the copied URL from the previous step.
  1. Po sklonowaniu rozwidlenia lokalnie możesz przejść do repozytorium, utworzyć nową gałąź z rozwidlenia i wprowadzić zmiany w kodzie tej gałęzi tymczasowej.

Zgodnie z konwencją możesz nazwać gałąź w następujący sposób:

  • Prośby o dodanie funkcji: feature/feature-name
  • Na potrzeby aktualizacji wewnętrznych internal/change-name
  • Poprawki błędów: bugfix/issue-name

Dodajesz nową funkcję, więc możesz nazwać swoją gałąź tymczasową 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"

Wszystko gotowe do rozpoczęcia pracy z Cloud Foundation Toolkit.

4. Tworzenie środowiska testowego

Standardowy proces tworzenia narzędzia do testowania CFT polega na wykorzystaniu izolowanego projektu testowego do testowania. Ten krok przeprowadzi Cię przez proces tworzenia projektu testowego (w oparciu o standardową konfigurację) za pomocą konta usługi.

0. Zainstaluj Docker Engine

Jeśli używasz komputera do programowania, musisz zainstalować Docker Engine.

1. Zainstaluj pakiet Google Cloud SDK

Jeśli korzystasz z GCP Cloud Shell, nie musisz instalować pakietu SDK Google Cloud.

Otwórz Google Cloud SDK i pobierz interaktywny instalator dla Twojej platformy.

2. Skonfiguruj

Aby utworzyć środowisko testowe, potrzebujesz organizacji Google Cloud, folderu testowego i konta rozliczeniowego. Te wartości należy ustawić za pomocą zmiennych środowiskowych:

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. Skonfiguruj konto usługi

Zanim utworzysz środowisko testowe, musisz pobrać klucz konta usługi do środowiska testowego. To konto usługi wymaga ról Twórca projektów, Użytkownik kont rozliczeniowych i Wyświetlający organizację. Te kroki pomogą Ci utworzyć nowe konto usługi, ale możesz też użyć istniejącego konta.

3.1 Utwórz lub wybierz początkowy projekt GCP

Zanim utworzysz konto usługi, musisz wybrać projekt, w którym będziesz je hostować. Możesz też utworzyć nowy projekt.

gcloud config set core/project YOUR_PROJECT_ID

3.2 Włączanie interfejsów Google Cloud APIs

Włącz w projekcie wyjściowym te interfejsy API Google Cloud:

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

3.3 Tworzenie konta usługi

Utwórz nowe konto usługi, aby zarządzać środowiskiem testowym:

# 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

Sprawdź, czy konto usługi zostało utworzone:

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

3.4 Przypisz do konta usługi role Twórca projektu, Użytkownik konta rozliczeniowego i Wyświetlający organizację:

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"

Masz teraz konto usługi, którego możesz używać do zarządzania środowiskiem testowym.

4. Przypisz rolę użytkownika konta rozliczeniowego do zasobu konta rozliczeniowego

4.1 Pobieranie zasad uprawnień konta rozliczeniowego

Pobierz istniejące powiązania zasad uprawnień na koncie rozliczeniowym

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

4.2 Zaktualizowanie zasady tak, aby obejmowało konto usługi

Zaktualizuj plik policy.yml, aby dodać nowe powiązanie dla konta usługi z przypisaną rolą roles/billing.user

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

4.3 Aktualizowanie zasad dotyczących konta rozliczeniowego

Zastosuj zmiany na koncie rozliczeniowym

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

5. Przygotuj dane logowania Terraform

Aby utworzyć środowisko testowe, musisz pobrać klucz konta usługi do powłoki.

5.1 Klucz konta usługi

Tworzenie i pobieranie klucza konta usługi dla Terraform

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

5.2 Konfigurowanie danych logowania Terraform

Przekaż klucz do Terraform za pomocą zmiennej środowiskowej SERVICE_ACCOUNT_JSON, ustawiając wartość na zawartość klucza konta usługi.

export SERVICE_ACCOUNT_JSON=$(< cft.json)

6. Utwórz projekt testowy dla wdrożeń Terraform

Gdy wszystko jest już przygotowane, możesz utworzyć projekt testowy za pomocą jednego polecenia. Uruchom to polecenie w katalogu głównym terraform-google-cloud-storage:

make docker_test_prepare

Po uruchomieniu make docker_test_prepare zobaczysz poniższe dane wyjściowe. Na końcu otrzymasz utworzony testowy identyfikator projektu (project_id), w którym wdrożysz i przetestujesz swój moduł Cloud Storage z nową funkcją.

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.

Udało Ci się utworzyć projekt testowy, do którego odwołuje się identyfikator projektu (project_id), tak jak widać w danych wyjściowych konsoli. Środowisko programistyczne i testowe jest skonfigurowane.

5. Dodaj nową funkcję do modułu CFT

Twoje środowisko programistyczne i testowe jest już skonfigurowane, zacznijmy więc dodawać „silly_label” do modułu CFT google-cloud-storage.

Upewnij się, że jesteś w terraform-google-cloud-storage, i otwórz plik main.tf zgodnie ze schematem folderów.

17f2d3b9893be853.png

Od „silly_label” jest etykietą, dodasz ją w wierszu 27 w zmiennej „etykiety” w pliku main.tf, jak widać poniżej:

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(
 <...>
}

Teraz dodasz zmienną silly_label w plikuvariable.tf widoczny w powyższej strukturze folderów.

Skopiuj poniższy kod i dodaj go w wierszu 29 w zmiennej.tf. Upewnij się, że nad i pod dodanym blokiem zmiennej jest nowy znak wiersza.

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. Dodaj nową funkcję do przykładowego zasobnika na dane

Twoja funkcja została dodana do pliku main.tf modułu. Teraz przetestujesz na przykładzie tę dodaną funkcję.

Parametr „silly_label” należy dodać do plików example/multiple-buckets/main.tf

Ten przykład zostanie wykorzystany przez urządzenie w następnym kroku do testów integracji.

Skopiuj poniższy wiersz zmiennej silly_label do wiersza 27 w pliku main.tf w folderze terraform-google-cloud-storage/examples/multiple-buckets/, tak jak w strukturze folderów:

408cb1365b2a0793

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. Napisz test sprawdzający, aby sprawdzić funkcję

Twoja funkcja została dodana do pliku main.tf modułu, a następnie do przykładu z wieloma zasobnikami do przetestowania w sprzęcie. Musisz przetestować tę funkcję za pomocą testu integracji InSpec napisanego w języku Ruby.

Nowe testy dodasz do pliku gsutil.rb znajdującego się w poniższej strukturze folderów:

b2bfeb203477e0c8.png

Dodano atrybut „silly_label” na wszystkich zasobnikach tworzonych w ramach modułu multiple_buckets. Teraz musisz napisać testy, aby przetestować nową funkcję.

W poniższym kodzie za pomocą polecenia gsutil otrzymujesz etykietę każdego zasobnika, a następnie sprawdzasz zwrócone dane wyjściowe tego polecenia.

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. Przeprowadzaj testy integracji w CFT

Testowanie integracji

Testy integracji służą do weryfikacji działania modułu głównego, modułów podrzędnych i przykładowych. Dodatki, zmiany i poprawki powinny być testowane.

Testy integracji są przeprowadzane za pomocą narzędzi Kuchnia, Kuchnia-Terraform i InSpec. Dla wygody narzędzia te są umieszczone w obrazie Dockera.

Ogólną strategią przeprowadzania takich testów jest sprawdzenie działania modułów przykładowych, a tym samym sprawdzenie, czy moduł główny, moduły podrzędne i moduły przykładowe działają prawidłowo.

W tym przypadku każdy krok wykonujesz za pomocą wielu poleceń.

  1. Uruchom make docker_run, aby przetestować kontener Dockera w trybie interaktywnym.

Make to narzędzie do automatyzacji kompilacji, które automatycznie kompiluje na podstawie kodu źródłowego programy wykonywalne i biblioteki, odczytując pliki o nazwie Makefiles, które określają sposób uzyskania programu docelowego. Po wprowadzeniu zmian w pliku kontener Dockera musi być aktualizowany automatycznie.

Po uruchomieniu make docker_run tworzysz obszar roboczy w kontenerze Dockera i aktywujesz dane logowania dla swojego konta usługi. Ten obszar roboczy zostanie użyty w następnych krokach do przeprowadzenia testów.

W terminalu zobaczysz te dane wyjściowe:

Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
  1. Uruchom kitchen_do list, aby wyświetlić listę wszystkich instancji w obszarze roboczym, które zawierają testy integracji.
     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. Uruchom kitchen_do create <EXAMPLE_NAME>, aby zainicjować katalog roboczy dla przykładowego modułu.

Ten krok uruchamia mikrokuchnię i terraform w obszarze roboczym.

W terminalu zobaczysz poniższe dane wyjściowe.

[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. Aby zastosować przykładowy moduł, uruchom polecenie kitchen_do converge <EXAMPLE_NAME>.

W tym kroku zastosujemy obszar roboczy Terraform utworzony w poprzednim kroku do projektu GCP utworzonego wcześniej w ramach ćwiczeń z programowania.

W terminalu zobaczysz poniższe dane wyjściowe.

[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. Aby przetestować przykładowy moduł, uruchom polecenie kitchen_do verify <EXAMPLE_NAME>.

Ten krok zostanie przetworzony przy użyciu pliku gsutils.rb zawierającego testy modułu multiple_buckets. Każdy test zawiera polecenie gsutil, które zostanie uruchomione w odniesieniu do utworzonego wcześniej projektu testowego z użyciem ustawień danych logowania konta usługi.

Jeśli pojawią się błędy, zobaczysz, co było oczekiwane, a co otrzymało polecenie w ramach testu.

W terminalu zobaczysz poniższe dane wyjściowe.

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. Uruchom polecenie kitchen_do destroy <EXAMPLE_NAME>, aby zniszczyć przykładowy stan modułu.

Ten krok zniszczy obszar roboczy utworzony w powyższych krokach. W tym kroku zniszczysz też zasobniki GCS utworzone w projekcie wraz z etykietą dodaną do modułu GCS.

Poniższe dane wyjściowe możesz wyświetlić w terminalu.

[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. Generowanie dokumentacji danych wejściowych i wyjściowych

Tabele danych wejściowych i wyjściowych w plikach README modułu głównego, modułów podrzędnych i modułów przykładowych są generowane automatycznie na podstawie parametrów variables i outputs odpowiednich modułów. W przypadku zmiany interfejsów modułów należy odświeżyć te tabele.

Uruchomienie:

make generate_docs
# This will generate new Inputs and Outputs tables

10. Przeprowadzanie testów lintowania w CFT

Linter to narzędzie, które analizuje kod źródłowy w celu zgłaszania błędów programowania, błędów, pomyłek stylistycznych i podejrzanych konstrukcji.

Wiele plików w repozytorium można lintować lub formatować, by utrzymać standard jakości. Aby zapewnić odpowiednią jakość w CFT, należy użyć testu lintowego.

Uruchomienie:

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

11. Przesyłanie PR w GitHubie

Po lokalnej zmianie kodu i przetestowaniu go za pomocą testów integracji możesz opublikować go w głównym repozytorium.

Aby udostępnić kod w głównym repozytorium, musisz zatwierdzić zmiany kodu w gałęzi i wypchnąć go do repozytorium głównego. Jeśli chcesz, aby Twój kod został dodany do głównego repozytorium rozgałęzionego na początku ćwiczeń z programowania, musisz wysłać żądanie pull (PR) do repozytorium głównego po wyrażeniu zgody na dodanie kodu do repozytorium.

Gdy zgłosisz prośbę o pomoc, administrator repozytorium zostanie powiadomiony o konieczności sprawdzenia proponowanych zmian w kodzie. Możesz też dodać innych użytkowników jako weryfikatorów, którzy będą otrzymywać ich opinie na temat zmian w Twoim kodzie. PR aktywuje usługę Cloud Build, która przeprowadzi testy w repozytorium.

Na podstawie zmian w kodzie weryfikatorzy będą go komentować i poprosić o wprowadzenie zmian, jeśli na podstawie sprawdzonych metod i dokumentacji trzeba będzie wprowadzić jakieś zmiany. Administrator sprawdzi zmiany w kodzie, upewni się, że kod jest zgodny z repozytorium i może ponownie poprosić Cię o wprowadzenie zmian przed scaleniem kodu z repozytorium głównym.

Wykonaj te czynności, aby zatwierdzić kod w rozwidlonej gałęzi i wypchnąć go do rozwidlonej gałęzi:

  1. Najpierw dodaj zmienione pliki do lokalnego repozytorium.
$ 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. Pliki są teraz podzielone na etapy. W następnym kroku zatwierdzisz zmiany.
$ 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. Przekaż zatwierdzone zmiany z lokalnego repozytorium do GitHuba, aby utworzyć żądanie pull (PR).
$ git push -u origin master
# Pushes the changes in your local repository up to the remote
# repository you specified as the origin

Zmiany w kodzie są teraz gotowe do użycia w żądaniu pull.

Aby zgłosić PR w repozytorium terraform-google-modules/terraform-google-cloud-storage, wykonaj te czynności:

  1. W przeglądarce otwórz stronę główną repozytorium.
  2. W menu Gałąź wybierz widelec zawierający zatwierdzenia.
  3. Po prawej stronie „Odgałęzienia” kliknij „Nowe żądanie pull”.

40087ce52ee5ed35.png

  1. Użyj podstawowej „podstawy” i wybierz gałąź, z którą chcesz scalić zmiany; zwykle jest to gałąź nadrzędna. , ponieważ zmiany kodu rozwidlenia zostały zatwierdzone.
  2. Wpisz tytuł i opis żądania pull, aby opisać zmiany w kodzie. Podaj jak najwięcej szczegółów i zwięzłość.
  3. Aby utworzyć żądanie pull, które jest gotowe do sprawdzenia, kliknij „Utwórz żądanie pull”.

a9e70a2ec9653cd7.png

  1. Zobaczysz uruchomione aktywatory Cloud Build, które są aktywowane ze względu na PR.

Udało Ci się wprowadzić pierwszą zmianę kodu do rozwidlonej gałęzi i utworzyć pierwszy PR CFT względem gałęzi głównej.

12. Gratulacje

Gratulacje! Udało Ci się dodać funkcję do modułu CFT i przesłać PR do sprawdzenia.

Udało Ci się dodać funkcję do modułu CFT, przetestować ją lokalnie za pomocą przykładu i przeprowadzić testy przed zatwierdzeniem kodu w usłudze GitHub. Na koniec przekazałeś(-aś) PR do sprawdzenia i końcowego scalenia w CFT.

Znasz już najważniejsze kroki, które należy wykonać, aby zacząć korzystać z Cloud Foundation Toolkit.