Add 07-vm-integration test

[?]
Apr 3, 2023, 4:51 PM
BH5XPS7CPEH4MNGTZONRZYABNOUUVYNNQ5YRXMBCHXIXTAAPH3RQC

Dependencies

Change contents

  • edit in README.md at line 44
    [2.1841]
    [5.473]
    * [07-vm-integration-test](07-vm-integration-test/demo.sh): Perform integration testing using virtual machines.
  • file addition: 07-vm-integration-test (d--r------)
    [4.2]
  • file addition: flake.nix (----------)
    [0.129]
    {
    description = "Example for running a VM network test";
    inputs.nixpkgs.url = "github:NixOS/nixpkgs";
    outputs = { self, nixpkgs }:
    let
    # Single source of truth for all tutorial constants
    database = "postgres";
    schema = "api";
    table = "todos";
    username = "authenticator";
    groupname = "authenticator";
    password = "mysecretpassword";
    webRole = "web_anon";
    postgrestPort = 3000;
    # NixOS module shared between server and client
    sharedModule = {
    # Since it's common for CI not to have $DISPLAY available,
    # we have to explicitly tell the tests "please don't expect any screen available"
    virtualisation.graphics = false;
    };
    # NixOS tests only support Linux for now:
    pkgs = import nixpkgs { system = "x86_64-linux"; };
    vm-test = pkgs.nixosTest ({
    # Name of the test
    name = "vm-test";
    nodes = {
    server = { config, pkgs, ... }: {
    imports = [ sharedModule ];
    networking.firewall.allowedTCPPorts = [ postgrestPort ];
    services.postgresql = {
    enable = true;
    initialScript = pkgs.writeText "initialScript.sql" ''
    create schema ${schema};
    create table ${schema}.${table} (
    id serial primary key,
    done boolean not null default false,
    task text not null,
    due timestamptz
    );
    insert into ${schema}.${table} (task) values ('finish tutorial 0'), ('pat self on back');
    create role ${webRole} nologin;
    grant usage on schema ${schema} to ${webRole};
    grant select on ${schema}.${table} to ${webRole};
    create role ${username} inherit login password '${password}';
    grant ${webRole} to ${username};
    '';
    };
    users = {
    mutableUsers = false;
    users = {
    # For ease of debugging the VM as the `root` user
    root.password = "";
    # Create a system user that matches the database user so that we
    # can use peer authentication. The tutorial defines a password,
    # but it's not necessary.
    "${username}" = {
    isSystemUser = true;
    group = groupname;
    };
    };
    groups."${groupname}" = {};
    };
    systemd.services.postgrest = {
    wantedBy = [ "multi-user.target" ];
    after = [ "postgresql.service" ];
    script =
    let
    configuration = pkgs.writeText "tutorial.conf" ''
    db-uri = "postgres://${username}:${password}@localhost:${toString config.services.postgresql.port}/${database}"
    db-schema = "${schema}"
    db-anon-role = "${username}"
    '';
    in "${pkgs.haskellPackages.postgrest}/bin/postgrest ${configuration}";
    serviceConfig.User = username;
    };
    };
    client = {
    imports = [ sharedModule ];
    };
    };
    # Disable linting for simpler debugging of the testScript
    skipLint = true;
    testScript = ''
    import json
    import sys
    start_all()
    server.wait_for_open_port(${toString postgrestPort})
    expected = [
    {"id": 1, "done": False, "task": "finish tutorial 0", "due": None},
    {"id": 2, "done": False, "task": "pat self on back", "due": None},
    ]
    actual = json.loads(
    client.succeed(
    "${pkgs.curl}/bin/curl http://server:${toString postgrestPort}/${table}"
    )
    )
    assert expected == actual, "table query returns expected content"
    '';
    });
    in
    {
    checks.x86_64-linux.default = vm-test;
    packages.x86_64-linux.default = vm-test;
    };
    }
  • file addition: demo.sh (---r------)
    [0.129]
    #!/usr/bin/env bash
    # shellcheck disable=SC1010,SC2288
    set -Eeuo pipefail
    dir="$(realpath --relative-to="${PWD}" "$(dirname "${BASH_SOURCE[0]}")")"
    source "${dir}/../bash/nix-container-demo-helper.sh"
    h "Integration testing using virtual machines"
    , "This demo is based on https://nix.dev/tutorials/integration-testing-using-virtual-machines,"
    , "but we adapt it to use flakes instead."
    , "One of the most powerful features in the Nix ecosystem is the ability to provide"
    , "a set of declarative NixOS configurations and use a simple Python interface"
    , "to interact with them using QEMU as the backend."
    h "Testing a typical web application backed by PostgreSQL"
    , "This tutorial follows PostgREST tutorial, a generic RESTful API for PostgreSQL."
    , "If you skim over the official tutorial, you'll notice there's quite a bit of setup in order to test if all the steps work."
    , "We are going to set up:"
    , " * A VM named 'server' running postgreSQL and postgREST."
    , " * A VM named 'client' running HTTP client queries using curl."
    , " * A testScript orchestrating testing logic between client and server."
    x pygmentize "${dir}/flake.nix"
    h "Let's run it!"
    n "One of these tests is just like any other derivation when it is built"
    , "So if we've run a successful test before, the result will be in the Nix store"
    , "and we will not re-run it automatically."
    x nix build "${dir}" -L
    n "Force a rebuild so we can see what is happening"
    x nix build "${dir}" -L --rebuild
    h "Flake check"
    , "'Checking' a flake involves making sure that all its output packages etc. build,"
    , "as well as all explicit checks."
    x nix flake check "${dir}" -L