Unverified Commit 06c01cba authored by Martin Weinelt's avatar Martin Weinelt Committed by GitHub
Browse files

nixos/tests/akkoma: re‐write end‐to‐end test (#388766)

parents c410b026 73e68329
Loading
Loading
Loading
Loading
+225 −129
Original line number Diff line number Diff line
/*
  End-to-end test for Akkoma.

  Based in part on nixos/tests/pleroma.

  TODO: Test federation.
*/
import ./make-test-python.nix (
# end‐to‐end test for Akkoma
{
  lib,
  pkgs,
    package ? pkgs.akkoma,
  confined ? false,
  ...
}:
let
    userPassword = "4LKOrGo8SgbPm1a6NclVU5Wb";
  inherit ((pkgs.formats.elixirConf { }).lib) mkRaw;

    provisionUser = pkgs.writers.writeBashBin "provisionUser" ''
      set -eu -o errtrace -o pipefail

      pleroma_ctl user new jamy jamy@nixos.test --password '${userPassword}' --moderator --admin -y
    '';
  package = pkgs.akkoma;

  tlsCert =
      pkgs.runCommand "selfSignedCerts"
    names:
    pkgs.runCommand "certificates-${lib.head names}"
      {
        nativeBuildInputs = with pkgs; [ openssl ];
      }
      ''
        mkdir -p $out
        openssl req -x509 \
            -subj '/CN=akkoma.nixos.test/' -days 49710 \
            -addext 'subjectAltName = DNS:akkoma.nixos.test' \
          -subj '/CN=${lib.head names}/' -days 49710 \
          -addext 'subjectAltName = ${lib.concatStringsSep ", " (map (name: "DNS:${name}") names)}' \
          -keyout "$out/key.pem" -newkey ed25519 \
          -out "$out/cert.pem" -noenc
      '';

    sendToot = pkgs.writers.writeBashBin "sendToot" ''
      set -eu -o errtrace -o pipefail

      export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"
  tlsCertA = tlsCert [
    "akkoma-a.nixos.test"
    "media.akkoma-a.nixos.test"
  ];

      ${pkgs.toot}/bin/toot login_cli -i "akkoma.nixos.test" -e "jamy@nixos.test" -p '${userPassword}'
      ${pkgs.toot}/bin/toot post "hello world Jamy here"
      ${pkgs.toot}/bin/toot timeline -1 | grep -F -q "hello world Jamy here"
  tlsCertB = tlsCert [
    "akkoma-b.nixos.test"
    "media.akkoma-b.nixos.test"
  ];

      # Test file upload
      echo "y" | ${pkgs.toot}/bin/toot upload <(dd if=/dev/zero bs=1024 count=1024 status=none) \
        | grep -F -q "https://akkoma.nixos.test:443/media"
  testMedia = pkgs.runCommand "blank.png" { nativeBuildInputs = with pkgs; [ imagemagick ]; } ''
    magick -size 640x480 canvas:transparent "PNG8:$out"
  '';

    checkFe = pkgs.writers.writeBashBin "checkFe" ''
      set -eu -o errtrace -o pipefail

  checkFe = pkgs.writeShellApplication {
    name = "checkFe";
    runtimeInputs = with pkgs; [ curl ];
    text = ''
      paths=( / /static/{config,styles}.json /pleroma/admin/ )

      for path in "''${paths[@]}"; do
        diff \
          <(${pkgs.curl}/bin/curl -f -S -s -o /dev/null -w '%{response_code}' "https://akkoma.nixos.test$path") \
          <(curl -f -S -s -o /dev/null -w '%{response_code}' "https://$1$path") \
          <(echo -n 200)
      done
    '';
  };

    hosts = nodes: ''
      ${nodes.akkoma.networking.primaryIPAddress} akkoma.nixos.test
      ${nodes.client.networking.primaryIPAddress} client.nixos.test
    '';
  in
  {
    name = "akkoma";
    nodes = {
      client =
        {
          nodes,
          pkgs,
          config,
          ...
        }:
  commonConfig =
    { nodes, ... }:
    {
          security.pki.certificateFiles = [ "${tlsCert}/cert.pem" ];
          networking.extraHosts = hosts nodes;
      security.pki.certificateFiles = [
        "${tlsCertA}/cert.pem"
        "${tlsCertB}/cert.pem"
      ];

      networking.extraHosts = ''
        ${nodes.akkoma-a.networking.primaryIPAddress} akkoma-a.nixos.test media.akkoma-a.nixos.test
        ${nodes.akkoma-b.networking.primaryIPAddress} akkoma-b.nixos.test media.akkoma-b.nixos.test
        ${nodes.client-a.networking.primaryIPAddress} client-a.nixos.test
        ${nodes.client-b.networking.primaryIPAddress} client-b.nixos.test
      '';
    };

      akkoma =
  clientConfig =
    { pkgs, ... }:
    {
          nodes,
          pkgs,
          config,
          ...
        }:
      environment = {
        sessionVariables = {
          REQUESTS_CA_BUNDLE = "/etc/ssl/certs/ca-certificates.crt";
        };
        systemPackages = with pkgs; [ toot ];
      };
    };

  serverConfig =
    { config, pkgs, ... }:
    {
          networking.extraHosts = hosts nodes;
          networking.firewall.allowedTCPPorts = [ 443 ];
          environment.systemPackages = with pkgs; [ provisionUser ];
      networking = {
        domain = "nixos.test";
        firewall.allowedTCPPorts = [ 443 ];
      };

      systemd.services.akkoma.confinement.enable = confined;

      services.akkoma = {
        enable = true;
            package = package;
        inherit package;
        config = {
          ":pleroma" = {
            ":instance" = {
@@ -112,38 +108,138 @@ import ./make-test-python.nix (
            };

            "Pleroma.Web.Endpoint" = {
                  url.host = "akkoma.nixos.test";
              url.host = config.networking.fqdn;
            };

            "Pleroma.Upload" = {
                  base_url = "https://akkoma.nixos.test:443/media/";
              base_url = "https://media.${config.networking.fqdn}/media/";
            };

            # disable certificate verification until we figure out how to
            # supply our own certificates
            ":http".adapter.pools = mkRaw "%{default: [conn_opts: [transport_opts: [verify: :verify_none]]]}";
          };
        };

            nginx = {
              addSSL = true;
              sslCertificate = "${tlsCert}/cert.pem";
              sslCertificateKey = "${tlsCert}/key.pem";
            };
        nginx.addSSL = true;
      };

      services.nginx.enable = true;
      services.postgresql.enable = true;
    };
in
{
  name = "akkoma";
  nodes = {
    client-a =
      { ... }:
      {
        imports = [
          clientConfig
          commonConfig
        ];
      };

    testScript =
      { nodes, ... }:
      ''
    client-b =
      { ... }:
      {
        imports = [
          clientConfig
          commonConfig
        ];
      };

    akkoma-a =
      { ... }:
      {
        imports = [
          commonConfig
          serverConfig
        ];

        services.akkoma.nginx = {
          sslCertificate = "${tlsCertA}/cert.pem";
          sslCertificateKey = "${tlsCertA}/key.pem";
        };
      };

    akkoma-b =
      { ... }:
      {
        imports = [
          commonConfig
          serverConfig
        ];

        services.akkoma.nginx = {
          sslCertificate = "${tlsCertB}/cert.pem";
          sslCertificateKey = "${tlsCertB}/key.pem";
        };
      };
  };

  testScript = ''
    import json
    import random
    import string
    from shlex import quote

    def randomString(len):
      return "".join(random.choice(string.ascii_letters + string.digits) for _ in range(len))

    def registerUser(user, password):
      return 'pleroma_ctl user new {0} {0}@nixos.test --password {1} -y'.format(
        quote(user), quote(password))

    def loginUser(instance, user, password):
      return 'toot login_cli -i {}.nixos.test -e {}@nixos.test -p {}'.format(
        quote(instance), quote(user), quote(password))

    userAName = randomString(11)
    userBName = randomString(11)
    userAPassword = randomString(22)
    userBPassword = randomString(22)

    testMessage = randomString(22)
    testMedia = '${testMedia}'

    start_all()
        akkoma.wait_for_unit('akkoma-initdb.service')
        akkoma.systemctl('restart akkoma-initdb.service')  # test repeated initialisation
        akkoma.wait_for_unit('akkoma.service')
        akkoma.wait_for_file('/run/akkoma/socket');
        akkoma.succeed('${provisionUser}/bin/provisionUser')
        akkoma.wait_for_unit('nginx.service')
        client.succeed('${sendToot}/bin/sendToot')
        client.succeed('${checkFe}/bin/checkFe')
    akkoma_a.wait_for_unit('akkoma-initdb.service')
    akkoma_b.wait_for_unit('akkoma-initdb.service')

    # test repeated initialisation
    akkoma_a.systemctl('restart akkoma-initdb.service')

    akkoma_a.wait_for_unit('akkoma.service')
    akkoma_b.wait_for_unit('akkoma.service')
    akkoma_a.wait_for_file('/run/akkoma/socket');
    akkoma_b.wait_for_file('/run/akkoma/socket');

    akkoma_a.succeed(registerUser(userAName, userAPassword))
    akkoma_b.succeed(registerUser(userBName, userBPassword))

    akkoma_a.wait_for_unit('nginx.service')
    akkoma_b.wait_for_unit('nginx.service')

    client_a.succeed(loginUser('akkoma-a', userAName, userAPassword))
    client_b.succeed(loginUser('akkoma-b', userBName, userBPassword))

    client_b.succeed('toot follow {}@akkoma-a.nixos.test'.format(userAName))
    client_a.wait_until_succeeds('toot followers | grep -F -q {}'.format(quote(userBName)))

    client_a.succeed('toot post {} --media {} --description "nothing to see here"'.format(
      quote(testMessage), quote(testMedia)))

    # verify test message
    status = json.loads(client_b.wait_until_succeeds(
      'toot status --json "$(toot timeline -1 | grep -E -o \'^ID [^ ]+\' | cut -d \' \' -f 2)"'))
    assert status['content'] == testMessage

    # compare attachment to original
    client_b.succeed('cmp {} <(curl -f -S -s {})'.format(quote(testMedia),
      quote(status['media_attachments'][0]['url'])))

    client_a.succeed('${lib.getExe checkFe} akkoma-a.nixos.test')
    client_b.succeed('${lib.getExe checkFe} akkoma-b.nixos.test')
  '';
}
)
+8 −2
Original line number Diff line number Diff line
@@ -156,8 +156,14 @@ in {
  age-plugin-tpm-decrypt = runTest ./age-plugin-tpm-decrypt.nix;
  agorakit = runTest ./web-apps/agorakit.nix;
  airsonic = runTest ./airsonic.nix;
  akkoma = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./akkoma.nix {};
  akkoma-confined = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./akkoma.nix { confined = true; };
  akkoma = runTestOn [ "x86_64-linux" "aarch64-linux" ] {
    imports = [ ./akkoma.nix ];
    _module.args.confined = false;
  };
  akkoma-confined = runTestOn [ "x86_64-linux" "aarch64-linux" ] {
    imports = [ ./akkoma.nix ];
    _module.args.confined = true;
  };
  alice-lg = runTest ./alice-lg.nix;
  alloy = runTest ./alloy.nix;
  allTerminfo = runTest ./all-terminfo.nix;