This commit is contained in:
2026-02-13 15:55:41 -05:00
parent 7e75fa0199
commit 7a7c57d0bc
15 changed files with 243 additions and 122 deletions

37
.ansible-lint Normal file
View File

@@ -0,0 +1,37 @@
---
profile: basic
# Paths to exclude from linting
exclude_paths:
- .ansible/
- collections/ansible_collections/
- roles/geerlingguy.java/
- roles/oatakan.rhel_ovirt_template/
- roles/oatakan.rhel_template_build/
- roles/oatakan.windows_template_build/
- roles/oatakan.windows_update/
- roles/oatakan.windows_virtio/
- roles/ikke_t.container_image_cleanup/
- roles/ikke_t.podman_container_systemd/
- roles/sage905.mineos/
- roles/sage905.waterfall/
# Warn rather than fail on these during initial adoption
warn_list:
- yaml[line-length]
- name[casing]
- fqcn[action-core]
- no-changed-when
# Rules to skip entirely during initial adoption
skip_list:
- role-name # toal-common doesn't follow FQCN yet
# Use progressive mode: only flag new violations on changed files
# (useful for gradual adoption in existing projects)
# progressive: true
mock_modules:
- community.general.proxmox_kvm
mock_roles: []

7
.claude/settings.json Normal file
View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"Bash(du:*)"
]
}
}

View File

@@ -33,5 +33,6 @@
"mounts": [
"source=${localEnv:XDG_RUNTIME_DIR}/containers/auth.json,target=/container-auth.json,type=bind,consistency=cached",
"source=${localEnv:HOME}/Dev/inventories/toallab-inventory,target=/workspaces/inventory,type=bind,consistency=cached",
"source=${localEnv:HOME}/Dev/ansible_collections/,target=/workspaces/collections/,type=bind,consistency=cached",
]
}

7
.gitignore vendored
View File

@@ -107,7 +107,14 @@ venv.bak/
# Ansible
*.retry
ansible-navigator.log
.ansible/
# Vendor roles (install via roles/requirements.yml)
roles/geerlingguy.*
roles/oatakan.*
roles/ikke_t.*
roles/sage905.*
.vscode/
keys/

View File

@@ -3,3 +3,26 @@ repos:
rev: v8.18.2
hooks:
- id: gitleaks
- repo: https://github.com/adrienverge/yamllint
rev: v1.35.1
hooks:
- id: yamllint
args: [--config-file, .yamllint]
exclude: |
(?x)^(
roles/geerlingguy\..*/|
roles/oatakan\..*/|
roles/ikke_t\..*/|
roles/sage905\..*/|
\.ansible/|
collections/ansible_collections/
)
- repo: https://github.com/ansible/ansible-lint
rev: v25.1.3
hooks:
- id: ansible-lint
# ansible-lint reads .ansible-lint for configuration
additional_dependencies:
- ansible-core>=2.15

39
.yamllint Normal file
View File

@@ -0,0 +1,39 @@
---
extends: default
rules:
# Allow longer lines for readability in tasks
line-length:
max: 160
level: warning
# Allow both true/false and yes/no boolean styles
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
check-keys: false
# Ansible uses double-bracket Jinja2 - allow in strings
braces:
min-spaces-inside: 0
max-spaces-inside: 1
# Allow some indentation flexibility for Ansible block style
indentation:
spaces: 2
indent-sequences: true
check-multi-line-strings: false
# Comments should have a space after #
comments:
min-spaces-from-content: 1
# Don't require document-start marker on every file
document-start: disable
ignore: |
roles/geerlingguy.*
roles/oatakan.*
roles/ikke_t.*
roles/sage905.*
.ansible/
collections/ansible_collections/

44
ansible.cfg Normal file
View File

@@ -0,0 +1,44 @@
[defaults]
# Inventory - override with -i or ANSIBLE_INVENTORY env var
inventory = /workspaces/inventory
# Role and collection paths
roles_path = roles
collections_path = /workspaces/collections:~/.ansible/collections
# Interpreter discovery
interpreter_python = auto_silent
# Performance
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_fact_cache
fact_caching_timeout = 3600
# Output
stdout_callback = yaml
bin_ansible_callbacks = True
callbacks_enabled = profile_tasks
# SSH settings
host_key_checking = False
timeout = 30
# Vault
vault_password_file = vault-id-from-op-client.sh
# Misc
retry_files_enabled = False
nocows = True
[inventory]
# Enable inventory plugins
enable_plugins = host_list, yaml, ini, auto, toml
[privilege_escalation]
become = False
become_method = sudo
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no

View File

@@ -1,47 +0,0 @@
#!/usr/bin/python
import ipaddress
import yaml
import os
from collections import defaultdict
def load_yaml_input(file_path):
with open(file_path, "r") as f:
return yaml.safe_load(f)
def group_by_subnet(data, mask=24):
grouped = defaultdict(list)
for record in data:
ip_str = record.get("address")
if not ip_str:
continue
try:
ip = ipaddress.ip_address(ip_str)
network = ipaddress.ip_network(f"{ip}/{mask}", strict=False)
grouped[str(network)].append(record)
except ValueError:
print(f"Skipping invalid IP: {ip_str}")
return grouped
def save_groups_to_yaml(grouped, output_dir="."):
os.makedirs(output_dir, exist_ok=True)
for subnet, entries in grouped.items():
safe_subnet = subnet.replace("/", "_")
filename = os.path.join(output_dir, f"subnet_{safe_subnet}.yaml")
with open(filename, "w") as f:
yaml.dump(entries, f, default_flow_style=False)
print(f"Saved {len(entries)} entries to {filename}")
def main():
input_file = "input.yaml" # change as needed
output_dir = "output_subnets"
cidr_mask = 24 # change to desired subnet size
records = load_yaml_input(input_file)
grouped = group_by_subnet(records, cidr_mask)
save_groups_to_yaml(grouped, output_dir)
if __name__ == "__main__":
main()

View File

@@ -1,59 +0,0 @@
---
- name: VM Provisioning
hosts: tag_ansible:&tag_tower
connection: local
collections:
- redhat.rhv
tasks:
- block:
- name: Obtain SSO token from username / password credentials
ovirt_auth:
url: "{{ ovirt_url }}"
username: "{{ ovirt_username }}"
password: "{{ ovirt_password }}"
- name: Disks Created
ovirt_disk:
auth: "{{ ovirt_auth }}"
description: "Boot Disk for {{ inventory_hostname }}"
interface: virtio
size: 120GiB
storage_domain: nas_iscsi
bootable: True
wait: true
name: "{{ inventory_hostname }}_disk0"
state: present
- name: VM Created
ovirt_vm:
- name: Add NIC to VM
ovirt_nic:
state: present
vm:
name: mynic
interface: e1000
mac_address: 00:1a:4a:16:01:56
profile: ovirtmgmt
network: ovirtmgmt
- name: Plug NIC to VM
redhat.rhv.ovirt_nic:
state: plugged
vm: myvm
name: mynic
always:
- name: Always revoke the SSO token
ovirt_auth:
state: absent
ovirt_auth: "{{ ovirt_auth }}"
# - name: VM Configuration
# - name: Automation Platform Installer
# - name:

View File

@@ -1,12 +0,0 @@
- name: Create an ovirt windows template
hosts: windows_template_base
gather_facts: false
connection: local
become: false
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
roles:
- oatakan.windows_ovirt_template

View File

@@ -0,0 +1,31 @@
---
- name: Create Gitea Server
hosts: gitea
gather_facts: false
vars:
dnsmadeeasy_hostname: "{{ service_dns_name.split('.') | first }}"
dnsmadeeasy_domain: "{{ service_dns_name.split('.',1) |last }}"
dnsmadeeasy_record_type: CNAME
dnsmadeeasy_record_value: gate.toal.ca.
dnsmadeeasy_record_ttl: 600
opnsense_service_hostname: "{{ dnsmadeeasy_hostname }}"
opnsense_service_domain: "{{ dnsmadeeasy_domain }}"
tasks:
- name: Configure DNS
ansible.builtin.import_role:
name: toallab.infra.dnsmadeeasy
tasks_from: provision.yml
- name: Configure Service
ansible.builtin.import_role:
name: toallab.infra.opnsense_service
tasks_from: provision.yml
module_defaults:
group/ansibleguy.opnsense.all:
firewall: "{{ opnsense_host }}"
api_key: "{{ opnsense_api_key }}"
api_secret: "{{ opnsense_api_secret }}"
ssl_verify: "{{ opnsense_ssl_verify }}"
api_port: "{{ opnsense_api_port|default(omit) }}"

View File

@@ -0,0 +1,6 @@
- name: Deploy OpenShift on Proxmox
hosts: all
gather_facts: false
connection: local
tasks:

View File

@@ -11,7 +11,18 @@
api_port: "{{ opnsense_api_port|default(omit) }}"
tasks:
# TODO: Clean up subnet / reservation structure
- name: Install packages
ansibleguy.opnsense.package:
name:
- os-acme-client
action: install
delegate_to: localhost
- name: Setup ACME Client
ansible.builtin.include_role:
name: toallab.infra.opnsense_service
tasks_from: setup.yml
- name: Configure KEA DHCP Server
ansibleguy.opnsense.dhcp_general:
enabled: "{{ dhcp_enabled }}"
@@ -51,5 +62,3 @@
reload: false
delegate_to: localhost
loop: "{{ all_dhcp_reservations }}"
- name: Add HAProxy

View File

@@ -1 +0,0 @@
hostname, domain, description, enabled, mx, mxprio, prio, record_type, server, value, uuid
1 hostname domain description enabled mx mxprio prio record_type server value uuid

36
vault-id-from-op-client.sh Executable file
View File

@@ -0,0 +1,36 @@
#!/bin/bash
# Parse input arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--vault-id)
VAULT_ID="$2"
shift 2
;;
*)
echo "Usage: $0 --vault-id <vault id>" >&2
exit 1
;;
esac
done
# Validate vault ID
if [[ -z "$VAULT_ID" ]]; then
echo "Error: Missing required --vault-id argument" >&2
exit 1
fi
ITEM_NAME="${VAULT_ID} vault key"
FIELD_NAME="password"
# Fetch the vault password from 1Password
VAULT_PASSWORD=$(op item get "$ITEM_NAME" --fields "$FIELD_NAME" --format=json --vault LabSecrets 2>/dev/null | jq -r '.value')
# Output the password or report error
if [[ -n "$VAULT_PASSWORD" && "$VAULT_PASSWORD" != "null" ]]; then
echo "$VAULT_PASSWORD"
else
echo "Error: Could not retrieve vault password for vault ID '$VAULT_ID' (item: '$ITEM_NAME')" >&2
exit 1
fi