# Assignment Developers are looking for dependencies to be installed and run on Nautilus app servers in Stratos DC. They have shared some requirements with the DevOps team. Because we are now managing packages installation and services management using Ansible, some playbooks need to be created and tested. As per details mentioned below please complete the task: a. On jump host create an Ansible playbook /home/thor/ansible/playbook.yml and configure it to install httpd on all app servers. b. After installation make sure to start and enable httpd service on all app servers. c. The inventory /home/thor/ansible/inventory is already there on jump host. d. Make sure user thor should be able to run the playbook on jump host. Note: Validation will try to run playbook using command ansible-playbook -i inventory playbook.yml so please make sure playbook works this way, without passing any extra arguments. # Solution # Ansible Playbook — install and enable httpd on all App Servers Create `/home/thor/ansible/playbook.yml` so `ansible-playbook -i inventory playbook.yml` installs httpd and brings the service up on all app servers — with **no extra arguments**. > Note: this is an Ansible task, not Kubernetes — no manifests to pipe into `kubectl`. The heredoc > below writes the playbook. ## Step 0 — The inventory already exists; leave it alone Requirement (c) confirms the inventory is already in place. **Don't recreate or overwrite it** — just verify its contents: ```bash cat /home/thor/ansible/inventory ``` Confirm it lists the app servers with their connection variables. If it lacks `ansible_become_pass` and the app-server users need a sudo password, add that per host — the playbook requires privilege escalation and you can't pass `-K` at runtime. ## Step 1 — Playbook ```bash cat > /home/thor/ansible/playbook.yml <<'EOF' --- - name: Install and enable httpd on all app servers hosts: all become: yes tasks: - name: Install httpd package ansible.builtin.yum: name: httpd state: present - name: Start and enable httpd service ansible.builtin.service: name: httpd state: started enabled: yes EOF ``` ## Step 2 — Ensure `thor` can run it (requirement d) ```bash ls -l /home/thor/ansible/ ``` Creating the playbook with the heredoc above (as `thor`) already gives correct ownership. If the directory was pre-created by another user and `thor` can't read the files, fix it: ```bash sudo chown -R thor:thor /home/thor/ansible chmod 644 /home/thor/ansible/playbook.yml ``` ## How it works ### Why `become: yes` Both tasks are privileged: installing a package writes to system directories and the RPM database, and managing a systemd service requires root. The SSH users on the app servers are unprivileged, so the play escalates once at the **play level** rather than repeating `become` on each task. Because validation runs the bare command with no `-K`, the sudo password must come from `ansible_become_pass` in the existing inventory. "Missing sudo password" at runtime means that variable is absent or wrong — and it's the most common failure on this task, since there's no way to supply it on the command line. ### Task 1 — install httpd `ansible.builtin.yum` with **`state: present`** installs the package if it's missing and does nothing if it's already there. That makes the task **idempotent**: the first run reports `changed`, subsequent runs report `ok`. `state: latest` would instead upgrade on every run, which isn't what "install" asks for. These app servers are RHEL/CentOS-family, so `yum` is the correct package module. (On modern RHEL 8+ the `dnf` module is its successor, and Ansible's `yum` module delegates to dnf where appropriate — so `yum` works regardless.) ### Task 2 — start *and* enable Requirement (b) has two distinct halves, and `ansible.builtin.service` covers both: | Option | Effect | |--------|--------| | `state: started` | httpd is running **right now**. | | `enabled: yes` | httpd starts automatically **on boot**. | These are independent — a service can be running but not enabled (dies on reboot), or enabled but not currently started. "Start and enable" requires both, so both are set. ### Ordering matters The install task must precede the service task: you can't start a service whose unit file doesn't exist yet. Ansible executes tasks top to bottom, so this ordering is a correctness requirement, not just style. Reversing them would fail with "Could not find the requested service httpd." ### `hosts: all` The inventory contains the app servers, so `all` targets exactly them — and it can't break if the inventory's group name and the playbook's `hosts:` value ever drift apart. ### Requirement (d) — "thor should be able to run the playbook" Validation runs as `thor`, so `thor` must be able to **read** the playbook and inventory. Writing the file via heredoc as `thor` satisfies this automatically; Step 2 is a safety check for the case where the directory was pre-created with root ownership, which would fail validation before Ansible even starts. ### Host key checking If a first-time SSH connection trips on host-key verification, add an `ansible.cfg` beside the playbook — safest because it needs no extra command-line arguments: ```bash cat > /home/thor/ansible/ansible.cfg <<'EOF' [defaults] host_key_checking = False EOF ``` ## Verify ```bash cd /home/thor/ansible # Connectivity first ansible -i inventory all -m ping # The actual validation command ansible-playbook -i inventory playbook.yml # httpd installed ansible -i inventory all -b -m command -a "rpm -q httpd" # Running AND enabled ansible -i inventory all -b -m command -a "systemctl is-active httpd" ansible -i inventory all -b -m command -a "systemctl is-enabled httpd" ``` Expected — `ping` returning `SUCCESS` on every server; the playbook finishing with `failed=0`; `rpm -q httpd` printing an installed version; `is-active` returning `active`; and `is-enabled` returning `enabled`. > Check **both** `is-active` and `is-enabled` — passing only one means half the requirement was met. > "Could not find the requested service httpd" ⇒ task order is wrong. "Missing sudo password" ⇒ the > inventory needs `ansible_become_pass`.