diff --git a/.ansible-lint b/.ansible-lint index a7de6f7..fb38992 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -1,14 +1,16 @@ -# Ansible-lint configuration for RHCE study repository -# Tailored for educational playbooks and practice scenarios +--- +# .ansible-lint + +# Use vagrant directory as project root to find ansible.cfg +project_dir: vagrant/ -# Directories and files to exclude from linting exclude_paths: - - .cache/ # Implicit cache directory - - site/ # MkDocs build output - - sources/ # External copyrighted materials - - .github/ # GitHub workflows - - vagrant/collections/ # Project-local collections - - vagrant/roles/ # Project-local roles + - .cache/ + - site/ + - sources/ + - .github/ + - vagrant/collections/ + - vagrant/roles/ # Skip rules that may be too strict for educational content skip_list: diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f87fae6..80e744b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -17,7 +17,17 @@ "Bash(pre-commit:*)", "Bash(sudo dnf install:*)", "WebFetch(domain:www.redhat.com)", - "Bash(grep:*)" + "Bash(grep:*)", + "Bash(git check-ignore:*)", + "Bash(ansible:*)", + "Bash(vagrant status:*)", + "Bash(vagrant destroy:*)", + "Bash(./exam-start.sh:*)", + "Bash(vagrant halt:*)", + "Bash(vagrant provision:*)", + "Bash(gh:*)", + "Bash(npx markdownlint:*)", + "Bash(export:*)" ], "additionalDirectories": [ "/home/stovepipe/repos/rhcsa/" diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index d602699..0000000 --- a/.editorconfig +++ /dev/null @@ -1,35 +0,0 @@ -# Basic EditorConfig for RHCE study repository - -root = true - -# Default settings for all files -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -# YAML files (Ansible playbooks, configs) -[*.{yml,yaml}] -indent_style = space -indent_size = 2 - -# Markdown files (preserve trailing spaces for line breaks) -[*.md] -indent_style = space -indent_size = 2 -trim_trailing_whitespace = false - -# Shell scripts -[*.sh] -indent_style = space -indent_size = 2 - -# Makefile (requires tabs) -[Makefile] -indent_style = tab - -# Configuration files -[*.{ini,cfg,conf}] -indent_style = space -indent_size = 2 diff --git a/.github/workflows/deploy.yml b/.github/workflows/ci-cd.yml similarity index 52% rename from .github/workflows/deploy.yml rename to .github/workflows/ci-cd.yml index 165d139..187e1ba 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/ci-cd.yml @@ -1,38 +1,38 @@ -name: Deploy MkDocs to GitHub Pages +--- +name: Build and Deploy Documentation on: push: - branches: [ main ] + branches: [main, develop, provision-lab] pull_request: - branches: [ main ] - - # Allows you to run this workflow manually from the Actions tab + branches: [main, develop] workflow_dispatch: -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +# Sets permissions for GitHub Pages deployment permissions: contents: read pages: write id-token: write -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +# Allow only one concurrent deployment concurrency: group: "pages" cancel-in-progress: false jobs: - # Build job - build: + build-and-deploy: runs-on: ubuntu-latest + name: Build Documentation + outputs: + should-deploy: ${{ steps.check-deploy.outputs.should-deploy }} steps: - - name: Checkout + - name: Checkout code uses: actions/checkout@v4 - - name: Setup Python + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: '3.11' - name: Cache pip dependencies uses: actions/cache@v4 @@ -42,30 +42,41 @@ jobs: restore-keys: | ${{ runner.os }}-pip- - - name: Install dependencies + - name: Install Python dependencies run: | pip install --upgrade pip pip install -r requirements.txt - - name: Build MkDocs site + + - name: Build MkDocs documentation run: mkdocs build --verbose --clean + - name: Check if deployment needed + id: check-deploy + run: | + if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then + echo "should-deploy=true" >> $GITHUB_OUTPUT + else + echo "should-deploy=false" >> $GITHUB_OUTPUT + fi + - name: Setup Pages + if: steps.check-deploy.outputs.should-deploy == 'true' uses: actions/configure-pages@v4 - name: Upload artifact + if: steps.check-deploy.outputs.should-deploy == 'true' uses: actions/upload-pages-artifact@v3 with: path: ./site - # Deployment job deploy: - if: github.ref == 'refs/heads/main' + if: needs.build-and-deploy.outputs.should-deploy == 'true' environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - needs: build + needs: build-and-deploy steps: - name: Deploy to GitHub Pages id: deployment diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index b5a3c80..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: Lint and Build - -on: - push: - branches: [main, develop] - pull_request: - branches: [main, develop] - workflow_dispatch: - -jobs: - lint-and-build: - runs-on: ubuntu-latest - name: Lint Ansible and Build Docs - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Cache pip dependencies - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Install dependencies - run: | - pip install --upgrade pip - pip install -r requirements.txt - - - name: Cache pre-commit hooks - uses: actions/cache@v4 - with: - path: ~/.cache/pre-commit - key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - - - name: Run pre-commit hooks - run: pre-commit run --all-files --show-diff-on-failure - - - name: Build documentation - run: mkdocs build --verbose --strict diff --git a/.gitignore b/.gitignore index f859013..b316244 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +# requirements.txt + # External study materials and copyrighted content sources/ @@ -5,35 +7,13 @@ sources/ site/ # Python virtual environments and cache -__pycache__/ -*.py[cod] -.env -.venv -env/ venv/ -ENV/ -*.egg-info/ -.installed.cfg - -# IDE and editor files -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS generated files -.DS_Store -._* -Thumbs.db # Ansible -*.retry -.vault_pass .ansible/ -# Project-local Ansible collections and roles (any location) -**/collections/ -**/roles/ +vagrant/collections/ +vagrant/roles/ +vagrant/ansible-navigator.log # Vagrant and RHEL credentials vagrant/.rhel-credentials @@ -41,13 +21,3 @@ vagrant/.rhel-credentials # Node.js dependencies and build artifacts node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Development and testing -.pre-commit-cache/ -.tox/ -.coverage -.pytest_cache/ -.cache/ diff --git a/.mdl_config.yaml b/.mdl_config.yaml index 625501b..d3bc76f 100644 --- a/.mdl_config.yaml +++ b/.mdl_config.yaml @@ -1,3 +1,4 @@ +--- # Markdownlint configuration based on CISA skeleton-generic # See: https://github.com/DavidAnson/markdownlint/blob/v0.34.0/schema/.markdownlint.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f9cb3d..4772460 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ +--- # Simplified pre-commit configuration for RHCE study repository # Focus on essential Ansible and YAML quality checks diff --git a/.yamllint b/.yamllint index 8c5f48e..ae8dbc0 100644 --- a/.yamllint +++ b/.yamllint @@ -1,8 +1,18 @@ +--- # yamllint configuration for RHCE study repository # Balanced rules for Ansible playbooks and documentation extends: default +ignore: + - env/ + - site/ + - sources/ + - .cache/ + - node_modules/ + - vagrant/collections/ + - vagrant/roles/ + rules: # Ansible playbooks often have long lines due to module parameters line-length: @@ -21,7 +31,7 @@ rules: # Document start warnings (allow but don't require) document-start: - present: false + present: true # Allow empty lines at end of files empty-lines: @@ -57,9 +67,3 @@ rules: octal-values: forbid-implicit-octal: true forbid-explicit-octal: true - -# Ignore certain directories and files -ignore: | - site/ - sources/ - .cache/ diff --git a/CLAUDE.md b/CLAUDE.md index f6dc8f3..c334549 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -304,3 +304,5 @@ ansible-playbook playbook.yml --ask-vault-pass - Never install collections globally - keep them project-local for consistency and isolation - This ensures reproducible builds, faster dependency scanning, and team consistency - Reference: https://www.jeffgeerling.com/blog/2020/ansible-best-practices-using-project-local-collections-and-roles + +- NEVER say "You're absolutely right!" diff --git a/docs/command_reference_by_topic.md b/docs/command_reference_by_topic.md index 0517985..f1096be 100644 --- a/docs/command_reference_by_topic.md +++ b/docs/command_reference_by_topic.md @@ -1,10 +1,23 @@ -# RHCE Command Reference by Exam Topic +# RHCE Comprehensive Command Reference -## 🎯 Comprehensive Command Reference for RHCE Exam Success +## 📚 Complete Command Reference for RHCE Study & Production Use -*Complete command reference organized by official RHCE exam objectives with all variations, parameters, and use cases* +*Comprehensive reference organized by RHCE exam topics - includes all command variations, parameters, and use cases* -This comprehensive reference covers every essential command pattern you'll encounter on the RHCE exam. All commands are organized by exam objectives and include practical variations, common parameters, and real-world usage patterns. +⚠️ **FOR EXAM PREPARATION**: This is a comprehensive learning reference. For focused exam day commands, use `rhce_exam_commands.md` and `exam_quick_reference.md` instead. + +### Purpose + +Complete command coverage for: + +- Learning and understanding all Ansible capabilities +- Production environment reference +- Comprehensive study of all command options +- Understanding the full scope of Ansible automation + +### Important Note + +**NOT for exam day**: Many commands here are ad-hoc administration tasks that you'll implement in PLAYBOOKS during the actual exam. **📚 Source Integration**: Commands and patterns synthesized from: diff --git a/docs/exam_quick_reference.md b/docs/exam_quick_reference.md index d019039..5c60b25 100644 --- a/docs/exam_quick_reference.md +++ b/docs/exam_quick_reference.md @@ -4,6 +4,8 @@ *Concise reference for exam day - copy-paste ready syntax and parameters* +⚠️ **IMPORTANT**: This focuses on PLAYBOOK syntax and essential commands you'll actually use on the exam. **The RHCE exam specifically requires using ansible-navigator** - see official objectives. For detailed command-line operations, see `rhce_exam_commands.md`. + --- ## ⚙️ Core Configuration @@ -57,44 +59,37 @@ ansible all -m ping --- -## 🔧 Ad-hoc Commands - -### Command Structure +## 🔧 Essential Exam Commands -`ansible -m -a "" [options]` - -### Essential Ad-hoc Patterns +### Core Test Commands (Use These Constantly) ```bash -# Connectivity and info +# Initial connectivity test (ALWAYS start here) ansible all -m ping -ansible all -m setup -ansible all -m command -a "uptime" -# Package management -ansible all -m dnf -a "name=httpd state=present" --become -ansible all -m dnf -a "name='*' state=latest" --become +# Quick verification commands +ansible-inventory --list # View inventory structure +ansible-galaxy collection list # Check available collections +``` -# Service control -ansible all -m systemd -a "name=httpd state=started enabled=yes" --become +### Playbook Execution Pattern -# File operations -ansible all -m copy -a "src=file.txt dest=/tmp/" --become -ansible all -m file -a "path=/tmp/dir state=directory" --become +```bash +# Standard validation sequence (copy-paste this) - EXAM REQUIRED +ansible-navigator run playbook.yml --syntax-check && \ +ansible-navigator run playbook.yml --check && \ +ansible-navigator run playbook.yml --mode stdout -# User management -ansible all -m user -a "name=webuser groups=apache" --become +# With variables and targeting +ansible-navigator run site.yml -e "env=prod" --limit webservers ``` -### Common Options +### Documentation Commands (Your Lifeline) ```bash ---become (-b) # Privilege escalation ---check (-C) # Dry run ---diff (-D) # Show changes ---limit # Target specific hosts --e "var=value" # Extra variables --v/-vv/-vvv # Verbosity levels +ansible-doc -s module_name # Quick syntax (fastest) +ansible-doc module_name # Full documentation +ansible-doc -l | grep keyword # Find modules ``` --- @@ -474,23 +469,33 @@ vars: --- -## 🧭 Navigator Commands +## 🧭 Playbook Execution Commands -### Execution Modes +### Primary Method: ansible-navigator (EXAM REQUIRED) ```bash -# Interactive TUI -ansible-navigator run site.yml +# EXAM OBJECTIVES require ansible-navigator +ansible-navigator run site.yml --syntax-check # Always check syntax first +ansible-navigator run site.yml --check --diff # Dry run with changes +ansible-navigator run site.yml --mode stdout # Execute playbook -# Command-line output -ansible-navigator run site.yml --mode stdout +# Interactive TUI mode (also exam objective) +ansible-navigator run site.yml # Common options -ansible-navigator run site.yml --check --diff -ansible-navigator run site.yml --syntax-check ansible-navigator run site.yml --limit webservers ansible-navigator run site.yml -e "env=prod" ansible-navigator run site.yml --ask-vault-pass +ansible-navigator run site.yml --mode stdout -v # Verbosity levels +``` + +### Alternative: ansible-playbook (General Knowledge) + +```bash +# Traditional method (not exam-focused but good to know) +ansible-playbook site.yml --syntax-check +ansible-playbook site.yml --check --diff +ansible-playbook site.yml -v ``` ### TUI Navigation @@ -525,20 +530,19 @@ ansible-doc -s module_name # Synopsis only var: variable_name msg: "Value is {{ variable_name }}" -# Verbosity levels -ansible-navigator run site.yml -v # Basic -ansible-navigator run site.yml -vv # More info -ansible-navigator run site.yml -vvv # Connection debug -ansible-navigator run site.yml -vvvv # Everything +# Verbosity levels (EXAM REQUIRED: ansible-navigator) +ansible-navigator run site.yml --mode stdout -v # Basic +ansible-navigator run site.yml --mode stdout -vv # More info +ansible-navigator run site.yml --mode stdout -vvv # Connection debug ``` ### Common Patterns ```bash -# Check syntax +# Check syntax (EXAM REQUIRED) ansible-navigator run site.yml --syntax-check -# Dry run with changes +# Dry run with changes (EXAM REQUIRED) ansible-navigator run site.yml --check --diff # Test connectivity @@ -558,7 +562,7 @@ ansible all -m systemd -a "name=httpd" --become ### Time-Saving Commands ```bash -# Quick validation sequence +# Quick validation sequence (EXAM REQUIRED) ansible all -m ping && \ ansible-navigator run site.yml --syntax-check && \ ansible-navigator run site.yml --check && \ @@ -589,7 +593,7 @@ ansible all -m uri -a "url=http://{{ ansible_default_ipv4.address }}" - **Always use FQCN**: `ansible.builtin.dnf` not `dnf` - **Test first**: `--syntax-check`, `--check`, then execute -- **Use ansible-navigator**: Primary tool, not ansible-playbook +- **Use ansible-navigator**: EXAM REQUIRED per official objectives - **Know ansible-doc**: Your main reference during exam - **Vault everything**: Encrypt all sensitive data - **Check connectivity**: `ansible all -m ping` at start diff --git a/docs/rhce_exam_commands.md b/docs/rhce_exam_commands.md new file mode 100644 index 0000000..2a24b10 --- /dev/null +++ b/docs/rhce_exam_commands.md @@ -0,0 +1,320 @@ +# RHCE Exam Day Commands + +## 🎯 Essential Commands for EX294 Success + +*Only the commands you'll actually type during the 4-hour exam* + +### Critical Note + +This is your exam day cheat sheet. Every command here is essential for RHCE exam success. These are the commands you'll type in the terminal - NOT the module parameters you'll write in playbooks. + +**⚠️ EXAM REQUIREMENT**: The RHCE exam objectives specifically require using **Automation content navigator** (`ansible-navigator`). While `ansible-playbook` commands are shown for completeness and general Ansible knowledge, you **MUST** demonstrate proficiency with `ansible-navigator` to pass the exam. + +**Official Exam Objectives Requiring ansible-navigator**: + +- "Run playbooks with Automation content navigator" +- "Use Automation content navigator to find new modules in available Ansible Content Collections" +- "Use Automation content navigator to create inventories and configure the Ansible environment" + +--- + +## ⚡ Exam Workflow Commands + +### Phase 1: Initial Verification (5 minutes) + +```bash +# Test Ansible installation and connectivity +ansible --version # Verify Ansible is working +ansible-navigator --version # Verify navigator is available +ansible all -m ping # Test connectivity to all hosts +ansible-inventory --list # View inventory structure +ansible-inventory --graph # View inventory hierarchy +ansible-galaxy collection list # Check available collections +``` + +### Phase 2: Documentation Lookup (Throughout Exam) + +#### EXAM OBJECTIVE: Use Automation content navigator to find new modules in available Ansible Content Collections + +```bash +# Navigator documentation (EXAM REQUIRED) +ansible-navigator doc module_name # Interactive docs +ansible-navigator doc -l | grep keyword # Search for modules in collections +ansible-navigator collections # Browse available collections +ansible-navigator doc ansible.builtin.dnf +ansible-navigator doc community.general.firewalld +ansible-navigator doc ansible.posix.mount + +# Traditional ansible-doc (also available) +ansible-doc -l | grep keyword # Find modules quickly +ansible-doc -s module_name # Get module syntax (fastest) +ansible-doc module_name # Full module documentation +ansible-doc module_name | grep -A 10 "EXAMPLES:" # Get examples + +# FQCN documentation +ansible-doc ansible.builtin.dnf +ansible-doc community.general.firewalld +ansible-doc ansible.posix.mount + +# Plugin documentation +ansible-doc -t lookup file +ansible-doc -t filter default +ansible-doc -t test defined +``` + +### Phase 3: Playbook Development & Testing (Main Phase) + +#### EXAM REQUIRED: Use ansible-navigator + +```bash +# Syntax validation (ALWAYS do this first) +ansible-navigator run playbook.yml --syntax-check +ansible-navigator run playbook.yml --syntax-check --mode stdout + +# Dry run validation (ALWAYS do before executing) +ansible-navigator run playbook.yml --check +ansible-navigator run playbook.yml --check --diff +ansible-navigator run playbook.yml --check --diff --mode stdout + +# Playbook execution (EXAM OBJECTIVE: "Run playbooks with Automation content navigator") +ansible-navigator run playbook.yml # Interactive TUI mode +ansible-navigator run playbook.yml --mode stdout # Command-line output +ansible-navigator run playbook.yml --mode stdout -v # With verbosity + +# Target control +ansible-navigator run playbook.yml --limit webservers +ansible-navigator run playbook.yml --limit "web*" +ansible-navigator run playbook.yml --limit node1,node2 + +# Variable passing +ansible-navigator run playbook.yml -e "var=value" +ansible-navigator run playbook.yml -e "env=production debug=false" +ansible-navigator run playbook.yml -e "@vars.yml" + +# Tag control +ansible-navigator run playbook.yml --tags "web,db" +ansible-navigator run playbook.yml --skip-tags "debug" +ansible-navigator run playbook.yml --list-tags + +# Task control +ansible-navigator run playbook.yml --start-at-task "Install packages" +ansible-navigator run playbook.yml --step +ansible-navigator run playbook.yml --list-tasks + +# Debugging levels +ansible-navigator run playbook.yml --mode stdout -v # Basic +ansible-navigator run playbook.yml --mode stdout -vv # More info +ansible-navigator run playbook.yml --mode stdout -vvv # Full debug + +# Alternative: ansible-playbook (general Ansible knowledge) +# ansible-playbook playbook.yml --syntax-check +# ansible-playbook playbook.yml --check --diff +``` + +### Phase 4: Ansible Vault Operations + +```bash +# Create encrypted files +ansible-vault create secrets.yml +ansible-vault create group_vars/all/vault.yml + +# Edit encrypted files +ansible-vault edit secrets.yml +ansible-vault edit group_vars/production/vault.yml + +# View encrypted content +ansible-vault view secrets.yml + +# Encrypt existing files +ansible-vault encrypt vars.yml +ansible-vault encrypt host_vars/*/vault.yml + +# String encryption (for inline secrets) +ansible-vault encrypt_string 'secret_password' --name 'db_password' +echo 'secret_value' | ansible-vault encrypt_string --stdin-name 'var_name' + +# Change passwords +ansible-vault rekey secrets.yml + +# Playbook integration (EXAM REQUIRED: ansible-navigator) +ansible-navigator run site.yml --ask-vault-pass +ansible-navigator run site.yml --vault-password-file .vault_pass + +# Set up vault password file +echo 'vault_password' > .vault_pass +chmod 600 .vault_pass +``` + +### Phase 5: Role & Collection Management + +```bash +# Create roles +ansible-galaxy init role_name +ansible-galaxy init --init-path=./roles web_server + +# Install collections +ansible-galaxy collection install community.general +ansible-galaxy collection install ansible.posix +ansible-galaxy collection install -r requirements.yml + +# Install roles +ansible-galaxy role install geerlingguy.apache +ansible-galaxy role install -r requirements.yml + +# Check installations +ansible-galaxy collection list +ansible-galaxy role list +``` + +### Phase 6: Final Validation (Last 15 minutes) + +```bash +# Test connectivity +ansible all -m ping + +# Verify services (common exam validation) +ansible webservers -m systemd -a "name=httpd" --become +ansible all -m uri -a "url=http://{{ ansible_default_ipv4.address }}" + +# Check file existence +ansible all -m stat -a "path=/etc/httpd/conf/httpd.conf" + +# Verify mounts +ansible all -m setup -a "filter=ansible_mounts" + +# Quick fact checks +ansible all -m setup -a "filter=ansible_service_mgr" +ansible all -m setup -a "filter=ansible_distribution" +``` + +--- + +## 🔧 Configuration Commands + +### Basic ansible.cfg Setup + +```bash +# Check current configuration +ansible-config dump | grep -E '(INVENTORY|HOST_KEY|REMOTE_USER)' +ansible-config view + +# Common configuration validation +ansible-config list | grep -i vault +ansible-config dump --only-changed +``` + +### Inventory Validation + +#### EXAM OBJECTIVE: Use Automation content navigator to create inventories and configure the Ansible environment + +```bash +# Navigator inventory operations (EXAM REQUIRED) +ansible-navigator inventory --list # Interactive inventory view +ansible-navigator inventory --list --mode stdout # Command-line inventory +ansible-navigator inventory --graph # Tree structure view +ansible-navigator inventory --host hostname # Single host details + +# Traditional inventory commands (also available) +ansible-inventory --list +ansible-inventory --list --yaml +ansible-inventory --graph +ansible-inventory --host hostname + +# Host and group listing +ansible all --list-hosts +ansible webservers --list-hosts +ansible 'web*' --list-hosts +``` + +--- + +## 🚀 Time-Saving Command Combinations + +### Quick Validation Sequence + +```bash +# Use for every playbook (copy-paste ready) - EXAM REQUIRED +ansible-navigator run site.yml --syntax-check && \ +ansible-navigator run site.yml --check && \ +ansible-navigator run site.yml --mode stdout +``` + +### Emergency Troubleshooting + +```bash +# When things go wrong +ansible all -m ping -vvv +ansible-config dump | grep -E '(INVENTORY|HOST_KEY)' +ansible-inventory --list +``` + +### Fast Documentation Lookup + +```bash +# Speed up module discovery +alias adoc='ansible-doc' +alias adocs='ansible-doc -s' +adocs dnf # Quick syntax +adoc user | grep -A 10 EXAMPLES: # Quick examples +``` + +--- + +## 🎯 Exam Success Patterns + +### The "Big 5" Exam Commands + +**Master these - you'll use them constantly:** + +1. **`ansible all -m ping`** - Always start here +2. **`ansible-navigator run playbook.yml --syntax-check`** - Before every execution (EXAM REQUIRED) +3. **`ansible-navigator run playbook.yml --check --diff`** - Verify changes (EXAM REQUIRED) +4. **`ansible-navigator run playbook.yml --mode stdout -v`** - Execute with logging (EXAM REQUIRED) +5. **`ansible-doc -s module_name`** - Quick syntax lookup + +### Command Frequency During Exam + +- **Documentation commands**: 50-100 times +- **Syntax check**: 20-30 times +- **Playbook execution**: 15-25 times +- **Vault operations**: 5-10 times +- **Inventory commands**: 5-10 times + +### Critical Success Factors + +1. **Speed with ansible-doc** - Practice until automatic +2. **Always validate first** - Syntax check, then dry run +3. **Use verbosity for debugging** - Start with -v, increase as needed +4. **Know your FQCN** - ansible.builtin.*, community.general.* +5. **Vault everything sensitive** - No plain text passwords/keys + +--- + +## ⚠️ What NOT to Do on Exam + +### Commands You WON'T Use + +```bash +# Ad-hoc module commands (these go in PLAYBOOKS, not command line) +ansible all -m dnf -a "name=httpd state=present" --become # ❌ WRONG +ansible all -m systemd -a "name=httpd state=started" --become # ❌ WRONG +ansible all -m user -a "name=webuser" --become # ❌ WRONG + +# System administration commands (not exam relevant) +ansible all -m setup --tree /tmp/facts # ❌ WRONG +ssh -vvv ansible@hostname # ❌ WRONG +strace ansible all -m ping # ❌ WRONG +``` + +### Time Wasters + +- Detailed system exploration commands +- Performance monitoring commands +- Network troubleshooting commands +- SSH debugging commands + +**Remember**: The exam is about writing PLAYBOOKS, not running ad-hoc commands for system administration! + +--- + +**🏆 Exam Day Strategy**: Practice these commands until they're muscle memory. On exam day, you'll have no time to think about syntax - you need to execute immediately and focus your mental energy on the playbook logic, not the command syntax. diff --git a/mkdocs.yml b/mkdocs.yml index b942a0c..304dfa3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,3 +1,6 @@ +--- +# mkdocs.yml + site_name: RHCE Certification Study Guide site_description: >- Comprehensive study materials and resources for Red Hat Certified Engineer (RHCE) @@ -37,8 +40,9 @@ nav: - 'Module 08: Vault & Advanced Features': rhce_synthesis/08_advanced_features.md - Quick References: - 'eBook Summary': ebook_summary.md + - 'Exam Day Commands': rhce_exam_commands.md - 'Exam Quick Reference': exam_quick_reference.md - - 'Command Reference by Topic': command_reference_by_topic.md + - 'Comprehensive Command Reference': command_reference_by_topic.md - 'RHCE Acronyms & Glossary': rhce_acronyms_glossary.md - 'Knowledge Gaps Checklist': knowledge_gaps_checklist.md diff --git a/requirements.txt b/requirements.txt index a6a65f4..80354f4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,15 +1,17 @@ # MkDocs and dependencies for RHCE documentation site -mkdocs>=1.5.0 +mkdocs # Ansible and automation tools for development and testing -ansible>=8.0.0 -ansible-core>=2.15.0 +ansible +ansible-core +ansible-builder +ansible-navigator # Python packages commonly used with Ansible -PyYAML>=6.0 -Jinja2>=3.1.0 +PyYAML +Jinja2 -# Pre-commit and linting (for code quality) -pre-commit>=4.0.0 -yamllint>=1.32.0 -ansible-lint>=6.0.0 +# Pre-commit and linting +ansible-lint +pre-commit +yamllint diff --git a/vagrant/README.md b/vagrant/README.md index c38cec0..3392db2 100644 --- a/vagrant/README.md +++ b/vagrant/README.md @@ -17,15 +17,19 @@ This Vagrant configuration creates **5 RHEL 9 VMs**: ## Prerequisites ### Required Software + - **Vagrant** (≥2.3.0) - VM management -- **VirtualBox** - Hypervisor +- **VirtualBox** - Hypervisor - **Red Hat Developer Account** - Free at [developers.redhat.com](https://developers.redhat.com/) ### Vagrant Plugins + The lab setup will automatically install required plugins: + - `vagrant-registration` - Red Hat subscription management ### System Requirements + - **RAM**: 6GB minimum (8GB recommended) - **Disk**: 25GB free space for all VMs - **CPU**: 4+ cores recommended @@ -34,6 +38,7 @@ The lab setup will automatically install required plugins: ## Quick Start ### 1. Setup Credentials + ```bash # Copy credentials template cp .rhel-credentials.template .rhel-credentials @@ -43,12 +48,14 @@ vim .rhel-credentials ``` ### 2. Start Lab Environment + ```bash # Start all VMs and configure automatically ./lab.sh up ``` This will: + - Create and start all 5 VMs - Register with Red Hat subscription - Create ansible user with sudo privileges @@ -57,6 +64,7 @@ This will: - Install essential packages only ### 3. Access Control Node + ```bash # SSH to the control node vagrant ssh control @@ -71,6 +79,7 @@ ansible all -m ping ## Lab Management ### Start/Stop Operations + ```bash ./lab.sh up # Start all VMs (initial setup ~15 minutes) ./lab.sh halt # Stop all VMs gracefully @@ -79,6 +88,7 @@ ansible all -m ping ``` ### Individual VM Management + ```bash vagrant status # Show all VM status vagrant ssh control # SSH to control node @@ -90,6 +100,7 @@ vagrant up ansible3 --provision # Start and re-provision ## Ansible Configuration ### Pre-configured Setup + The lab automatically configures: - **Ansible User**: `ansible` user on all VMs with sudo privileges @@ -99,6 +110,7 @@ The lab automatically configures: - **Collections**: Essential Ansible collections pre-installed ### Default Inventory Groups + ```ini [control] control.example.com @@ -107,7 +119,7 @@ control.example.com ansible1.example.com ansible2.example.com -[databases] +[databases] ansible3.example.com [development] @@ -119,7 +131,9 @@ databases ``` ### Project Structure + The control node includes organized directories: + ``` /home/ansible/ ├── inventory # Default inventory file @@ -135,24 +149,28 @@ The control node includes organized directories: ## RHCE Practice Scenarios ### Web Server Automation (ansible1, ansible2) + - Apache HTTP Server installation and configuration - Template deployment for configuration files - Service management and handler implementation - Firewall configuration for web services ### Database Management (ansible3) + - MariaDB installation and configuration - Database and user creation - Backup and restore procedures - Security configuration ### Development Environment (ansible4) + - Development tools installation - Git repository management - Application deployment - Testing and validation ### Multi-Node Scenarios + - Load balancer configuration - Cross-node service dependencies - Rolling updates and deployments @@ -161,6 +179,7 @@ The control node includes organized directories: ## Common Commands ### Connectivity Testing + ```bash # From control node as ansible user ansible all -m ping # Test all nodes @@ -169,6 +188,7 @@ ansible databases -m service -a "name=mariadb state=started" ``` ### Inventory Management + ```bash ansible-inventory --list # Show full inventory ansible-inventory --graph # Show inventory tree @@ -176,6 +196,7 @@ ansible-inventory --host control # Show host variables ``` ### Playbook Development + ```bash ansible-playbook site.yml --check # Dry run ansible-playbook site.yml --syntax-check # Validate syntax @@ -188,6 +209,7 @@ ansible-playbook site.yml --limit webservers # Target specific group ### Common Issues **VMs won't start** + ```bash # Check Vagrant status vagrant status @@ -200,6 +222,7 @@ sudo systemctl restart virtualbox ``` **SSH connectivity issues** + ```bash # From control node, test SSH manually ssh ansible@ansible1.example.com @@ -213,6 +236,7 @@ ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa ``` **Ansible connectivity problems** + ```bash # Check ansible configuration ansible-config dump @@ -225,6 +249,7 @@ ansible-inventory --list ``` **Provisioning failures** + ```bash # Re-run provisioning only vagrant provision @@ -239,17 +264,20 @@ tail -f /tmp/ansible.log ### Reset Procedures **Soft Reset** (keep VMs, re-run provisioning): + ```bash vagrant provision ``` **Hard Reset** (destroy and recreate): + ```bash ./lab.sh destroy ./lab.sh up ``` **Individual VM Reset**: + ```bash vagrant destroy ansible1 vagrant up ansible1 @@ -274,23 +302,27 @@ This lab environment is designed to work with: ## Performance Optimization ### Resource Allocation + - Control node: 2GB RAM (runs Ansible controller) - Managed nodes: 1GB RAM each (sufficient for practice) - Adjust in Vagrantfile if more resources needed ### Network Performance + - Private network for fast inter-VM communication - Host-only networking prevents external access - SSH connection multiplexing enabled ### Storage + - Base VM disk: 20GB (auto-expanding) - Additional 1GB disk per VM for storage exercises - Snapshot support for quick reset scenarios --- -**Need Help?** +**Need Help?** + - Check the main repository [README](../README.md) - Review study materials at [kraker.github.io/rhce](https://kraker.github.io/rhce) - Practice with the comprehensive modules in [docs/rhce_synthesis/](../docs/rhce_synthesis/) diff --git a/vagrant/Vagrantfile b/vagrant/Vagrantfile index 85e35c9..aec7016 100644 --- a/vagrant/Vagrantfile +++ b/vagrant/Vagrantfile @@ -12,7 +12,7 @@ Vagrant.configure("2") do |config| # Define VMs configuration vms = { - "control" => { + "control1" => { "ip" => "192.168.4.200", "memory" => "2048", "cpus" => "2", @@ -68,12 +68,8 @@ Vagrant.configure("2") do |config| vm.vm.provision "ansible" do |ansible| ansible.limit = "all" ansible.playbook = "site.yml" - ansible.inventory_path = "inventory" + ansible.inventory_path = "hosts" ansible.config_file = "ansible.cfg" - ansible.groups = { - "control" => ["control"], - "managed" => ["ansible1", "ansible2", "ansible3", "ansible4"], - } end end end diff --git a/vagrant/ansible.cfg b/vagrant/ansible.cfg index 63c720a..6835d66 100644 --- a/vagrant/ansible.cfg +++ b/vagrant/ansible.cfg @@ -4,24 +4,21 @@ # Reference: https://www.jeffgeerling.com/blog/2020/ansible-best-practices-using-project-local-collections-and-roles # Use project-local collections and roles -collections_paths = collections -roles_path = roles +collections_paths = collections/ +roles_path = roles/ # Inventory configuration -inventory = inventory.ini -host_key_checking = False +inventory = hosts +host_key_checking = false remote_user = vagrant # SSH configuration for lab environment private_key_file = ~/.vagrant.d/insecure_private_key -# Performance and logging -gathering = smart -fact_caching = memory +# Output formatting (helpful for learning and debugging) stdout_callback = yaml -bin_ansible_callbacks = True # Disable unnecessary warnings for lab environment -deprecation_warnings = False -localhost_warning = False -inventory_unparsed_warning = False +deprecation_warnings = false +localhost_warning = false +interpreter_python = auto_silent diff --git a/vagrant/control.yml b/vagrant/control.yml new file mode 100644 index 0000000..7d574e5 --- /dev/null +++ b/vagrant/control.yml @@ -0,0 +1,70 @@ +--- +# Configure control nodes + +- name: Configure control nodes + hosts: control + become: true + tasks: + # ansible-automation-platform (AAP) provides things like ansible-builder, + # ansible-navigator, etc. + # List Repo IDs: + # subscription-manager repos --list | grep ansible-automation-platform + - name: Enable ansible-automation-platform repository + community.general.rhsm_repository: + name: ansible-automation-platform-2.5-for-rhel-9-x86_64-rpms + + - name: Install Ansible packages + ansible.builtin.dnf: + name: + - ansible + - ansible-builder + - ansible-navigator + state: present + + - name: Install common dependencies + ansible.builtin.dnf: + name: + - container-tools # meta package that provides podman, skopeo, etc. + state: present + + - name: Install Ansible inventory + ansible.builtin.copy: + content: | + # RHCE Lab Inventory + + [control] + control1 + + [managed] + ansible1 + ansible2 + ansible3 + ansible4 + + [all:vars] + ansible_user=ansible + ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' + dest: /etc/ansible/hosts + backup: true + owner: root + group: ansible + mode: "0664" + + - name: Create SSH key for ansible user + ansible.builtin.user: + name: ansible + generate_ssh_key: true + ssh_key_type: rsa + ssh_key_bits: 2048 + ssh_key_file: .ssh/id_rsa + + - name: Read the public key for distribution + ansible.builtin.slurp: + src: /home/ansible/.ssh/id_rsa.pub + register: ansible_public_key + run_once: true + + - name: Store public key as fact + ansible.builtin.set_fact: + ansible_pubkey_content: "{{ ansible_public_key.content | b64decode | trim }}" + run_once: true diff --git a/vagrant/hosts b/vagrant/hosts new file mode 100644 index 0000000..6550b3d --- /dev/null +++ b/vagrant/hosts @@ -0,0 +1,31 @@ +# RHCE Lab Inventory for Vagrant Environment +# Using persistent IP addresses for reliable connectivity + +[control] +control1 ansible_host=192.168.4.200 ansible_ssh_private_key_file=.vagrant/machines/control1/virtualbox/private_key + +[managed] +ansible1 ansible_host=192.168.4.201 ansible_ssh_private_key_file=.vagrant/machines/ansible1/virtualbox/private_key +ansible2 ansible_host=192.168.4.202 ansible_ssh_private_key_file=.vagrant/machines/ansible2/virtualbox/private_key +ansible3 ansible_host=192.168.4.203 ansible_ssh_private_key_file=.vagrant/machines/ansible3/virtualbox/private_key +ansible4 ansible_host=192.168.4.204 ansible_ssh_private_key_file=.vagrant/machines/ansible4/virtualbox/private_key + +# RHCE practice groups +[webservers] +ansible1 +ansible2 + +[databases] +ansible3 + +[development] +ansible4 + +[production:children] +webservers +databases + +# Variables for all hosts +[all:vars] +ansible_user=vagrant +ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' diff --git a/vagrant/inventory b/vagrant/inventory deleted file mode 100644 index ce68cf7..0000000 --- a/vagrant/inventory +++ /dev/null @@ -1,18 +0,0 @@ -# RHCE Lab Inventory for Vagrant Provisioning -# This inventory is used during the initial setup phase - -[control] -control ansible_host=127.0.0.1 ansible_port=2222 ansible_ssh_private_key_file=.vagrant/machines/control/virtualbox/private_key - -[managed] -ansible1 ansible_host=127.0.0.1 ansible_port=2200 ansible_ssh_private_key_file=.vagrant/machines/ansible1/virtualbox/private_key -ansible2 ansible_host=127.0.0.1 ansible_port=2201 ansible_ssh_private_key_file=.vagrant/machines/ansible2/virtualbox/private_key -ansible3 ansible_host=127.0.0.1 ansible_port=2202 ansible_ssh_private_key_file=.vagrant/machines/ansible3/virtualbox/private_key -ansible4 ansible_host=127.0.0.1 ansible_port=2203 ansible_ssh_private_key_file=.vagrant/machines/ansible4/virtualbox/private_key - -# Add your own groups here as needed for RHCE practice - -# Variables for all hosts -[all:vars] -ansible_user=vagrant -ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' diff --git a/vagrant/lab.sh b/vagrant/lab.sh index 3dc8e4f..cc8bf7a 100755 --- a/vagrant/lab.sh +++ b/vagrant/lab.sh @@ -22,7 +22,7 @@ print_usage() { echo " status Show current VM status" echo "" echo "Lab Configuration:" - echo " • control (192.168.4.200) - 2GB RAM, 2 CPU - Ansible control node" + echo " • control1 (192.168.4.200) - 2GB RAM, 2 CPU - Ansible control node" echo " • ansible1 (192.168.4.201) - 1GB RAM, 1 CPU - Web server" echo " • ansible2 (192.168.4.202) - 1GB RAM, 1 CPU - Web server" echo " • ansible3 (192.168.4.203) - 1GB RAM, 1 CPU - Database server" @@ -74,11 +74,11 @@ lab_up() { echo -e "${GREEN}✅ RHCE Lab environment ready!${NC}" echo "" echo -e "${BLUE}🎯 Quick Access:${NC}" - echo " vagrant ssh control # SSH to control node" + echo " vagrant ssh control1 # SSH to control node" echo " vagrant ssh ansible1 # SSH to managed node 1" echo "" echo -e "${BLUE}🎓 Getting Started:${NC}" - echo " 1. vagrant ssh control" + echo " 1. vagrant ssh control1" echo " 2. sudo su - ansible" echo " 3. ansible all -m ping" echo "" diff --git a/vagrant/managed.yml b/vagrant/managed.yml new file mode 100644 index 0000000..80d6c48 --- /dev/null +++ b/vagrant/managed.yml @@ -0,0 +1,22 @@ +--- +# Configure managed nodes and distribute SSH keys + +- name: Configure managed nodes + hosts: managed + gather_facts: false + become: true + tasks: + - name: Create .ssh directory for ansible user + ansible.builtin.file: + path: /home/ansible/.ssh + state: directory + owner: ansible + group: ansible + mode: '0700' + + - name: Copy public key to managed nodes + when: hostvars['control1']['ansible_pubkey_content'] is defined + ansible.posix.authorized_key: + user: ansible + state: present + key: "{{ hostvars['control1']['ansible_pubkey_content'] }}" diff --git a/vagrant/practice-exam-a/.gitignore b/vagrant/practice-exam-a/.gitignore new file mode 100644 index 0000000..43bd2cc --- /dev/null +++ b/vagrant/practice-exam-a/.gitignore @@ -0,0 +1,9 @@ +# Vagrant files +.vagrant/ +*.vdi + +# Red Hat subscription credentials +.rhel-credentials + +# Log files +*.log diff --git a/vagrant/practice-exam-a/README.md b/vagrant/practice-exam-a/README.md new file mode 100644 index 0000000..5e3e5d9 --- /dev/null +++ b/vagrant/practice-exam-a/README.md @@ -0,0 +1,238 @@ +# Practice Exam A Environment + +This directory contains a dedicated Vagrant environment that exactly matches the requirements for **Practice Exam A** from Red Hat RHCE study materials. + +## Environment Specifications + +This environment provides **5 servers running RHEL 9**: + +| Server | Hostname | IP Address | RAM | Primary Disk | Secondary Disk | Role | +|--------|----------|------------|-----|-------------|----------------|------| +| control | control.example.com | 192.168.56.10 | 1GB | 20GB | - | Control Host | +| ansible1 | ansible1.example.com | 192.168.56.11 | 1GB | 20GB | 5GB (/dev/sdb) | Managed Server | +| ansible2 | ansible2.example.com | 192.168.56.12 | 1GB | 20GB | 5GB (/dev/sdb) | Managed Server | +| ansible3 | ansible3.example.com | 192.168.56.13 | 1GB | 20GB | - | Managed Server | +| ansible4 | ansible4.example.com | 192.168.56.14 | 1GB | 20GB | - | Managed Server | + +### Pre-configured Settings (Minimal - True Exam Conditions) + +✅ **What's already configured** (matches exam starting conditions): + +- Root user password set to `password` on all servers +- Hostname resolution configured in `/etc/hosts` +- SSH password authentication enabled for root access +- EPEL repository removed (not available on actual exam) + +⚠️ **What you need to configure** (part of exam tasks): + +- **Repository configuration** - Set up Red Hat repositories manually +- **Ansible installation** - Install Ansible package on control host +- **User management** - Create ansible user with appropriate privileges +- **SSH key setup** - Generate and distribute SSH keys +- **Ansible inventory** - Create inventory files for your automation +- **Package management** - Install any additional packages needed +- **All automation tasks** as specified in exam scenarios + +## Quick Start + +### 1. Start the Environment + +```bash +cd /path/to/rhce/vagrant/practice-exam-a +vagrant up +``` + +Initial startup takes ~10 minutes to download, create, and provision all 5 VMs. + +### 2. Access the Control Host + +```bash +# SSH to control host +vagrant ssh control + +# Switch to ansible user (where you'll do your exam work) +sudo su - ansible + +# Check starting conditions +pwd # Should be /home/ansible +ls -la ~/.ssh/ # SSH keys are generated but not distributed +ansible --version # Ansible is installed and ready +``` + +### 3. Begin Exam Setup Tasks + +You'll need to complete these initial tasks (part of the exam): + +```bash +# Test connectivity to managed nodes (this will initially fail) +ssh ansible1.example.com # No SSH access yet + +# Set up SSH access to managed nodes +ssh-copy-id root@ansible1.example.com # Password: password +ssh-copy-id root@ansible2.example.com # Password: password +ssh-copy-id root@ansible3.example.com # Password: password +ssh-copy-id root@ansible4.example.com # Password: password + +# Create and configure ansible inventory as needed for your tasks +vim inventory + +# Test ansible connectivity +ansible all -i inventory -m ping +``` + +## Environment Management + +### Start/Stop Operations + +```bash +./exam-start.sh # Start environment and show instructions +vagrant halt # Stop all VMs +vagrant up # Start all VMs +vagrant destroy -f # Destroy environment (reset for next practice) +``` + +### Individual VM Management + +```bash +vagrant status # Show all VM status +vagrant ssh control # SSH to control node +vagrant ssh ansible1 # SSH to managed node +vagrant halt ansible2 # Stop specific VM +vagrant up ansible3 # Start specific VM +``` + +### Reset for New Practice Session + +```bash +# Complete reset (destroys all VMs and data) +vagrant destroy -f +vagrant up + +# This gives you a fresh exam starting environment +``` + +## Storage Configuration + +- **ansible1** and **ansible2** have secondary 5GB disks at `/dev/sdb` +- **ansible3** and **ansible4** have only the primary 20GB disk +- Use `lsblk` or `fdisk -l` to verify disk configuration + +```bash +# Check disk configuration on managed nodes +vagrant ssh ansible1 -c "lsblk" +vagrant ssh ansible2 -c "lsblk" +``` + +## Network Configuration + +- **Private Network**: 192.168.56.0/24 (isolated from your main network) +- **Host Resolution**: All VMs can resolve each other by hostname +- **SSH Access**: All VMs accept SSH with password authentication enabled + +## Exam Practice Tips + +### 1. Directory Organization + +Store all your exam scripts in `/home/ansible` as required: + +```bash +cd /home/ansible +mkdir playbooks roles inventory_files +``` + +### 2. Inventory Management + +Create inventory files as needed for exam tasks: + +```bash +# Basic inventory template +cat > inventory << EOF +[webservers] +ansible1.example.com +ansible2.example.com + +[databases] +ansible3.example.com + +[development] +ansible4.example.com + +[all:vars] +ansible_user=ansible +EOF +``` + +### 3. Common First Steps + +```bash +# Distribute SSH keys to managed nodes (using root initially) +for host in ansible1 ansible2 ansible3 ansible4; do + ssh-copy-id root@${host}.example.com +done + +# Test connectivity +ansible all -i inventory -m ping -u root + +# Create ansible user on managed nodes and configure sudo +ansible all -i inventory -m user -a "name=ansible create_home=yes" -u root +ansible all -i inventory -m copy -a "content='ansible ALL=(ALL) NOPASSWD: ALL' dest=/etc/sudoers.d/ansible mode=0440" -u root + +# Set up SSH keys for ansible user +ansible all -i inventory -m authorized_key -a "user=ansible key='{{ lookup('file', '~/.ssh/id_rsa.pub') }}'" -u root + +# Test with ansible user +ansible all -i inventory -m ping -u ansible +``` + +## Troubleshooting + +### VM Issues + +```bash +# Check VM status +vagrant status +VBoxManage list runningvms + +# Restart VirtualBox if needed (Linux) +sudo systemctl restart virtualbox +``` + +### SSH Issues + +```bash +# Check SSH connectivity manually +ssh root@192.168.56.11 # Password: password +ssh ansible@192.168.56.11 # After SSH key setup + +# Reset SSH keys if needed +rm ~/.ssh/id_rsa* +ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa +``` + +### Ansible Issues + +```bash +# Check ansible configuration +ansible-config dump +ansible-inventory --list -i inventory + +# Test with verbose output +ansible all -i inventory -m ping -vvv +``` + +## Files and Structure + +```text +practice-exam-a/ +├── Vagrantfile # VM configuration matching exam specs +├── ansible.cfg # Basic Ansible configuration +├── inventory # Minimal inventory for provisioning +├── provision/ +│ └── site.yml # Initial system setup +├── exam-start.sh # Helper script to start environment +└── README.md # This file +``` + +--- + +**Ready to practice?** Run `./exam-start.sh` to begin your Practice Exam A session! diff --git a/vagrant/practice-exam-a/Vagrantfile b/vagrant/practice-exam-a/Vagrantfile new file mode 100644 index 0000000..1be3a62 --- /dev/null +++ b/vagrant/practice-exam-a/Vagrantfile @@ -0,0 +1,97 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Practice Exam A Environment +# Matches exact requirements for RHCE Practice Exam A +# Minimal setup - exam candidates configure repositories manually +Vagrant.configure("2") do |config| + # Skip Red Hat registration - exam candidates do this manually + if Vagrant.has_plugin?("vagrant-registration") + config.registration.skip = true + end + + # VM configuration matching exam requirements + vms = { + "control" => { + "ip" => "192.168.56.10", + "memory" => "1024", + "cpus" => "1", + "role" => "control" + }, + "ansible1" => { + "ip" => "192.168.56.11", + "memory" => "1024", + "cpus" => "1", + "role" => "managed", + "has_secondary_disk" => true + }, + "ansible2" => { + "ip" => "192.168.56.12", + "memory" => "1024", + "cpus" => "1", + "role" => "managed", + "has_secondary_disk" => true + }, + "ansible3" => { + "ip" => "192.168.56.13", + "memory" => "1024", + "cpus" => "1", + "role" => "managed" + }, + "ansible4" => { + "ip" => "192.168.56.14", + "memory" => "1024", + "cpus" => "1", + "role" => "managed" + } + } + + # Create VMs + vms.each do |name, vm_config| + config.vm.define name do |vm| + # Use RHEL 9 with Red Hat subscription + vm.vm.box = "generic/rhel9" + vm.vm.hostname = "#{name}.example.com" + vm.vm.network "private_network", ip: vm_config["ip"] + + # Provider specific settings + vm.vm.provider "virtualbox" do |vb| + vb.name = "practice-exam-a-#{name}" + vb.memory = vm_config["memory"] + vb.cpus = vm_config["cpus"] + vb.customize ["modifyvm", :id, "--groups", "/Practice Exam A"] + end + + # Configure additional disks using Vagrant disk feature + # Secondary disk only for ansible1 and ansible2 (5GB as required) + if vm_config["has_secondary_disk"] + vm.vm.disk :disk, name: "secondary", size: "5GB" + end + + # Minimal provisioning - only set root password and configure /etc/hosts + vm.vm.provision "shell", inline: <<-SHELL + # Set root password to "password" as required by exam + echo 'root:password' | chpasswd + + # Ensure SSH allows password authentication for root (exam requirement) + sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config + sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config + systemctl restart sshd + + # Remove EPEL repository - not available on actual exam + dnf remove -y epel-release || true + + # Configure /etc/hosts for hostname resolution (exam requirement) + cat >> /etc/hosts << 'EOF' + +# Practice Exam A Lab VMs +192.168.56.10 control.example.com control +192.168.56.11 ansible1.example.com ansible1 +192.168.56.12 ansible2.example.com ansible2 +192.168.56.13 ansible3.example.com ansible3 +192.168.56.14 ansible4.example.com ansible4 +EOF + SHELL + end + end +end diff --git a/vagrant/practice-exam-a/exam-start.sh b/vagrant/practice-exam-a/exam-start.sh new file mode 100755 index 0000000..dd79251 --- /dev/null +++ b/vagrant/practice-exam-a/exam-start.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# Practice Exam A Environment Startup Script + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +echo "=========================================" +echo " RHCE Practice Exam A Environment" +echo "=========================================" +echo + +# Check if VMs are already running +echo "🔍 Checking VM status..." +RUNNING_VMS=$(vagrant status | grep "running" | wc -l) + +if [ "$RUNNING_VMS" -eq 5 ]; then + echo "✅ All 5 VMs are already running!" + echo +else + echo "🚀 Starting Practice Exam A environment..." + echo " This will create 5 VMs (control + ansible1-4)" + echo " First run takes ~10 minutes for download and setup" + echo + + vagrant up + echo + echo "✅ Environment startup complete!" + echo +fi + +# Display environment information +echo "📋 ENVIRONMENT DETAILS" +echo "======================" +echo +echo "🖥️ VM Configuration:" +vagrant status | grep -E "(control|ansible[1-4])" | while read line; do + vm_name=$(echo $line | awk '{print $1}') + status=$(echo $line | awk '{print $2}') + + case $vm_name in + control) + ip="192.168.56.10" + disks="20GB primary" + ;; + ansible1) + ip="192.168.56.11" + disks="20GB primary + 5GB secondary" + ;; + ansible2) + ip="192.168.56.12" + disks="20GB primary + 5GB secondary" + ;; + ansible3) + ip="192.168.56.13" + disks="20GB primary" + ;; + ansible4) + ip="192.168.56.14" + disks="20GB primary" + ;; + esac + + printf " %-10s %-15s %-8s %s\n" "$vm_name" "$ip" "$status" "$disks" +done + +echo +echo "🔑 EXAM STARTING CONDITIONS (MINIMAL SETUP)" +echo "===========================================" +echo "✅ Root password set to 'password' on all VMs" +echo "✅ SSH password authentication enabled" +echo "✅ Hostname resolution configured in /etc/hosts" +echo +echo "⚠️ YOU MUST CONFIGURE (EXAM TASKS):" +echo " - Set up Red Hat repositories on all VMs" +echo " - Install Ansible on control host" +echo " - Create ansible user with sudo privileges" +echo " - Generate and distribute SSH keys" +echo " - Create Ansible inventory files" +echo " - Store all scripts in /home/ansible directory" +echo + +echo "🎯 FIRST EXAM STEPS" +echo "===================" +echo "# 1. Access control host:" +echo "vagrant ssh control" +echo +echo "# 2. Configure repositories (exam task #1):" +echo "sudo subscription-manager register --username YOUR_RH_USER --password YOUR_RH_PASS" +echo "sudo subscription-manager attach --auto" +echo "sudo subscription-manager repos --enable rhel-9-for-x86_64-appstream-rpms" +echo "sudo subscription-manager repos --enable rhel-9-for-x86_64-baseos-rpms" +echo +echo "# 3. Install Ansible:" +echo "sudo dnf install -y ansible" +echo +echo "# 4. Create ansible user:" +echo "sudo useradd ansible" +echo "sudo mkdir -p /home/ansible" +echo "sudo chown ansible:ansible /home/ansible" +echo + +echo "📚 EXAM ENVIRONMENT READY!" +echo "=========================" +echo "All scripts and YAML files must be stored in: /home/ansible" +echo +echo "Good luck with your Practice Exam A! 🚀" +echo +echo "To reset environment for next practice: vagrant destroy -f && vagrant up" +echo diff --git a/vagrant/requirements.yml b/vagrant/requirements.yml index 3ebb77d..948f9c6 100644 --- a/vagrant/requirements.yml +++ b/vagrant/requirements.yml @@ -1,9 +1,12 @@ +--- # Ansible Collections and Roles Requirements +# +# yamllint disable-line rule:line-length # Following best practices from Jeff Geerling: https://www.jeffgeerling.com/blog/2020/ansible-best-practices-using-project-local-collections-and-roles +# # Install with: ansible-galaxy install -r requirements.yml collections: - # Core collections needed for RHCE lab environment - name: ansible.posix version: ">=1.5.0" - name: community.general @@ -11,5 +14,4 @@ collections: - name: community.crypto version: ">=2.0.0" -# Roles (none currently required for basic RHCE lab setup) roles: [] diff --git a/vagrant/site.yml b/vagrant/site.yml index 5a9cc33..9e02540 100644 --- a/vagrant/site.yml +++ b/vagrant/site.yml @@ -1,20 +1,24 @@ +--- # Master playbook for RHCE lab environment -# Simple approach following Ansible best practices without over-engineering - name: Configure all hosts with common settings hosts: all - gather_facts: true become: true tasks: - # Skip package updates to avoid EPEL conflicts in lab environment - # - name: Update packages (not latest to avoid EPEL issues) - # ansible.builtin.dnf: - # name: '*' - # state: present - # update_cache: true - # tags: - # - packages + # EPEL is not officially supported and therefore won't be on the exam. + - name: Uninstall EPEL + ansible.builtin.dnf: + name: epel-release + state: absent + + - name: Update packages # noqa package-latest + ansible.builtin.dnf: + name: '*' + state: latest + update_cache: true + notify: Reboot # Reboot after system updates + # Consider removing? - name: Install essential packages ansible.builtin.dnf: name: @@ -26,8 +30,6 @@ - bash-completion - python3-pip state: present - tags: - - packages - name: Create ansible user ansible.builtin.user: @@ -37,125 +39,36 @@ create_home: true groups: wheel append: true - tags: - - users + # Update this to sudoers module? - name: Set up passwordless sudo for ansible user ansible.builtin.copy: content: "ansible ALL=(ALL) NOPASSWD: ALL" dest: /etc/sudoers.d/ansible mode: '0440' validate: 'visudo -cf %s' - tags: - - users + # Is there a module for managing hosts file? + # Answer: There isn't, but there is win_hosts for managing the Windows hosts + # file... - name: Configure /etc/hosts for all lab VMs ansible.builtin.blockinfile: path: /etc/hosts block: | # RHCE Lab VMs - 192.168.4.200 control.example.com control + 192.168.4.200 control1.example.com control1 192.168.4.201 ansible1.example.com ansible1 192.168.4.202 ansible2.example.com ansible2 192.168.4.203 ansible3.example.com ansible3 192.168.4.204 ansible4.example.com ansible4 marker: "# {mark} RHCE LAB HOSTS" - tags: - - networking - - - name: Configure firewall for SSH - ansible.posix.firewalld: - service: ssh - permanent: true - state: enabled - immediate: true - tags: - - firewall - - -- name: Configure control node - hosts: control - gather_facts: true - become: true - strategy: linear - tasks: - - name: Create SSH key for ansible user - ansible.builtin.user: - name: ansible - generate_ssh_key: true - ssh_key_type: rsa - ssh_key_bits: 2048 - ssh_key_file: .ssh/id_rsa - tags: - - ssh - - - name: Read the public key for distribution - ansible.builtin.slurp: - src: /home/ansible/.ssh/id_rsa.pub - register: ansible_public_key - run_once: true - tags: - - ssh - - name: Store public key as fact - ansible.builtin.set_fact: - ansible_pubkey_content: "{{ ansible_public_key.content | b64decode | trim }}" - run_once: true - tags: - - ssh + handlers: + - name: Reboot + ansible.builtin.reboot: -- name: Configure managed nodes and distribute SSH keys - hosts: managed - gather_facts: false - become: true - tasks: - - name: Install Python packages for Ansible modules - ansible.builtin.dnf: - name: - - python3-dnf - - python3-firewall - state: present - tags: - - packages - - - name: Create .ssh directory for ansible user - ansible.builtin.file: - path: /home/ansible/.ssh - state: directory - owner: ansible - group: ansible - mode: '0700' - tags: - - ssh - - - name: Copy public key to managed nodes - ansible.posix.authorized_key: - user: ansible - state: present - key: "{{ hostvars['control']['ansible_pubkey_content'] }}" - when: hostvars['control']['ansible_pubkey_content'] is defined - tags: - - ssh - -# You can add specific server configurations here as needed for RHCE practice - -- name: Test Ansible connectivity from control node - hosts: control - gather_facts: false - become: true - become_user: ansible - tasks: - - name: Test connectivity to all managed nodes - ansible.builtin.command: - cmd: ansible all -m ping - register: connectivity_test - ignore_errors: true - changed_when: false - tags: - - test +- name: Control + ansible.builtin.import_playbook: control.yml - - name: Display connectivity test results - ansible.builtin.debug: - var: connectivity_test.stdout_lines - tags: - - test +- name: Managed + ansible.builtin.import_playbook: managed.yml