Add reproducible Nix dev environment
Replace the Python venv with a Nix devshell pinning ansible-core 2.21.3, ansible-lint, yamllint and a Python with proxmoxer/requests. The Python dependencies share the interpreter that runs ansible, so pve-*.yml plays on implicit localhost can import proxmoxer without inventory changes. The shellHook exports absolute ANSIBLE_CONFIG, ANSIBLE_INVENTORY, ANSIBLE_ROLES_PATH and ANSIBLE_COLLECTIONS_PATH, so commands work from the repository root as well as from ansible/. Also un-ignore .envrc, which the global gitignore hides, and ignore the stray .ansible/ runtime directory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
# direnv: load the Nix dev shell defined in flake.nix
|
||||||
|
# Enable once per checkout with: direnv allow
|
||||||
|
use flake
|
||||||
@@ -20,3 +20,9 @@ __pycache__/
|
|||||||
.direnv/
|
.direnv/
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
|
# direnv shell hook lives in the repo (global gitignore hides it)
|
||||||
|
!.envrc
|
||||||
|
|
||||||
|
# Ansible local runtime dir (facts cache, locks)
|
||||||
|
.ansible/
|
||||||
|
|||||||
Generated
+27
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1787498568,
|
||||||
|
"narHash": "sha256-9i/VTdusq/+NM/tz+J1Re+ojkMB8MBf0QshnYfzHz30=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "56c02bc00adcf003215cc4bd996d6efaf4cff188",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
description = "HomeLab infras — reproducible Ansible control-plane dev shell";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }:
|
||||||
|
let
|
||||||
|
systems = [ "x86_64-linux" "aarch64-linux" ];
|
||||||
|
forAllSystems = f:
|
||||||
|
nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = forAllSystems (pkgs:
|
||||||
|
let
|
||||||
|
# One Python environment carrying ansible-core *and* the libraries the
|
||||||
|
# modules import in-process (community.proxmox needs proxmoxer +
|
||||||
|
# requests). Ansible sets ansible_python_interpreter for the implicit
|
||||||
|
# localhost to sys.executable, so `hosts: localhost` and
|
||||||
|
# `delegate_to: localhost` tasks pick these up automatically.
|
||||||
|
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||||
|
ansible-core
|
||||||
|
proxmoxer
|
||||||
|
requests
|
||||||
|
]);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
name = "homelab-infras";
|
||||||
|
|
||||||
|
packages = [
|
||||||
|
pythonEnv
|
||||||
|
pkgs.ansible-lint
|
||||||
|
pkgs.yamllint
|
||||||
|
pkgs.git
|
||||||
|
pkgs.jq
|
||||||
|
pkgs.openssh
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.gnumake
|
||||||
|
];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
repo_root="$(${pkgs.git}/bin/git rev-parse --show-toplevel 2>/dev/null || pwd)"
|
||||||
|
ansible_dir="$repo_root/ansible"
|
||||||
|
|
||||||
|
if [ -f "$ansible_dir/ansible.cfg" ]; then
|
||||||
|
# ansible.cfg spells its paths relative to ansible/, so pin them
|
||||||
|
# absolutely here — that makes the shell usable from the repo
|
||||||
|
# root as well as from inside ansible/.
|
||||||
|
export ANSIBLE_CONFIG="$ansible_dir/ansible.cfg"
|
||||||
|
export ANSIBLE_INVENTORY="$ansible_dir/inventory/hosts.yml"
|
||||||
|
export ANSIBLE_ROLES_PATH="$ansible_dir/roles"
|
||||||
|
export ANSIBLE_COLLECTIONS_PATH="$ansible_dir/collections"
|
||||||
|
else
|
||||||
|
echo "warn: $ansible_dir/ansible.cfg not found — run commands from ansible/" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Banner goes to stderr so `nix develop --command ...` keeps a
|
||||||
|
# clean stdout for scripting.
|
||||||
|
{
|
||||||
|
_ver_ansible="$(ansible --version 2>/dev/null | head -n1 | tr -d '[]' | awk '{print $3}')"
|
||||||
|
_ver_lint="$(NO_COLOR=1 ansible-lint --version 2>/dev/null | tail -n1 | awk '{print $2}')"
|
||||||
|
_ver_yaml="$(yamllint --version 2>/dev/null | awk '{print $2}')"
|
||||||
|
_ver_py="$(python3 --version 2>&1 | awk '{print $2}')"
|
||||||
|
|
||||||
|
echo "HomeLab infras dev shell"
|
||||||
|
echo " ansible-core $_ver_ansible"
|
||||||
|
echo " ansible-lint $_ver_lint"
|
||||||
|
echo " yamllint $_ver_yaml"
|
||||||
|
echo " python $_ver_py (proxmoxer, requests)"
|
||||||
|
echo ""
|
||||||
|
echo "ANSIBLE_CONFIG=$ANSIBLE_CONFIG"
|
||||||
|
echo ""
|
||||||
|
echo "Galaxy collections are NOT installed automatically. Run once:"
|
||||||
|
echo " ansible-galaxy collection install -r $ansible_dir/requirements.yml -p $ansible_dir/collections"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
unset _ver_ansible _ver_lint _ver_yaml _ver_py
|
||||||
|
} >&2
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
formatter = forAllSystems (pkgs: pkgs.nixpkgs-fmt);
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user