[Ansible] Playbook Style Guide
Table of Contents
- Practices
- Start of Files
- End of Files
- Quotes
- Environment
- Booleans
- Key value pairs
- Sudo
- Hosts Declaration
- Task Declaration
- Include Declaration
- Spacing
Practices
Playbook을 작성할 때 모범 사례를 따르는 것이 좋다.
Best Practices
Why?
Ansible 개발자는 Playbook의 작동 방식과 특정 파일의 위치를 잘 알고 있기 때문에, 많은 문제를 피할 수 있다.
Why Doesn't Your Style Follow Theirs?
이 가이드의 목적은 Ansible Playbook 전체에서 사용할 수 있는 일관된 스타일을 정의하고 강력하고 읽기 쉬운 코드를 작성하는 것이다.
Start of Files
목적이 무엇인지 설명하고 필요한 경우 주석으로 표시하고, 그 뒤에 빈줄, ---
을 표시 한다
#bad
- name: 'Change s1m0n3's status'
service:
enabled: true
name: 's1m0ne'
state: '{{ state }}'
become: true
#good
# Example usage: ansible-playbook -e state=started playbook.yml
# This playbook changes the state of s1m0n3 the robot
---
- name: 'Change s1m0n3's status'
service:
enabled: true
name: 's1m0ne'
state: '{{ state }}'
become: true
Why?
파일을 열거나 head 명령을 사용하여 스크립트의 목적과 사용법을 보다 쉽게 찾을 수 있다
End of Files
마지막 라인은 항상 줄바꿈으로 파일을 끝내야 한다
Why?
일반적은 Unix 모범 사례이며, 터미널에서 파일을 인쇄 할 때 프롬프트가 잘못 정렬되는 것을 방지한다
Quotes
문자열에서는 큰 따옴표보다 작은 따옴표를 선호한다. 큰 따옴표는 작은 따옴표 안에 중첩되거나 (Ex> Jinja 맵 참조), 문자열에 이스케이프 문자가 필요한 경우 (Ex> 줄 바꾸기를 나타내는 "\n" 사용). 긴 문자열을 작성해야하는 경우 "folded, scalar" 스타일을 사용하면 모든 따옴표를 생략한다. 쿼터를 사용하면 안되는 경우는 부울논리 (Ex> true/false), 숫자 (Ex> 42), 그리고 Ansible 환경을 참조 하는 것 (Ex> 부울 논리 또는 값을 할당 할 변수의 이름)
# bad
- name: start robot named S1m0ne
service:
name: s1m0ne
state: started
enabled: true
become: true
# good
- name: 'start robot named S1m0ne'
service:
name: 's1m0ne'
state: 'started'
enabled: true
become: true
# double quotes w/ nested single quotes
- name: 'start all robots'
service:
name: '{{ item["robot_name"] }}''
state: 'started'
enabled: true
with_items: '{{ robots }}'
become: true
# double quotes to escape characters
- name 'print some text on two lines'
debug:
msg: "This text is on\ntwo lines"
# folded scalar style
- name: 'robot infos'
debug:
msg: >
Robot {{ item['robot_name'] }} is {{ item['status'] }} and in {{ item['az'] }}
availability zone with a {{ item['curiosity_quotient'] }} curiosity quotient.
with_items: robots
# folded scalar when the string has nested quotes already
- name: 'print some text'
debug:
msg: >
“I haven’t the slightest idea,” said the Hatter.
# don't quote booleans/numbers
- name: 'download google homepage'
get_url:
dest: '/tmp'
timeout: 60
url: 'https://google.com'
validate_certs: true
# variables example 1
- name: 'set a variable'
set_fact:
my_var: 'test'
# variables example 2
- name: 'print my_var'
debug:
var: my_var
when: ansible_os_family == 'Darwin'
# variables example 3
- name: 'set another variable'
set_fact:
my_second_var: '{{ my_var }}'
Why?
문자열이 YAML의 기본 유형이지만 명시적으로 유형을 설정하면 구문 강조가 더 좋아 보인다. 또한 원하는 문자열을 올바르게 이스케이프해야 할 때 잘못된 문자열 문제를 해결하는데 도움이 된다.
Environment
환경 변수가 있는 서버를 프로비저닝 할 때 lininfile이 있는 /etc/evnironment에 추가해라. 설치중인 서비스 또는 어플리케이션과 관련된 허용이 가능한 역할에서 이 작업을 수행해라. 예를 들어 Tomcat 설치의 경우 CATALINA_HOME
환경 변수는 Tomcat 및 관련 웹앱을 포함하는 폴더를 참조하는 데 자주 사용된다.
- name: 'add line CATALINA_HOME to /etc/environment'
lineinfile:
dest: '/etc/environment'
line: 'CATALINA_HOME={{ tomcat_home }}'
state: 'present'
sudo: true
Why?
환경 정의 파일은 일반적으로 공유되므로 템플릿을 사용하여 파일을 보내면 문제가 발생할 수 있다. lininfile에 포함 된 특정 환경 변수를 사용하면 환경 변수에 종속 된 어플리케이션을 쉽게 추적할 수 있다.
Booleans
# bad
- name: 'start sensu-client'
service:
name: 'sensu-client'
state: 'restarted'
enabled: 1
become: 'yes'
# good
- name: 'start sensu-client'
service:
name: 'sensu-client'
state: 'restarted'
enabled: true
become: true
Why?
부울 값을 표현하는 방식은 True/False, true/falswe, yes/no, 1/0 등이 있다. 다양한 표현 방식 중에서 하나를 고수하는 것을 선호 한다. 이것의 주된 이유는 Java와 JavaScript가 부울값에 대해 비슷한 명칭을 가지고 있기 때문이다.
Key value pairs
key: value
를 정의할 때는 하나의 공백만 사용해라
# bad
- name : 'start sensu-client'
service:
name : 'sensu-client'
state : 'restarted'
enabled : true
become : true
# good
- name: 'start sensu-client'
service:
name: 'sensu-client'
state: 'restarted'
enabled: true
become: true
YAML은 인간 친화적인 데이터 직렬화 형식이므로 가독성을 높여주므로, key: value
는 수에 관계없이 항상 개행을 하자.
# bad
- name: 'create checks directory to make it easier to look at checks vs handlers'
file: 'path=/etc/sensu/conf.d/checks state=directory mode=0755 owner=sensu group=sensu'
become: true
- name: 'copy check-memory.json to /etc/sensu/conf.d'
copy: 'dest=/etc/sensu/conf.d/checks/ src=checks/check-memory.json'
become: true
# good
- name: 'create checks directory to make it easier to look at checks vs handlers'
file:
group: 'sensu'
mode: '0755'
owner: 'sensu'
path: '/etc/sensu/conf.d/checks'
state: 'directory'
become: true
- name: 'copy check-memory.json to /etc/sensu/conf.d'
copy:
dest: '/etc/sensu/conf.d/checks/'
src: 'checks/check-memory.json'
become: true
Why?
읽는 것이 쉽고, 버전 관리를 위한 변경 충돌을 줄일 수 있다
Sudo
작업을 sudo
권한으로 실행해야 할때, become 구문을 사용하자
#bad
- name: 'template client.json to /etc/sensu/conf.d/'
template:
dest: '/etc/sensu/conf.d/client.json'
src: 'client.json.j2'
sudo: true
# good
- name: 'template client.json to /etc/sensu/conf.d/'
template:
dest: '/etc/sensu/conf.d/client.json'
src: 'client.json.j2'
become: true
Why?
sudo 사용은 더 이상 사용되지 않는다. Ansible version 1.9.1
Hosts Declaration
host
섹션은 다음과 같은 일반적인 순서를 따라야 한다
# host declaration
# host options in alphabetical order
# pre_tasks
# roles
# tasks
# example
- hosts: 'webservers'
remote_user: 'centos'
vars:
tomcat_state: 'started'
pre_tasks:
- name: 'set the timezone to America/Boise'
lineinfile:
dest: '/etc/environment'
line: 'TZ=America/Boise'
state: 'present'
become: true
roles:
- { role: 'tomcat', tags: 'tomcat' }
tasks:
- name: 'start the tomcat service'
service:
name: 'tomcat'
state: '{{ tomcat_state }}'
Why?
이러한 방법에 대한 적절한 정의는 일관되고 쉽게 읽을 수 있는 코드를 생성한다
Task Declaration
작업은 다음과 같은 일반적인 순서를 따르는 방식으로 정의한다
# task name
# tags
# task map declaration (e.g. service:)
# task parameters in alphabetical order (remember to always use multi-line map syntax)
# loop operators (e.g. with_items)
# task options in alphabetical order (e.g. become, ignore_errors, register)
# example
- name: 'create some ec2 instances'
tags: 'ec2'
ec2:
assign_public_ip: true
image: 'ami-c7d092f7'
instance_tags:
Name: '{{ item }}'
key_name: 'my_key'
with_items: '{{ instance_names }}'
ignore_errors: true
register: ec2_output
when: ansible_os_family == 'Darwin'
Why?
호스트 정의와 유사하게 여기에 잘 정의 된 스타일이 있으면 일관된 코드를 만드는 데 도움이 된다.
Include Declaration
include 문의 경우 파일 이름을 사용하고, include 문의 사이에는 빈줄만 사용해야 한다.(Tag가 있는 경우)
# bad
- include: other_file.yml
- include: 'second_file.yml'
- include: third_file.yml tags=third
# good
- include: 'other_file.yml'
- include: 'second_file.yml'
- include: 'third_file.yml'
tags: 'third'
Why?
이것은 당신의 코드에 문장을 포함시키는 가장 읽기 쉬운 방법이다.
Spacing
두 개의 호스트 블록 사이에 빈 줄이 있어야 한다. 들여쓰기 할 때 2개의 공백을 사용하여 하위 항목을 나타내고 여러 줄은 `-` 로 시작해야 한다. 간격의 대한 예제는 링크를 참조 하자 style.yml
Why?
읽기 쉬운 멋진 코드를 생성한다
Variable Names
playpool에서 snake_case
변수 이름을 사용하자
# bad
- name: 'set some facts'
set_fact:
myBoolean: true
myint: 20
MY_STRING: 'test'
# good
- name: 'set some facts'
set_fact:
my_boolean: true
my_int: 20
my_string: 'test'
Why?
Ansible은 모듈 이름으로 snake_case
를 사용하므로 규칙을 변수 이름으로 확장하는 것이 좋습니다.
snake_case
는 각 요소의 초기 문자가 일반적으로 소문자로 표시되고 첫 번째 문자가 대문자 또는 소문자로 "foo_bar"와 같이 공백이없는 하나의 밑줄 문자로 요소가 분리되는 복합 단어 또는 구문을 작성하는 방법