Compare commits

..

80 Commits
test ... master

Author SHA1 Message Date
dvirlabs
c83725a027 Make this repo generic
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-05-20 16:07:38 +03:00
dvirlabs
59204be5fe test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-29 11:24:44 +03:00
dvirlabs
00f4c4b730 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-29 11:13:10 +03:00
dvirlabs
80e39650f9 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-29 10:01:17 +03:00
dvirlabs
8b62ba780d test
Some checks failed
ci/woodpecker/cron/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-29 10:00:15 +03:00
dvirlabs
81263fc950 test
Some checks failed
ci/woodpecker/cron/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-29 09:59:10 +03:00
dvirlabs
ea9004e382 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-29 09:57:35 +03:00
dvirlabs
b39537c3e3 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-29 09:47:33 +03:00
7a83b68feb test
Some checks failed
ci/woodpecker/cron/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 16:22:17 +03:00
17a6311792 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 16:19:20 +03:00
db79f854f4 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 16:15:32 +03:00
5f6f641bb4 drift-check recursive
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 16:13:34 +03:00
5c52acf456 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:49:32 +03:00
287bb60211 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:48:18 +03:00
fa9ab6e123 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:41:18 +03:00
0b799bef84 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:33:50 +03:00
bbd675460f Works perfect
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:24:50 +03:00
dc1dce2e07 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-24 15:21:04 +03:00
89dd8aeb40 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline failed
2026-04-24 15:13:21 +03:00
05c190bb9b Fix files
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 15:12:04 +03:00
549fc97b54 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:30:17 +03:00
d2e747880c test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:27:24 +03:00
c0b4cf27c6 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:22:52 +03:00
1b1b9a1dfd test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:21:26 +03:00
1b9a7d85ce test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:18:03 +03:00
d7b580c9aa test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:16:59 +03:00
eddad9b770 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-24 02:14:46 +03:00
fa682da7a6 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:05:49 +03:00
7958cf54b4 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 02:04:39 +03:00
7ad21286e3 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-24 02:03:09 +03:00
20a3c14d66 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 01:55:12 +03:00
f3c947c9c4 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 01:53:48 +03:00
1968e787b1 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 01:48:17 +03:00
b16aa7cc7e test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-24 01:46:13 +03:00
4a2629ae0e test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-24 01:42:57 +03:00
dvirlabs
16702cb408 test: Config change for line ending normalization verification
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 14:06:35 +03:00
dvirlabs
66df6c74ec fix: Normalize line endings in drift-check content comparison
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
CRITICAL FIX FOR WINDOWS:

Problem: Git on Windows uses CRLF, but deployed files use LF. When comparing
with slurp (byte-for-byte base64 comparison), CRLF != LF causes false positives.

Solution: Decode base64 content and normalize line endings:
  - Replace CRLF with LF in both Git and server file content
  - Then compare the normalized content

This ensures that line ending differences don't trigger false OUT_OF_SYNC alerts.
After deploy, content will match regardless of platform line ending differences.
2026-04-23 14:06:14 +03:00
dvirlabs
96bd931e2f test: Config change for drift detection debugging
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 14:00:55 +03:00
dvirlabs
2b6b3011a6 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 13:30:54 +03:00
dvirlabs
4d5880c232 test: Trigger pipeline with fd fix verification
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 13:28:41 +03:00
dvirlabs
ac4278a451 fix: Simplify drift-check to avoid fsnotify watcher exhaustion
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
CRITICAL FIX:

Problem: Previous version used multiple stat operations and loops which created
too many file descriptors and fsnotify watchers, causing 'too many open files' errors.

Solution: Use only:
- slurp: Direct file content reading (no watchers)
- find: Single operation to list directory files (no loops)

New logic is clean and simple:
1. Read Git rsyslog.conf + server rsyslog.conf (slurp)
2. Compare content directly (byte comparison)
3. List Git rsyslog.d files + server rsyslog.d files (find)
4. Compare file names (no permission checks, no loops)
5. Output DRIFTED_FILES and SYNC_STATUS markers

This eliminates file descriptor exhaustion while maintaining correct drift detection.
After deploy, when content matches, playbook exits 0 (SYNCED).
2026-04-23 13:28:16 +03:00
dvirlabs
2b192dd26a test: Re-verify sync detection with checksum-based comparison
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 13:21:39 +03:00
dvirlabs
1cbe3d4de7 fix: Use checksum-based content comparison to avoid permission-based drift false positives
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
CRITICAL FIX:

Problem: drift-check.yml was using 'copy' module in check_mode, which compares:
  - File content ✓
  - Permissions (owner, group, mode) ✗
  - Ownership ✗

After deploy, files have root:root 0644 permissions. Even though content matches,
the copy module marked files as 'changed' because permissions were being compared.
This caused false OUT_OF_SYNC reports even when configuration was actually synced.

Solution: Use MD5 checksum-based comparison instead:
  - Compare only file CONTENT using stat checksums
  - Ignore permissions/ownership differences
  - This is what matters for config management

Also fixed URLs:
  - Changed back from port 80 to port 5000 (API only)
  - Updated service name to gitops-status-api

Now drift detection only triggers on actual config changes, not permission differences.
After successful deploy, should correctly report SYNCED status.
2026-04-23 13:21:20 +03:00
dvirlabs
57870e65ce test: Verify GitOps sync detection with simple comment change
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 13:14:00 +03:00
dvirlabs
380eaf175a fix: Resolve OUT_OF_SYNC false positive after successful deploy
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
CRITICAL FIXES:

1. Fix API URL port: 5000 → 80 (.woodpecker.yml)
   - update-gitops-status step was POSTing to wrong port
   - gitops-status-server Service exposes port 80, not 5000
   - This caused silent POST failures that weren't detected

2. Initialize missing_on_server variable (drift-check.yml)
   - Variable was only set inside block scope
   - Could remain undefined if block failed or didn't execute
   - Now initialized to empty list before block runs
   - Prevents undefined variable errors in container environment

3. Fix drift detection logic (drift-check.yml)
   - Changed from: drift_detected uses extra_files_on_server flag
   - Changed to: drift_detected directly checks missing_on_server length
   - Adds safety with | default([]) filter
   - Prevents false positives when extra_files_on_server wasn't set properly

ROOT CAUSE:
The combination of port 5000, uninitialized variables, and flag-based logic
caused the playbook to report OUT_OF_SYNC without listing changed files
(drift_count=0, files=[]). After deployment, server config matches Git,
so drift_detected should be false and playbook should exit 0 with SYNCED status.

Now correctly reports SYNCED after successful deploy.
2026-04-23 13:13:07 +03:00
dvirlabs
d200914057 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-23 12:55:25 +03:00
dvirlabs
06827001e6 Ajust the pipeline to the new api
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-23 12:50:46 +03:00
dvirlabs
6420a584c4 test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-23 12:33:08 +03:00
dvirlabs
5285f4c241 debug: Add comprehensive debugging for drift detection and JSON POSTing
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Add debug output showing rsyslogd_check.diff structure
- Simplify file extraction logic for rsyslog.d directory changes
- Show full JSON payload before sending to API
- Add connectivity test to gitops-status-server before POST
- Show curl command and response codes for debugging
- Display warning if OUT_OF_SYNC but no files extracted

This helps diagnose why drift is detected but files aren't listed in the JSON.
2026-04-23 11:52:32 +03:00
dvirlabs
de99902959 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-23 11:43:19 +03:00
dvirlabs
cdec5ce87c Debug api request
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-23 11:40:17 +03:00
e8fed366b4 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-23 00:35:03 +03:00
7d3dbf6395 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 23:55:59 +03:00
b9af1e4534 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 23:52:52 +03:00
1837b7794b test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 23:50:12 +03:00
e500e21fab fix: resolve OUT_OF_SYNC and empty files array issues
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Root causes:
1. Inconsistent Ansible callback (minimal) broke debug output parsing
2. DRIFTED_FILES extraction failed due to format changes
3. Files array stayed empty even when drift was detected

Fixes:
1. Use YAML callback for consistent, structured output
2. Improve DRIFTED_FILES parsing to handle YAML format
3. Remove conflicting ANSIBLE_CALLBACKS_ENABLED/minimal settings
4. Add GITOPS_STATUS_FIX.md with complete analysis

Result:
- Files array now populates correctly when drift exists
- Sync status accurately reflects actual server state
- Better debug logging for troubleshooting

See GITOPS_STATUS_FIX.md for full root cause analysis and testing guide.
2026-04-22 23:46:14 +03:00
be352ae9c9 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 23:20:07 +03:00
4212daba7a test: trigger pipeline with improved DRIFTED_FILES parsing
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 23:05:31 +03:00
46b0bb449e fix: improve DRIFTED_FILES parsing and reduce file descriptor issues
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
- Add comprehensive debug output to track parsing steps
- Fix DRIFTED_FILES extraction from Ansible output
- Always output DRIFTED_FILES line (even when empty) for reliable parsing
- Add ANSIBLE_CALLBACKS_ENABLED='' to prevent inotify exhaustion
- Add KEEP_PLAYBOOK_LOG option for debugging
- Add validation warning when OUT_OF_SYNC but no files found
- Create DEBUGGING_GITOPS_STATUS.md guide
2026-04-22 23:03:34 +03:00
57911b7f52 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 22:57:15 +03:00
654259c7cd test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 22:56:11 +03:00
15b0e153f0 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 22:48:24 +03:00
8e54f82e12 Fix update-gitops-status
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 22:46:18 +03:00
dvirlabs
6fbadf73e3 Fix failed step
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-22 21:57:15 +03:00
dvirlabs
fc8cb0c40e fix: Resolve 'too many open files' error in pipeline
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Remove -v verbose flag from ansible-playbook (was causing file descriptor exhaustion)
- Add recurse: false to find tasks (prevents recursive directory traversal)
- Set ulimit -n 4096 in Woodpecker container to increase FD limit
- Add ANSIBLE_* environment variables for container optimization:
  - ANSIBLE_HOST_KEY_CHECKING=False (skip SSH key verification)
  - ANSIBLE_CALLBACK_WHITELIST=minimal (reduce output verbosity)
  - ANSIBLE_FORCE_COLOR=False (no ANSI color codes)
  - ANSIBLE_RETRY_FILES_ENABLED=False (don't create retry files)

This resolves fsnotify watcher errors in container environments with low FD limits.
2026-04-22 21:54:00 +03:00
dvirlabs
f926b7eb0d Update drift-check to let the pipeline update also what files changed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-22 21:50:39 +03:00
dvirlabs
7aeb957eb3 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 21:43:37 +03:00
dvirlabs
7cf1380007 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-22 21:21:49 +03:00
dvirlabs
adc8d1e50c Update pipeline
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-21 19:55:14 +03:00
dvirlabs
1bac032155 Fix: Enhanced error reporting and response verification in update-gitops-status.sh
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Capture and display full curl response body for debugging
- Add verification step to confirm JSON was stored on server
- Improve error messages with connectivity troubleshooting hints
2026-04-21 12:46:41 +03:00
dvirlabs
db28c9da82 Migrate from pushgateway to infinity
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-21 12:41:09 +03:00
dvirlabs
c18acce05e test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-21 12:13:47 +03:00
082ed0a0a4 Migrate to infinity datasource
Some checks failed
ci/woodpecker/cron/woodpecker Pipeline failed
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-21 04:54:47 +03:00
dvirlabs
3282870e8f test
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-20 13:23:35 +03:00
dvirlabs
b3e96d343f test amit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-20 12:35:10 +03:00
dvirlabs
197647fb15 test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-19 11:35:36 +03:00
dvirlabs
5c7fdf101e test
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-19 11:13:57 +03:00
5219f32d79 Add README.md
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-19 07:05:36 +03:00
3a8ad2a1e2 test new branch
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
2026-04-19 06:08:14 +03:00
ea7e1ee066 Merge pull request 'test new branch' (#2) from test into master
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/cron/woodpecker Pipeline was successful
Reviewed-on: #2
2026-04-19 03:05:21 +00:00
12 changed files with 531 additions and 444 deletions

View File

@ -8,13 +8,15 @@
# so a drift-check here would always be OUT_OF_SYNC by # so a drift-check here would always be OUT_OF_SYNC by
# design and is meaningless as a failure signal. # design and is meaningless as a failure signal.
# #
# push (master) → syntax-check, validate, deploy, update-sync-metric # push (master) → syntax-check, validate, deploy, update-gitops-status
# Deploys to the server, then verifies sync and pushes metric. # Deploys to the server, then verifies sync and sends
# JSON status snapshot to gitops-status-server for Grafana.
# #
# cron → gitops_sync_check (read-only drift check, no deploy) # cron → gitops_sync_check (read-only drift check, no deploy)
# Continuously verifies that the live server still matches # Continuously verifies that the live server still matches
# Git even when no push has happened. Detects manual edits # Git even when no push has happened. Detects manual edits
# made directly on the server. # made directly on the server. Sends JSON status with
# detailed file-level drift information to gitops-status-server.
# #
# NOTE: Woodpecker does not support multiple YAML documents (---) in one file. # NOTE: Woodpecker does not support multiple YAML documents (---) in one file.
# All pipelines must live in a single document with step-level filtering. # All pipelines must live in a single document with step-level filtering.
@ -80,44 +82,48 @@ steps:
event: push event: push
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# update-sync-metric: Post-deploy sync check + Prometheus metric push # update-gitops-status: Post-deploy sync check + JSON status update
# Runs on push to master only, after deploy succeeds. # Runs on push to master only, after deploy succeeds.
# STATUS=1 means SYNCED, STATUS=0 means OUT_OF_SYNC. # Generates structured JSON with sync status, drift count, and changed files.
# Sends JSON to gitops-status-server for Grafana visualization.
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
update-sync-metric: update-gitops-status:
image: alpine/ansible:latest image: alpine/ansible:latest
depends_on: [deploy] depends_on: [deploy]
environment: environment:
ANSIBLE_CONFIG: ansible.cfg ANSIBLE_CONFIG: ansible.cfg
SSH_PRIVATE_KEY: SSH_PRIVATE_KEY:
from_secret: SSH_PRIVATE_KEY from_secret: SSH_PRIVATE_KEY
PUSHGATEWAY_URL: http://pushgateway.observability-stack.svc.cluster.local:9091 GITOPS_STATUS_SERVER_URL: http://gitops-status-server.observability-stack.svc.cluster.local:5000
REPO_NAME: rsyslog
SERVER_NAME: rsyslog-lab
MODE: post-deploy
# Optimize Ansible for container environment
ANSIBLE_HOST_KEY_CHECKING: "False"
ANSIBLE_FORCE_COLOR: "False"
ANSIBLE_RETRY_FILES_ENABLED: "False"
ANSIBLE_UNSAFE_WRITES: "True"
ANSIBLE_FORKS: "1"
commands: commands:
- | - |
apk add --no-cache curl > /dev/null 2>&1 # Increase file descriptor limit for Ansible (max safe value)
ulimit -n 65536
# Install dependencies: git for detecting deployed files, curl for HTTP requests, jq for JSON formatting
apk add --no-cache git curl jq > /dev/null 2>&1
# Setup SSH key for Ansible
mkdir -p ~/.ssh mkdir -p ~/.ssh
printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa
echo "==> Verifying post-deploy sync status..." echo "==> Running post-deploy GitOps status check..."
set +e
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/drift-check.yml
DRIFT_RC=$?
set -e
if [ "$DRIFT_RC" -eq 0 ]; then # Make script executable and run it
STATUS=1 chmod +x update-gitops-status.sh
echo "==> SYNCED (1) server configuration matches Git" ./update-gitops-status.sh
else
STATUS=0
echo "==> OUT OF SYNC (0) drift detected after deploy"
fi
printf 'gitops_sync_status{repo="rsyslog",server="rsyslog-lab"} %s\n' "$STATUS" | \ echo "==> JSON status update complete. Pipeline always succeeds."
curl --silent --show-error --fail --data-binary @- \
"$${PUSHGATEWAY_URL}/metrics/job/gitops_rsyslog/instance/rsyslog-lab"
echo "==> Metric pushed. Pipeline always succeeds; sync status is in Prometheus."
when: when:
branch: master branch: master
event: push event: push
@ -125,13 +131,14 @@ steps:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# gitops_sync_check: ArgoCD-style cron drift check read-only, no deploy # gitops_sync_check: ArgoCD-style cron drift check read-only, no deploy
# Detects manual changes made directly on the server between pushes. # Detects manual changes made directly on the server between pushes.
# STATUS=1 → SYNCED, STATUS=0 → OUT_OF_SYNC # Generates structured JSON with sync status, drift count, and changed files.
# Pipeline marked FAILED when drift found so it is visible in the UI. # Sends JSON to gitops-status-server for continuous GitOps monitoring.
# Pipeline always succeeds - check Grafana dashboard for drift status.
# #
# ─── Woodpecker Cron UI settings ────────────────────────────────────────── # ─── Woodpecker Cron UI settings ──────────────────────────────────────────
# Name: gitops_sync_check # Name: gitops_sync_check
# Branch: master # Branch: master
# Schedule: */2 * * * * # Schedule: */1 * * * * (every 1 minute for testing, adjust as needed)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
gitops_sync_check: gitops_sync_check:
image: alpine/ansible:latest image: alpine/ansible:latest
@ -139,34 +146,35 @@ steps:
ANSIBLE_CONFIG: ansible.cfg ANSIBLE_CONFIG: ansible.cfg
SSH_PRIVATE_KEY: SSH_PRIVATE_KEY:
from_secret: SSH_PRIVATE_KEY from_secret: SSH_PRIVATE_KEY
PUSHGATEWAY_URL: http://pushgateway.observability-stack.svc.cluster.local:9091 GITOPS_STATUS_SERVER_URL: http://gitops-status-server.observability-stack.svc.cluster.local:5000
REPO_NAME: rsyslog
SERVER_NAME: rsyslog-lab
# Optimize Ansible for container environment
ANSIBLE_HOST_KEY_CHECKING: "False"
ANSIBLE_FORCE_COLOR: "False"
ANSIBLE_RETRY_FILES_ENABLED: "False"
ANSIBLE_UNSAFE_WRITES: "True"
ANSIBLE_FORKS: "1"
commands: commands:
- | - |
apk add --no-cache curl > /dev/null 2>&1 # Increase file descriptor limit for Ansible (max safe value)
ulimit -n 65536
# Install dependencies: curl for HTTP requests, jq for JSON formatting
apk add --no-cache curl jq bash > /dev/null 2>&1
# Setup SSH key for Ansible
mkdir -p ~/.ssh mkdir -p ~/.ssh
printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa
echo "==> [cron] Running drift check against remote server..." echo "==> [cron] Running continuous GitOps drift check..."
set +e
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/drift-check.yml
DRIFT_RC=$?
set -e
if [ "$DRIFT_RC" -eq 0 ]; then # Make script executable and run it (always succeeds - just updates JSON)
STATUS=1 chmod +x update-gitops-status.sh
echo "==> STATUS: SYNCED (1) server configuration matches Git" ./update-gitops-status.sh
else
STATUS=0
echo "==> STATUS: OUT OF SYNC (0) manual drift detected on server"
fi
echo "==> Pushing metric: gitops_sync_status{repo=\"rsyslog\",server=\"rsyslog-lab\"} $STATUS" echo "==> Cron drift check complete. JSON status updated successfully."
printf 'gitops_sync_status{repo="rsyslog",server="rsyslog-lab"} %s\n' "$STATUS" | \ echo " Pipeline always succeeds. Check gitops-status-server for sync status."
curl --silent --show-error --fail --data-binary @- \
"$${PUSHGATEWAY_URL}/metrics/job/gitops_rsyslog/instance/rsyslog-lab"
echo "==> Metric pushed. Pipeline always succeeds; sync status is in Prometheus."
when: when:
event: cron event: cron

348
README.md Normal file
View File

@ -0,0 +1,348 @@
# File Deployment & GitOps Management
A simple, generic Ansible-based system to deploy and manage files on multiple servers using Git as the single source of truth.
---
## Overview
This repository uses **Ansible** to:
- **Deploy** files from Git to target servers
- **Check Drift** to ensure servers stay in sync with the repository
- **Validate** that deployed files are correct
No rsyslog-specific code. Just simple file deployment that works for any file or service.
---
## Project Structure
```
.
├── README.md # This file
├── ansible.cfg # Ansible configuration
├── .woodpecker.yml # CI/CD pipeline configuration
├── ansible/
│ ├── inventory/
│ │ ├── hosts.yml # Define target servers
│ │ └── group_vars/
│ │ └── all.yml # Global variables (SSH credentials, etc.)
│ │
│ └── playbooks/
│ ├── apply.yml # Deploy file to servers
│ ├── drift-check.yml # Check if servers are in sync with repo
│ └── validate.yml # Verify file exists on server
└── files/
└── dvir.txt # The file to deploy (edit this to your needs)
```
---
## How It Works (Simple Version)
1. **You edit the file** in `files/dvir.txt`
2. **You commit to Git** (the source of truth)
3. **Run `apply.yml`** to deploy to all servers
4. **Run `drift-check.yml`** anytime to verify servers match Git
5. **If drift is detected**, run `apply.yml` again to fix it
That's it!
---
## Quick Start
### 1. Edit the file you want to deploy
Open `files/dvir.txt` and add your content:
```bash
nano files/dvir.txt
```
To deploy a **different file**, rename it or update the paths in the playbooks.
### 2. Add target servers
Edit `ansible/inventory/hosts.yml`:
```yaml
all:
children:
servers:
hosts:
server1:
ansible_host: 192.168.10.161
server2:
ansible_host: 192.168.10.162
```
### 3. Run the playbooks
#### Deploy the file:
```bash
ansible-playbook ansible/playbooks/apply.yml
```
#### Check if servers are in sync:
```bash
ansible-playbook ansible/playbooks/drift-check.yml
```
#### Validate file on server:
```bash
ansible-playbook ansible/playbooks/validate.yml
```
---
## Playbook Breakdown
### `apply.yml` - Deploy Files
**What it does:**
- Copies `files/dvir.txt` to `/tmp/dvir.txt` on all target servers
- Sets file ownership to `root:root` with permissions `0644`
**When to use:**
- Initial deployment of the file
- After updating the file in Git
**Example:**
```bash
ansible-playbook ansible/playbooks/apply.yml
```
---
### `drift-check.yml` - Detect Configuration Drift
**What it does:**
- Reads the file from the Git repository (local)
- Reads the file from each target server (`/tmp/dvir.txt`)
- Compares the content byte-for-byte
- Reports `SYNCED` or `OUT_OF_SYNC`
**When to use:**
- Verify servers match the repository state
- Detect if someone manually changed the file on the server
- Run periodically (via cron or CI/CD) to monitor compliance
**Example:**
```bash
ansible-playbook ansible/playbooks/drift-check.yml
```
**Output:**
```
✓ dvir.txt is synced # Files match
✗ dvir.txt is out of sync # Files differ or file missing
```
---
### `validate.yml` - Validate Deployment
**What it does:**
- Checks that `/tmp/dvir.txt` exists on the server
- Verifies the file is readable
- Fails if the file is missing or not readable
**When to use:**
- After running `apply.yml` to verify success
- To confirm the deployment was successful
**Example:**
```bash
ansible-playbook ansible/playbooks/validate.yml
```
---
## Configuration
### Inventory: `ansible/inventory/hosts.yml`
Define which servers to manage:
```yaml
all:
children:
servers:
hosts:
server1:
ansible_host: 192.168.10.161
server2:
ansible_host: 192.168.10.162
```
### Global Variables: `ansible/inventory/group_vars/all.yml`
SSH and connection settings:
```yaml
ansible_user: root
ansible_ssh_private_key_file: "~/.ssh/id_rsa"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
```
### Ansible Config: `ansible.cfg`
Global Ansible settings (host checking, plugins, etc.)
---
## Workflow Examples
### Example 1: Deploy a new file
```bash
# 1. Edit the file
echo "new config content" > files/dvir.txt
# 2. Commit to Git
git add files/dvir.txt
git commit -m "Update deployment file"
git push
# 3. Deploy to servers
ansible-playbook ansible/playbooks/apply.yml
# 4. Verify success
ansible-playbook ansible/playbooks/validate.yml
```
### Example 2: Monitor for drift (continuous compliance)
```bash
# Run drift check periodically (cron job)
0 */6 * * * cd /path/to/repo && ansible-playbook ansible/playbooks/drift-check.yml
```
### Example 3: Detect and fix manual changes
```bash
# Someone manually edited /tmp/dvir.txt on server1
# Check for drift
ansible-playbook ansible/playbooks/drift-check.yml
# Output: ✗ dvir.txt is out of sync
# Restore from Git
ansible-playbook ansible/playbooks/apply.yml
# Verify it's fixed
ansible-playbook ansible/playbooks/drift-check.yml
# Output: ✓ dvir.txt is synced
```
---
## Prerequisites
- **Ansible** installed on your machine
- **SSH access** to all target servers (password or key-based)
- **Root or sudo access** on target servers (for writing to `/tmp`)
### Install Ansible
```bash
# macOS
brew install ansible
# Ubuntu/Debian
apt-get install ansible
# RHEL/CentOS
yum install ansible
# Python pip
pip install ansible
```
---
## Customization
### Deploy to a different path
Edit `ansible/playbooks/apply.yml`:
```yaml
- name: Copy file to destination
copy:
src: ../../files/dvir.txt
dest: /your/custom/path/filename.txt # ← Change this
owner: root
group: root
mode: "0644"
```
### Deploy multiple files
Add more tasks to `apply.yml`:
```yaml
- name: Copy file 1
copy:
src: ../../files/dvir.txt
dest: /tmp/dvir.txt
- name: Copy file 2
copy:
src: ../../files/another.txt
dest: /tmp/another.txt
```
### Use different target servers
Edit `hosts.yml` and use:
```bash
ansible-playbook ansible/playbooks/apply.yml -i ansible/inventory/hosts.yml --limit "server2"
```
---
## Troubleshooting
### "SSH connection refused"
- Check `ansible_host` is correct in `hosts.yml`
- Verify SSH key in `group_vars/all.yml`
- Test manually: `ssh -i ~/.ssh/id_rsa root@192.168.10.161`
### "Permission denied" on deployment
- Ensure `become: true` is in the playbook
- Verify user has sudo access
- Check SSH key has correct permissions: `chmod 600 ~/.ssh/id_rsa`
### Drift check shows "out of sync" but I didn't change anything
- File permissions or ownership might have changed
- Line endings (CRLF vs LF) might differ
- The server file might be missing
### Can't read file on server
- Check `/tmp/dvir.txt` exists: `ls -la /tmp/dvir.txt`
- Verify permissions: `stat /tmp/dvir.txt`
- Ensure file is readable: `cat /tmp/dvir.txt`
---
## Tips & Best Practices
1. **Always commit before deploying**
- Use Git as the single source of truth
- Never manually edit `/tmp/dvir.txt` on servers
2. **Run drift-check regularly**
- Use cron or CI/CD to monitor compliance
- Alert on `OUT_OF_SYNC` status
3. **Test in dev first**
- Add a `dev` group in `hosts.yml`
- Test playbooks on dev servers before prod
4. **Use version control for everything**
- Keep all changes in Git
- Easy rollback: just revert and re-run `apply.yml`
---
## License
MIT (or your preferred license)

View File

@ -1,17 +1,7 @@
--- ---
# Global variables for rsyslog configuration management # Global variables for deployment
# Ansible connection settings # Ansible connection settings
ansible_user: root ansible_user: root
ansible_ssh_private_key_file: "~/.ssh/id_rsa" ansible_ssh_private_key_file: "~/.ssh/id_rsa"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no" ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
# Root directory of the rsyslog repository
repo_root: /root/rsyslog
# rsyslog service name
rsyslog_service: rsyslog
# Configuration paths
rsyslog_main_config: /etc/rsyslog.conf
rsyslog_config_dir: /etc/rsyslog.d

View File

@ -1,12 +1,12 @@
--- ---
all: all:
children: children:
rsyslog_servers: servers:
hosts: hosts:
rsyslog-lab: server1:
ansible_host: 192.168.10.161 ansible_host: 192.168.10.161
# Future servers can be added here: # Add more servers here:
# rsyslog-prod: # server2:
# ansible_host: 192.168.10.162 # ansible_host: 192.168.10.162
# rsyslog-backup: # server3:
# ansible_host: 192.168.10.163 # ansible_host: 192.168.10.163

View File

@ -1,145 +1,31 @@
--- ---
- name: Apply rsyslog configuration (safe staged deployment) # =============================================================================
hosts: rsyslog_servers # APPLY PLAYBOOK
# Purpose: Deploy dvir.txt file to target servers at /tmp/dvir.txt
# Usage: ansible-playbook apply.yml
# =============================================================================
- name: Deploy file to servers
hosts: all
become: true become: true
vars:
backup_dir: /var/backups/rsyslog-ansible
backup_conf: "{{ backup_dir }}/rsyslog.conf.bak"
backup_confd: "{{ backup_dir }}/rsyslog.d.bak"
tasks: tasks:
# ─────────────────────────────────────────────────────────────────────
# ------------------------------------------------------------------------- # TASK 1: Copy file to destination
# STAGE 1 — Backup current working configuration # Copies the dvir.txt from the repo to /tmp/dvir.txt on target servers
# ------------------------------------------------------------------------- # ─────────────────────────────────────────────────────────────────────
- name: Copy file to destination
- name: Ensure backup directory exists
file:
path: "{{ backup_dir }}"
state: directory
mode: "0700"
- name: Backup current rsyslog.conf
copy: copy:
src: "{{ rsyslog_main_config }}" src: ../../files/dvir.txt
dest: "{{ backup_conf }}" dest: /tmp/dvir.txt
remote_src: true
mode: "0600"
- name: Remove stale rsyslog.d backup
file:
path: "{{ backup_confd }}"
state: absent
- name: Backup current rsyslog.d directory
copy:
src: "{{ rsyslog_config_dir }}/"
dest: "{{ backup_confd }}/"
remote_src: true
# -------------------------------------------------------------------------
# STAGE 2 — Deploy new configuration files from repo
# -------------------------------------------------------------------------
- name: Copy new rsyslog.conf from repo
copy:
src: ../../files/rsyslog.conf
dest: "{{ rsyslog_main_config }}"
owner: root owner: root
group: root group: root
mode: "0644" mode: "0644"
- name: Copy new rsyslog.d configs from repo # ─────────────────────────────────────────────────────────────────────
copy: # TASK 2: Confirm deployment success
src: ../../files/rsyslog.d/ # Displays success message with the hostname for verification
dest: "{{ rsyslog_config_dir }}/" # ─────────────────────────────────────────────────────────────────────
owner: root - name: Confirm deployment
group: root
mode: "0644"
# -------------------------------------------------------------------------
# STAGE 3 — Validate against the full real config tree on the remote host
# Runs rsyslogd -N1 against the actual /etc/rsyslog.conf so all includes,
# modules, and templates are resolved in the real environment.
# -------------------------------------------------------------------------
- name: Validate new configuration on remote host
command: rsyslogd -N1 -f "{{ rsyslog_main_config }}"
register: validation_result
changed_when: false
failed_when: false # We handle failure manually below
# -------------------------------------------------------------------------
# STAGE 4a — Validation FAILED: restore backup and abort
# -------------------------------------------------------------------------
- name: Print validation error output
debug: debug:
msg: | msg: "✅ File deployed successfully to /tmp/dvir.txt on {{ inventory_hostname }}"
##################################################
❌ RSYSLOG VALIDATION FAILED
##################################################
HOST : {{ inventory_hostname }} ({{ ansible_host }})
RC : {{ validation_result.rc }}
--- STDOUT ----------------------------------
{{ validation_result.stdout | default('(empty)') }}
--- STDERR ----------------------------------
{{ validation_result.stderr | default('(empty)') }}
##################################################
⚠ Rolling back to previous working configuration
##################################################
when: validation_result.rc != 0
- name: Restore rsyslog.conf from backup
copy:
src: "{{ backup_conf }}"
dest: "{{ rsyslog_main_config }}"
remote_src: true
mode: "0644"
when: validation_result.rc != 0
- name: Restore rsyslog.d from backup
copy:
src: "{{ backup_confd }}/"
dest: "{{ rsyslog_config_dir }}/"
remote_src: true
when: validation_result.rc != 0
- name: Fail pipeline — config restored to previous working state
fail:
msg: |
##################################################
❌ PIPELINE FAILED — rsyslog validation error
##################################################
Previous working config has been restored.
rsyslog was NOT restarted.
rc={{ validation_result.rc }}
stderr: {{ validation_result.stderr | default('(empty)') }}
##################################################
when: validation_result.rc != 0
# -------------------------------------------------------------------------
# STAGE 4b — Validation PASSED: restart rsyslog and report success
# -------------------------------------------------------------------------
- name: Restart rsyslog service
service:
name: "{{ rsyslog_service }}"
state: restarted
when: validation_result.rc == 0
- name: Print success status
debug:
msg: |
##################################################
✅ RSYSLOG CONFIGURATION DEPLOYED SUCCESSFULLY
##################################################
HOST : {{ inventory_hostname }} ({{ ansible_host }})
STATUS : Validation passed. Service restarted.
##################################################
when: validation_result.rc == 0

View File

@ -1,101 +1,76 @@
--- ---
- name: Check rsyslog configuration drift # =============================================================================
hosts: rsyslog_servers # DRIFT-CHECK PLAYBOOK
# Purpose: Compare file on repo vs server to detect if they're in sync
# Usage: ansible-playbook drift-check.yml
# Output: SYNCED or OUT_OF_SYNC status
# =============================================================================
- name: Check file drift
hosts: all
gather_facts: false gather_facts: false
# NOTE: src paths below resolve relative to the Ansible controller (the
# Woodpecker CI container), so they always reflect the latest Git commit
# NOT the server's local clone, which may be stale.
tasks: tasks:
# ------------------------------------------------------------------------- # ─────────────────────────────────────────────────────────────────────
# Use Ansible copy in check_mode so it compares controller files (Git) # TASK 1: Read local file from repo
# against live server files without actually writing anything. # Reads dvir.txt from the local repository using base64 encoding
# changed=true → file differs → drift # ─────────────────────────────────────────────────────────────────────
# changed=false → files match → synced - name: Read local file
# ------------------------------------------------------------------------- slurp:
- name: Check main rsyslog.conf src: "{{ playbook_dir }}/../../files/dvir.txt"
ansible.builtin.copy:
src: "{{ playbook_dir }}/../../files/rsyslog.conf"
dest: "{{ rsyslog_main_config }}"
owner: root
group: root
mode: '0644'
check_mode: true
diff: true
register: main_config_check
- name: Check rsyslog.d config files
ansible.builtin.copy:
src: "{{ playbook_dir }}/../../files/rsyslog.d/"
dest: "{{ rsyslog_config_dir }}/"
owner: root
group: root
mode: '0644'
check_mode: true
diff: true
register: rsyslogd_check
- name: Check for extra files on server not present in Git
block:
- name: Find config files on server
ansible.builtin.find:
paths: "{{ rsyslog_config_dir }}"
patterns: "*.conf"
register: server_configs
- name: Find config files in Git (controller)
ansible.builtin.find:
paths: "{{ playbook_dir }}/../../files/rsyslog.d"
patterns: "*.conf"
delegate_to: localhost delegate_to: localhost
register: repo_configs register: local_file
- name: Build list of Git-managed filenames # ─────────────────────────────────────────────────────────────────────
ansible.builtin.set_fact: # TASK 2: Read file from server
git_filenames: "{{ repo_configs.files | map(attribute='path') | map('basename') | list }}" # 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
- name: Build list of server filenames # ─────────────────────────────────────────────────────────────────────
ansible.builtin.set_fact: # TASK 3: Compare file contents (if server file exists)
server_filenames: "{{ server_configs.files | map(attribute='path') | map('basename') | list }}" # 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
- name: Find server files that are managed by Git but missing on server # ─────────────────────────────────────────────────────────────────────
ansible.builtin.set_fact: # TASK 4: Mark as drift if server file is missing
missing_on_server: "{{ git_filenames | difference(server_filenames) }}" # 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
- name: Flag if any Git-managed file is missing from server # ─────────────────────────────────────────────────────────────────────
ansible.builtin.set_fact: # TASK 5: Output SYNCED status
extra_files_on_server: true # Displayed when file on server matches repo file exactly
when: missing_on_server | length > 0 # ─────────────────────────────────────────────────────────────────────
- name: Output SYNCED status
- name: Show missing files debug:
ansible.builtin.debug: msg: "✓ dvir.txt is synced"
msg: "Files in Git but missing on server: {{ missing_on_server }}"
when: missing_on_server | length > 0
- name: Set overall drift flag
ansible.builtin.set_fact:
drift_detected: "{{ main_config_check.changed or rsyslogd_check.changed or (extra_files_on_server | default(false)) }}"
- name: Print SYNCED status
ansible.builtin.debug:
msg: |
╭─────────────────────────────╮
│ ✓ SYNCED │
│ Configuration is up-to-date │
╰─────────────────────────────╯
when: not drift_detected when: not drift_detected
- name: Print OUT OF SYNC status # ─────────────────────────────────────────────────────────────────────
ansible.builtin.debug: # TASK 6: Output OUT_OF_SYNC status
msg: | # Displayed when file on server differs from repo or is missing
╭─────────────────────────────╮ # ─────────────────────────────────────────────────────────────────────
│ ✗ OUT OF SYNC │ - name: Output OUT_OF_SYNC status
│ Configuration has drifted │ debug:
╰─────────────────────────────╯ msg: "✗ dvir.txt is out of sync"
when: drift_detected when: drift_detected
- name: Fail if drift detected - name: Fail if drift detected
ansible.builtin.fail: fail:
msg: "Configuration drift detected. Live system does not match repository." msg: "Configuration drift detected."
when: drift_detected when: drift_detected

View File

@ -1,48 +1,41 @@
--- ---
- name: Validate rsyslog configuration # =============================================================================
hosts: rsyslog_servers # VALIDATE PLAYBOOK
# Purpose: Verify that dvir.txt exists and is readable on target servers
# Usage: ansible-playbook validate.yml
# Output: Success if file exists and is readable, Failure if not
# =============================================================================
- name: Validate file exists
hosts: all
gather_facts: false gather_facts: false
vars:
validate_dir: /tmp/rsyslog-validate
validate_conf: /tmp/rsyslog-validate/rsyslog.conf
tasks: tasks:
- name: Create temp validation directory # ─────────────────────────────────────────────────────────────────────
file: # TASK 1: Check file status
path: "{{ validate_dir }}/rsyslog.d" # Gathers file stats (exists, readable, permissions, etc.)
state: directory # ─────────────────────────────────────────────────────────────────────
mode: "0700" - name: Check if file is readable
stat:
path: /tmp/dvir.txt
register: file_stat
- name: Copy main config to temp location # ─────────────────────────────────────────────────────────────────────
copy: # TASK 2: Assert file requirements
src: "{{ repo_root }}/files/rsyslog.conf" # Verifies that the file exists and is readable
dest: "{{ validate_conf }}" # Fails the playbook if either condition is false
remote_src: true # ─────────────────────────────────────────────────────────────────────
- name: Verify file exists and is readable
- name: Copy rsyslog.d configs to temp location assert:
copy: that:
src: "{{ repo_root }}/files/rsyslog.d/" - file_stat.stat.exists
dest: "{{ validate_dir }}/rsyslog.d/" - file_stat.stat.readable
remote_src: true msg: "dvir.txt not found or not readable"
- name: Update IncludeConfig path to point to temp dir
replace:
path: "{{ validate_conf }}"
regexp: '^\$IncludeConfig\s+.*$'
replace: '$IncludeConfig {{ validate_dir }}/rsyslog.d/*.conf'
- name: Validate repo rsyslog configuration
command: rsyslogd -N1 -f "{{ validate_conf }}"
register: validate_result
failed_when: validate_result.rc != 0
changed_when: false
# ─────────────────────────────────────────────────────────────────────
# TASK 3: Display validation result
# Shows success message if all checks passed
# ─────────────────────────────────────────────────────────────────────
- name: Display validation result - name: Display validation result
debug: debug:
msg: "✓ rsyslog configuration is valid" msg: "✓ dvir.txt is valid and readable"
- name: Clean up temp validation directory
file:
path: "{{ validate_dir }}"
state: absent

View File

@ -1,16 +0,0 @@
#!/bin/bash
set -e
echo "Applying rsyslog config from git repo..."
cp rsyslog.conf /etc/rsyslog.conf
mkdir -p /etc/rsyslog.d
cp rsyslog.d/*.conf /etc/rsyslog.d/
echo "Validating config..."
rsyslogd -N1
echo "Restarting rsyslog..."
systemctl restart rsyslog
echo "Done."

View File

@ -1,39 +0,0 @@
#!/bin/bash
set -e
echo "Checking drift between git repo and live server..."
DIFF_FOUND=0
echo
echo "Comparing /etc/rsyslog.conf"
if ! diff -u rsyslog.conf /etc/rsyslog.conf; then
DIFF_FOUND=1
fi
echo
echo "Comparing rsyslog.d configs"
for file in rsyslog.d/*.conf; do
base=$(basename "$file")
target="/etc/rsyslog.d/$base"
if [ ! -f "$target" ]; then
echo "Missing on server: $target"
DIFF_FOUND=1
continue
fi
if ! diff -u "$file" "$target"; then
DIFF_FOUND=1
fi
done
if [ "$DIFF_FOUND" -eq 0 ]; then
echo
echo "No drift detected."
exit 0
else
echo
echo "Drift detected!"
exit 1
fi

3
files/dvir.txt Normal file
View File

@ -0,0 +1,3 @@
This is a generic deployment file.
It can be used for any service or configuration.
Simply replace this with your own content as needed.

View File

@ -1,60 +0,0 @@
# /etc/rsyslog.conf configuration file for rsyslog
#
# For more information install rsyslog-doc and see
# /usr/share/doc/rsyslog-doc/html/configuration/index.html
#
# Default logging rules can be found in /etc/rsyslog.d/50-default.conf
# TEST branch
#################
#### MODULES ####
#################
module(load="imuxsock") # provides support for local system logging
#module(load="immark") # provides --MARK-- message capability
# provides UDP syslog reception
#module(load="imudp")
#input(type="imudp" port="514")
# provides TCP syslog reception
#module(load="imtcp")
#input(type="imtcp" port="514")
# provides kernel logging support and enable non-kernel klog messages
module(load="imklog" permitnonkernelfacility="on")
###########################
#### GLOBAL DIRECTIVES ####
###########################
# Use traditional timestamp format.
# To enable high precision timestamps, comment out the following line.
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
# Filter duplicated messages
$RepeatedMsgReduction on
#
# Set the default permissions for all log files.
#
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
$PrivDropToUser syslog
$PrivDropToGroup syslog
#
# Where to place spool and state files
#
$WorkDirectory /var/spool/rsyslog
#
# Include all config files in /etc/rsyslog.d/
#
$IncludeConfig /etc/rsyslog.d/*.conf
# Dvir was here

View File

@ -1 +0,0 @@
local0.* /var/log/lab.log