diff --git a/.gitignore b/.gitignore index b7fe848..a2ee69a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +# Nix # +/result + +# Direnv # +/.direnv/ + # Python # # Virtual Environment /.venv/ @@ -13,18 +19,6 @@ __pycache__/ /.pytest_cache/ /.mypy_cache/ -# Nix # - -# Build -/result - -# MicroVM -/var.img -/control.socket - -# Direnv # -/.direnv/ - # Project specific files # config.json db.json diff --git a/flake.lock b/flake.lock index 5648e75..0f23326 100644 --- a/flake.lock +++ b/flake.lock @@ -27,11 +27,11 @@ "spectrum": "spectrum" }, "locked": { - "lastModified": 1735074045, - "narHash": "sha256-CeYsC8J2dNiV2FCQOxK1oZ/jNpOF2io7aCEFHmfi95U=", + "lastModified": 1748464257, + "narHash": "sha256-PdnQSE2vPfql9WEjunj2qQnDpuuvk7HH+4djgXJSwFs=", "owner": "astro", "repo": "microvm.nix", - "rev": "2ae08de8e8068b00193b9cfbc0acc9dfdda03181", + "rev": "e238645b6f0447a2eb1d538d300d5049d4006f9f", "type": "github" }, "original": { @@ -42,17 +42,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733759999, - "narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=", - "owner": "nixos", + "lastModified": 1748370509, + "narHash": "sha256-QlL8slIgc16W5UaI3w7xHQEP+Qmv/6vSNTpoZrrSlbk=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56", + "rev": "4faa5f5321320e49a78ae7848582f684d64783e9", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", + "ref": "nixos-unstable", "repo": "nixpkgs", - "rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56", "type": "github" } }, @@ -65,11 +65,11 @@ "spectrum": { "flake": false, "locked": { - "lastModified": 1733308308, - "narHash": "sha256-+RcbMAjSxV1wW5UpS9abIG1lFZC8bITPiFIKNnE7RLs=", + "lastModified": 1746869549, + "narHash": "sha256-BKZ/yZO/qeLKh9YqVkKB6wJiDQJAZNN5rk5NsMImsWs=", "ref": "refs/heads/main", - "rev": "80c9e9830d460c944c8f730065f18bb733bc7ee2", - "revCount": 792, + "rev": "d927e78530892ec8ed389e8fae5f38abee00ad87", + "revCount": 862, "type": "git", "url": "https://spectrum-os.org/git/spectrum" }, diff --git a/flake.nix b/flake.nix index 76e570c..b2bbd84 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "A webserver to create files for testing purposes"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs?rev=a73246e2eef4c6ed172979932bc80e1404ba2d56"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; microvm = { url = "github:astro/microvm.nix"; @@ -10,163 +10,92 @@ }; }; - outputs = { - self, - nixpkgs, - ... - } @ inputs: let - supportedSystems = ["x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin"]; - forAllSystems = nixpkgs.lib.genAttrs supportedSystems; - pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system}.extend overlay); - - overlay = final: prev: rec { - python3Packages = prev.python3Packages.overrideScope (pfinal: pprev: { - packageNameToDrv = x: builtins.getAttr (cleanPythonPackageName x) final.python3Packages; + outputs = + { + self, + nixpkgs, + ... + }@inputs: + let + supportedSystems = [ "x86_64-linux" ]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + pkgs = forAllSystems (system: nixpkgs.legacyPackages.${system}); + in + { + # `nix build` + packages = forAllSystems (system: rec { + default = testdata; + testdata = pkgs.${system}.callPackage ./nix/package.nix { src = ./.; }; + vm = self.nixosConfigurations.vm.config.microvm.declaredRunner; }); - cleanPythonPackageName = x: let - cleanName = builtins.match "([a-z,A-Z,0-9,_,-]+).*" x; - in - if cleanName != null - then builtins.elemAt cleanName 0 - else builtins.warn "Could not determine package name from '${x}'" null; - }; + # `nix develop` + devShells = forAllSystems (system: rec { + default = venv; - pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml); + venv = pkgs.${system}.mkShell { + shellHook = '' + if [ ! -d .venv/ ]; then + echo "Creating Virtual Environment..." + ${pkgs.${system}.python3}/bin/python3 -m venv .venv + fi - buildDependencies = forAllSystems (system: builtins.map pkgs.${system}.python3Packages.packageNameToDrv pyproject.build-system.requires); - runtimeDependencies = forAllSystems (system: builtins.map pkgs.${system}.python3Packages.packageNameToDrv pyproject.project.dependencies); - optionalDependencies = forAllSystems (system: builtins.mapAttrs (name: value: builtins.map pkgs.${system}.python3Packages.packageNameToDrv value) pyproject.project.optional-dependencies); - in { - # `nix build` - packages = forAllSystems (system: let - buildTestdata = {skipCheck ? false}: - pkgs.${system}.python3Packages.buildPythonPackage { - pname = pyproject.project.name; - version = pyproject.project.version; - src = ./.; + alias activate='source .venv/bin/activate' - pyproject = true; - - build-system = buildDependencies.${system}; - - dependencies = runtimeDependencies.${system}; - - optional-dependencies = optionalDependencies.${system}; - - nativeCheckInputs = optionalDependencies.${system}.dev; - - checkPhase = let - dev = builtins.map (x: x.pname) optionalDependencies.${system}.dev; - in '' - ${ - if builtins.elem "pytest" dev && !skipCheck - then "pytest tests" - else "" - } - ${ - if builtins.elem "mypy" dev && !skipCheck - then "mypy src" - else "" - } - ${ - if builtins.elem "pylint" dev && !skipCheck - then "pylint src" - else "" - } + echo "Entering Virtual Environment..." + source .venv/bin/activate ''; }; - in rec { - default = testdata; - testdata = buildTestdata {skipCheck = false;}; - quick = buildTestdata {skipCheck = true;}; - vm = self.nixosConfigurations.vm.config.microvm.declaredRunner; - }); + }); - # `nix fmt` - formatter = forAllSystems (system: pkgs.${system}.alejandra); + # NixOS Module + nixosModules.default = import ./nix/module.nix inputs; - # `nix develop` - devShells = forAllSystems (system: rec { - default = venv; - - venv = pkgs.${system}.mkShell { - shellHook = '' - if [ ! -d .venv/ ]; then - echo "Creating Virtual Environment..." - ${pkgs.${system}.python3}/bin/python3 -m venv .venv - fi - - alias activate='source .venv/bin/activate' - - echo "Entering Virtual Environment..." - source .venv/bin/activate - ''; - }; - }); - - # NixOS Module - nixosModules.default = import ./nix/module.nix inputs; - - # nixos definition for a microvm to test nixosModules - nixosConfigurations = let - system = "x86_64-linux"; - in { - vm = nixpkgs.lib.nixosSystem { - inherit system; + # NixOS definition for a microvm to test nixosModules + nixosConfigurations."vm" = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; modules = [ inputs.microvm.nixosModules.microvm - ({config, ...}: { - system.stateVersion = config.system.nixos.version; + ( + { config, ... }: + { + services.getty.autologinUser = "root"; - networking.hostName = "vm"; - users.users.root.password = ""; + microvm = { + hypervisor = "qemu"; - microvm = { - # volumes = [ - # { - # mountPoint = "/var"; - # image = "var.img"; - # size = 256; - # } - # ]; - shares = [ - { - # use proto = "virtiofs" for MicroVMs that are started by systemd - proto = "9p"; - tag = "ro-store"; - # a host's /nix/store will be picked up so that no - # squashfs/erofs will be built for it. - source = "/nix/store"; - mountPoint = "/nix/.ro-store"; - } - ]; + shares = [ + { + # Host's /nix/store will be picked up so that no squashfs/erofs will be built for it. + tag = "ro-store"; + source = "/nix/store"; + mountPoint = "/nix/.ro-store"; + } + ]; - interfaces = [ - { - type = "user"; - id = "qemu"; - mac = "02:00:00:01:01:01"; - } - ]; + interfaces = [ + { + type = "user"; + id = "qemu"; + # Locally administered have one of 2/6/A/E in the second nibble. + mac = "02:00:00:01:01:01"; + } + ]; - forwardPorts = [ - { - host.port = config.services.testdata.port; - guest.port = config.services.testdata.port; - } - ]; - - # "qemu" has 9p built-in! - hypervisor = "qemu"; - socket = "control.socket"; - }; - }) + forwardPorts = [ + { + host.port = config.services.testdata.port; + guest.port = config.services.testdata.port; + } + ]; + }; + } + ) self.nixosModules.default rec { - networking.firewall.allowedTCPPorts = [services.testdata.port]; + networking.firewall.allowedTCPPorts = [ services.testdata.port ]; services.testdata = { enable = true; @@ -174,11 +103,15 @@ port = 1234; settings = { - keys = ["one" "two" "three"]; + keys = [ + "one" + "two" + "three" + ]; max-size = "1GB"; max-data = "100GB"; buffer-size = "12MiB"; - database = "/root/testdata_state.json"; + database = "/root/testdata-state.json"; database-update-interval = 5.0; log = "/root/log.jsonl"; }; @@ -187,5 +120,4 @@ ]; }; }; - }; } diff --git a/nix/module.nix b/nix/module.nix index 5f2ea32..900f70f 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -1,32 +1,41 @@ -inputs: { +inputs: +{ config, lib, pkgs, ... -}: let +}: +let cfg = config.services.testdata; package = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}.default; - inherit (lib) mkIf mkEnableOption mkOption types; + inherit (lib) + mkIf + mkEnableOption + mkOption + types + ; - format = pkgs.formats.json {}; + format = pkgs.formats.json { }; configFile = format.generate "config.json" cfg.settings; -in { +in +{ options.services.testdata = { enable = mkEnableOption "testdata"; settings = mkOption { - type = with types; let - valueType = nullOr (oneOf [ - # TODO: restrict type to actual config file structure - bool - int - float - str - path - (attrsOf valueType) - (listOf valueType) - ]); - in + type = + with types; + let + valueType = nullOr (oneOf [ + bool + int + float + str + path + (attrsOf valueType) + (listOf valueType) + ]); + in valueType; default = throw "Please specify services.testdata.settings"; }; @@ -43,7 +52,7 @@ in { }; config = mkIf cfg.enable { - environment.systemPackages = [package]; + environment.systemPackages = [ package ]; systemd.services.testdata = { enable = true; @@ -53,7 +62,7 @@ in { ExecStart = "${package}/bin/testdata --config ${configFile} --listen ${cfg.host} --port ${builtins.toString cfg.port}"; }; - wantedBy = ["multi-user.target"]; + wantedBy = [ "multi-user.target" ]; }; }; } diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..865f057 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,46 @@ +{ + src, + python3Packages, +}: +let + inherit (python3Packages) + setuptools + fastapi + uvicorn + pydantic + pytest + requests + mypy + pylint + ; + + project = (builtins.fromTOML (builtins.readFile "${src}/pyproject.toml")).project; + pname = project.name; + version = project.version; +in +python3Packages.buildPythonPackage { + inherit pname version src; + + pyproject = true; + + build-system = [ setuptools ]; + + dependencies = [ + fastapi + uvicorn + pydantic + ]; + + nativeCheckInputs = [ + pytest + requests + mypy + pylint + ]; + + checkPhase = '' + pytest tests + mypy src + pylint src + ''; +} diff --git a/pyproject.toml b/pyproject.toml index 462429f..3265282 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,8 @@ [project] name = "testdata" -version = "1.2.1" +version = "1.2.2" requires-python = "~=3.12, <4" -dependencies = [ - "fastapi~=0.115", - "uvicorn~=0.32", - "pydantic~=2.9", -] +dependencies = ["fastapi~=0.115", "uvicorn~=0.32", "pydantic~=2.9"] [project.optional-dependencies] dev = [ @@ -14,14 +10,14 @@ dev = [ "mypy~=1.13", "pylint~=3.3", "requests~=2.32", - "types-requests~=2.32" + "types-requests~=2.32", ] [project.scripts] testdata = "testdata.main:main" [build-system] -requires = ["setuptools~=75.1"] +requires = ["setuptools~=78.1"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] @@ -40,5 +36,5 @@ disable = [ "missing-class-docstring", "missing-function-docstring", "too-few-public-methods", - "broad-exception-caught" + "broad-exception-caught", ]