commit 1ae6576dabde428e2438ec3cc100a3c4c5de8206 Author: Semaphore Date: Tue Mar 10 14:03:29 2026 -0700 Initial repo structure — playbook skeletons, roles, client template inventory diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b257325 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.retry +.vault_pass +*.log +__pycache__/ +*.pyc +.ansible/ +fact_cache/ +*.swp diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..f24117b --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,27 @@ +[defaults] +inventory = inventories/ +roles_path = roles/ +callback_plugins = callback_plugins/ +stdout_callback = yaml +callbacks_enabled = n8n_reporter +retry_files_enabled = False +host_key_checking = True +timeout = 30 +forks = 10 +gathering = smart +fact_caching = jsonfile +fact_caching_connection = /tmp/ansible_facts_cache +fact_caching_timeout = 3600 + +[privilege_escalation] +become = True +become_method = sudo +become_ask_pass = False + +[ssh_connection] +ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=yes +pipelining = True + +[persistent_connection] +connect_timeout = 30 +command_timeout = 30 diff --git a/callback_plugins/n8n_reporter.py b/callback_plugins/n8n_reporter.py new file mode 100644 index 0000000..59f065f --- /dev/null +++ b/callback_plugins/n8n_reporter.py @@ -0,0 +1,9 @@ +# n8n_reporter.py +# Ansible callback plugin +# Posts structured patch run results to n8n webhook +# Full implementation to follow +DOCUMENTATION = ''' + callback: n8n_reporter + type: notification + short_description: Posts patch run results to n8n webhook +''' diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..cfd825a --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,16 @@ +--- +min_free_disk_percent: 20 +max_load_multiplier: 2 +snapshot_max_age_hours: 24 + +human_estimates: + linux_full_patch: 2700 + linux_security_only: 1800 + windows_full_patch: 3600 + preflight_check: 600 + +report_on_success: true +report_on_failure: true + +snapshot_retain_count: 3 +snapshot_name_prefix: "ansible-pre-patch" diff --git a/inventories/client_template/group_vars/all.yml b/inventories/client_template/group_vars/all.yml new file mode 100644 index 0000000..cbf88b9 --- /dev/null +++ b/inventories/client_template/group_vars/all.yml @@ -0,0 +1,7 @@ +--- +# Client-specific overrides go here +# client_id: "ACME-001" +# client_name: "ACME Corp" +# billing_model: "hybrid" +# change_freeze: false +# human_estimate_seconds: 2700 diff --git a/inventories/client_template/hosts.yml b/inventories/client_template/hosts.yml new file mode 100644 index 0000000..41cd387 --- /dev/null +++ b/inventories/client_template/hosts.yml @@ -0,0 +1,29 @@ +--- +all: + vars: + client_id: "CLIENT_ID" + client_name: "Client Name" + billing_model: "hybrid" + maintenance_window_start: "02:00" + maintenance_window_end: "05:00" + maintenance_window_tz: "UTC" + n8n_webhook_url: "{{ lookup('env', 'N8N_WEBHOOK_URL') }}" + human_estimate_seconds: 2700 + change_freeze: false + + children: + linux_hosts: + hosts: {} + vars: + ansible_user: root + ansible_ssh_private_key_file: "~/.ssh/client_key" + os_family: "debian" + + windows_hosts: + hosts: {} + vars: + ansible_user: Administrator + ansible_connection: winrm + ansible_winrm_transport: ntlm + ansible_winrm_server_cert_validation: validate + ansible_port: 5986 diff --git a/playbooks/linux_patch.yml b/playbooks/linux_patch.yml new file mode 100644 index 0000000..8e55a7c --- /dev/null +++ b/playbooks/linux_patch.yml @@ -0,0 +1,9 @@ +--- +- name: Linux patching + hosts: linux_hosts + gather_facts: true + roles: + - snapshot + - preflight + - linux_patch + - report diff --git a/playbooks/site_maintenance.yml b/playbooks/site_maintenance.yml new file mode 100644 index 0000000..4626029 --- /dev/null +++ b/playbooks/site_maintenance.yml @@ -0,0 +1,7 @@ +--- +# Master wrapper — runs full maintenance sequence +# This is the single template to schedule in Semaphore per client +- import_playbook: snapshot_pre.yml +- import_playbook: site_preflight.yml +- import_playbook: linux_patch.yml +- import_playbook: windows_patch.yml diff --git a/playbooks/site_preflight.yml b/playbooks/site_preflight.yml new file mode 100644 index 0000000..e216cff --- /dev/null +++ b/playbooks/site_preflight.yml @@ -0,0 +1,6 @@ +--- +- name: Pre-flight safety checks + hosts: all + gather_facts: true + roles: + - preflight diff --git a/playbooks/snapshot_pre.yml b/playbooks/snapshot_pre.yml new file mode 100644 index 0000000..d3ace0f --- /dev/null +++ b/playbooks/snapshot_pre.yml @@ -0,0 +1,6 @@ +--- +- name: Pre-patch snapshot + hosts: all + gather_facts: true + roles: + - snapshot diff --git a/playbooks/snapshot_verify.yml b/playbooks/snapshot_verify.yml new file mode 100644 index 0000000..7fae649 --- /dev/null +++ b/playbooks/snapshot_verify.yml @@ -0,0 +1,8 @@ +--- +- name: Verify snapshot exists + hosts: all + gather_facts: false + tasks: + - name: Placeholder - snapshot verification tasks + ansible.builtin.debug: + msg: "Snapshot verification to be implemented" diff --git a/playbooks/windows_patch.yml b/playbooks/windows_patch.yml new file mode 100644 index 0000000..fb633b8 --- /dev/null +++ b/playbooks/windows_patch.yml @@ -0,0 +1,8 @@ +--- +- name: Windows patching + hosts: windows_hosts + gather_facts: true + roles: + - preflight + - windows_patch + - report diff --git a/roles/linux_patch/defaults/main.yml b/roles/linux_patch/defaults/main.yml new file mode 100644 index 0000000..0720b8f --- /dev/null +++ b/roles/linux_patch/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# linux_patch default variables diff --git a/roles/linux_patch/tasks/main.yml b/roles/linux_patch/tasks/main.yml new file mode 100644 index 0000000..e7a8c64 --- /dev/null +++ b/roles/linux_patch/tasks/main.yml @@ -0,0 +1,6 @@ +--- +# linux_patch tasks +# Implementation to follow +- name: Placeholder + ansible.builtin.debug: + msg: "linux_patch role - tasks to be implemented" diff --git a/roles/preflight/defaults/main.yml b/roles/preflight/defaults/main.yml new file mode 100644 index 0000000..db10a6b --- /dev/null +++ b/roles/preflight/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# preflight default variables diff --git a/roles/preflight/tasks/main.yml b/roles/preflight/tasks/main.yml new file mode 100644 index 0000000..872eb0d --- /dev/null +++ b/roles/preflight/tasks/main.yml @@ -0,0 +1,6 @@ +--- +# preflight tasks +# Implementation to follow +- name: Placeholder + ansible.builtin.debug: + msg: "preflight role - tasks to be implemented" diff --git a/roles/report/defaults/main.yml b/roles/report/defaults/main.yml new file mode 100644 index 0000000..5878d32 --- /dev/null +++ b/roles/report/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# report default variables diff --git a/roles/report/tasks/main.yml b/roles/report/tasks/main.yml new file mode 100644 index 0000000..76bc991 --- /dev/null +++ b/roles/report/tasks/main.yml @@ -0,0 +1,6 @@ +--- +# report tasks +# Implementation to follow +- name: Placeholder + ansible.builtin.debug: + msg: "report role - tasks to be implemented" diff --git a/roles/snapshot/defaults/main.yml b/roles/snapshot/defaults/main.yml new file mode 100644 index 0000000..67ce35b --- /dev/null +++ b/roles/snapshot/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# snapshot default variables diff --git a/roles/snapshot/tasks/main.yml b/roles/snapshot/tasks/main.yml new file mode 100644 index 0000000..dc42904 --- /dev/null +++ b/roles/snapshot/tasks/main.yml @@ -0,0 +1,6 @@ +--- +# snapshot tasks +# Implementation to follow +- name: Placeholder + ansible.builtin.debug: + msg: "snapshot role - tasks to be implemented" diff --git a/roles/windows_patch/defaults/main.yml b/roles/windows_patch/defaults/main.yml new file mode 100644 index 0000000..b3a6990 --- /dev/null +++ b/roles/windows_patch/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# windows_patch default variables diff --git a/roles/windows_patch/tasks/main.yml b/roles/windows_patch/tasks/main.yml new file mode 100644 index 0000000..98fe768 --- /dev/null +++ b/roles/windows_patch/tasks/main.yml @@ -0,0 +1,6 @@ +--- +# windows_patch tasks +# Implementation to follow +- name: Placeholder + ansible.builtin.debug: + msg: "windows_patch role - tasks to be implemented"