Golang 에서 소스 코드의 스타일을 맞춰주는 gofmt 커맨드가 있다면 Terraform에는 terraform fmt 커맨드가 있다.
Terraform으로 인프라스트럭처를 코드화 하다보면 각자 스타일에 따라 들여쓰기나 뛰어쓰기를 하게되는데, 이 때 terraform fmt
명령을 사용하면 들여쓰기, 뛰어쓰기를 Terraform의 표준 포맷에 맞게 자동으로 수정해준다.
지금 일하고 있는 팀(글을 포스팅하는 현재는 퇴사했지만…ㅠ_ㅠ)에서는 처음엔 이 fmt 명령을 사용하지 않고 Terraform 파일을 작성했었는데 최근에 포맷을 맞추면 좋겠다는 이야기가 나와서 fmt 를 적용하게 되었다.
개발자 각자가 PR을 올리기 전에 git hook 등으로 fmt 체크를 할 수도 있겠지만 인프라스트럭처를 코드로 작성하기로 했다면 인프라스트럭처 코드 역시 CI 를 통해 자동화된 테스트나 빌드, 혹은 실제 인프라에 적용하는 단계까지 고려해 볼 수 있다.
CircleCI config.yml 작성
결론부터 이야기하면 다음과 같이 terraform validate
, terraform fmt
, tflint 를 PR이 생성/수정 될 때 마다 CircleCI 에 의해서 자동 실행될 수 있도록 설정해서 사용하고 있다.
다음은 실제 빌드에 사용하고 있는 .circleci/config.yml
파일의 내용이다.
마침 circleci 2.0 을 도입한 직후라 version: 2 를 명시하고 CircleCI 2.0 포맷에 맞춰 작성되어 있다.
{Project Root}/.circleci/config.yml
version: 2
terraform: &terraform
docker:
- image: hashicorp/terraform:0.11.1
working_directory: /tmp/workspace/terraform
jobs:
validate:
<<: *terraform
steps:
- checkout
- run:
name: Validate Terraform configurations
command: find . -type f -name "*.tf" -exec dirname {} \;|sort -u | while read m; do (terraform validate -check-variables=false "$m" && echo "√ $m") || exit 1 ; done
- run:
name: Check if Terraform configurations are properly formatted
command: files=$(terraform fmt -write=false); if [ -n "$files" ]; then echo "$files"; echo -e "\nSome terraform files need be formatted, run 'terraform fmt' to fix"; exit 1; fi
- run:
name: Install tflint
command: curl -L -o /tmp/tflint.zip https://github.com/wata727/tflint/releases/download/v0.5.2/tflint_linux_amd64.zip && unzip /tmp/tflint.zip -d /usr/local/bin
- run:
name: Check Terraform configurations with tflint
command: tflint
workflows:
version: 2
build:
jobs:
- validate
위에서 부터 파일을 부분별로 나눠서 살펴보자.
docker image 정의
version: 2
terraform: &terraform
docker:
- image: hashicorp/terraform:0.11.1
working_directory: /tmp/workspace/terraform
hashicorp/terraform:0.11.1
도커 이미지를 사용해서 빌드를 수행한다.
terraform: &terraform
으로 정의한 부분은 아래 소스에서 <<: *terraform
부분에 치환된다.
validate job 정의
jobs:
validate:
<<: *terraform
steps:
- checkout
validate 잡을 정의한다. project를 repo에서 checkout 한다.
terraform validate 실행
- run:
name: Validate Terraform configurations
command: find . -type f -name "*.tf" -exec dirname {} \;|sort -u | while read m; do (terraform validate -check-variables=false "$m" && echo "√ $m") || exit 1 ; done
*.tf
형식의 파일을 찾아 정렬하고 terraform validate를 실행한다.
terraform validate
에서는 Terraform 파일의 문법상 오류를 검증한다.
여기에는 -check-variables=false
옵션을 사용했는데 default인 -check-variables=true
옵션을 사용할 경우 provider 설치 유무 등 모든 required variables 의 입력여부를 체크하기 때문에 이를 통과시키기 위해서 aws provider를 필요한 경로에 모두 설치하는 등의 불필요한 작업을 실행해야 한다. 이 옵션은 체크가 필요한 요건에 따라 수정해서 사용할 수 있겠다.
terraform fmt 실행
- run:
name: Check if Terraform configurations are properly formatted
command: files=$(terraform fmt -write=false); if [ -n "$files" ]; then echo "$files"; echo -e "\nSome terraform files need be formatted, run 'terraform fmt' to fix"; exit 1; fi
terraform fmt
명령을 실행하고 수정이 필요한 파일이 있는 경우 리스트를 화면에 출력하고 exit 1
으로 에러(EXIT_FAILURE) 를 리턴하고 빌드를 종료한다.
fmt 명령은 기본적으로 recursive하게 실행되고 수정이 필요한 파일이 있으면 명령실행과 동시에 수정한다.
개발자가 해당 파일을 확인하고 직접 수정, commit(rebase)할 수 있도록 -write=false
옵션을 사용해서 파일 수정은 하지 않고 fmt 체크만 실행 한다.
tflint 설치
- run:
name: Install tflint
command: curl -L -o /tmp/tflint.zip https://github.com/wata727/tflint/releases/download/v0.5.2/tflint_linux_amd64.zip && unzip /tmp/tflint.zip -d /usr/local/bin
tflint 를 GitHub repo에서 받아와 /usr/local/bin
아래에 설치한다.
tflint 실행
- run:
name: Check Terraform configurations with tflint
command: tflint
tflint를 실행한다. 프로젝트 설명에 따르면, terraform plan
으로 검증할 수 없는 오류들을 tflint가 검증해 준다고 한다. ex) aws_instance.instance_type 이 잘못 입력된 경우
tflint/detector · wata727/tflint · GitHub 에서 terraform plan
이 체크하지 못하는 오류를 탐지하는 소스를 확인할 수 있다.
validate job을 실행하는 workflow 정의
workflows:
version: 2
build:
jobs:
- validate
위에서 정의한 validate
job을 실행한다.
이제 CircleCI 적용을 위해서 해당 config.yml 파일 을 git repo에 push 한다.
CircleCI 에 해당 프로젝트를 추가
.circleci/config.yml 파일을 repo에 push 완료했다면,
CircleCI에서 Projects -> Add Project
를 선택해 CI를 반영할 프로젝트를 추가한다.
나는 GitHub – asbubam/2dal-infrastructure 프로젝트를 반영할 예정이므로, 해당 프로젝트를 선택했다.
CircleCI Platform에 2.0을 선택하고 Start Building
버튼을 클릭한다.
Build에 성공하면
레이블을 확인할 수 있다!
Github PR을 통해 Build를 수행한 경우 다음과 같이 체크 결과를 화면에 출력해준다.
리뷰어는 안심하고 PR을 리뷰할 수 있다. 😉
Build에 실패하면
레이블과 함께 오류메시지를 통해서 다음과 같이 수정이 필요한 부분을 확인할 수 있다.
위의 메시지는 terraform/common/dev_vpc/eip.tf
파일에 fmt 명령 실행이 필요함을 알려준다.
GitHub PR을 통해 Build를 수행할 경우 다음과 같이 체크 결과를 화면에 출력해준다.
정리
CircleCI 를 이용해서 Terraform validate, fmt, lint 등을 프로젝트에 변경사항이 있을 때마다 자동 실행하도록 적용해봤다. 이번에 적용한 커맨드 외에도 terraform plan
리포트를 화면에 출력한다거나, 필요에 따라 상황별로 Terraform 커맨드를 자동실행하도록 CI에 연동해 볼 수 있을 것 같다.
설명에 사용된 파일은 GitHub – asbubam/2dal-infrastructure에서 확인할 수 있다.
참고자료
- Sample 2.0 config.yml Files – CircleCI
- GitHub – terraform-aws-modules/terraform-aws-vpc
- GitHub – wata727/tflint
2 thoughts to “CircleCI 에서 Terraform fmt 수행하기”
Comments are closed.