├── .gitignore ├── README.md ├── init.yml ├── production ├── project.json └── roles └── init ├── tasks └── main.yml └── templates ├── all.j2 ├── handlers.j2 ├── inventory.j2 ├── master.j2 ├── role.j2 └── tasks.j2 /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs 2 | *~ 3 | 4 | # Editor 5 | .editorconfig 6 | 7 | *.retry 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ansible-init 2 | ========================= 3 | 4 | Ansible playbook for creating ansible playbooks. 5 | 6 | The playbook sets up the common ansible project structure described in the [ansible best practices](http://docs.ansible.com/playbooks_best_practices.html). 7 | 8 | 9 | ## Usage: 10 | 11 | Use either of the methods below to set up a local directory and file structure ready for `ansible-playbook` use. All that's needed is to modify the inventory, then add tasks, handlers, files and templates. 12 | 13 | ansible-playbook \ 14 | init.yml \ 15 | -i production \ 16 | --connection=local \ 17 | --extra-vars='{"roles": ["web", "database"], "project_dir": "/tmp/ansible-project"}' 18 | 19 | or using a JSON file with variables: 20 | 21 | ansible-playbook \ 22 | init.yml \ 23 | -i production \ 24 | --connection=local \ 25 | --extra-vars='@project.json' 26 | 27 | Default project JSON file: 28 | 29 | { 30 | "roles": [ 31 | "web", 32 | "database" 33 | ], 34 | "project_dir": "/tmp/ansible-project" 35 | } 36 | 37 | **roles:** array of roles that should be created 38 | 39 | **project_dir:** the directory in which to create the ansible project 40 | 41 | ## Notes 42 | 43 | The project will be built locally by default. 44 | 45 | To run on a remote server, remove `--connection=local` from the CLI and change the `production` inventory file to specify the destination server. 46 | 47 | In the [ansible best practices](http://docs.ansible.com/playbooks_best_practices.html) the inventory file is called `production`. I chose to follow this convention for the inventory of **ansible-init** itself. If you prefer a different name for the **ansible-init** inventory (like `inventory`), just change the name of the file and run the `ansible-playbook` with `-i inventory` instead. If you prefer different inventory files for your generated project, update the list in the `"Create inventory files"` task in [roles/init/tasks/main.yml](roles/init/tasks/main.yml) 48 | 49 | `roles` is a reserved word: `[WARNING]: Found variable using reserved name: roles`. This variable name will change in future versions, probably a breaking change. 50 | 51 | ## Examples 52 | 53 | ### Project 54 | 55 | /tmp/ansible-project/ 56 | ├── database.yml 57 | ├── group_vars 58 | ├── host_vars 59 | ├── library 60 | ├── master.yml 61 | ├── production 62 | ├── roles 63 | │   ├── database 64 | │   │   ├── defaults 65 | │   │   ├── files 66 | │   │   ├── handlers 67 | │   │   │   └── main.yml 68 | │   │   ├── meta 69 | │   │   ├── tasks 70 | │   │   │   └── main.yml 71 | │   │   ├── templates 72 | │   │   └── vars 73 | │   └── web 74 | │      ├── defaults 75 | │   ├── files 76 | │   ├── handlers 77 | │   │   └── main.yml 78 | │   ├── meta 79 | │   ├── tasks 80 | │   │   └── main.yml 81 | │   ├── templates 82 | │   └── vars 83 | ├── staging 84 | └── web.yml 85 | 86 | ### Files 87 | 88 | #### master.yml 89 | 90 | --- 91 | # master playbook 92 | 93 | - include: web.yml 94 | - include: database.yml 95 | 96 | 97 | #### web.yml 98 | 99 | --- 100 | # web role 101 | 102 | - hosts: web 103 | roles: 104 | - { role: web } 105 | 106 | #### roles/web/tasks/main.yml 107 | 108 | --- 109 | # Tasks for web 110 | 111 | #- name: example 112 | # action: example 113 | # notify: 114 | # - restart service 115 | # tags: 116 | # - example 117 | 118 | #### roles/web/handlers/main.yml 119 | 120 | --- 121 | # Handlers for web 122 | 123 | #- name: example restart 124 | # action: service name=service state=restarted 125 | 126 | 127 | ## CHANGELOG 128 | 129 | ### Version 0.0.1 – April 2, 2014 130 | - Initial release. 131 | ### Version 0.1.0 – May 23, 2017 132 | - Added `library` to main directory and `defaults` to role directories 133 | - Added default `group_vars/all` file 134 | - Fixed YAML syntax to quote strings and use colon separators for attributes 135 | - Fixed unquoted `{{ roles }}` variable in [roles/init/tasks/main.yml](roles/init/tasks/main.yml. This was breaking role creation in newer versions of ansible. 136 | 137 | ## License 138 | 139 | MIT: http://davestern.mit-license.org 140 | -------------------------------------------------------------------------------- /init.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # ansible-init 3 | - hosts: all 4 | roles: 5 | - { role: init } 6 | -------------------------------------------------------------------------------- /production: -------------------------------------------------------------------------------- 1 | localhost 2 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "roles": [ 3 | "web", 4 | "database" 5 | ], 6 | "project_dir": "/tmp/ansible-project" 7 | } 8 | -------------------------------------------------------------------------------- /roles/init/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # init tasks main 3 | 4 | - name: "Create general directories" 5 | file: 6 | path: "{{ project_dir }}/{{ item }}" 7 | state: directory 8 | with_items: 9 | - group_vars 10 | - host_vars 11 | - library 12 | 13 | - name: "Create directory structure for roles" 14 | file: 15 | path: "{{ project_dir }}/roles/{{ item[0] }}/{{ item[1] }}" 16 | state: directory 17 | with_nested: 18 | - "{{ roles }}" 19 | - [ 'defaults', 'files', 'handlers', 'meta', 'tasks', 'templates', 'vars' ] 20 | tags: 21 | - roles 22 | 23 | - name: "Create main.yml in directory structure for roles" 24 | template: 25 | src: "{{ item[1] }}.j2" 26 | dest: "{{ project_dir }}/roles/{{ item[0] }}/{{ item[1] }}/main.yml" 27 | with_nested: 28 | - "{{ roles }}" 29 | - [ 'handlers', 'tasks' ] 30 | tags: 31 | - roles 32 | 33 | - name: "Create group_vars/all" 34 | template: 35 | src: "{{ item }}.j2" 36 | dest: "{{ project_dir }}/group_vars/{{ item }}" 37 | with_items: 38 | - all 39 | tags: 40 | - group_vars 41 | 42 | - name: "Create inventory files" 43 | template: 44 | src: inventory.j2 45 | dest: "{{ project_dir }}/{{ item }}" 46 | with_items: 47 | - production 48 | - staging 49 | tags: 50 | - inventory 51 | 52 | - name: "Create role playbooks" 53 | template: 54 | src: role.j2 55 | dest: "{{ project_dir }}/{{ item }}.yml" 56 | with_items: 57 | - "{{ roles }}" 58 | tags: 59 | - roles 60 | 61 | - name: "Create master playbook" 62 | template: 63 | src: master.j2 64 | dest: "{{ project_dir }}/master.yml" 65 | tags: 66 | - master 67 | 68 | - name: "Register all directories" 69 | find: 70 | paths: "{{ project_dir }}" 71 | file_type: directory 72 | recurse: yes 73 | register: project_dirs 74 | 75 | - name: "Add .gitkeep to all directories" 76 | copy: 77 | dest: "{{ item.path }}/.gitkeep" 78 | content: '' 79 | with_items: 80 | - "{{ project_dirs.files }}" 81 | -------------------------------------------------------------------------------- /roles/init/templates/all.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # file: group_vars/all 3 | -------------------------------------------------------------------------------- /roles/init/templates/handlers.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Handlers for {{ item[0] }} 3 | 4 | #- name: example restart 5 | # action: service name=service state=restarted 6 | -------------------------------------------------------------------------------- /roles/init/templates/inventory.j2: -------------------------------------------------------------------------------- 1 | # {{ item }} inventory 2 | 3 | {% for role in roles %} 4 | [{{ role }}] 5 | # host 6 | 7 | {% endfor %} 8 | -------------------------------------------------------------------------------- /roles/init/templates/master.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # master playbook 3 | 4 | {% for role in roles %} 5 | - include: {{ role }}.yml 6 | {% endfor %} 7 | -------------------------------------------------------------------------------- /roles/init/templates/role.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # {{ item }} role 3 | 4 | - hosts: {{ item }} 5 | roles: 6 | - { role: {{ item }} } 7 | -------------------------------------------------------------------------------- /roles/init/templates/tasks.j2: -------------------------------------------------------------------------------- 1 | --- 2 | # Tasks for {{ item[0] }} 3 | 4 | #- name: example 5 | # action: example 6 | # notify: 7 | # - restart service 8 | # tags: 9 | # - example 10 | --------------------------------------------------------------------------------