The sidecar image booted in docker inside a VM (flake check
sidecar-image), against the loopback target of nix/test-target.nix,
on the host network. It checks what the image promises:
CREATE EXTENSION postjevsqlhas run on the sidecar;- the target's tables are read over verify-full TLS, with the mapping's password from a mounted file;
- a jev call over a foreign table plans as the scan over a ForeignScan;
- starting the container again applies a target migration;
- a secret given both as a file and as an env var stops the container with the CLI's refusal;
- the image holds no secret and no identity.
13{ pkgs, image }: 14let 15 target = import ./test-target.nix { inherit pkgs; }; 16 config = pkgs.writeText "config.toml" '' 17 [target] 18 server = "target" 19 host = "localhost" 20 port = 5433 21 dbname = "appdb" 22 sslrootcert = "/run/secrets/ca.crt" 23 schemas = ["public"] 24 25 [[mapping]] 26 local_user = "postgres" 27 remote_user = "app" 28 password_file = "/run/secrets/target-password" 29 30 [jev] 31 api_key_file = "/run/secrets/typesafe-key" 32 ''; 33in 34pkgs.testers.runNixOSTest { 35 name = "postjevsql-sidecar-image"; 36 37 nodes.machine = { 38 imports = [ target.module ]; 39 virtualisation.memorySize = 2048; 40 virtualisation.diskSize = 4096; 41 virtualisation.docker.enable = true; 42 }; 43 44 testScript = '' 45 from shlex import quote 46 47 run = ( 48 "docker run -d --name sidecar --network host" 49 " -v /secrets:/run/secrets:ro -v ${config}:/etc/postjevsql-sidecar/config.toml:ro" 50 " -v sidecar-data:/var/lib/postgresql" 51 " postjevsql-sidecar:${image.imageTag} -- -c jev.model=jev-1.13.0 -c port=5432" 52 ) 53 54 def sidecar(sql): 55 return machine.succeed( 56 f"docker exec sidecar psql --no-psqlrc -v ON_ERROR_STOP=1 -At -h /run/postgresql -U postgres -d postgres -c {quote(sql)}" 57 ).strip() 58 59 def target(sql): 60 return machine.succeed( 61 f"sudo -u postgres ${target.psql} -At -d appdb -c {quote(sql)}" 62 ).strip() 63 64 # serve starts postgres once to converge and sync, stops it, then 65 # execs it: ready is the second start, after the sync's output. 66 def ready(): 67 machine.wait_until_succeeds( 68 "docker logs sidecar 2>&1 | grep -Eq 'applied|in sync' " 69 "&& [ $(docker logs sidecar 2>&1 | grep -c 'database system is ready to accept connections') -ge 2 ] " 70 "&& docker exec sidecar psql -h /run/postgresql -U postgres -d postgres -c 'SELECT 1'", 71 timeout=180, 72 ) 73 74 machine.wait_for_unit("pg-target.service") 75 machine.wait_for_unit("docker.service") 76 machine.succeed( 77 "mkdir -p /secrets", 78 "cp ${target.certs}/ca.crt /secrets/ca.crt", 79 "printf %s ${target.password} > /secrets/target-password", 80 "printf %s test-key-never-sent > /secrets/typesafe-key", 81 "chmod 0644 /secrets/*", 82 ) 83 84 with subtest("the tarball loads with docker load"): 85 machine.succeed("docker load < ${image}") 86 87 with subtest("the image holds no secret and no identity"): 88 # The layers are uncompressed tars inside, so grep reads their contents. 89 machine.succeed("mkdir /img && tar -xf ${image} -C /img") 90 machine.fail("grep -rq ${target.password} /img") 91 machine.fail("grep -rq test-key-never-sent /img") 92 env = machine.succeed("docker inspect -f '{{json .Config.Env}} {{.Author}}' postjevsql-sidecar:${image.imageTag}") 93 assert "TYPESAFE" not in env and "PASSWORD" not in env, env 94 95 with subtest("a secret set as a file and an env var stops the container with the refusal"): 96 out = machine.fail(run.replace("run -d --name sidecar", "run --rm -e TYPESAFE_API_KEY=x") + " 2>&1") 97 assert "is set twice" in out, out 98 assert "TYPESAFE_API_KEY" in out, out 99 100 machine.succeed(run) 101 ready() 102 103 with subtest("the extension is installed on the sidecar"): 104 installed = sidecar("SELECT string_agg(extname, ',' ORDER BY extname) FROM pg_extension") 105 assert "postjevsql" in installed.split(","), installed 106 assert "postgres_fdw" in installed.split(","), installed 107 108 with subtest("the target's tables are read over verify-full TLS"): 109 options = sidecar("SELECT array_to_string(srvoptions, ' ') FROM pg_foreign_server WHERE srvname = 'target'") 110 assert "sslmode=verify-full" in options, options 111 rows = sidecar("SELECT string_agg(id || ':' || body, ';' ORDER BY id) FROM public.tickets") 112 assert rows == "1:server down;2:typo on page", rows 113 114 with subtest("a jev call over a foreign table plans as the scan over a ForeignScan"): 115 plan = sidecar("EXPLAIN (COSTS OFF) SELECT id FROM public.tickets t WHERE jev(t, 'Urgent?')") 116 assert "Custom Scan" in plan, plan 117 assert "Foreign Scan" in plan, plan 118 119 with subtest("starting the container again applies a target migration"): 120 target("ALTER TABLE public.tickets ADD COLUMN IF NOT EXISTS priority int") 121 machine.succeed("docker stop sidecar && docker start sidecar") 122 machine.wait_until_succeeds( 123 "docker exec sidecar psql -At -h /run/postgresql -U postgres -d postgres -c " 124 + quote("SELECT string_agg(attname, ',' ORDER BY attnum) FROM pg_attribute WHERE attrelid = 'public.tickets'::regclass AND attnum > 0") 125 + " | grep -qx id,body,priority", 126 timeout=180, 127 ) 128 ''; 129}