parent
55fc47f627
commit
8d55618ef9
42
ansible/deploy-config.yml
Normal file
42
ansible/deploy-config.yml
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# Deploy Configuration
|
||||
# Purpose: Centralized list of files and folders to deploy to target servers
|
||||
# Usage: Referenced by apply.yml and drift-check.yml playbooks
|
||||
# =============================================================================
|
||||
|
||||
# List of files to deploy
|
||||
# Each item specifies:
|
||||
# - src: source path (relative to repo root)
|
||||
# - dest: destination path on target servers
|
||||
# - owner: file owner (default: root)
|
||||
# - group: file group (default: root)
|
||||
# - mode: file permissions (default: 0644)
|
||||
# - recursive: if True, use recursive copy for directories (optional)
|
||||
# =============================================================================
|
||||
|
||||
deploy_items:
|
||||
- name: "dvir.txt"
|
||||
src: "files/dvir.txt"
|
||||
dest: "/tmp/dvir.txt"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
description: "Main configuration file"
|
||||
|
||||
# Example: add more files below
|
||||
# - name: "example.conf"
|
||||
# src: "files/example.conf"
|
||||
# dest: "/etc/example/example.conf"
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: "0644"
|
||||
#
|
||||
# Example: recursive folder deployment
|
||||
# - name: "config_folder"
|
||||
# src: "files/config/"
|
||||
# dest: "/etc/myapp/config/"
|
||||
# owner: root
|
||||
# group: root
|
||||
# mode: "0755"
|
||||
# recursive: true
|
||||
@ -1,31 +1,78 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# APPLY PLAYBOOK
|
||||
# Purpose: Deploy dvir.txt file to target servers at /tmp/dvir.txt
|
||||
# Purpose: Deploy files from deploy-config.yml to target servers
|
||||
# Usage: ansible-playbook apply.yml
|
||||
# Note: Uses Ansible's register mechanism to capture deployed files
|
||||
# =============================================================================
|
||||
|
||||
- name: Deploy file to servers
|
||||
- name: Deploy files to servers
|
||||
hosts: all
|
||||
become: true
|
||||
vars_files:
|
||||
- ../deploy-config.yml
|
||||
|
||||
tasks:
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 1: Copy file to destination
|
||||
# Copies the dvir.txt from the repo to /tmp/dvir.txt on target servers
|
||||
# TASK 1: Deploy each configured file/folder
|
||||
# Loops through deploy_items and copies each to destination
|
||||
# Registers which files were successfully deployed
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Copy file to destination
|
||||
- name: Deploy configured files
|
||||
copy:
|
||||
src: ../../files/dvir.txt
|
||||
dest: /tmp/dvir.txt
|
||||
src: "{{ playbook_dir }}/{{ '../../' + item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
owner: "{{ item.owner | default('root') }}"
|
||||
group: "{{ item.group | default('root') }}"
|
||||
mode: "{{ item.mode | default('0644') }}"
|
||||
backup: yes
|
||||
register: deploy_results
|
||||
loop: "{{ deploy_items }}"
|
||||
loop_control:
|
||||
loop_var: item
|
||||
label: "{{ item.name }}"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 2: Extract deployed file information
|
||||
# Builds a list of deployed files from the copy task results
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Extract deployed file information
|
||||
set_fact:
|
||||
deployed_file_list: |
|
||||
[
|
||||
{%- for result in deploy_results.results -%}
|
||||
{
|
||||
"name": "{{ result.item.name }}",
|
||||
"src": "{{ result.item.src }}",
|
||||
"dest": "{{ result.item.dest }}",
|
||||
"changed": {{ result.changed | lower }}
|
||||
}{{ "," if not loop.last else "" }}
|
||||
{%- endfor -%}
|
||||
]
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 3: Save deployed files list to a temporary file
|
||||
# This file will be read by the GitOps status script
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Save deployed files list
|
||||
copy:
|
||||
content: "{{ deployed_file_list }}"
|
||||
dest: "/tmp/deployed_files_{{ inventory_hostname }}.json"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 2: Confirm deployment success
|
||||
# Displays success message with the hostname for verification
|
||||
# TASK 4: Confirm deployment success
|
||||
# Displays summary of deployed files
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Confirm deployment
|
||||
- name: Display deployment summary
|
||||
debug:
|
||||
msg: "✅ File deployed successfully to /tmp/dvir.txt on {{ inventory_hostname }}"
|
||||
msg: "✅ Deployed {{ deploy_results.results | length }} file(s) to {{ inventory_hostname }}"
|
||||
|
||||
- name: Display deployed files
|
||||
debug:
|
||||
msg: " - {{ item.item.name }} → {{ item.item.dest }} ({{ 'changed' if item.changed else 'unchanged' }})"
|
||||
loop: "{{ deploy_results.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item.name }}"
|
||||
@ -1,76 +1,140 @@
|
||||
---
|
||||
# =============================================================================
|
||||
# DRIFT-CHECK PLAYBOOK
|
||||
# Purpose: Compare file on repo vs server to detect if they're in sync
|
||||
# Purpose: Check file drift and output detailed file-level JSON report
|
||||
# Usage: ansible-playbook drift-check.yml
|
||||
# Output: SYNCED or OUT_OF_SYNC status
|
||||
# Output: Structured JSON with sync status and drifted files info
|
||||
# Registers: drift_detected, drifted_files_json for consumption by update script
|
||||
# =============================================================================
|
||||
|
||||
- name: Check file drift
|
||||
hosts: all
|
||||
gather_facts: false
|
||||
vars_files:
|
||||
- ../deploy-config.yml
|
||||
|
||||
tasks:
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 1: Read local file from repo
|
||||
# Reads dvir.txt from the local repository using base64 encoding
|
||||
# TASK 1: Initialize drift tracking variables
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Read local file
|
||||
slurp:
|
||||
src: "{{ playbook_dir }}/../../files/dvir.txt"
|
||||
- name: Initialize drift tracking
|
||||
set_fact:
|
||||
drift_detected: false
|
||||
drifted_items: []
|
||||
synced_items: []
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 2: Check each configured file for drift
|
||||
# Compares local (repo) file with server file (content and existence)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Check file drift for each configured file
|
||||
block:
|
||||
# Read local file from repo
|
||||
- name: Read local file ({{ item.name }})
|
||||
slurp:
|
||||
src: "{{ playbook_dir }}/{{ '../../' + item.src }}"
|
||||
delegate_to: localhost
|
||||
register: local_file_content
|
||||
failed_when: false
|
||||
|
||||
# Try to read file from server
|
||||
- name: Read server file ({{ item.name }})
|
||||
slurp:
|
||||
src: "{{ item.dest }}"
|
||||
register: server_file_content
|
||||
failed_when: false
|
||||
|
||||
# Compare contents and detect drift
|
||||
- name: Analyze drift for {{ item.name }}
|
||||
set_fact:
|
||||
file_drift_status: "{{ {} }}"
|
||||
file_has_drift: false
|
||||
|
||||
- name: Check if server file is missing ({{ item.name }})
|
||||
set_fact:
|
||||
file_has_drift: true
|
||||
file_drift_status: |
|
||||
{
|
||||
"name": "{{ item.name }}",
|
||||
"destination": "{{ item.dest }}",
|
||||
"status": "MISSING",
|
||||
"reason": "File not found on server"
|
||||
}
|
||||
when: server_file_content.rc != 0
|
||||
|
||||
- name: Check if file content differs ({{ item.name }})
|
||||
set_fact:
|
||||
file_has_drift: true
|
||||
file_drift_status: |
|
||||
{
|
||||
"name": "{{ item.name }}",
|
||||
"destination": "{{ item.dest }}",
|
||||
"status": "CONTENT_DIFFERS",
|
||||
"reason": "File content differs from repository"
|
||||
}
|
||||
when:
|
||||
- server_file_content.rc == 0
|
||||
- local_file_content.content | b64decode != server_file_content.content | b64decode
|
||||
|
||||
# Track drifted and synced files
|
||||
- name: Track drifted file ({{ item.name }})
|
||||
set_fact:
|
||||
drift_detected: true
|
||||
drifted_items: "{{ drifted_items + [file_drift_status | from_json] }}"
|
||||
when: file_has_drift
|
||||
|
||||
- name: Track synced file ({{ item.name }})
|
||||
set_fact:
|
||||
synced_items: "{{ synced_items + [{'name': item.name, 'destination': item.dest, 'status': 'SYNCED'}] }}"
|
||||
when: not file_has_drift
|
||||
|
||||
loop: "{{ deploy_items }}"
|
||||
loop_control:
|
||||
loop_var: item
|
||||
label: "{{ item.name }}"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 3: Generate JSON report with drift details
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Generate drift detection JSON report
|
||||
set_fact:
|
||||
drifted_files_json: "{{ drifted_items | to_nice_json }}"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 4: Save drift report to file for script consumption
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Save drift report to file
|
||||
copy:
|
||||
content: "{{ drifted_files_json }}"
|
||||
dest: "/tmp/drifted_files_{{ inventory_hostname }}.json"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
delegate_to: localhost
|
||||
register: local_file
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 2: Read file from server
|
||||
# Attempts to read dvir.txt from /tmp on the target server
|
||||
# Failure is allowed here (we'll handle it in next task)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Read server file
|
||||
slurp:
|
||||
src: /tmp/dvir.txt
|
||||
register: server_file
|
||||
failed_when: false
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 3: Compare file contents (if server file exists)
|
||||
# Decodes base64 and compares content between repo and server
|
||||
# Sets drift_detected to true if content differs
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Compare file contents
|
||||
set_fact:
|
||||
drift_detected: "{{ (local_file.content | b64decode) != (server_file.content | b64decode) }}"
|
||||
when: server_file.rc == 0
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 4: Mark as drift if server file is missing
|
||||
# If the server file doesn't exist, it's also considered drift
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Mark as drift if server file missing
|
||||
set_fact:
|
||||
drift_detected: true
|
||||
when: server_file.rc != 0
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 5: Output SYNCED status
|
||||
# Displayed when file on server matches repo file exactly
|
||||
# TASK 5: Output status summary
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Output SYNCED status
|
||||
debug:
|
||||
msg: "✓ dvir.txt is synced"
|
||||
msg: |
|
||||
✓ All files are in sync
|
||||
Synced files: {{ synced_items | length }}
|
||||
when: not drift_detected
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 6: Output OUT_OF_SYNC status
|
||||
# Displayed when file on server differs from repo or is missing
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Output OUT_OF_SYNC status
|
||||
- name: Output OUT_OF_SYNC status with details
|
||||
debug:
|
||||
msg: "✗ dvir.txt is out of sync"
|
||||
msg: |
|
||||
✗ Configuration drift detected!
|
||||
Drifted files: {{ drifted_items | length }}
|
||||
Details: {{ drifted_files_json }}
|
||||
when: drift_detected
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# TASK 6: Fail if drift detected (for CI/CD pipeline)
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
- name: Fail if drift detected
|
||||
fail:
|
||||
msg: "Configuration drift detected."
|
||||
msg: "Configuration drift detected. {{ drifted_items | length }} file(s) out of sync."
|
||||
when: drift_detected
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user