Skip to content

Add tests for ansible and system manager modules #1746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: update-nixpkgs
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ansible/tasks/files
12 changes: 12 additions & 0 deletions ansible/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def pytest_addoption(parser):
parser.addoption(
"--ansible-dir",
action="store",
help="Directory containing Ansible playbooks and roles",
)

parser.addoption(
"--docker-image",
action="store",
help="Docker image and tag to use for testing",
)
14 changes: 14 additions & 0 deletions ansible/tests/nginx.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
- hosts: localhost
tasks:
- name: Install dependencies
apt:
pkg:
- build-essential
update_cache: yes
- import_tasks: ../tasks/setup-nginx.yml
- name: Start Nginx service
service:
name: nginx
state: started
enabled: yes
61 changes: 61 additions & 0 deletions ansible/tests/test_nginx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import pytest
import subprocess
import testinfra
from rich.console import Console

console = Console()


@pytest.fixture(scope="session")
def host(request):
ansible_dir = request.config.getoption("--ansible-dir")
docker_id = (
subprocess.check_output(
[
"docker",
"run",
"--privileged",
"--cap-add",
"SYS_ADMIN",
"--security-opt",
"seccomp=unconfined",
"--cgroup-parent=docker.slice",
"--cgroupns",
"private",
"-v",
f"{ansible_dir}/:/ansible/",
"-d",
"ubuntu-cloudimg-with-tools:0.1",
]
)
.decode()
.strip()
)
yield testinfra.get_host("docker://" + docker_id)
subprocess.check_call(["docker", "rm", "-f", docker_id], stdout=subprocess.DEVNULL)


@pytest.fixture(scope="session", autouse=True)
def run_ansible(host):
cmd = [
"ANSIBLE_HOST_KEY_CHECKING=False",
"ansible-playbook",
"--connection=local",
"-i",
"localhost,",
"--extra-vars",
"@/ansible/vars.yml",
"/ansible/tests/nginx.yaml",
]
result = host.run(" ".join(cmd))
if result.failed:
console.log(result.stdout)
console.log(result.stderr)
raise pytest.fail(
"Ansible playbook nginx.yaml failed with return code {}".format(result.rc)
)


def test_nginx_service(host):
assert host.service("nginx.service").is_valid
assert host.service("nginx.service").is_running
21 changes: 21 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
system-manager = {
url = "github:numtide/system-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs =
Expand All @@ -54,6 +58,7 @@
nix/nixpkgs.nix
nix/packages
nix/overlays
nix/systemModules
];
});
}
90 changes: 90 additions & 0 deletions nix/packages/ansible-test.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
pkgs,
lib,
}:
let
ubuntu-cloudimg =
let
cloudImg = builtins.fetchurl {
url = "http://cloud-images-archive.ubuntu.com/releases/noble/release-20250430/ubuntu-24.04-server-cloudimg-amd64-root.tar.xz";
sha256 = "sha256:0rfi3qqs0sqarixfic7pzjpx7d4vldv2d98c5zjv7b90mirznvf9";
};
in
pkgs.runCommand "ubuntu-cloudimg" { nativeBuildInputs = [ pkgs.xz ]; } ''
mkdir -p $out
tar --exclude='dev/*' \
--exclude='etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service' \
--exclude='etc/systemd/system/multi-user.target.wants/systemd-resolved.service' \
--exclude='usr/lib/systemd/system/tpm-udev.service' \
--exclude='usr/lib/systemd/system/systemd-remount-fs.service' \
--exclude='usr/lib/systemd/system/systemd-resolved.service' \
--exclude='var/lib/apt/lists/*' \
-xJf ${cloudImg} -C $out
rm $out/bin $out/lib $out/lib64 $out/sbin
mkdir -p $out/run/systemd && echo 'docker' > $out/run/systemd/container
mkdir $out/var/lib/apt/lists/partial
'';

dockerImageUbuntu = pkgs.dockerTools.buildImage {
name = "ubuntu-cloudimg";
tag = "0.1";
created = "now";
extraCommands = ''
ln -s usr/bin
ln -s usr/lib
ln -s usr/lib64
ln -s usr/sbin
'';
copyToRoot = pkgs.buildEnv {
name = "image-root";
pathsToLink = [ "/" ];
paths = [ ubuntu-cloudimg ];
};
config.Cmd = [ "/lib/systemd/systemd" ];
};

dockerImageUbuntuWithTools =
let
tools = [ pkgs.ansible ];
in
pkgs.dockerTools.buildLayeredImage {
name = "ubuntu-cloudimg-with-tools";
tag = "0.1";
created = "now";
maxLayers = 30;
fromImage = dockerImageUbuntu;
config = {
Env = [
"PATH=${lib.makeBinPath tools}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
];
Cmd = [ "/lib/systemd/systemd" ];
};
};
in
pkgs.writeShellApplication {
name = "ansible-test";
runtimeInputs = with pkgs; [
(python3.withPackages (
ps: with ps; [
requests
pytest
pytest-testinfra
rich
]
))
];
text = ''
echo "Running Ansible tests..."
export DOCKER_IMAGE=${dockerImageUbuntuWithTools.imageName}:${dockerImageUbuntuWithTools.imageTag}
if ! docker image inspect $DOCKER_IMAGE > /dev/null; then
echo "Loading Docker image..."
docker load < ${dockerImageUbuntuWithTools}
fi
ANSIBLE_DIR=${../../ansible}
pytest -p no:cacheprovider -s -v "$@" $ANSIBLE_DIR/tests --ansible-dir=$ANSIBLE_DIR --docker-image=$DOCKER_IMAGE
'';
meta = with pkgs.lib; {
description = "Ansible test runner";
platforms = platforms.linux;
};
}
2 changes: 2 additions & 0 deletions nix/packages/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
packages = (
{
build-test-ami = pkgs.callPackage ./build-test-ami.nix { };
ansible-test = pkgs.callPackage ./ansible-test.nix { };
cleanup-ami = pkgs.callPackage ./cleanup-ami.nix { };
dbmate-tool = pkgs.callPackage ./dbmate-tool.nix { inherit (self.supabase) defaults; };
docker-image-ubuntu = pkgs.callPackage ./docker-ubuntu.nix { };
docs = pkgs.callPackage ./docs.nix { };
supabase-groonga = pkgs.callPackage ./groonga { };
local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { };
Expand Down
48 changes: 48 additions & 0 deletions nix/packages/docker-ubuntu.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
runCommand,
dockerTools,
xz,
buildEnv,
}:
let
ubuntu-cloudimg =
let
cloudImg = builtins.fetchurl {
url = "http://cloud-images-archive.ubuntu.com/releases/noble/release-20250430/ubuntu-24.04-server-cloudimg-amd64-root.tar.xz";
sha256 = "sha256:0rfi3qqs0sqarixfic7pzjpx7d4vldv2d98c5zjv7b90mirznvf9";
};
in
runCommand "ubuntu-cloudimg" { nativeBuildInputs = [ xz ]; } ''
mkdir -p $out
tar --exclude='dev/*' \
--exclude='etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service' \
--exclude='etc/systemd/system/multi-user.target.wants/systemd-resolved.service' \
--exclude='usr/lib/systemd/system/tpm-udev.service' \
--exclude='usr/lib/systemd/system/systemd-remount-fs.service' \
--exclude='usr/lib/systemd/system/systemd-resolved.service' \
--exclude='usr/lib/systemd/system/proc-sys-fs-binfmt_misc.automount' \
--exclude='usr/lib/systemd/system/sys-kernel-*' \
--exclude='var/lib/apt/lists/*' \
-xJf ${cloudImg} -C $out
rm $out/bin $out/lib $out/lib64 $out/sbin
mkdir -p $out/run/systemd && echo 'docker' > $out/run/systemd/container
mkdir $out/var/lib/apt/lists/partial
'';
in
dockerTools.buildImage {
name = "ubuntu-cloudimg";
tag = "24.04";
created = "now";
extraCommands = ''
ln -s usr/bin
ln -s usr/lib
ln -s usr/lib64
ln -s usr/sbin
'';
copyToRoot = buildEnv {
name = "image-root";
pathsToLink = [ "/" ];
paths = [ ubuntu-cloudimg ];
};
config.Cmd = [ "/lib/systemd/systemd" ];
}
9 changes: 9 additions & 0 deletions nix/systemModules/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
...
}:
{
imports = [ ./tests ];
flake = {
systemModules = { };
};
}
Loading
Loading