Initial commit

This commit is contained in:
Jamie Helmke
2025-10-30 21:36:38 +01:00
commit 792f4a7f82
8 changed files with 192 additions and 0 deletions

25
.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
# Python virtual environment
env/
venv/
# Ansible local data
ansible/lib/collections/
# Backups
*backup*/
*.bak
# Caches and logs
__pycache__/
*.pyc
*.pyo
*.retry
*.log
# macOS system files
.DS_Store
# Editor and OS stuff
.idea/
.vscode/
*.swp

27
README.md Normal file
View File

@@ -0,0 +1,27 @@
# ⚡️ Portable Ansible Environment
A self-contained Ansible workspace for MacOS, Linux and other posix compliant systems.
## Requirements
git, python3, pip3
## Setup
1. Clone the repository:
```bash
git clone https://github.com/jamieahelmke/portable-ansible
cd portable-ansible
```
2. Build the environment:
```bash
python3 setup.py
```
3. Activate the environment:
```bash
source ./start_venv.sh
```
4. Run the example playbook:
```bash
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/example.yml
```

7
ansible/ansible.cfg Normal file
View File

@@ -0,0 +1,7 @@
[defaults]
inventory = ./ansible/inventory/hosts.ini
roles_path = ./ansible/roles
collections_paths = ./ansible/lib/collections
host_key_checking = False
retry_files_enabled = False
stdout_callback = yaml

View File

@@ -0,0 +1,22 @@
# Tips for building inventories
# - Ensure that group names are meaningful and unique. Group names are also case sensitive.
# - Avoid spaces, hyphens, and preceding numbers (use floor_19, not 19th_floor) in group names.
# - Group hosts in your inventory logically according to their What, Where, and When.
#
# Example inventory
#production:
# children:
# web:
# hosts:
# web1.example.com:
# web2.example.com:
# db:
# hosts:
# db1.example.com:
# db2.example.com:
local:
hosts:
localhost:
ansible_host: localhost
ansible_connection: local

View File

@@ -0,0 +1,7 @@
---
- name: Example Playbook
hosts: local
gather_facts: false
tasks:
- name: Test connection
ansible.builtin.ping:

2
requirements.txt Normal file
View File

@@ -0,0 +1,2 @@
ansible
ansible-lint

98
setup.py Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/env python3
import os
import platform
import subprocess
import sys
import time
# --- Config ---
REQUIRED_PATHS = [
"ansible/ansible.cfg",
"ansible/inventory/",
"ansible/playbooks/",
"requirements.txt",
"start_venv.sh",
]
VENV_DIR = "env/venv"
COLLECTIONS_DIR = "ansible/lib/collections"
# --- Helper functions ---
def print_step(step, message, end="\n"):
sys.stdout.write(f"[{step}] {message}{end}")
sys.stdout.flush()
def live_status(message):
sys.stdout.write(f"\r{message}")
sys.stdout.flush()
def verify_repo_structure():
missing = [p for p in REQUIRED_PATHS if not os.path.exists(p)]
if missing:
print_step("2/5", "Checking repository structure...")
print(f"ERROR: Missing required file or directory:\n {missing[0]}")
print("\nFix this by running:")
print(" git fetch origin")
print(" git reset --hard origin/main")
sys.exit(1)
print_step("2/5", "Checking repository structure... OK")
def create_local_dirs():
print_step("3/5", "Creating local directories...")
os.makedirs("env", exist_ok=True)
os.makedirs(COLLECTIONS_DIR, exist_ok=True)
for d in [
"ansible/inventory",
"ansible/playbooks",
"ansible/roles",
"ansible/group_vars",
"ansible/host_vars",
]:
os.makedirs(d, exist_ok=True)
print("Local directories verified or created.")
def recreate_venv():
print_step("4/5", "Creating and initializing Python virtual environment...")
if os.path.exists(VENV_DIR):
subprocess.run(["rm", "-rf", VENV_DIR], check=True)
subprocess.run([sys.executable, "-m", "venv", VENV_DIR], check=True)
pip_path = f"{VENV_DIR}/bin/pip"
live_status("[4/5] Installing dependencies... 0%")
result = subprocess.run([pip_path, "install", "-r", "requirements.txt"], capture_output=True, text=True)
if result.returncode != 0:
print("\nDependency installation failed:")
print(result.stderr)
sys.exit(1)
live_status("[4/5] Installing dependencies... 100%\n")
def verify_ansible():
print_step("5/5", "Final checks...")
ansible_path = f"{VENV_DIR}/bin/ansible"
result = subprocess.run([ansible_path, "--version"], capture_output=True, text=True)
if result.returncode == 0:
version_line = result.stdout.splitlines()[0]
print(f"Ansible version: {version_line}")
print("\nSetup complete.\n")
print("Next steps:")
print("1. Activate environment: source ./start_venv.sh")
print("2. Run playbook example: ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/example.yml")
print("3. To rebuild: python3 setup_env.py")
else:
print("Ansible verification failed. Check installation.")
# --- Main ---
def main():
print_step("1/5", "Detecting operating system...")
system = platform.system()
print(f"Detected OS: {system}")
if system not in ("Darwin", "Linux"):
print("Unsupported OS. Use macOS or Linux.")
sys.exit(1)
verify_repo_structure()
create_local_dirs()
recreate_venv()
verify_ansible()
if __name__ == "__main__":
main()

4
start_venv.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
DIR="$(cd "$(dirname "$0")" && pwd)"
source "$DIR/env/venv/bin/activate"
echo "Virtual environment activated. Type 'deactivate' to exit."