1. CFT 소개
최종 업데이트: 2020년 3월 3일
Cloud Foundation Toolkit이란 무엇인가요?
본질적으로 CFT는 Google Cloud Platform을 빠르게 시작할 수 있도록 권장사항 템플릿을 제공합니다. 이 튜토리얼에서는 Cloud Foundation Toolkit에 참여하는 방법을 알아봅니다.
필요한 항목
- GitHub 계정
- 머신에 설치된 Docker ( Mac 설치, Windows 설치)
- 코드 편집을 위한 코드 편집기 (예: Visual Studio Code)
- Git 및 GitHub에 관한 기본 지식
- Terraform 및 코드형 인프라 사용 경험
- 서비스 계정에 프로젝트 생성자 역할을 부여할 수 있는 권한
빌드할 항목
이 Codelab에서는 Cloud Foundation Toolkit (CFT)에 참여하는 방법을 알아봅니다.
실습할 내용은 다음과 같습니다.
- CFT에 참여하기 위한 개발 환경 설정
- CFT 모듈에 기능 추가
- 추가된 기능의 테스트 추가
- CFT에서 통합 테스트 실행
- 린트 테스트 실행
- GitHub에 코드를 커밋하고 pull 요청 (PR)을 제출합니다.
위의 모든 단계는 Google Cloud Storage CFT 모듈에 새 기능을 추가하여 실행합니다. "silly_label"
라는 라벨을 추가합니다. 이 라벨은 GCS CFT 모듈을 통해 생성된 모든 버킷에 자동으로 추가됩니다. 또한 기능을 검증하고 엔드 투 엔드 통합을 보장하는 테스트를 작성하게 됩니다.
2. 개발 환경 설정
원하는 경우 개발 목적으로 Cloud Shell을 활용할 수 있습니다. CFT에 기여하는 데 Cloud Shell을 사용하지 않으려면 머신에서 개발 환경을 설정하면 됩니다.
Git 설정
GitHub는 Git이라는 오픈소스 버전 제어 시스템 (VCS)을 기반으로 합니다. Git은 머신 또는 Cloud Shell에서 로컬로 발생하는 GitHub 관련 모든 작업을 담당합니다.
- Cloud Shell을 사용하는 경우 git이 사전 설치되어 있으므로 설치할 필요가 없습니다.
$ git --version
# This will display the git version on the Cloud Shell.
머신에서 개발 환경을 설정하려면 Git을 설치해야 합니다.
Git에서 사용자 이름 및 이메일 설정
Git은 사용자 이름을 사용하여 커밋을 ID와 연결합니다. Git 사용자 이름은 GitHub 사용자 이름과 다릅니다.
git config 명령어를 사용하여 Git 커밋과 연결된 이름을 변경할 수 있습니다. git config
를 사용하여 Git 커밋과 연결된 이름을 변경하면 이후 커밋에만 영향을 미치며 이전 커밋에 사용된 이름은 변경되지 않습니다.
Git을 성공적으로 설정했으며 브랜치를 포크하고 만들고 클론할 수 있어야 합니다. 이 Codelab에서는 Git을 광범위하게 사용합니다.
3. CFT의 GCS 저장소 포크
CFT 저장소 포크
이전 단계에서 로컬 머신 또는 Cloud Shell에 Git을 설정합니다. 이제 참여를 시작하려면 Google Cloud Storage CFT 저장소를 포크해야 합니다.
포크는 저장소의 사본입니다. 저장소를 포크하면 원래 프로젝트에 영향을 주지 않고 변경사항을 자유롭게 실험할 수 있습니다.
가장 일반적으로 포크는 다른 사람의 프로젝트에 대한 변경사항을 제안하거나 다른 사람의 프로젝트를 자신의 아이디어에 대한 시작점으로 사용하는 데 사용됩니다.
예를 들어 포크를 사용하여 버그 수정과 관련된 변경사항을 제안할 수 있습니다. 다음과 같은 방법으로 버그를 수정할 수 있습니다.
- 저장소를 포크합니다.
- 문제를 해결하세요.
- 프로젝트 소유자에게 pull 요청을 제출합니다.
CFT 저장소를 포크하는 단계는 다음과 같습니다.
- 웹브라우저를 열고 terraform-google-modules/terraform-google-cloud-storage 저장소로 이동합니다. 전체 Codelab에서 이 저장소를 사용합니다.
- 페이지 오른쪽 상단에서 포크를 클릭합니다.
- 포크를 원하는 위치에 대한 옵션이 표시되며 프로필을 선택하면 저장소가 포크됩니다.
로컬에서 포크 클론
만든 포크는 GCS 모듈 저장소의 사본입니다. 이제 이 저장소를 로컬 환경에 클론하여 새 기능을 추가합니다.
포크를 클론하는 단계는 다음과 같습니다.
- 웹브라우저를 열고 terraform-google-modules/terraform-google-cloud-storage에서 포크로 이동합니다.
- 오른쪽 상단에 '복제 또는 다운로드'가 있습니다. 클릭합니다.
- '복제 또는 다운로드'를 클릭한 후 '메모장'을 클릭한 다음 아이콘을 클릭하여 포크의 URL을 복사합니다. 이 URL을 사용하여 포크를 로컬 환경으로 클론합니다.
- 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에 키를 제공하고 값을 서비스 계정 키의 콘텐츠로 설정합니다.
export SERVICE_ACCOUNT_JSON=$(< cft.json)
6. Terraform 배포를 위한 테스트 프로젝트 만들기
이제 모든 것이 준비되었으므로 단일 명령어로 테스트 프로젝트를 만들 수 있습니다. terraform-google-cloud-storage 디렉터리 루트에서 다음 명령어를 실행합니다.
make docker_test_prepare
make docker_test_prepare
를 실행하면 아래와 같은 출력이 표시됩니다. 마지막에는 생성된 테스트 project_id를 받게 됩니다. 여기서 생성된 테스트 project_id는 새 기능으로 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번 줄의 'labels' 변수에 해당 특성을 추가합니다. 아래와 같이 main.tf에서 처리됩니다.
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(
<...>
}
이제 위의 폴더 구조에 표시된 variables.tf에 silly_label 변수를 추가합니다.
아래 코드를 복사하여 variables.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. 스토리지 버킷 예시에 새 특성 추가
기능을 모듈의 main.tf에 추가했으므로 이제 예제를 통해 추가된 기능을 테스트합니다.
'silly_label' example/multiple-buckets/main.tf에 추가해야 합니다.
이 예는 다음 단계에서 통합 테스트를 실행하기 위해 픽스처에서 사용합니다.
폴더 구조에서 볼 수 있듯이 terraform-google-cloud-storage/examples/multiple-buckets/ 의 main.tf에서 아래 변수 silly_label 행을 27행에 복사하여 붙여넣습니다.
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는 대상 프로그램 파생 방법을 지정하는 Makefile이라는 파일을 읽어 소스 코드에서 실행 가능한 프로그램과 라이브러리를 자동으로 빌드하는 빌드 자동화 도구입니다. 파일을 변경하면 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 작업공간을 Codelab의 앞부분에서 만든 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>
를 실행하여 예시 모듈을 테스트합니다.
이 단계는 multi_buckets 모듈에 대한 테스트가 포함된 gsutils.rb 파일을 통해 실행됩니다. 각 테스트에는 서비스 계정 사용자 인증 정보 설정을 사용하여 이전에 만든 테스트 프로젝트에 대해 실행되는 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에 있는 입력 및 출력 표는 각 모듈의 variables
및 outputs
에 따라 자동으로 생성됩니다. 모듈 인터페이스가 변경되면 이러한 테이블을 새로고침해야 합니다.
실행:
make generate_docs
# This will generate new Inputs and Outputs tables
10. CFT에서 린트 테스트 실행
린터는 소스 코드를 분석하여 프로그래밍 오류, 버그, 스타일 오류, 의심스러운 구성에 플래그를 지정하는 도구입니다.
저장소에 있는 대부분의 파일은 품질 표준을 유지하기 위해 린트 처리하거나 형식을 지정할 수 있습니다. CFT의 품질을 보장하기 위해 린트 테스트를 사용합니다.
실행:
make docker_test_lint
# This will run all lint tests on your repo
11. GitHub에서 PR 제출
이제 코드를 로컬에서 변경하고 통합 테스트를 통해 테스트했으므로 이 코드를 마스터 저장소에 게시합니다.
마스터 저장소에서 코드를 사용할 수 있도록 하려면 브랜치에 코드 변경사항을 커밋하고 마스터 저장소에 푸시해야 합니다. Codelab을 시작할 때 포크한 기본 저장소에 코드를 추가하려면 저장소에 코드를 커밋한 후 마스터 저장소에서 pull 요청 (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로 푸시하여 pull 요청 (PR)을 만듭니다.
$ git push -u origin master
# Pushes the changes in your local repository up to the remote
# repository you specified as the origin
이제 코드 변경사항을 pull 요청을 위한 준비가 되었습니다.
다음 단계를 실행하여 terraform-google-modules/terraform-google-cloud-storage 저장소에 PR을 제출합니다.
- 웹브라우저에서 저장소의 기본 페이지로 이동합니다.
- 브랜치 메뉴에서 커밋이 포함된 포크를 선택합니다.
- '분기' 오른쪽 메뉴에서 '새 pull 요청'을 클릭합니다.
- 기본 'base'를 사용합니다. 변경사항을 병합할 브랜치를 선택하는 드롭다운 메뉴(일반적으로 '마스터') 포크에 코드 변경사항을 커밋했으므로 이 브랜치가 다시 생성됩니다.
- 코드 변경사항을 설명하는 pull 요청의 제목과 설명을 입력합니다. 최대한 구체적으로 간결하게 작성하세요.
- 검토 준비가 된 pull 요청을 만들려면 'Pull 요청 만들기'를 클릭하세요.
- PR으로 인해 트리거된 Cloud Build 트리거가 실행됩니다.
첫 번째 코드 변경사항을 포크된 브랜치에 성공적으로 푸시하고 마스터 브랜치에 대해 첫 CFT PR을 올렸습니다.
12. 축하합니다
축하합니다. CFT 모듈에 기능을 추가하고 검토를 위해 PR을 제출했습니다.
CFT 모듈에 기능을 추가하고, 예시를 통해 로컬에서 테스트하고, 코드를 GitHub에 커밋하기 전에 테스트를 수행했습니다. 마지막으로 검토를 위해 PR을 제출했고 최종 CFT로 병합했습니다.
지금까지 Cloud Foundation Toolkit을 시작하기 위한 중요한 단계를 알아봤습니다.