chore: initial commit

This commit is contained in:
technofab 2025-07-15 19:28:42 +02:00
commit 7602719790
No known key found for this signature in database
24 changed files with 1916 additions and 0 deletions

View file

@ -0,0 +1,45 @@
{
stdenv,
lib,
pkgs,
}: ansible: collections: let
inherit (lib) concatStringsSep mapAttrsToList;
mkCollection = {
name,
version,
hash,
}:
stdenv.mkDerivation {
pname = name;
inherit version;
src = pkgs.fetchurl {
inherit hash;
url = "https://galaxy.ansible.com/download/${name}-${version}.tar.gz";
};
phases = ["installPhase"];
installPhase = ''
mkdir -p $out
cp $src $out/collection.tar.gz
'';
};
installCollection = collection: "${ansible}/bin/ansible-galaxy collection install ${collection}/collection.tar.gz";
installCollections = concatStringsSep "\n" (
mapAttrsToList (
name: coll:
installCollection (
mkCollection ({inherit name;} // coll)
)
)
collections
);
in
pkgs.runCommand "ansible-collections" {} ''
mkdir -p $out
export HOME=./
export ANSIBLE_COLLECTIONS_PATH=$out
${installCollections}
''

91
lib/ansible-core.nix Normal file
View file

@ -0,0 +1,91 @@
{
lib,
buildPythonPackage,
fetchPypi,
installShellFiles,
docutils,
setuptools,
cryptography,
jinja2,
junit-xml,
lxml,
ncclient,
packaging,
paramiko,
ansible-pylibssh,
pexpect,
psutil,
pycrypto,
pyyaml,
requests,
resolvelib,
scp,
windowsSupport ? false,
pywinrm,
xmltodict,
}:
buildPythonPackage rec {
pname = "ansible-core";
version = "2.18.6";
pyproject = true;
src = fetchPypi {
pname = "ansible_core";
inherit version;
hash = "sha256-JbsgzhUWobcweDGyY872hAQ7NyBxFGa9nUFk5f1XZVc=";
};
# ansible_connection is already wrapped, so don't pass it through
# the python interpreter again, as it would break execution of
# connection plugins.
postPatch = ''
substituteInPlace lib/ansible/executor/task_executor.py \
--replace "[python," "["
patchShebangs --build packaging/cli-doc/build.py
SETUPTOOLS_PATTERN='"setuptools[0-9 <>=.,]+"'
PYPROJECT=$(cat pyproject.toml)
if [[ "$PYPROJECT" =~ $SETUPTOOLS_PATTERN ]]; then
echo "setuptools replace: ''${BASH_REMATCH[0]}"
echo "''${PYPROJECT//''${BASH_REMATCH[0]}/'"setuptools"'}" > pyproject.toml
else
exit 2
fi
'';
nativeBuildInputs = [
installShellFiles
docutils
];
build-system = [setuptools];
dependencies =
[
# from requirements.txt
cryptography
jinja2
packaging
pyyaml
resolvelib
# optional dependencies
junit-xml
lxml
ncclient
paramiko
ansible-pylibssh
pexpect
psutil
pycrypto
requests
scp
xmltodict
]
++ lib.optionals windowsSupport [pywinrm];
pythonRelaxDeps = ["resolvelib"];
# internal import errors, missing dependencies
doCheck = false;
}

20
lib/default.nix Normal file
View file

@ -0,0 +1,20 @@
{
pkgs,
lib ? pkgs.lib,
...
}: let
inherit (lib) evalModules;
in rec {
module = ./module.nix;
mkNixible = config:
evalModules {
specialArgs = {inherit pkgs;};
modules = [
module
config
];
};
mkNixibleCli = config: (mkNixible config).config.cli;
}

6
lib/flake.nix Normal file
View file

@ -0,0 +1,6 @@
{
outputs = {...}: {
lib = import ./.;
flakeModule = ./flakeModule.nix;
};
}

33
lib/flakeModule.nix Normal file
View file

@ -0,0 +1,33 @@
{
flake-parts-lib,
lib,
...
}: let
inherit (lib) mkOption types;
in {
options.perSystem = flake-parts-lib.mkPerSystemOption (
{
config,
pkgs,
...
}: let
nixible-lib = import ./. {inherit pkgs lib;};
in {
options.nixible = mkOption {
type = types.attrsOf (types.submodule (args:
# needed to get pkgs in there, weirdly enough
import nixible-lib.module (args
// {
inherit pkgs;
})));
default = {};
};
config.legacyPackages = lib.fold (playbook: acc: acc // playbook) {} (
map (playbook_name: {
"nixible:${playbook_name}" = (builtins.getAttr playbook_name config.nixible).cli;
}) (builtins.attrNames config.nixible)
);
}
);
}

103
lib/module.nix Normal file
View file

@ -0,0 +1,103 @@
{
lib,
pkgs,
config,
...
}: let
inherit (lib) types mkOption;
collectionType = types.submodule {
options = {
version = mkOption {
type = types.str;
description = "Version of collection";
};
hash = mkOption {
type = types.str;
description = "Hash of the collection tarball";
};
};
};
in {
options = {
ansiblePackage = mkOption {
type = types.package;
default = pkgs.python3Packages.callPackage ./ansible-core.nix {};
description = "Ansible package to use (default doesn't have any collections installed for size)";
};
collections = mkOption {
type = types.attrsOf collectionType;
default = {};
description = "Collections to fetch and install";
};
dependencies = mkOption {
type = types.listOf types.package;
default = [];
description = "List of packages to include at runtime";
};
playbook = mkOption {
type = types.listOf (types.submodule {
options = {
name = mkOption {
type = types.str;
description = "Name of the play";
};
hosts = mkOption {
type = types.str;
description = "The target hosts for this play (e.g., 'all', 'webservers')";
};
become = mkOption {
type = types.bool;
default = false;
description = "Whether to use privilege escalation (become: yes)";
};
tasks = mkOption {
type = types.listOf types.attrs;
default = [];
description = "List of tasks to execute in this play";
};
};
});
description = "The actual playbook, defined as a Nix data structure";
};
inventory = mkOption {
type = types.attrs;
default = {};
description = "Ansible inventory, will be converted to json and passed to ansible";
};
inventoryFile = mkOption {
internal = true;
type = types.package;
};
playbookFile = mkOption {
internal = true;
type = types.package;
};
installedCollections = mkOption {
internal = true;
type = types.package;
};
cli = mkOption {
internal = true;
type = types.package;
};
};
config = {
inventoryFile = (pkgs.formats.json {}).generate "inventory.json" config.inventory;
playbookFile = (pkgs.formats.yaml {}).generate "playbook.yml" config.playbook;
installedCollections = pkgs.callPackage ./ansible-collections.nix {} config.ansiblePackage config.collections;
cli = pkgs.writeShellApplication {
name = "nixible";
runtimeInputs = config.dependencies;
text = ''
set -euo pipefail
export ANSIBLE_COLLECTIONS_PATH=${config.installedCollections}
git_repo=$(git rev-parse --show-toplevel 2>/dev/null || true)
${config.ansiblePackage}/bin/ansible-playbook -i ${config.inventoryFile} ${config.playbookFile} -e "pwd=$(pwd)" -e "git_root=$git_repo" "$@"
'';
};
};
}