Ansible-Init is designed to initialize a new project of ansible playbook for best practice.
[TOC]
- Platforms:
- CentOS-7
- CentOS-8
- Fedora
- Dependencies:
- ansible>=2.9, <2.10, !=2.9.10
- git>=1.8.3.1
-
Install dependencies:
yum -y install ansible
yum -y install git
-
Install ansible-init:
git clone https://github.com/zakzhu/ansible-init.git
cd ansible-init
ansible-playbook -e project=<project-name> -e 'author="<full name>"' site.yml
To generate a new project of ansible playbook with ansible-init, simply run:
cd ansible-init
ansible-playbook -e project=my-new-project -e 'author="zak zhu"' site.yml
After have learned ansible documentation about best practices, I want to find a CLI tool that could simply generate a new project of ansible playbook, but nothing have found. So I use ansible to write the ansible-init tool which can initialize a new project of ansible playbook for best practice.
To achieve best practice, the design concept of ansible-init mostly follows two thought below:
- Decouple and Share
- Convention over Configuration
The top level of a new ansible project's directory would contain files and directories like so:
├── ansible.cfg
├── CONTRIBUTING.md
├── docs
├── inventories
│ ├── production
│ │ ├── group_vars
│ │ ├── host_vars
│ │ └── inventory
│ └── staging
│ ├── group_vars
│ ├── host_vars
│ └── inventory
├── LICENSE
├── plugins
│ └── README.md
├── README.md
├── roles
│ ├── common
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ ├── from_common.yml
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ ├── common.yml
│ │ │ └── main.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ └── vars
│ │ └── main.yml
│ ├── post_roles
│ │ └── common
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── handlers
│ │ │ ├── from_common.yml
│ │ │ ├── from_set_local_facts.yml
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ ├── common.yml
│ │ │ ├── main.yml
│ │ │ └── set_local_facts.yml
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ └── vars
│ │ └── main.yml
│ └── pre_roles
│ └── common
│ ├── defaults
│ │ └── main.yml
│ ├── handlers
│ │ ├── from_common.yml
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── README.md
│ ├── tasks
│ │ ├── common.yml
│ │ └── main.yml
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
│ └── main.yml
├── site.yml
├── tests
├── tmp
├── TODO.md
└── utils
The file named site.yml is main playbook of a new project as follows:
---
- name: "{{ playbook_dir | basename }}"
hosts: localhost
remote_user:
gather_facts: yes
vars:
status: "{{ ansible_local[stats_file_name]['status'] | default('0') }}"
force_handlers: no
pre_tasks:
- name: only collect the default minimum amount of facts
setup:
gather_subset:
- "!all"
- when: status == '0'
block:
- import_role:
name: pre_roles/common
tags:
- pr_r_common
- meta: flush_handlers
tasks:
- when: status == '0'
block:
- import_role:
name: common
tags:
- r_common
- meta: flush_handlers
post_tasks:
- when: status == '0'
block:
- import_role:
name: post_roles/common
tags:
- po_r_common
- meta: flush_handlers
For best practice, I specify some conventions in a new project of ansible playbook. And I recommend you follow these conventions.
NOTE:
There is a convention what I specify.
The play name is a fixed writing.
- name: "{{ playbook_dir | basename }}"
├── roles
│ ├── common
│ │
│ ├── bar_role
│ │
│ ├── foo_role
│ │
│ ├── post_roles
│ │ ├── common
│ │ │
│ │ ├── post_bar_role
│ │ │
│ │ └── post_foo_role
│ │
│ ├── pre_roles
│ │ ├── common
│ │ │
│ │ ├── pre_bar_role
│ │ │
│ │ └── pre_foo_role
-
handlers file name
from_<tasks file name>.yml # e.g. from_common.yml
-
decouple handlers file
For example:
cat roles/common/handlers/main.yml
--- # handlers file for common # Below is a code example - import_tasks: from_common.yml
cat roles/common/handlers/from_common.yml
--- # Below is a code example - name: "({{ role_name }}) hello world" debug:
-
always name handlers
Handler name format:
NOTE:
There is a convention what I specify.
({{ role_name }})
is a fixed writing in the head of handler name.- name: "({{ role_name }}) HANDLER NAME"
For example:
- name: "({{ role_name }}) hello world"
-
decouple tasks file
For example:
cat roles/common/tasks/main.yml
--- # tasks file for common - import_tasks: common.yml tags: - r_common_t_common
cat roles/common/tasks/common.yml
--- # Below is a code example - name: <r_common_t_common> test task debug: - name: <r_common_t_common> test trigger handler command: echo notify: "({{ role_name }}) hello world"
-
always name tasks
Task name format:
NOTE:
There is a convention what I specify.
The task name should start with a tag name enclosed in angle brackets (e.g.
-name: <r_common_t_common> test task
).And the tag name in the task name should follow the tag that you apply in the tasks/main.yml file.
- name: <tag name> TASK NAME
For example:
# ansible-playbook --list-tasks site.yml
playbook: site.yml
play #1 (localhost): my-new-project TAGS: []
tasks:
only collect the default minimum amount of facts TAGS: []
pre_roles/common : <pr_r_common_t_common> be failed when the os not supported TAGS: [pr_r_common, pr_r_common_t_common]
pre_roles/common : <pr_r_common_t_common> set start stats TAGS: [pr_r_common, pr_r_common_t_common]
common : <r_common_t_common> test task TAGS: [r_common, r_common_t_common]
common : <r_common_t_common> test trigger handler TAGS: [r_common, r_common_t_common]
post_roles/common : <po_r_common_t_common> set end stats TAGS: [po_r_common, po_r_common_t_common]
post_roles/common : <po_r_common_t_set_local_facts> create /etc/ansible/facts.d/ dir TAGS: [po_r_common, po_r_common_t_set_local_facts]
post_roles/common : <po_r_common_t_set_local_facts> copy custom stats to local facts TAGS: [po_r_common, po_r_common_t_set_local_facts]
-
role tag
NOTE:
There is a convention what I specify.
One role applies one tag at least.
pr_r_common # complete spelling: "pre_roles roles common" # tag meaning: roles/pre_roles/common role r_common # complete spelling: "roles common" # tag meaning: roles/common role po_r_common # complete spelling: "post_roles roles common" # tag meaning: roles/post_roles/common role
-
tasks tag
NOTE:
There is a convention what I specify.
One tasks file applies one tag at least.
pr_r_common_t_common # complete spelling: "pre_roles roles common tasks common" # tag meaning: roles/pre_roles/common/tasks/common.yml tasks file r_common_t_common # complete spelling: "roles common tasks common" # tag meaning: roles/common/tasks/common.yml tasks file po_r_common_t_common # complete spelling: "post_roles roles common tasks common" # tag meaning: roles/post_roles/common/tasks/common.yml tasks file po_r_common_t_set_local_facts # complete spelling: "post_roles roles common tasks set_local_facts" # tag meaning: roles/post_roles/common/tasks/set_local_facts.yml tasks file
See the contribution guide.
Please see FAQ.md for frequently asked questions.
The following excellent people helped massively:
Ansible-Init is licensed under the BSD-3-Clause license. Copyright © 2020, Zak Zhu