diff --git a/ansible/playbooks/drift-check.yml b/ansible/playbooks/drift-check.yml index ef35e74..254dea3 100644 --- a/ansible/playbooks/drift-check.yml +++ b/ansible/playbooks/drift-check.yml @@ -21,87 +21,94 @@ set_fact: drift_detected: false drifted_items: [] - synced_items: [] + drift_items_result: [] + synced_count: 0 # ───────────────────────────────────────────────────────────────────── - # TASK 2: Check each configured file for drift - # Compares local (repo) file with server file (content and existence) + # TASK 2: Read local files from repo # ───────────────────────────────────────────────────────────────────── - - 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 + - name: Read local files from repository + slurp: + src: "{{ playbook_dir }}/{{ '../../' + item.src }}" + delegate_to: localhost + register: local_files + loop: "{{ deploy_items }}" + loop_control: + loop_var: item + label: "{{ item.name }}" + 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 + # ───────────────────────────────────────────────────────────────────── + # TASK 3: Read files from server + # ───────────────────────────────────────────────────────────────────── + - name: Read files from servers + slurp: + src: "{{ item.dest }}" + register: server_files + loop: "{{ deploy_items }}" + loop_control: + loop_var: item + label: "{{ item.name }}" + failed_when: false + # ───────────────────────────────────────────────────────────────────── + # TASK 4: Detect drift for each file + # Compares local (repo) vs server file, detects missing or content diff + # ───────────────────────────────────────────────────────────────────── + - name: Detect drift for each file + set_fact: + drift_items_result: "{{ drift_items_result | default([]) + [file_drift_info] }}" + vars: + local_file: "{{ local_files.results[index] }}" + server_file: "{{ server_files.results[index] }}" + index: "{{ loop_index0 }}" + file_drift_info: | + {%- if server_file.rc != 0 -%} + { + "name": "{{ item.name }}", + "destination": "{{ item.dest }}", + "status": "MISSING", + "reason": "File not found on server" + } + {%- elif local_file.content | b64decode != server_file.content | b64decode -%} + { + "name": "{{ item.name }}", + "destination": "{{ item.dest }}", + "status": "CONTENT_DIFFERS", + "reason": "File content differs from repository" + } + {%- else -%} + {} + {%- endif -%} loop: "{{ deploy_items }}" loop_control: loop_var: item label: "{{ item.name }}" # ───────────────────────────────────────────────────────────────────── - # TASK 3: Generate JSON report with drift details + # TASK 5: Filter drifted files + # ───────────────────────────────────────────────────────────────────── + - name: Extract drifted files + set_fact: + drifted_items: "{{ drift_items_result | map('from_json') | selectattr('status', 'defined') | list }}" + synced_count: "{{ drift_items_result | map('from_json') | rejectattr('status', 'defined') | list | length }}" + + # ───────────────────────────────────────────────────────────────────── + # TASK 6: Update drift detection flag + # ───────────────────────────────────────────────────────────────────── + - name: Set drift_detected flag + set_fact: + drift_detected: "{{ drifted_items | length > 0 }}" + + # ───────────────────────────────────────────────────────────────────── + # TASK 7: 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 + # TASK 8: Save drift report to file for script consumption # ───────────────────────────────────────────────────────────────────── - name: Save drift report to file copy: @@ -113,13 +120,13 @@ delegate_to: localhost # ───────────────────────────────────────────────────────────────────── - # TASK 5: Output status summary + # TASK 9: Output status summary # ───────────────────────────────────────────────────────────────────── - name: Output SYNCED status debug: msg: | ✓ All files are in sync - Synced files: {{ synced_items | length }} + Synced files: {{ synced_count }} when: not drift_detected - name: Output OUT_OF_SYNC status with details @@ -131,7 +138,7 @@ when: drift_detected # ───────────────────────────────────────────────────────────────────── - # TASK 6: Fail if drift detected (for CI/CD pipeline) + # TASK 10: Fail if drift detected (for CI/CD pipeline) # ───────────────────────────────────────────────────────────────────── - name: Fail if drift detected fail: