1. 《CFT 101》簡介
上次更新時間:2020 年 3 月 3 日
什麼是 Cloud Foundation Toolkit?
CFT 基本上提供最佳做法範本,方便您快速開始使用 Google Cloud Platform。在這個教學課程中,您會瞭解如何為 Cloud Foundation Toolkit 貢獻工作。
軟硬體需求
- GitHub 帳戶。
- 電腦上安裝 Docker ( Mac 安裝、Windows 安裝)
- 用來編輯程式碼的程式碼編輯器 (例如 Visual Studio Code)
- 對 Git 和 GitHub 有基本瞭解
- 具備某些 Terraform 和基礎架構即程式碼的經驗
- 將專案建立者角色授予服務帳戶的權限
建構項目
在這個程式碼研究室中,您將瞭解如何為 Cloud Foundation Toolkit (CFT) 貢獻心力。
您將學會以下內容:
- 設定可對 CFT 有貢獻的開發環境
- 在 CFT 模組中新增功能
- 新增功能的測試
- 在 CFT 中執行整合測試
- 執行 Lint 測試
- 將程式碼修訂至 GitHub 並提交提取要求 (PR)
您須在 Google Cloud Storage CFT 模組中新增新功能,才能執行上述所有步驟。您即將新增名為 "silly_label"
的標籤,這個標籤會自動新增至透過 GCS CFT 模組建立的所有值區。您也會撰寫測試來驗證功能,並確保端對端整合。
2. 設定開發環境
您可以視需要使用 Cloud Shell 進行開發。如果不想使用 Cloud Shell 來貢獻 CFT,可以在電腦上設定開發環境。
設定 Git
GitHub 是以名為 Git 的開放原始碼版本管控系統 (VCS) 為基礎。Git 負責在本機或 Cloud Shell 上發生的所有 GitHub 相關事務。
- 使用 Cloud Shell 時,不必安裝 Git,因為 Git 已預先安裝。
$ git --version
# This will display the git version on the Cloud Shell.
如要在機器上設定開發環境,您必須安裝 Git。
在 Git 中設定使用者名稱和電子郵件
Git 會使用使用者名稱,將修訂版本與身分建立關聯。Git 使用者名稱與您的 GitHub 使用者名稱不同。
您可以使用 git config 指令變更與 Git 修訂版本相關聯的名稱。使用 git config
變更與 Git 修訂版本相關聯的名稱只會影響日後的修訂版本,不會影響過去修訂版本使用的名稱。
您已成功設定 Git,現在應該能夠建立分支、建立及複製分支版本。我們會在本程式碼研究室中廣泛使用 Git。
3. Fork CFT 的 GCS 存放區
建立 CFT 存放區分支
在先前的步驟中,您會在本機電腦或 Cloud Shell 中設定 Git。您現在需要建立 Google Cloud Storage CFT 存放區分支,才能開始貢獻內容。
分支是存放區的副本。建立存放區分支後,您可以自由測試變更,而不會影響原始專案。
最常見的用途是,用來提議變更他人的專案,或利用他人的專案做為您的構想。
舉例來說,您可以使用分支提出與修正錯誤的變更相關的變更。如要修正錯誤,可以採取下列行動:
- 建立存放區分支。
- 加以修正。
- 向專案擁有者提交提取要求。
建立 CFT 存放區的分支步驟:
- 開啟網路瀏覽器,然後前往 terraform-google-modules/terraform-google-cloud-storage 存放區。我們會在整個程式碼研究室中使用這個存放區。
- 按一下頁面右上角的 [Fork] (分支)。
- 系統會提供選項,讓您選擇建立分支的位置、選擇設定檔,然後建立存放區分支。
在本機複製分支
您建立的分支是 GCS 模組存放區的副本。現在請將這個存放區複製到本機環境,以便新增地圖項目。
複製分支的步驟:
- 開啟網路瀏覽器,前往 terraform-google-modules/terraform-google-cloud-storage 前往分支。
- 畫面右上角會顯示「複製或下載」訊息。按鈕,按一下該按鈕。
- 點選 [複製或下載]之後,按一下「記事本」圖示來複製分支的網址您會使用這個網址將分支複製到本機環境。
- 前往 VSCode 或機器的終端機,複製叉子。
$ git clone <url>
# This command will clone your fork locally.
# Paste the copied URL from the previous step.
- 您已在本機複製分支,現在請前往存放區,從分支處建立新的分支版本,並變更臨時分支版本的程式碼。
按照慣例,您可以按照以下方式為分支版本命名:
- 功能要求:
feature/feature-name
- 如果是內部更新,請
internal/change-name
- 修正錯誤:
bugfix/issue-name
由於您要新增功能,可以呼叫臨時分支版本 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"
您現在可以開始設定 Cloud Foundation Toolkit 了!
4. 建立測試環境
標準 CFT 開發程序是以使用「獨立」的測試專案為基礎來進行測試。這個步驟會引導您透過服務帳戶建立測試專案 (根據標準設定)。
0.安裝 Docker Engine
如果您將機器用於開發,則必須安裝 Docker Engine。
1. 安裝 Google Cloud SDK
如果您使用的是 GCP Cloud Shell,就不需要安裝 Google Cloud SDK。
前往 Google Cloud SDK,並下載平台適用的互動式安裝程式。
2. 調整設定
如要建立測試環境,您必須擁有 Google Cloud 機構、測試資料夾和帳單帳戶。這些值必須透過環境變數設定:
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 設定服務帳戶
建立測試環境前,您必須先將服務帳戶金鑰下載至測試環境。這個服務帳戶必須具備專案建立者、帳單帳戶使用者和機構檢視者角色。這些步驟可協助您建立新的服務帳戶,但您也可以重複使用現有的帳戶。
3.1 建立或選取種子 GCP 專案
建立服務帳戶之前,您必須先選取託管專案。您也可以建立新專案。
gcloud config set core/project YOUR_PROJECT_ID
3.2 啟用 Google Cloud API
在種子專案中啟用下列 Google Cloud API:
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable iam.googleapis.com
gcloud services enable cloudbilling.googleapis.com
3.3 建立服務帳戶
建立新的服務帳戶來管理測試環境:
# 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
確認服務帳戶已建立:
gcloud iam service-accounts list --filter="EMAIL=${SERVICE_ACCOUNT}"
3.4 將「專案建立者」、「帳單帳戶使用者和機構檢視者」角色授予服務帳戶:
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"
您現在擁有可管理測試環境的服務帳戶。
4. 為帳單帳戶資源指派帳單帳戶使用者角色
4.1 擷取帳單帳戶的 IAM 政策
下載帳單帳戶現有的 IAM 政策繫結
gcloud beta billing accounts get-iam-policy ${TF_VAR_billing_account} | tee policy.yml
4.2 更新政策,加入服務帳戶
更新 policy.yml
檔案,為具有 roles/billing.user
角色的服務帳戶新增繫結
bindings:
- members:
- serviceAccount:cft-onboarding@<YOUR_PROJECT_ID>.iam.gserviceaccount.com
role: roles/billing.user
4.3 更新帳單帳戶政策
對帳單帳戶套用變更
gcloud beta billing accounts set-iam-policy ${TF_VAR_billing_account} policy.yml
5. 準備 Terraform 憑證
為了建立測試環境,您必須將服務帳戶金鑰下載至殼層。
5.1 服務帳戶金鑰
建立及下載 Terraform 的服務帳戶金鑰
gcloud iam service-accounts keys create cft.json --iam-account=${SERVICE_ACCOUNT}
5.2 設定 Terraform 憑證
使用環境變數 SERVICE_ACCOUNT_JSON
將金鑰提供給 Terraform,並將值設為服務帳戶金鑰的 contents。
export SERVICE_ACCOUNT_JSON=$(< cft.json)
6. 建立 Terraform 部署作業的測試專案
現在一切都已準備就緒,您可以使用單一指令建立測試專案。從 terraform-google-cloud-storage 目錄根目錄執行下列指令:
make docker_test_prepare
執行 make docker_test_prepare
時,您會看到以下輸出內容,最後會收到已建立的測試 project_id,您將在其中部署及測試 Cloud Storage 模組,並使用新功能測試 Cloud Storage 模組。
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.
現在,您已成功建立由 project_id 參照的測試專案,如控制台輸出內容所示。您的開發與測試環境已設定完畢。
5. 在 CFT 模組中新增功能
現在您已設定開發和測試環境,可以開始新增「silly_label」google-cloud-storage CFT 模組的功能
確認您位於 terraform-google-cloud-storage 中,並開啟 main.tf 檔案,如以下資料夾結構所示。
自「silly_label」起是標籤,請在「標籤」變數的第 27 行加入功能,如下所示:
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(
<...>
}
現在,請在上述資料夾結構中顯示的變數.tf 中新增 silly_label 變數。
請複製下列程式碼,並將程式碼新增至「Variable.tf」的第 29 行中,並確保在您新增的變數區塊上方與下方新增一行字元。
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. 將新功能新增至 Storage 值區範例
您已在模組的 main.tf 中新增功能,現在會透過範例測試新增的功能。
"silly_label"您必須新增至 example/multiple-buckets/main.tf
在下一個步驟中,韌體將使用這個範例執行整合測試。
將以下變數 silly_label 貼到 terraform-google-cloud-storage/examples/multiple-buckets/ 的 main.tf 行,如資料夾結構所示:
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. 編寫 Inspec 測試來檢查功能
您已將功能新增至模組的 main.tf 中,然後將功能新增至 multi_buckets 範例,以便透過固件進行測試。您需要透過以 Ruby 編寫的 InSpec 整合測試,測試您的功能。
您將在以下資料夾結構的 gsutil.rb 檔案中新增測試:
您已新增「silly_label」對所有透過 multi_buckets 模組建立的值區進行呼叫,現在您需要撰寫測試來測試新功能。
在下列程式碼中,您會透過 gsutil 指令取得每個值區的標籤,然後檢查指令傳回的輸出內容。
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. 在 CFT 中執行整合測試
整合測試
整合測試可用於驗證根模組、子模組和範例模組的行為。新增、變更及修正時,也應一併進行測試。
整合測試是使用 Kitchen、Kitchen-Terraform 和 InSpec 來執行。為方便起見,這些工具會封裝在 Docker 映像檔中。
這類測試的一般策略是驗證範例模組的行為,確保根模組、子模組和範例模組全都可以正常運作。
在互動式執行中,您可以透過多個指令執行每個步驟。
- 執行
make docker_run
,以互動模式啟動測試 Docker 容器。
Make 是一套版本自動化工具,透過讀取名為 Makefiles 的檔案自動化工具,從原始碼自動建構可執行檔和程式庫,這種工具會指定如何衍生目標程式。當您對檔案進行變更時,Docker 容器必須自動更新。
執行 make docker_run
時,請在 Docker 容器中建立工作區,然後啟用服務帳戶的憑證。後續步驟會使用工作區執行測試。
終端機中會顯示下列輸出內容:
Activated service account credentials for: [cft@<PROJECT_ID>.iam.gserviceaccount.com]
- 執行
kitchen_do list
,列出工作區中所有包含整合測試的執行個體。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>
- 執行
kitchen_do create <EXAMPLE_NAME>
來初始化範例模組的工作目錄。
這個步驟會初始化廚房,並在工作區中初始化 Terraform。
終端機中會顯示下列輸出內容。
[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)
- 執行
kitchen_do converge <EXAMPLE_NAME>
以套用範例模組。
這個步驟會將您在先前步驟中建立的 Terraform 工作區,套用至先前在程式碼研究室中建立的 GCP 專案。
終端機中會顯示下列輸出內容。
[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)
- 執行
kitchen_do verify <EXAMPLE_NAME>
來測試範例模組。
這個步驟會執行 gsutils.rb 檔案,該檔案包含 multi_buckets 模組的測試。每項測試都有一個 gsutil 指令,您可以透過服務帳戶憑證先前建立的測試專案執行這個指令。
如果發生任何錯誤,系統會顯示測試指令所預期的內容及收到的內容。
終端機中會顯示下列輸出內容。
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)
- 執行
kitchen_do destroy <EXAMPLE_NAME>
以刪除範例模組狀態。
這個步驟會刪除您在上述步驟中建立的工作區。這個步驟也會刪除在專案中建立的 GCS 值區,以及您新增至 GCS 模組的標籤。
您可以在終端機中查看下列輸出內容。
[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. 為輸入內容和輸出內容產生說明文件
根模組、子模組和範例模組的 README 檔中的「Inputs」和「Outputs」表格,會自動根據各模組的 variables
和 outputs
產生。如果模組介面有所變更,就必須重新整理這些表格。
執行作業:
make generate_docs
# This will generate new Inputs and Outputs tables
10. 在 CFT 中執行 Lint 測試
Linter 會分析原始碼,找出程式錯誤、錯誤、樣式錯誤和可疑的結構。
存放區中的許多檔案都可以進行程式碼檢查或格式化,以便維持品質標準。為確保 CFT 的品質,您將使用 Lint 測試。
執行作業:
make docker_test_lint
# This will run all lint tests on your repo
11. 在 GitHub 上提交 PR
現在您已在本機變更程式碼,並透過整合測試進行測試,接下來您會想將這個程式碼發布至主要存放區。
如要在主要存放區中使用您的程式碼,您必須將程式碼變更修訂至分支,並推送至主要存放區。為了讓您的程式碼新增到您在程式碼研究室一開始建立分支的主要存放區,您將程式碼提交至存放區後,您必須在主要存放區上提出提取要求 (PR)。
提出 PR 時,存放區管理員會收到通知,說明提議的程式碼變更。此外,您也可以將其他使用者新增為審查者,取得對程式碼變更的意見回饋。PR 會觸發 Cloud Build,並在存放區中執行測試。
程式碼變更之後,程式碼審查人員會根據您的程式碼提供註解,並詢問是否有必要根據最佳做法和說明文件進行調整。管理員會審查您的程式碼變更,確保您的程式碼符合存放區規範,而且可能會再次要求您進行變更,然後再將程式碼合併至主要存放區。
執行下列步驟,將程式碼修訂至分支的分支版本,並將程式碼推送至分支的分支版本:
- 首先,將變更的檔案新增至本機存放區。
$ 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
- 檔案已準備完成,下一步是提交變更。
$ 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.
- 將本機存放區中的修訂變更推送至 GitHub,以便建立提取要求 (PR)。
$ git push -u origin master
# Pushes the changes in your local repository up to the remote
# repository you specified as the origin
程式碼變更現已可以接受提取要求!
執行下列步驟,將 PR 提報給 terraform-google-modules/terraform-google-cloud-storage 存放區:
- 在網路瀏覽器中,前往存放區的主頁面。
- 在「分支版本」選單中,選擇包含修訂版本的分支。
- 「分支版本」右側按一下 [新增提取要求]
- 使用底數「基準」下拉式選單,然後選取要合併變更的分支版本,通常是「主要」不分支,因為您已修改分支的程式碼
- 為提取要求輸入標題和說明,說明程式碼變更。請盡可能具體,並簡明扼要。
- 如要建立可送交審查的提取要求,請按一下「建立提取要求」。
- 您會看到 Cloud Build 觸發條件正在執行,因 PR 而觸發。
您已成功將第一次程式碼變更推送至分支的分支,並針對主要分支版本提高第一個 CFT PR!
12. 恭喜
恭喜,你已成功將功能新增至 CFT 模組,並將 PR 送交審查!
您已將功能新增至 CFT 模組、透過範例在本機進行測試,並在將程式碼提交至 GitHub 前執行測試。最後,您提高了公關宣傳,並將最終團隊合併到 CFT。
您現已瞭解開始使用 Cloud Foundation Toolkit 的重要步驟。