Playbook structure

Hi,

after using ansible for quite a while, my project to manage my own
servers has grown to a respectable size. I was a puppet user before, so
I have a single big playbook containing everything. I have the feeling
this is like holding ansible wrong, and I also have the feeling that I
have my playbook structured wrong. Judging from the single "name"
setting, I took the wrong turn in the very beginning. The playbook does
what it is intended to do, however.

Here is an excerpt from my playbook.

Hi,

after using ansible for quite a while, my project to manage my own
servers has grown to a respectable size. I was a puppet user before, so
I have a single big playbook containing everything. I have the feeling
this is like holding ansible wrong, and I also have the feeling that I
have my playbook structured wrong. Judging from the single "name"
setting, I took the wrong turn in the very beginning. The playbook does
what it is intended to do, however.

Here is an excerpt from my playbook.

---
- name: apply common configuration
  hosts: all
  remote_user: zgansible
  become: "yes"

What is the reason for quoting this boolean? It is usually done to force it to be a string, but AFAIK this parameter requires a boolean.

  tasks:
  ⦙ - name: install ansible dependencies
  ⦙ ⦙ apt:
  ⦙ ⦙ ⦙ name: ['python3', 'python3-apt']
  ⦙ ⦙ ⦙ state: present
  ⦙ - name: get package facts
  ⦙ ⦙ package_facts:
  ⦙ ⦙ ⦙ manager: "auto"
  ⦙ ⦙ tags: always
  ⦙ - name: print facts
  ⦙ ⦙ debug:
  ⦙ ⦙ ⦙ var: ansible_facts
  ⦙ ⦙ tags: [never, debug, printfacts]
  ⦙ - name: print package facts
  ⦙ ⦙ debug:
  ⦙ ⦙ ⦙ var: ansible_facts.packages
  ⦙ ⦙ tags: [never, debug, printpackagefacts]
  ⦙ - include_role:
  ⦙ ⦙ ⦙ name: clean-motd
  ⦙ ⦙ ⦙ apply:
  ⦙ ⦙ ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ ⦙ ⦙ - clean-motd
  ⦙ ⦙ ⦙ ⦙ ⦙ - clean-all
  ⦙ ⦙ ⦙ ⦙ ⦙ - never
  ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ - clean-motd
  ⦙ ⦙ ⦙ - clean-all
  ⦙ ⦙ ⦙ - never
  ⦙ - include_role:
  ⦙ ⦙ ⦙ name: sysctl
  ⦙ ⦙ ⦙ apply:
  ⦙ ⦙ ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ ⦙ ⦙ - sysctl
  ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ - sysctl
(LOTS of other include_role stanzas defining roles that are on all machines)

- name: apply configuration for bind9 servers
  hosts:
  ⦙ - alemana
  ⦙ - cadencia
  ⦙ - gancho
  ⦙ - impetus
  ⦙ - lasso
  ⦙ - torres
  ⦙ - dns1
  remote_user: zgansible
  become: "yes"
  vars:
  ⦙ bind_role: "{{ (bind|default({}))|combine(bind_group|default({}), recursive=true, list_merge='append') }}"
  tasks:
  ⦙ - include_role:
  ⦙ ⦙ ⦙ name: bind9
  ⦙ ⦙ ⦙ apply:
  ⦙ ⦙ ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ ⦙ ⦙ - bind9
  ⦙ ⦙ tags:
  ⦙ ⦙ ⦙ - bind9
> - name: apply configuration for DHCP servers
    hosts:
   ⦙ - chasse
   ⦙ - cadencia
   remote_user: zgansible
   become: "yes"
   tasks:
   ⦙ - include_role:
   ⦙ ⦙ ⦙ name: isc-dhcp-server
   ⦙ ⦙ ⦙ apply:
   ⦙ ⦙ ⦙ ⦙ tags:
   ⦙ ⦙ ⦙ ⦙ ⦙ - isc-dhcp-server
   ⦙ ⦙ tags:
   ⦙ ⦙ ⦙ - isc-dhcp-server

Is this the way to do it? Any comments will be appreciated.

I don't see anything totally wrong with the above approach.
Perhaps try to avoid the inline lists but that's cosmetics.

In the other news, where would I correctly place (and activate) this handler:

---
- name: apt update
   command: "apt-get update"

if I intend to notify this handler from any role that might use the apt
provider to install packages?

What is the use case for this?
If you want to make sure this is always run prior to any package task, then you should use the update_cache parameters of the apt module:

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html#parameter-update_cache

Dick

Hi Dirk,

> after using ansible for quite a while, my project to manage my own
> servers has grown to a respectable size. I was a puppet user before, so
> I have a single big playbook containing everything. I have the feeling
> this is like holding ansible wrong, and I also have the feeling that I
> have my playbook structured wrong. Judging from the single "name"
> setting, I took the wrong turn in the very beginning. The playbook does
> what it is intended to do, however.
>
> Here is an excerpt from my playbook.
>
> ---
> - name: apply common configuration
> hosts: all
> remote_user: zgansible
> become: "yes"

What is the reason for quoting this boolean? It is usually done to force it
to be a string, but AFAIK this parameter requires a boolean.

Historical reasons, fixed. I probably didnt know any better, and it's
still a matter of try-and-err whether to find out whether ansible
wants/insists on things being quoted or not.

[snip]

I don't see anything totally wrong with the above approach.
Perhaps try to avoid the inline lists but that's cosmetics.

How would I write them any better?

> In the other news, where would I correctly place (and activate) this handler:
>
> ---
> - name: apt update
> command: "apt-get update"
>
> if I intend to notify this handler from any role that might use the apt
> provider to install packages?

What is the use case for this?
If you want to make sure this is always run prior to any package task, then
you should use the update_cache parameters of the apt module:

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html#parameter-update_cache

updating the package lists after fiddling with things in /etc/apt, for
example preparing a release upgrade or adding an external repository
(docker *cough*). Doing an apt update right before any check whether any
required package is already installed seems overkill, but I need to
ponder about that.

Greetings
Marc

Hi,

after using ansible for quite a while, my project to manage my own
servers has grown to a respectable size. I was a puppet user before, so
I have a single big playbook containing everything. I have the feeling
this is like holding ansible wrong, and I also have the feeling that I
have my playbook structured wrong. Judging from the single "name"
setting, I took the wrong turn in the very beginning. The playbook does
what it is intended to do, however.

My two cents:

- host name / remote user should be in the inventory and not in the playbook
- consider using import_role instead of include_role

Regards
        Racke

Hi Dirk,

after using ansible for quite a while, my project to manage my own
servers has grown to a respectable size. I was a puppet user before, so
I have a single big playbook containing everything. I have the feeling
this is like holding ansible wrong, and I also have the feeling that I
have my playbook structured wrong. Judging from the single "name"
setting, I took the wrong turn in the very beginning. The playbook does
what it is intended to do, however.

Here is an excerpt from my playbook.

---
- name: apply common configuration
   hosts: all
   remote_user: zgansible
   become: "yes"

What is the reason for quoting this boolean? It is usually done to force it
to be a string, but AFAIK this parameter requires a boolean.

Historical reasons, fixed. I probably didnt know any better, and it's
still a matter of try-and-err whether to find out whether ansible
wants/insists on things being quoted or not.

[snip]

I don't see anything totally wrong with the above approach.
Perhaps try to avoid the inline lists but that's cosmetics.

How would I write them any better?

In the other news, where would I correctly place (and activate) this handler:

---
- name: apt update
    command: "apt-get update"

if I intend to notify this handler from any role that might use the apt
provider to install packages?

What is the use case for this?
If you want to make sure this is always run prior to any package task, then
you should use the update_cache parameters of the apt module:

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_module.html#parameter-update_cache

updating the package lists after fiddling with things in /etc/apt, for
example preparing a release upgrade or adding an external repository
(docker *cough*). Doing an apt update right before any check whether any
required package is already installed seems overkill, but I need to
ponder about that.

You can add/modify/delete the external repo with Ansible and run the apt update only when the repo changed.

The equivalent for "apt-get update" is:

     - name: Update APT cache
       apt:
         update_cache: yes

Regards
        Racke

stylistic nit pick

tasks:
⦙ - name: install ansible dependencies
⦙ ⦙ apt:
⦙ ⦙ ⦙ name: ['python3', 'python3-apt']
⦙ ⦙ ⦙ state: present

   - name: install ansible dependencies
     apt:
     name:
      - python3
      - python3-apt
    state: present

Fair enough, thanks. Those hints are the most important.

Greetings
Marc

It's gotten a bit strange out there. I'd encourage you to focus your
installation on "ansible-core", which contains the relevant python
modules and executable scripts, and entirely ignore the upstream
"ansible" package unless you have a compelling need for 100 third
party modules in a semi-organized and monolithic bundle taking up
roughly half a Gig of local disk space. It's not really useful for
most ansible server setups.