Tasks

main.yml

Synopsis: Main task.

Import tasks if enabled.

[tasks/main.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
---
# tasks for config_light

- name: Import setup.yml
  ansible.builtin.import_tasks: setup.yml
  when: cl_setup|bool
  delegate_to: localhost
  run_once: true
  tags: [cl_setup, always]

- name: Import vars.yml
  ansible.builtin.import_tasks: vars.yml
  tags: [cl_vars, always]

- name: Import sanity.yml
  ansible.builtin.import_tasks: sanity.yml
  when: cl_sanity|bool
  tags: [cl_sanity, always]

- name: Import debug.yml
  ansible.builtin.import_tasks: debug.yml
  when: cl_debug|bool
  tags: cl_debug

- name: Import packages.yml
  ansible.builtin.import_tasks: packages.yml
  when: cl_install|bool
  tags: cl_packages

- name: Import states.yml
  ansible.builtin.import_tasks: states.yml
  tags: cl_states

- name: Import files.yml
  ansible.builtin.import_tasks: files.yml
  tags: cl_files

- name: Import services.yml
  ansible.builtin.import_tasks: services.yml
  tags: cl_services

# EOF
...

setup.yml

Synopsis: Configure setup.

Description of the task.

[tasks/setup.yml]

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
---

- name: "setup: Debug"
  vars:
    msg: |-
      cl_dird [{{ cl_dird }}]
      cl_dird_owner [{{ cl_dira_owner|default('UNDEFINED') }}]
      cl_dird_group [{{ cl_dira_group|default('UNDEFINED') }}]
      cl_dird_dmode [{{ cl_dira_dmode }}]
      cl_handlersd_dir [{{ cl_handlersd_dir }}]
      cl_packagesd_dir [{{ cl_packagesd_dir }}]
      cl_servicesd_dir [{{ cl_servicesd_dir }}]
      cl_filesd_dir [{{ cl_filesd_dir }}]
      cl_statesd_dir [{{ cl_statesd_dir }}]
      cl_dira [{{ cl_dira }}]
      cl_dira_owner [{{ cl_dira_owner|default('UNDEFINED') }}]
      cl_dira_group [{{ cl_dira_group|default('UNDEFINED') }}]
      cl_dira_dmode [{{ cl_dira_dmode }}]
      cl_dira_fmode [{{ cl_dira_fmode }}]
      cl_assemble_regexp [{{ cl_assemble_regexp }}]
      cl_handlersd [{{ cl_handlersd }}]
      cl_packagesd [{{ cl_packagesd }}]
      cl_servicesd [{{ cl_servicesd }}]
      cl_filesd [{{ cl_filesd }}]
      cl_statesd [{{ cl_statesd }}]
      cl_handlers_clean_all [{{ cl_handlers_clean_all }}]
      cl_handlers_create [{{ cl_handlers_create }}]
      cl_handlers_delete [{{ cl_handlers_delete }}]
      cl_handlers_dir_become [{{ cl_handlers_dir_become }}]
      cl_handlers_dir_owner [{{ cl_handlers_dir_owner|default('UNDEFINED') }}]
      cl_handlers_dir_group [{{ cl_handlers_dir_group|default('UNDEFINED') }}]
      cl_handlers_dir_dmode [{{ cl_handlers_dir_dmode|default('UNDEFINED') }}]
      cl_handlers_main_mode [{{ cl_handlers_main_mode|default('UNDEFINED') }}]
  ansible.builtin.debug:
    msg: "{{ '{}'.format(msg) }}"
  when: cl_debug|bool

# directories
- name: "setup: Create directories in {{ cl_dird }}"
  ansible.builtin.file:
    state: directory
    path: "{{ item }}"
    owner: "{{ cl_dird_owner|default(omit) }}"
    group: "{{ cl_dird_group|default(omit) }}"
    mode: "{{ cl_dird_dmode }}"
  loop:
    - "{{ cl_dird }}"
    - "{{ cl_handlersd_dir }}"
    - "{{ cl_packagesd_dir }}"
    - "{{ cl_servicesd_dir }}"
    - "{{ cl_filesd_dir }}"
    - "{{ cl_statesd_dir }}"

- name: "setup: Create directory {{ cl_dira }}"
  ansible.builtin.file:
    state: directory
    path: "{{ cl_dira }}"
    owner: "{{ cl_dira_owner|default(omit) }}"
    group: "{{ cl_dira_group|default(omit) }}"
    mode: "{{ cl_dira_dmode }}"

# handlers
- name: "setup: Create dir {{ role_path }}/handlers"
  become: "{{ cl_handlers_dir_become }}"
  ansible.builtin.file:
    state: directory
    path: "{{ role_path }}/handlers"
    owner: "{{ cl_handlers_dir_owner|default(omit) }}"
    group: "{{ cl_handlers_dir_group|default(omit) }}"
    mode: "{{ cl_handlers_dir_dmode|default(omit) }}"

- name: "setup: Create handlers/main.yml"
  ansible.builtin.lineinfile:
    path: "{{ role_path }}/handlers/main.yml"
    insertbefore: BOF
    line: "---"
    validate: "{{ cl_handlers_validate|default(omit) }}"
    backup: "{{ cl_backup }}"
    create: true
    mode: "{{ cl_handlers_main_mode|default(omit) }}"

- name: "setup: Assemble handlers"
  ansible.builtin.import_tasks: vars-handlers.yml

- name: "setup: Delete all handlers"
  block:
    - name: "setup: Find all handlers"
      ansible.builtin.find:
        path: "{{ role_path }}/handlers"
        patterns: handlers-auto-*.yml
      register: result
    - name: "setup: Debug result"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
    - name: "setup: Delete all handlers"
      ansible.builtin.file:
        state: absent
        path: "{{ item.path }}"
      loop: "{{ result.files }}"
      loop_control:
        label: "{{ item.path|basename }}"
    - name: "setup: Exclude all found handlers from handlers/main.yml"
      ansible.builtin.lineinfile:
        state: absent
        path: "{{ role_path }}/handlers/main.yml"
        line: "- import_tasks: {{ item.path|basename }}"
        backup: "{{ cl_backup }}"
      loop: "{{ result.files }}"
      loop_control:
        label: "{{ item.path|basename }}"
  when: cl_handlers_clean_all|bool

- name: "setup: Delete handlers listed in cl_handlers"
  block:
    - name: "setup: Delete handlers listed in cl_handlers"
      ansible.builtin.file:
        state: absent
        path: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
      loop: "{{ cl_handlers|dict2items }}"
      loop_control:
        label: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
    - name: "setup: Exclude handlers from handlers/main.yml"
      ansible.builtin.lineinfile:
        state: absent
        path: "{{ role_path }}/handlers/main.yml"
        line: "- import_tasks: handlers-auto-{{ item.key }}.yml"
        backup: "{{ cl_backup }}"
      loop: "{{ cl_handlers|dict2items }}"
      loop_control:
        label: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
  when: cl_handlers_delete|bool

- name: "setup: Create handlers listed in cl_handlers"
  block:
    - name: "setup: Create handlers listed in cl_handlers"
      ansible.builtin.template:
        dest: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
        src: "{{ item.value.template }}"
        mode: "{{ item.value.mode|default(omit) }}"
        validate: "{{ cl_handlers_validate|default(omit) }}"
        backup: "{{ cl_backup }}"
      loop: "{{ cl_handlers|dict2items }}"
      loop_control:
        label: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
    - name: "setup: Include handlers in handlers/main.yml"
      ansible.builtin.lineinfile:
        path: "{{ role_path }}/handlers/main.yml"
        line: "- import_tasks: handlers-auto-{{ item.key }}.yml"
        validate: "{{ cl_handlers_validate|default(omit) }}"
        backup: "{{ cl_backup }}"
      loop: "{{ cl_handlers|dict2items }}"
      loop_control:
        label: "{{ role_path }}/handlers/handlers-auto-{{ item.key }}.yml"
  when: cl_handlers_create|bool

# EOF
...

vars-handlers.yml

Synopsis: Configure vars-handlers.

Description of the task.

[tasks/vars-handlers.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
---

- block:
    - name: "vars-handlers: Assemble handlers to {{ cl_handlersd }}"
      ansible.builtin.assemble:
        regexp: "{{ cl_assemble_regexp }}"
        src: "{{ cl_handlersd_dir }}"
        dest: "{{ cl_handlersd }}"
        owner: "{{ cl_dira_owner|default(omit) }}"
        group: "{{ cl_dira_group|default(omit) }}"
        mode: "{{ cl_dira_fmode }}"
        validate: "{{ cl_assemble_validate|default(omit) }}"
  rescue:
    - name: "vars-handlers: Assemble handlers to {{ cl_handlersd }} failed"
      ansible.builtin.debug:
        msg: |-
          Can not assemble handlers. End of play.
          {{ ansible_failed_result }}
    - name: "vars-handlers: End of play"
      meta: end_play

- name: "vars-handlers: Include files from {{ cl_handlersd }} to cl_handlersd_items"
  ansible.builtin.include_vars:
    file: "{{ cl_handlersd }}"
    name: cl_handlersd_items

- name: "vars-handlers: Combine cl_handlers with cl_handlersd_items"
  ansible.builtin.set_fact:
    cl_handlers: "{{ cl_handlers|combine(cl_handlersd_items|default({})) }}"

- name: "vars-handlers: Debug"
  ansible.builtin.debug:
    var: cl_handlers
  when: cl_debug|bool

# EOF
...

vars.yml

Synopsis: Configure vars.

Description of the task.

[tasks/vars.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
---

- name: "vars: Debug"
  vars:
    msg: |-
      cl_handlersd_dir [{{ cl_handlersd_dir }}]
      cl_packagesd_dir [{{ cl_packagesd_dir }}]
      cl_statesd_dir [{{ cl_statesd_dir }}]
      cl_servicesd_dir [{{ cl_servicesd_dir }}]
      cl_filesd_dir [{{ cl_filesd_dir }}]
      cl_dira [{{ cl_dira }}]
      cl_handlersd [{{ cl_handlersd }}]
      cl_packagesd [{{ cl_packagesd }}]
      cl_statesd [{{ cl_statesd }}]
      cl_servicesd [{{ cl_servicesd }}]
      cl_filesd [{{ cl_filesd }}]
  ansible.builtin.debug:
    msg: "{{ '{}'.format(msg) }}"
  when: cl_debug|bool

- name: "vars: Packages"
  ansible.builtin.import_tasks: vars-packages.yml

- name: "vars: States"
  ansible.builtin.import_tasks: vars-states.yml

- name: "vars: Services"
  ansible.builtin.import_tasks: vars-services.yml

- name: "vars: Files"
  ansible.builtin.import_tasks: vars-files.yml

# EOF
...

vars-packages.yml

Synopsis: Configure vars-packages.

Description of the task.

[tasks/vars-packages.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
---

- block:
    - name: "vars-packages: Assemble packages to {{ cl_packagesd }}"
      ansible.builtin.assemble:
        regexp: "{{ cl_assemble_regexp }}"
        src: "{{ cl_packagesd_dir }}"
        dest: "{{ cl_packagesd }}"
        owner: "{{ cl_dira_owner|default(omit) }}"
        group: "{{ cl_dira_group|default(omit) }}"
        mode: "{{ cl_dira_fmode }}"
        validate: "{{ cl_assemble_validate|default(omit) }}"
      delegate_to: localhost
  rescue:
    - name: "vars-packages: Assemble packages to {{ cl_packagesd }} failed"
      ansible.builtin.debug:
        msg: |-
          Can not assemble packages. End of play.
          {{ ansible_failed_result }}
    - name: "vars-packages: End of play"
      meta: end_play

- name: "vars-packages: Include files from {{ cl_packagesd }} to cl_packagesd_items"
  ansible.builtin.include_vars:
    file: "{{ cl_packagesd }}"
    name: cl_packagesd_items

- name: "vars-packages: Combine cl_packages with cl_packagesd_items"
  ansible.builtin.set_fact:
    cl_packages: "{{ cl_packages|combine(cl_packagesd_items|default({})) }}"

- name: "vars-packages: Debug"
  ansible.builtin.debug:
    var: cl_packages
  when: cl_debug|bool

# TODO: sort|unique list of packages/ports

# EOF
...

vars-states.yml

Synopsis: Configure vars-states.

Description of the task.

[tasks/vars-states.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
---

- block:
    - name: "vars-states: Assemble states to {{ cl_states }}"
      ansible.builtin.assemble:
        regexp: "{{ cl_assemble_regexp }}"
        src: "{{ cl_statesd_dir }}"
        dest: "{{ cl_statesd }}"
        owner: "{{ cl_dira_owner|default(omit) }}"
        group: "{{ cl_dira_group|default(omit) }}"
        mode: "{{ cl_dira_fmode }}"
        validate: "{{ cl_assemble_validate|default(omit) }}"
      delegate_to: localhost
  rescue:
    - name: "vars-states: Assemble states to {{ cl_states }} failed"
      ansible.builtin.debug:
        msg: |-
          Can not assemble states. End of play.
          {{ ansible_failed_result }}
    - name: "vars-states: End of play"
      meta: end_play

- name: "vars-states: Include files from {{ cl_statesd }} to cl_statessd_items"
  ansible.builtin.include_vars:
    file: "{{ cl_statesd }}"
    name: cl_statesd_items

- name: "vars-states: Combine cl_statess with cl_statesd_items"
  ansible.builtin.set_fact:
    cl_states: "{{ cl_states|combine(cl_statesd_items|default({})) }}"

- name: "vars-states: Debug"
  ansible.builtin.debug:
    var: cl_states
  when: cl_debug|bool

# EOF
...

vars-services.yml

Synopsis: Configure vars-services.

Description of the task.

[tasks/vars-services.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
---

- block:
    - name: "vars-services: Assemble services to {{ cl_servicesd }}"
      ansible.builtin.assemble:
        regexp: "{{ cl_assemble_regexp }}"
        src: "{{ cl_servicesd_dir }}"
        dest: "{{ cl_servicesd }}"
        owner: "{{ cl_dira_owner|default(omit) }}"
        group: "{{ cl_dira_group|default(omit) }}"
        mode: "{{ cl_dira_fmode }}"
        validate: "{{ cl_assemble_validate|default(omit) }}"
      delegate_to: localhost
  rescue:
    - name: "vars-services: Assemble services to {{ cl_servicesd }} failed"
      ansible.builtin.debug:
        msg: |-
          Can not assemble services. End of play.
          {{ ansible_failed_result }}
    - name: "vars-services: End of play"
      meta: end_play

- name: "vars-services: Include files from {{ cl_servicesd }} to cl_cervicesd_items"
  ansible.builtin.include_vars:
    file: "{{ cl_servicesd }}"
    name: cl_servicesd_items

- name: "vars-services: Combine cl_services with cl_servicesd_items"
  ansible.builtin.set_fact:
    cl_services: "{{ cl_services|combine(cl_servicesd_items|default({})) }}"

- name: "vars-services: Debug"
  ansible.builtin.debug:
    var: cl_services
  when: cl_debug|bool

# EOF
...

vars-files.yml

Synopsis: Configure vars-files.

Description of the task.

[tasks/vars-files.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
---

- block:
    - name: "vars-files: Assemble files to {{ cl_filesd }}"
      ansible.builtin.assemble:
        regexp: "{{ cl_assemble_regexp }}"
        src: "{{ cl_filesd_dir }}"
        dest: "{{ cl_filesd }}"
        owner: "{{ cl_dira_owner|default(omit) }}"
        group: "{{ cl_dira_group|default(omit) }}"
        mode: "{{ cl_dira_fmode }}"
        validate: "{{ cl_assemble_validate|default(omit) }}"
      delegate_to: localhost
  rescue:
    - name: "vars-files: Assemble files to {{ cl_filesd }} failed"
      ansible.builtin.debug:
        msg: |-
          Can not assemble files. End of play.
          {{ ansible_failed_result }}
    - name: "vars-files: End of play"
      meta: end_play

- name: "vars-files: Include files from {{ cl_filesd }} to cl_filesd_items"
  ansible.builtin.include_vars:
    file: "{{ cl_filesd }}"
    name: cl_filesd_items

- name: "vars-files: Combine cl_files with cl_filesd_items"
  ansible.builtin.set_fact:
    cl_files: "{{ cl_files|combine(cl_filesd_items|default({})) }}"

- name: "vars-files: Debug"
  ansible.builtin.debug:
    var: cl_files
  when: cl_debug|bool

# EOF
...

sanity.yml

Synopsis: Configure sanity.

Description of the task.

[tasks/sanity.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
---

- block:
    - name: "sanity: Directories to assemble data from must exist"
      ansible.builtin.debug:
        msg: "{{ '{}'.format(msg) }}"
      vars:
        msg: |-
          Directories to assemble data from do not exist. End of play.
          Hint: Double check existence of the directories
          {{ cl_handlersd_dir }}
          {{ cl_packagesd_dir }}
          {{ cl_statesd_dir }}
          {{ cl_servicesd_dir }}
          {{ cl_filesd_dir }}
    - name: "sanity: End of play"
      meta: end_play
  when:
    - cl_handlersd_dir is not exists or
      cl_packagesd_dir is not exists or
      cl_statesd_dir is not exists or
      cl_servicesd_dir is not exists or
      cl_filesd_dir is not exists

- block:
    - name: "sanity: Check mode not possible without assembled data"
      ansible.builtin.debug:
        msg: "{{ '{}'.format(msg) }}"
      vars:
        msg: |-
          Check mode not possible without assembled data. End of play.
          Hint: Assemble the variables first.
          Run: ansible-playbook playbook.yml -t cl_vars
    - name: "sanity: End of play"
      ansible.builtin.meta: end_play
  when:
    - ansible_check_mode
    - cl_packagesd is not exists or
      cl_statesd is not exists or
      cl_servicesd is not exists or
      cl_filesd is not exists

- block:
    - name: "sanity: yamllint must be installed"
      ansible.builtin.assert:
        that: _out is match(_regex)
        fail_msg: |-
          Failed. yamllint not installed on controller.
        success_msg: |-
          Passed. yamllint found on controller.
      vars:
        _regex: '^yamllint \d+\.\d+\.\d+$'
        _out: "{{ lookup('pipe', cl_yamllint ~ ' --version') }}"
  rescue:
    - name: "sanity: Rescue: yamllint must be installed"
      ansible.builtin.debug:
        msg: "{{ '{}'.format(msg) }}"
      vars:
        msg: |-
          Failed. yamllint must be installed on controller. {{ cl_yamllint }} does not exist. End of play.
    - name: "sanity: Rescue: End of play"
      ansible.builtin.meta: end_play
  when: cl_yamllint_missing_fatal|bool

# EOF
...

debug.yml

Synopsis: Configure debug.

Description of the task.

[tasks/debug.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
---

- name: "debug: Config Light"
  vars:
    msg: |-
      ansible_os_family [{{ ansible_os_family }}]
      ansible_distribution [{{ ansible_distribution }}]
      ansible_distribution_major_version [{{ ansible_distribution_major_version }}]
      ansible_distribution_version [{{ ansible_distribution_version }}]
      ansible_distribution_release [{{ ansible_distribution_release }}]
      ansible_python_version [{{ ansible_python_version }}]

      cl_sanity [{{ cl_sanity }}]
      cl_setup [{{ cl_setup }}]
      cl_install [{{ cl_install }}]
      cl_backup [{{ cl_backup }}]
      cl_copyfile_delete [{{ cl_copyfile_delete }}]
      cl_template_delete [{{ cl_template_delete }}]

      cl_handlers_clean_all [{{ cl_handlers_clean_all }}]
      cl_handlers_delete [{{ cl_handlers_delete }}]
      cl_handlers_create [{{ cl_handlers_create }}]
      cl_handlers
      {{ cl_handlers|to_nice_yaml }}
      cl_packages
      {{ cl_packages|to_nice_yaml }}
      cl_services
      {{ cl_services|to_nice_yaml }}
      cl_files
      {{ cl_files|to_nice_yaml }}
      cl_states
      {{ cl_states|to_nice_yaml }}

      cl_dird [{{ cl_dird }}]
      cl_dird_owner [{{ cl_dira_owner|default('UNDEFINED') }}]
      cl_dird_group [{{ cl_dira_group|default('UNDEFINED') }}]
      cl_dird_dmode [{{ cl_dira_dmode }}]

      cl_handlersd_dir [{{ cl_handlersd_dir }}]
      cl_packagesd_dir [{{ cl_packagesd_dir }}]
      cl_servicesd_dir [{{ cl_servicesd_dir }}]
      cl_filesd_dir [{{ cl_filesd_dir }}]
      cl_statesd_dir [{{ cl_statesd_dir }}]

      cl_dira [{{ cl_dira }}]
      cl_dira_owner [{{ cl_dira_owner|default('UNDEFINED') }}]
      cl_dira_group [{{ cl_dira_group|default('UNDEFINED') }}]
      cl_dira_dmode [{{ cl_dira_dmode }}]
      cl_dira_fmode [{{ cl_dira_fmode }}]
      cl_assemble_regexp [{{ cl_assemble_regexp }}]

      cl_handlersd [{{ cl_handlersd }}]
      cl_packagesd [{{ cl_packagesd }}]
      cl_servicesd [{{ cl_servicesd }}]
      cl_filesd [{{ cl_filesd }}]
      cl_statesd [{{ cl_statesd }}]

      cl_yamllint_missing_fatal [{{ cl_yamllint_missing_fatal }}]
      cl_yamllint [{{ cl_yamllint }}]
      cl_assemble_validate [{{ cl_assemble_validate|default('UNDEFINED') }}]
      cl_handlers_validate [{{ cl_handlers_validate|default('UNDEFINED') }}]

      cl_files_order
      {{ cl_files_order|to_yaml }}

      install_retries [{{ install_retries }}]
      install_delay [{{ install_delay }}]

      freebsd_install_method [{{ freebsd_install_method }}]
      freebsd_use_packages [{{ freebsd_use_packages }}]
      cl_services_freebsd_rcconf_auto [{{ cl_services_freebsd_rcconf_auto }}]

  ansible.builtin.debug:
    msg: "{{ '{}'.format(msg) }}"

# EOF
...

packages.yml

Synopsis: Configure packages.

Description of the task.

[tasks/packages.yml]

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
---

- name: "packages: Debug"
  ansible.builtin.debug:
    msg: "{{ cl_packages.values()|list }}"
  when: cl_debug|bool

# FreeBSD packages - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Manage FreeBSD packages"
      community.general.pkgng:
        name: "{{ item.name }}"  # list / elements=string / required
        state: "{{ item.state|default(omit) }}"
        annotation: "{{ item.annotation|default(omit) }}"
        autoremove: "{{ freebsd_pkgng_autoremove|default(omit) }}"
        cached: "{{ freebsd_pkgng_cached|default(omit) }}"
        chroot: "{{ freebsd_pkgng_chroot|default(omit) }}"
        ignore_osver: "{{ freebsd_pkgng_ignore_osver|default(omit) }}"
        jail: "{{ freebsd_pkgng_jail|default(omit) }}"
        pkgsite: "{{ freebsd_pkgng_pkgsite|default(omit) }}"
        rootdir: "{{ freebsd_pkgng_rootdir|default(omit) }}"
      loop: "{{ cl_packages.values()|list }}"
      loop_control:
        label: "{{ item.name }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
    - name: "packages: Debug FreeBSD packages"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  when:
    - ansible_os_family == "FreeBSD"
    - freebsd_install_method|lower == "packages"

# FreeBSD ports - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Manage FreeBSD ports"
      community.general.portinstall:
        name: "{{ item.1 }}"  # string / required
        state: "{{ item.0.state|default(omit) }}"
        use_packages: "{{ item.0.use_packages|default(freebsd_use_packages) }}"
      with_subelements:
        - "{{ cl_packages.values()|list }}"
        - name
      loop_control:
        label: "{{ item.1 }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
    - name: "packages: Debug FreeBSD ports"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  when:
    - ansible_os_family == "FreeBSD"
    - freebsd_install_method|lower == "ports"

# Linux snap - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Find snap"
      ansible.builtin.find:
        paths: "{{ cl_snap_paths }}"
        patterns: "{{ cl_snap_patterns }}"
      register: _find_snap
    - name: "packages: Debug find snap"
      ansible.builtin.debug:
        var: _find_snap
      when: cl_debug|bool
    - name: "packages: Fail if snap is missing"
      ansible.builtin.fail:
        msg: "[ERROR] snap not installed."
      when: _find_snap.matched == 0
  vars:
    _cl_packages_snap: "{{ cl_packages.values()|list|json_query('[?module == `snap`]') }}"
  when:
    - _cl_packages_snap|length > 0
    - ansible_os_family == "RedHat" or
      ansible_os_family == "Debian"
- block:
    - name: "packages: Manage Linux packages by snap module"
      community.general.snap:
        name: "{{ item.name }}"  #  list / elements=string
        state: "{{ item.state|default(omit) }}"
      loop: "{{ _cl_packages_snap }}"
      loop_control:
        label: "{{ item.name }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
      when: item.module|default('package') == 'snap'
    - name: "packages: Debug Linux snap"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  vars:
    _cl_packages_snap: "{{ cl_packages.values()|list|json_query('[?module == `snap`]') }}"
  when:
    - _cl_packages_snap|length > 0
    - ansible_os_family == "RedHat" or
      ansible_os_family == "Debian"

# Linux package - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Manage Linux packages by package module"
      ansible.builtin.package:
        name: "{{ item.1 }}"  # string / required
        state: "{{ item.0.state|default('present') }}"
        use: "{{ item.0.use|default('auto') }}"
      with_subelements:
        - "{{ cl_packages.values()|list }}"
        - name
      loop_control:
        label: "{{ item.1 }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
      when: item.0.module|default('package') == 'package'
    - name: "packages: Debug Linux package"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  when: ansible_os_family == "RedHat" or
        ansible_os_family == "Debian"

# Linux yum - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Manage Linux packages by yum module"
      ansible.builtin.yum:
        name: "{{ item.name }}"  #  list / elements=string
        state: "{{ item.state|default(omit) }}"
        use_backend: "{{ item.use|default(omit) }}"
      loop: "{{ cl_packages.values()|list }}"
      loop_control:
        label: "{{ item.name }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
      when: item.module|default('package') == 'yum'
    - name: "packages: Debug Linux yum"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  when: ansible_os_family == "RedHat" or
        ansible_os_family == "Debian"

# Linux apt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- block:
    - name: "packages: Manage Linux packages by apt module"
      ansible.builtin.apt:
        name: "{{ item.name }}"  #  list / elements=string
        state: "{{ item.state|default(omit) }}"
        purge: "{{ item.purge|default(omit) }}"
      loop: "{{ cl_packages.values()|list }}"
      loop_control:
        label: "{{ item.name }}"
      register: result
      until: result is succeeded
      retries: "{{ install_retries }}"
      delay: "{{ install_delay }}"
      when: item.module|default('package') == 'apt'
    - name: "packages: Debug Linux apt"
      ansible.builtin.debug:
        var: result
      when: cl_debug|bool
  when: ansible_os_family == "RedHat" or
        ansible_os_family == "Debian"

# TODO: Complete parameters of modules

# EOF
...

states.yml

Synopsis: Configure states.

Description of the task.

[tasks/states.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
---

- name: "states: Debug"
  ansible.builtin.debug:
    msg: "{{ cl_states }}"
  when: cl_debug|bool

- name: "states: Apply unmount states"
  ansible.posix.mount:
    path: "{{ item.value.path }}"
    state: "{{ item.value.state|default('absent') }}"
    backup: "{{ item.value.backup|default(omit) }}"
    boot: "{{ item.value.boot|default(omit) }}"
    dump: "{{ item.value.dump|default(omit) }}"
    fstab: "{{ item.value.fstab|default(omit) }}"
    opts: "{{ item.value.opts|default(omit) }}"
    passno: "{{ item.value.passno|default(omit) }}"
    src: "{{ item.value.src|default(omit) }}"
  loop: "{{ cl_states|dict2items }}"
  loop_control:
    label: "{{ item.value.path }}"
  when: item.value.state|default('absent') in cl_states_unmount

- name: "states: Apply file states"
  ansible.builtin.file:
    path: "{{ item.value.path }}"
    state: "{{ item.value.state|default(omit) }}"
    src: "{{ item.value.src|default(omit) }}"
    owner: "{{ item.value.owner|default(omit) }}"
    group: "{{ item.value.group|default(omit) }}"
    mode: "{{ item.value.mode|default(omit) }}"
    attributes: "{{ item.value.attributes|default(omit) }}"
    recurse: "{{ item.value.recurse|default(omit) }}"
    force: "{{ item.value.force|default(omit) }}"
    follow: "{{ item.value.follow|default(omit) }}"
    access_time: "{{ item.value.access_time|default(omit) }}"
    access_time_format: "{{ item.value.access_time_format|default(omit) }}"
    modification_time: "{{ item.value.modification_time|default(omit) }}"
    modification_time_format: "{{ item.value.modification_time_format|default(omit) }}"
    unsafe_writes: "{{ item.value.unsafe_writes|default(omit) }}"
  loop: "{{ cl_states|dict2items }}"
  loop_control:
    label: "{{ item.value.path }}"
  when: item.value.state|default('file') in cl_states_file

- name: "states: Apply mount states"
  ansible.posix.mount:
    path: "{{ item.value.path }}"
    state: "{{ item.value.state }}"
    backup: "{{ item.value.backup|default(omit) }}"
    boot: "{{ item.value.boot|default(omit) }}"
    dump: "{{ item.value.dump|default(omit) }}"
    fstab: "{{ item.value.fstab|default(omit) }}"
    opts: "{{ item.value.opts|default(omit) }}"
    passno: "{{ item.value.passno|default(omit) }}"
    src: "{{ item.value.src|default(omit) }}"
  loop: "{{ cl_states|dict2items }}"
  loop_control:
    label: "{{ item.value.path }}"
  when: item.value.state|default('absent') in cl_states_mount

# EOF
...

files.yml

Synopsis: Manage files.

Iterate cl_files_order (6) and include tasks with particular modules.

[tasks/files.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---

- name: "files: Manage files"
  ansible.builtin.include_tasks:
    file: "files-{{ fitem }}.yml"
  loop: "{{ cl_files_order }}"
  loop_control:
    loop_var: fitem

# EOF
...

See also

  • See Files Order of options

Hint

  • Customize the list cl_files_order and fit the order of the options to your needs.

files-blockinfile.yml

Synopsis: Configure files-blockinfile.

Description of the task.

[tasks/files-blockinfile.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
---

- name: "files-blockinfile: Debug blocks in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('blocks', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-blockinfile: Blockinfile"
  ansible.builtin.blockinfile:
    path: "{{ item.0.path }}"
    marker: "# {mark} ANSIBLE MANAGED BLOCK {{ item.1.marker }}"
    block: "{{ item.1.block }}"
    state: "{{ item.1.state|default(omit) }}"
    insertafter: "{{ item.1.insertafter|default(omit) }}"
    insertbefore: "{{ item.1.insertbefore|default(omit) }}"
    marker_begin: "{{ item.1.marker_begin|default(omit) }}"
    marker_end: "{{ item.1.marker_end|default(omit) }}"
    owner: "{{ item.0.owner|default(omit) }}"
    group: "{{ item.0.group|default(omit) }}"
    mode: "{{ item.0.mode|default(omit) }}"
    attributes: "{{ item.0.attributes|default(omit) }}"
    create: "{{ item.0.create|default(omit) }}"
    validate: "{{ item.0.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|list|subelements('blocks', skip_missing=true) }}"
  loop_control:
    label: "{{ item.0.path }} {{ item.1.marker }}"
  notify: "{{ item.0.handlers|default(omit) }}"
  register: cl_results_blocks

- block:
    - name: "files-blockinfile: Debug cl_results_blocks"
      ansible.builtin.debug:
        var: cl_results_blocks
    - name: "files-blockinfile: Debug changed blocks paths"
      ansible.builtin.debug:
        msg: "{{ cl_results_blocks.results|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-copy.yml

Synopsis: Configure files-copy.

Description of the task.

[tasks/files-copy.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
---

- name: "files-copy: Debug copyfile in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('copyfile', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-copy: Delete copyfile in cl_files.values()"
  ansible.builtin.file:
    state: absent
    path: "{{ item.path }}"
  loop: "{{ cl_files.values()|selectattr('copyfile', 'defined')|list }}"
  loop_control:
    label: "{{ item.path }}"
  when: cl_copyfile_delete|bool

- name: "files-copy: Copy copyfile in cl_files.values()"
  ansible.builtin.copy:
    dest: "{{ item.path }}"
    src: "{{ item.copyfile.path }}"
    checksum: "{{ item.copyfile.checksum|default(omit) }}"
    content: "{{ item.copyfile.content|default(omit) }}"
    decrypt: "{{ item.copyfile.decrypt|default(omit) }}"
    directory_mode: "{{ item.copyfile.directory_mode|default(omit) }}"
    follow: "{{ item.copyfile.follow|default(omit) }}"
    force: "{{ item.copyfile.force|default(omit) }}"
    local_follow: "{{ item.copyfile.local_follow|default(omit) }}"
    remote_src: "{{ item.copyfile.remote_src|default(omit) }}"
    owner: "{{ item.owner|default(omit) }}"
    group: "{{ item.group|default(omit) }}"
    mode: "{{ item.mode|default(omit) }}"
    attributes: "{{ item.attributes|default(omit) }}"
    validate: "{{ item.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|selectattr('copyfile', 'defined')|list }}"
  loop_control:
    label: "{{ item.path }}"
  notify: "{{ item.handlers|default(omit) }}"
  register: cl_results_copy

- block:
    - name: "files-copy: Debug cl_results_copy"
      ansible.builtin.debug:
        var: cl_results_copy
    - name: "files-copy: Debug changed copy path"
      ansible.builtin.debug:
        msg: "{{ cl_results_copy|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-create-backup.yml

Synopsis: Configure files-create-backup.

Description of the task.

[tasks/files-create-backup.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---

- name: "file-create-backup: Create time-stamp"
  ansible.builtin.set_fact:
    cl_timestamp: "{{ '%Y-%m-%d_%H_%M_%S'|strftime }}"

- name: "file-create-backup: Stat cl_files"
  ansible.builtin.stat:
    path: "{{ item }}"
  loop: "{{ cl_files.values()|map(attribute='path')|list|unique }}"
  loop_control:
    label: "{{ item }}"
  register: result

- name: "file-create-backup: Debug result"
  ansible.builtin.debug:
    var: result
  when: cl_debug|bool

- name: "file-create-backup: Create backup files"
  ansible.builtin.copy:
    remote_src: true
    src: "{{ item.item }}"
    dest: "{{ item.item }}_{{ cl_timestamp }}.bak"
    mode: preserve
  loop: "{{ result.results }}"
  loop_control:
    label: "{{ item.item }}"
  when: item.stat.exists
  changed_when: false

# EOF
...

files-delete-backup.yml

Synopsis: Configure files-delete-backup.

Description of the task.

[tasks/files-delete-backup.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
---

- name: "files-delete-backup: Delete backup files that did not change"
  ansible.builtin.file:
    state: absent
    path: "{{ item }}_{{ cl_timestamp }}.bak"
  loop: "{{ cl_files.values()|list|json_query('[].path')|
            difference(cl_results_copy.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_template.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_lines.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_blocks.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_inifile.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_ucl.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique|
            difference(cl_results_patch.results|default([])|
                       json_query('[?changed].invocation.module_args.path'))|unique
            }}"
  when:
    - cl_backup|bool
    - not ansible_check_mode
  changed_when: false

# EOF
...

files-inifile.yml

Synopsis: Configure files-inifile.

Description of the task.

[tasks/files-inifile.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
---

- name: "files-inifile: Debug ini in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('ini', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-inifile: INI files"
  community.general.ini_file:
    path: "{{ item.0.path }}"
    section: "{{ item.1.section }}"
    option: "{{ item.1.option|default(omit) }}"
    value: "{{ item.1.value|default(omit) }}"
    state: "{{ item.1.state|default(omit) }}"
    allow_no_value: "{{ item.1.allow_no_value|default(omit) }}"
    no_extra_spaces: "{{ item.1.no_extra_spaces|default(omit) }}"
    owner: "{{ item.0.owner|default(omit) }}"
    group: "{{ item.0.group|default(omit) }}"
    mode: "{{ item.0.mode|default(omit) }}"
    attributes: "{{ item.0.attributes|default(omit) }}"
    create: "{{ item.0.create|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|list|subelements('ini', {'skip_missing': True}) }}"
  loop_control:
    label: "{{ item.0.path }}"
  notify: "{{ item.0.handlers|default(omit) }}"
  register: cl_results_ini

- block:
    - name: "files-inifile: Debug cl_results_ini"
      ansible.builtin.debug:
        var: cl_results_ini
    - name: "files-inifile: Debug changed ini paths"
      ansible.builtin.debug:
        msg: "{{ cl_results_ini.results|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-lineinfile.yml

Synopsis: Configure files-lineinfile.

Description of the task.

[tasks/files-lineinfile.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
---

# lines
- name: "files-lineinfile: Debug lines in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('lines', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-lineinfile: Lineinfile lines"
  ansible.builtin.lineinfile:
    path: "{{ item.0.path }}"
    regexp: "{{ item.1.regexp|default(omit) }}"
    line: "{{ item.1.line|default(omit) }}"
    backrefs: "{{ item.1.backrefs|default(omit) }}"
    state: "{{ item.1.state|default(omit) }}"
    firstmatch: "{{ item.1.firstmatch|default(omit) }}"
    insertafter: "{{ item.1.insertafter|default(omit) }}"
    insertbefore: "{{ item.1.insertbefore|default(omit) }}"
    owner: "{{ item.0.owner|default(omit) }}"
    group: "{{ item.0.group|default(omit) }}"
    mode: "{{ item.0.mode|default(omit) }}"
    attributes: "{{ item.0.attributes|default(omit) }}"
    others: "{{ item.0.others|default(omit) }}"
    create: "{{ item.0.create|default(omit) }}"
    validate: "{{ item.0.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|list|subelements('lines', skip_missing=true) }}"
  loop_control:
    label: "{{ item.0.path }} {{ item.1.line|default('') }}"
  notify: "{{ item.0.handlers|default(omit) }}"
  register: cl_results_lines

- block:
    - name: "files-lineinfile: Debug cl_results_lines"
      ansible.builtin.debug:
        var: cl_results_lines
    - name: "files-lineinfile: Debug changed lines paths"
      ansible.builtin.debug:
        msg: "{{ cl_results_lines.results|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# dict
- name: "files-lineinfile: Debug dict in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('dict', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-lineinfile: Lineinfile dict"
  ansible.builtin.lineinfile:
    path: "{{ item.0.path }}"
    regexp: '^\s*[#;]*\s*{{ item.1.key }}\s*{{ item.0.assignment|default("=")|trim }}\s*(.*)$'
    line: "{{ item.1.key }}{{ item.0.assignment|default('=') }}{{ item.1.value }}"
    backrefs: "{{ item.1.backrefs|default(omit) }}"
    state: "{{ item.1.state|default(omit) }}"
    firstmatch: "{{ item.1.firstmatch|default(omit) }}"
    insertafter: "{{ item.1.insertafter|default(omit) }}"
    insertbefore: "{{ item.1.insertbefore|default(omit) }}"
    owner: "{{ item.0.owner|default(omit) }}"
    group: "{{ item.0.group|default(omit) }}"
    mode: "{{ item.0.mode|default(omit) }}"
    attributes: "{{ item.0.attributes|default(omit) }}"
    others: "{{ item.0.others|default(omit) }}"
    create: "{{ item.0.create|default(omit) }}"
    validate: "{{ item.0.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|list|subelements('dict', skip_missing=true) }}"
  loop_control:
    label: "{{ item.0.path }} {{ item.1.key }}"
  notify: "{{ item.0.handlers|default(omit) }}"
  register: cl_results_dict

- block:
    - name: "files-lineinfile: Debug cl_results_dict"
      ansible.builtin.debug:
        var: cl_results_dict
    - name: "files-lineinfile: Debug changed dict paths"
      ansible.builtin.debug:
        msg: "{{ cl_results_dict.results|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-markers.yml

Synopsis: Configure files-markers.

Description of the task.

[tasks/files-markers.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---

- name: "files-markers: Debug markers in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('markers', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-markers: Mark block {{ item.1.marker }}"
  ansible.builtin.include_tasks: fn/mark-block.yml
  loop: "{{ cl_files.values()|list|subelements('markers', skip_missing=true) }}"
  loop_control:
    label: "{{ item.0.path }}"

# EOF
...

mark-block.yml

Synopsis: Configure mark-block.

Description of the task.

[tasks/fn/mark-block.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
---

- name: "mark-block: Check begin marker {{ item.1.marker }}"
  ansible.builtin.command:
    cmd: >
      grep -q '# BEGIN ANSIBLE MANAGED BLOCK {{ item.1.marker }}' {{ item.0.path }}
  register: checkmarker
  ignore_errors: true
  changed_when: false

- block:
    - name: "mark-block: Create begin marker {{ item.1.marker }}"
      ansible.builtin.replace:
        path: '{{ item.0.path }}'
        regexp: '{{ item.1.regex1 }}'
        replace: |-
          {{ '#' }} BEGIN ANSIBLE MANAGED BLOCK {{ item.1.marker }}
          {{ item.1.replace1 }}
    - name: "mark-block: Create end marker {{ item.1.marker }}"
      ansible.builtin.replace:
        path: '{{ item.0.path }}'
        regexp: '({{ item.1.regex1 }}[\s\S]*?){{ item.1.regex2 }}'
        replace: |-
          \g<1>
          {{ item.1.replace2 }}
          {{ '#' }} END ANSIBLE MANAGED BLOCK {{ item.1.marker }}
  when:
    - not ansible_check_mode
    - checkmarker.rc != 0

# EOF
...

files-patch.yml

Synopsis: Configure files-patch.

Description of the task.

[tasks/files-patch.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
---

- name: "files-patch: Debug patch in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('patch', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-patch: Patch"
  ansible.posix.patch:
    dest: "{{ item.path }}"
    src: "{{ item.patch.src }}"
    basedir: "{{ item.patch.basedir|default(omit) }}"
    binary: "{{ item.patch.binary|default(omit) }}"
    ignore_whitespace: "{{ item.patch.ignore_whitespace|default(omit) }}"
    remote_src: "{{ item.patch.remote_src|default(omit) }}"
    state: "{{ item.patch.state|default(omit) }}"
    strip: "{{ item.patch.strip|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|selectattr('patch', 'defined')|list }}"
  loop_control:
    label: "{{ item.path }}"
  notify: "{{ item.handlers|default(omit) }}"
  register: cl_results_patch

- block:
    - name: "files-patch: Debug cl_results_patch"
      ansible.builtin.debug:
        var: cl_results_patch
    - name: "files-patch: Debug changed patch patch"
      ansible.builtin.debug:
        msg: "{{ cl_results_patch|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-template.yml

Synopsis: Configure files-template.

Description of the task.

[tasks/files-template.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
---

- name: "files-template: Debug template in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('template', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-template: Delete template in cl_files.values()"
  ansible.builtin.file:
    state: absent
    path: "{{ item.path }}"
  loop: "{{ cl_files.values()|selectattr('template', 'defined')|list }}"
  loop_control:
    label: "{{ item.path }}"
  when: cl_template_delete|bool

- name: "files-template: Template"
  ansible.builtin.template:
    dest: "{{ item.path }}"
    src: "{{ item.template.path }}"
    follow: "{{ item.template.follow|default(omit) }}"
    force: "{{ item.template.force|default(omit) }}"
    block_start_string: "{{ item.template.block_start_string|default(omit) }}"
    block_end_string: "{{ item.template.block_end_string|default(omit) }}"
    lstrip_blocks: "{{ item.template.lstrip_blocks|default(omit) }}"
    newline_sequence: "{{ item.template.newline_sequence|default(omit) }}"
    output_encoding: "{{ item.template.output_encoding|default(omit) }}"
    trim_blocks: "{{ item.template.trim_blocks|default(omit) }}"
    variable_end_string: "{{ item.template.variable_end_string|default(omit) }}"
    variable_start_string: "{{ item.template.variable_start_string|default(omit) }}"
    owner: "{{ item.owner|default(omit) }}"
    group: "{{ item.group|default(omit) }}"
    mode: "{{ item.mode|default(omit) }}"
    attributes: "{{ item.attributes|default(omit) }}"
    validate: "{{ item.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|selectattr('template', 'defined')|list }}"
  loop_control:
    label: "{{ item.path }}"
  notify: "{{ item.handlers|default(omit) }}"
  register: cl_results_template

- block:
    - name: "files-template: Debug cl_results_template"
      ansible.builtin.debug:
        var: cl_results_template
    - name: "files-template: Debug changed template path"
      ansible.builtin.debug:
        msg: "{{ cl_results_template|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

files-ucl.yml

Synopsis: Configure files-ucl.

Description of the task.

[tasks/files-ucl.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
---

- name: "files-ucl: Debug ucl in cl_files.values()"
  ansible.builtin.debug:
    msg: "{{ cl_files.values()|selectattr('ucl', 'defined')|list }}"
  when: cl_debug|bool

- name: "files-ucl: UCL files cl_files.values()"
  vbotka.freebsd.ucl:
    path: "{{ item.0.path }}"
    chdir: "{{ item.1.chdir|default(omit) }}"
    upath: "{{ item.1.upath|default(omit) }}"
    ipath: "{{ item.1.ipath|default(omit) }}"
    icontent: "{{ item.1.icontent|default(omit) }}"
    value: "{{ item.1.value|default(omit) }}"
    vtype: "{{ item.1.vtype|default(omit) }}"
    merge: "{{ item.1.merge|default(omit) }}"
    state: "{{ item.1.state|default(omit) }}"
    delimiter: "{{ item.1.delimiter|default(omit) }}"
    lang: "{{ item.1.lang|default(omit) }}"
    owner: "{{ item.0.owner|default(omit) }}"
    group: "{{ item.0.group|default(omit) }}"
    mode: "{{ item.0.mode|default(omit) }}"
    attributes: "{{ item.0.attributes|default(omit) }}"
    create: "{{ item.0.create|default(omit) }}"
    validate: "{{ item.0.validate|default(omit) }}"
    # backup: "{{ cl_backup }}"
  loop: "{{ cl_files.values()|list|subelements('ucl', {'skip_missing': True}) }}"
  loop_control:
    label: "{{ item.0.path }}"
  notify: "{{ item.0.handlers|default(omit) }}"
  register: cl_results_ucl

- block:
    - name: "files-ucl: Debug cl_results_ucl"
      ansible.builtin.debug:
        var: cl_results_ucl
    - name: "files-ucl: Debug changed ucl paths"
      ansible.builtin.debug:
        msg: "{{ cl_results_ucl.results|default([])|
                 json_query('[?changed].invocation.module_args.path') }}"
  when: cl_debug|bool

# EOF
...

services.yml

Synopsis: Configure services.

Description of the task.

[tasks/services.yml]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
---

- name: "services: Debug"
  vars:
    msg: |-
      cl_services_freebsd_rcconf_auto [{{ cl_services_freebsd_rcconf_auto }}]
      cl_services
      {{ cl_services|to_nice_yaml }}
  ansible.builtin.debug:
    msg: "{{ '{}'.format(msg) }}"
  when: cl_debug|bool

# FreeBSD auto ------------------------------------------------------------
- block:

    - name: "services: Enable service in rc.conf FreeBSD"
      ansible.builtin.lineinfile:
        dest: /etc/rc.conf
        regexp: '^\s*{{ item.value.name }}_enable\s*=(.*)$'
        line: '{{ item.value.name }}_enable="YES"'
        backup: "{{ cl_backup }}"
      loop: "{{ cl_services|dict2items }}"
      loop_control:
        label: "{{ item.key }}"
      when: item.value.enabled|default(true)|bool

    - name: "services: Disable service in rc.conf FreeBSD"
      ansible.builtin.lineinfile:
        dest: /etc/rc.conf
        regexp: '^\s*{{ item.value.name }}_enable\s*=(.*)$'
        line: '{{ item.value.name }}_enable="NO"'
        backup: "{{ cl_backup }}"
      loop: "{{ cl_services|dict2items }}"
      loop_control:
        label: "{{ item.key }}"
      when: not item.value.enabled|default(true)|bool

  when:
    - ansible_os_family == 'FreeBSD'
    - cl_services_freebsd_rcconf_auto|bool

# All ---------------------------------------------------------------------
- block:

    - name: "services: Manage services"
      ansible.builtin.service:
        name: "{{ item.value.name }}"
        state: "{{ item.value.state|default('started') }}"
        enabled: "{{ item.value.enabled|default(true) }}"
      loop: "{{ cl_services|dict2items }}"
      loop_control:
        label: "{{ item.key }}"

  when: ansible_os_family == 'RedHat' or
        ansible_os_family == 'Debian' or
        ansible_os_family == 'FreeBSD'

# EOF
...