Skip to content

Commit

Permalink
Add idempotentcy to pihole role.
Browse files Browse the repository at this point in the history
Added:
* pihole_idempotent. This will force role to be idempotent each run. Classic
  behavior is 'false' (not idempotent); but may now be optionally toggled on.

Changed:
* Added 'Default' group to blocklist defaults to conform to pihole defaults.
* Added 'remove_default_group' to 'pihole_clients' (backwards compatible).
  Hosts toggling this flag will be removed from the 'Default' group on role
  application.
* Adding clients moved to separate 'add_clients' file enabling management of
  client and removal of 'Default' group in one loop.
* Databases may now be removed on role application to enable idempotent runs.
  • Loading branch information
r-pufky committed Aug 1, 2023
1 parent 6b9c819 commit 32d75e9
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 10 deletions.
19 changes: 15 additions & 4 deletions defaults/main/blocklist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
###############################################################################
# Define Adlist sources for generating domain blocklists.
#
# stevenblack's hosts adlist is automatically added when installing as ID 1.
#
# pihole_ad_sources:
# - id: int (unique id starting at 1)
# address: str (URL for adlist)
Expand All @@ -13,7 +15,6 @@
# Reference:
# * https://docs.pi-hole.net/database/gravity/#adlist-table-adlist

# Pi-Hole currently adds the stevenblack adlist when installing, as ID 1.
pihole_ad_sources:
- id: 1
address: 'https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts'
Expand Down Expand Up @@ -43,12 +44,14 @@ pihole_domain_blocklists: []
###############################################################################
# Pi-Hole Clients Table
###############################################################################
# Define Pi-Hole clients.
# Define Pi-Hole clients. All clients are automatically added to the 'Default'
# group in Pi-Hole to automatically enforce blocking.
#
# pihole_clients:
# - id: int (unique id starting at 1)
# ip: str (IPv4,IPv6,CIDR)
# comment: str (user comment)
# remove_default_group: bool (remove from automatic 'Default' group)
#
# Reference:
# * https://docs.pi-hole.net/database/gravity/#client-table-client
Expand All @@ -60,6 +63,10 @@ pihole_clients: []
###############################################################################
# Define Pi-Hole group management.
#
# Group 'Default' (id 0) is special as it is automatically assigned to domains
# and clients not being a member of other groups. Each newly added client or
# domain gets assigned to group zero when being added.
#
# pihole_groups:
# - id: int (unique id starting at 1)
# enabled: bool (enable use)
Expand All @@ -69,7 +76,11 @@ pihole_clients: []
# Reference:
# * https://docs.pi-hole.net/database/gravity/groups/#group-management

pihole_groups: []
pihole_groups:
- id: 0
enabled: true
name: 'Default'
description: 'The default group'

###############################################################################
# Pi-Hole Groups Adlist Table
Expand All @@ -88,7 +99,7 @@ pihole_ad_groups_blocklist: []
###############################################################################
# Pi-Hole Groups Clients Table
###############################################################################
# Define Pi-Hole group clients management.
# Define Pi-Hole group clients blocklists management.
#
# pihole_ad_groups_blocklist:
# - client_id: int (existing client ID)
Expand Down
16 changes: 16 additions & 0 deletions defaults/main/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ pihole_update_enable: false
# Disable role behavior change warnings. Default: True.
pihole_disable_warning: true

# Enable idempotent pihole operation. Default: False.
# The default behavior before this option existed is the equivalent of 'false'.
#
# Idempotent operation will:
# * Clears all pihole databases and rebuilds them to prevent 'skew'.
# * Service **WILL** be interrupted while role is being applied (use multiple
# pihole instances or disable this).
# * All adlists will be redownloaded.
# * Existing logging/client information will be lost.
#
# Long running pihole instances with large volume of changes to clients/groups
# may see 'skew' between what exists on the pihole server and what the role
# defines. This corrects the issue at the expense of service downtime and
# rebuilding.
pihole_idempotent: false

###############################################################################
# Pi-Hole setupVars.conf
###############################################################################
Expand Down
28 changes: 28 additions & 0 deletions tasks/db/add_clients.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
###############################################################################
# Pi-Hole Add Clients
###############################################################################
# Clients are automatically added to the 'Default' (id=0) group in Pi-Hole upon
# creation, which apply the default blocklists. Add clients and optionally
# remove them from the 'Default' if enabled.
#
# Args:
# client: dict (pihole_clients)
# - id: int (unique id starting at 1)
# ip: str (IPv4,IPv6,CIDR)
# comment: str (user comment)
# remove_default_group: bool (remove from automatic 'Default' group)
#
# Reference:
# * https://docs.pi-hole.net/database/

- name: 'db | add client {{ client.id }}'
ansible.builtin.command: '{{ pihole_default_sqlite3 }} "{{ pihole_default_client_insert }} ({{ client.id }}, \"{{ client.ip }}\", \"{{ client.comment }}\")"'
become: true

- name: 'db | remove client {{ client.id }} from default group'
ansible.builtin.command: '{{ pihole_default_sqlite3 }} "{{ pihole_default_client_groups_delete_default }} {{ client.id }}"'
become: true
when: |
'remove_default_group' in client and
client.remove_default_group
26 changes: 26 additions & 0 deletions tasks/db/clear_databases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
###############################################################################
# Pi-Hole Clear Databases
###############################################################################
# Removes existing databases for Pi-Hole to rebuild on restart. This enables
# idempotent role application for Pi-Hole.
#
# Given the DB triggers and simplistic nature of handling clients; major
# changes to clients and groups (including additions, removals) **WILL** lead
# to a skew in the actual database versus what the role explicitly codifies.
#
# By removing the databases before applying changes, this enables consistent
# application at the expense of recreating the DB's and downloading/rebuilding
# blocklists each run.

- name: 'clear databases | remove databases'
ansible.builtin.file:
path: '/etc/pihole/{{ item }}'
state: 'absent'
loop:
- 'gravity.db'
- 'pihole-FTL.db'

- name: 'clear databases | regenerate databases'
ansible.builtin.command: '/etc/.pihole/automated\ install/basic-install.sh --reconfigure --unattended'
changed_when: false
File renamed without changes.
11 changes: 7 additions & 4 deletions tasks/db.yml → tasks/db/db.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
# Reference:
# * https://docs.pi-hole.net/database/

- ansible.builtin.include_tasks: clear_databases.yml
when: pihole_idempotent

- name: 'db | add adlist source'
ansible.builtin.command: '{{ pihole_default_sqlite3 }} "{{ pihole_default_ad_insert }} ({{ item.id }}, \"{{ item.address }}\", {{ item.enabled|int }}, \"{{ item.comment }}\")"'
become: true
Expand All @@ -31,11 +34,11 @@
loop: '{{ pihole_domain_blocklists }}'
when: not pihole_use_cli and pihole_domain_blocklists|length > 0

- name: 'db | add clients'
ansible.builtin.command: '{{ pihole_default_sqlite3 }} "{{ pihole_default_client_insert }} ({{ item.id }}, \"{{ item.ip }}\", \"{{ item.comment }}\")"'
become: true
loop: '{{ pihole_clients }}'
- ansible.builtin.include_tasks: add_clients.yml
when: pihole_clients|length > 0
loop: '{{ pihole_clients }}'
loop_control:
loop_var: client

- name: 'db | add groups'
ansible.builtin.command: '{{ pihole_default_sqlite3 }} "{{ pihole_default_groups_insert }} ({{ item.id }}, {{ item.enabled|int }}, \"{{ item.name }}\", \"{{ item.description }}\")"'
Expand Down
2 changes: 1 addition & 1 deletion tasks/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
- name: 'install | create /etc/pihole'
ansible.builtin.file:
path: '/etc/pihole'
mode: 0755
mode: 0775
state: 'directory'

- name: 'install | WARNING ROLE BEHAVIOR CHANGED'
Expand Down
2 changes: 1 addition & 1 deletion tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
- ansible.builtin.import_tasks: install.yml
- ansible.builtin.import_tasks: db.yml
- ansible.builtin.import_tasks: db/db.yml
- ansible.builtin.import_tasks: update.yml
1 change: 1 addition & 0 deletions vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ pihole_default_client_insert: 'insert or replace into \"client\" (id, ip, commen
pihole_default_groups_insert: 'insert or replace into \"group\" (id, enabled, name, description) values'
pihole_default_ad_groups_insert: 'insert or replace into \"adlist_by_group\" (adlist_id, group_id) values'
pihole_default_client_groups_insert: 'insert or replace into \"client_by_group\" (client_id, group_id) values'
pihole_default_client_groups_delete_default: 'delete from \"client_by_group\" where group_id = 0 and client_id = '
pihole_default_domain_groups_insert: 'insert or replace into \"domainlist_by_group\" (domainlist_id, group_id) values'

0 comments on commit 32d75e9

Please sign in to comment.