Skip to content

feat(groq): Installs a daily random apocalypse-themed MOTD using Ansible and a cron job.#4264

Open
polsala wants to merge 1 commit intomainfrom
ai/groq-20260419-1313
Open

feat(groq): Installs a daily random apocalypse-themed MOTD using Ansible and a cron job.#4264
polsala wants to merge 1 commit intomainfrom
ai/groq-20260419-1313

Conversation

@polsala
Copy link
Copy Markdown
Owner

@polsala polsala commented Apr 19, 2026

Implementation Summary

  • Utility: nightly-apocalypse-quote-rotator
  • Provider: groq
  • Location: ansible-playbooks/nightly-nightly-apocalypse-quote-rot
  • Files Created: 5
  • Description: Installs a daily random apocalypse-themed MOTD using Ansible and a cron job.

Rationale

  • Automated proposal from the Groq generator delivering a fresh community utility.
  • This utility was generated using the groq AI provider.

Why safe to merge

  • Utility is isolated to ansible-playbooks/nightly-nightly-apocalypse-quote-rot.
  • README + tests ship together (see folder contents).
  • No secrets or credentials touched.
  • All changes are additive and self-contained.

Test Plan

  • Follow the instructions in the generated README at ansible-playbooks/nightly-nightly-apocalypse-quote-rot/README.md
  • Run tests located in ansible-playbooks/nightly-nightly-apocalypse-quote-rot/tests/

Links

  • Generated docs and examples committed alongside this change.

Mock Justification

  • Not applicable; generator did not introduce new mocks.

@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Apr 19, 2026

🤖 Review by GROQ Agent

✅ What's solid

  • Clear purpose & isolation – The playbook lives in its own directory (nightly‑nightly‑apocalypse‑quote‑rot) and does not touch any existing infrastructure.
  • Idempotent designcopy and cron modules are used, both of which are naturally idempotent, so re‑running the playbook will not create duplicate cron entries or overwrite the quotes file unnecessarily.
  • Immediate MOTD update – The extra command + copy steps give users instant feedback after the first run, which is a nice UX touch.
  • Minimal dependencies – Only shuf (part of coreutils) is required on the target, and the README lists this explicitly.
  • Simple inventory – Using a local inventory (localhost ansible_connection=local) makes the playbook runnable on a developer box without extra configuration.

🧪 Tests

  • Current test is a thin wrappertests/test_setup_quotes.yml merely imports the main playbook. While this validates syntax, it does not assert any state.

  • Add idempotence verification – Run the playbook twice in check mode and assert that the second run reports “0 changed”. Example:

    - name: Verify idempotence
      hosts: all
      tasks:
        - name: First run (apply)
          import_playbook: ../src/setup_quotes.yml
    
        - name: Second run (check)
          import_playbook: ../src/setup_quotes.yml
          check_mode: true
          register: second_run
    
        - name: Assert no changes on second run
          assert:
            that:
              - second_run.changed == false
  • Validate file contents – After the playbook runs, confirm that:

    1. /usr/local/share/apocalypse_quotes.txt exists and contains the expected lines.
    2. /etc/motd contains a line that matches one of the quotes.

    Example snippet:

    - name: Verify quotes file
      slurp:
        src: /usr/local/share/apocalypse_quotes.txt
      register: quotes_file
    
    - name: Decode and split
      set_fact:
        quotes_list: "{{ quotes_file.content | b64decode | splitlines }}"
    
    - name: Verify MOTD is one of the quotes
      command: cat /etc/motd
      register: motd_content
    
    - name: Assert MOTD matches a quote
      assert:
        that:
          - motd_content.stdout in quotes_list
  • Check cron entry – Use the cron module in a test to assert that the job exists with the correct schedule and command.

  • Integrate with CI – Ensure the test suite runs under the CI matrix (e.g., GitHub Actions) with an appropriate Docker image that includes Ansible and shuf.

🔒 Security

  • Privilege escalation – The playbook runs everything with become: true. Consider limiting escalation to only the tasks that truly need it (copying to /usr/local/share and /etc/motd, installing a cron job). Example:

    tasks:
      - name: Deploy quotes file
        become: true
        copy: ...
    
      - name: Install daily cron job
        become: true
        cron: ...
    
      - name: Select a random quote now
        command: shuf -n 1 /usr/local/share/apocalypse_quotes.txt
        register: quote_output
        changed_when: false
    
      - name: Write the selected quote to MOTD
        become: true
        copy: ...
  • Absolute paths in cron – Cron runs with a minimal $PATH. The current job relies on shuf being found via the default path, which may fail on some minimal systems. Use the full path (e.g., /usr/bin/shuf) or set PATH explicitly:

    job: "/usr/bin/shuf -n 1 /usr/local/share/apocalypse_quotes.txt > /etc/motd"
  • Avoid command injection – The command module is safe here, but if you ever switch to shell, remember to quote variables properly.

  • File permissions – The quotes file is world‑readable (0644). If the content were ever sensitive, you’d want tighter permissions. Even though the quotes are public, documenting the rationale helps future reviewers.

  • Auditability – Consider adding a handler that logs each MOTD change to a separate file (e.g., /var/log/apocalypse_motd.log). This can be useful for debugging or compliance.

🧩 Docs/DX

  • README completeness – The README covers prerequisites, installation, and a brief description. A few enhancements:
    • Usage example – Show the exact command to verify the MOTD after the playbook runs.
    • Variable customization – Explain how a user could override the quote file location or cron schedule via extra vars.
    • Troubleshooting – Add a short “What if the cron job doesn’t fire?” section (e.g., check /var/log/cron or systemctl status cron).
  • Consistent naming – The directory name repeats “nightly” twice (nightly-nightly-apocalypse-quote-rot). Consider simplifying to nightly-apocalypse-quote-rot to avoid confusion.
  • Inventory documentation – Mention that the provided inventory.ini is for local testing only and that users can point the playbook at remote hosts by adjusting the inventory.
  • License header – If your repo requires a license file, add a short header comment at the top of the playbook (e.g., # SPDX-License-Identifier: MIT).

🧱 Mocks/Fakes

  • No mocks needed – The change does not introduce external services, so the “Mock Justification” note is accurate.
  • Future extensibility – If you later add a remote API to fetch quotes, consider adding a mock role or a test inventory that points to a local HTTP server (e.g., using ansible.builtin.uri with localhost).

Quick win checklist

  • Scope become: true to the three privileged tasks.
  • Use absolute path for shuf in the cron job.
  • Expand the test suite to assert file contents, cron entry, and idempotence.
  • Refine the README with usage, customization, and troubleshooting sections.
  • Rename the directory to remove the duplicated “nightly”.

These adjustments will make the utility more robust, secure, and user‑friendly while keeping the spirit of a fun, apocalypse‑themed MOTD. Happy Ansible‑ing!

@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Apr 19, 2026

🤖 Review by GEMINI Agent

✅ What's solid

  • Clear Purpose and Scope: The utility's goal of providing a daily apocalypse-themed MOTD is well-defined and contained within its own directory structure.
  • Idempotent Design: The use of Ansible's copy and cron modules ensures that re-running the playbook will not create duplicate entries or unnecessary changes, which is a good practice for infrastructure as code.
  • Self-Contained: The playbook, quotes, inventory, and basic test are all bundled together, making it easy to understand and deploy as a single unit.
  • Minimal Dependencies: The playbook primarily relies on core Ansible modules and the shuf utility, which is widely available.

🧪 Tests

  • The provided test_setup_quotes.yml currently only imports and effectively performs a syntax check/dry run of the main playbook. This is a minimal starting point.
    • Consider adding integration tests that verify the actual state changes on a target system. For example:
      • Assert that /usr/local/share/apocalypse_quotes.txt exists and contains the expected quotes.
      • Verify that the cron job is correctly installed for the specified user (root, due to become: true) and runs at the correct time with the correct command.
      • Check that /etc/motd is updated immediately after playbook execution with one of the quotes.
      • A more advanced test could involve waiting for the cron job to execute (e.g., by fast-forwarding time in a test environment or using a mock cron) and then verifying the MOTD content.
  • The changed_when: false for the command task is appropriate, but ensure that the copy task for /etc/motd correctly registers a change when the content is different. If the copy module is used with content, it should handle this automatically.

🔒 Security

  • The playbook uses become: true, meaning it runs tasks with elevated privileges (typically root).
    • Ensure that the shuf command and the paths /usr/local/share/apocalypse_quotes.txt and /etc/motd are not susceptible to path injection or other privilege escalation vectors if the quotes.txt file or the environment variables were compromised. In this specific case, the paths are hardcoded and the input is controlled, reducing immediate risk, but it's a general consideration for command module usage with become.
  • The quotes.txt file is copied with mode: "0644". This allows read access to all users.
    • Confirm that there are no sensitive quotes or information that should not be world-readable in this file. While unlikely for "apocalypse quotes," it's a good security hygiene check.
  • The cron job command shuf -n 1 /usr/local/share/apocalypse_quotes.txt > /etc/motd directly redirects output to /etc/motd.
    • Verify that /etc/motd is the intended and secure location for this content. Some systems might prefer /run/motd.dynamic or other mechanisms for dynamic MOTD generation to avoid overwriting static content. If other services also write to /etc/motd, this playbook will overwrite them.

🧩 Docs/DX

  • The README.md is comprehensive and provides clear instructions for installation, prerequisites, and testing.
    • Consider adding a section on how to uninstall or revert the changes made by the playbook (e.g., removing the cron job and the quotes file). This improves the overall developer experience for managing the utility's lifecycle.
  • The naming convention nightly-nightly-apocalypse-quote-rot for the directory seems to have a redundant "nightly".
    • Review the directory name for conciseness and consistency. Perhaps nightly-apocalypse-quote-rotator or motd-apocalypse-quotes would be clearer.
  • The inventory.ini uses localhost ansible_connection=local.
    • For broader applicability, consider documenting how to target remote hosts, or provide an example hosts.yml that can be easily adapted for different environments. While the current setup is fine for local testing, the hosts: all in the playbook implies it could be used more widely.

🧱 Mocks/Fakes

  • The PR body states "Not applicable; generator did not introduce new mocks." This is generally true for simple Ansible playbooks that interact directly with the system.
  • For more complex Ansible scenarios, especially when dealing with external APIs or services, consider how to mock those interactions for faster and more reliable testing.
    • While not strictly necessary for this specific playbook, if the shuf command or the file system interactions were more complex or involved external dependencies, using Ansible's set_fact or add_host with specific variables could simulate different system states or command outputs for testing purposes.
    • For example, if shuf was not guaranteed to be present, a mock could simulate its absence or different outputs. However, for a core utility like shuf, this is likely overkill.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant