forked from actualbudget/actual-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
127 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { writeFile } from 'fs/promises'; | ||
import { GenericContainer, Wait } from 'testcontainers'; | ||
|
||
/** | ||
* Add a log consumer to container which captures and logs events. | ||
* @param {GenericContainer} container | ||
* @param {string} logPrefix | ||
* @returns {GenericContainer} | ||
*/ | ||
export function consumeLogsWithPrefix(container, logPrefix) { | ||
return container.withLogConsumer((stream) => { | ||
stream.on('data', (line) => console.log(logPrefix + line)); | ||
stream.on('err', (line) => console.error(logPrefix + line)); | ||
stream.on('end', () => console.log(logPrefix + 'Stream closed')); | ||
}); | ||
} | ||
|
||
/** | ||
* Start an `actual-server` instance from the local Dockerfile. | ||
* @returns {Promise<import('testcontainers').StartedTestContainer>} | ||
*/ | ||
export async function startActualContainer() { | ||
let newContainer = new GenericContainer('../../Dockerfile') | ||
.withExposedPorts(5006) | ||
.withWaitStrategy(Wait.forListeningPorts()); | ||
|
||
newContainer = consumeLogsWithPrefix(newContainer, 'ActualServer: '); | ||
|
||
return newContainer.start(); | ||
} | ||
|
||
/** | ||
* Start a `caddy` instance with a generated Caddyfile. | ||
* | ||
* https://actualbudget.org/docs/config/reverse-proxies/#caddy | ||
* @param {number} actualServerPort Mapped port of the actual-server container. | ||
* @returns {Promise<import('testcontainers').StartedTestContainer>} | ||
*/ | ||
export async function startCaddyContainer(actualServerPort) { | ||
let caddyContainer = new GenericContainer('caddyContainer:latest') | ||
.withExposedPorts(80) | ||
.withWaitStrategy(Wait.forListeningPorts()); | ||
|
||
await writeFile( | ||
'./Caddyfile', | ||
'http://localhost {\n\tencode gzip zstd\n\treverse_proxy ' + | ||
`actual_server:${actualServerPort.toString()}\n}\n`, | ||
); | ||
|
||
caddyContainer = caddyContainer.withCopyFilesToContainer([ | ||
{ | ||
source: './Caddyfile', | ||
target: '/etc/caddyContainer/Caddyfile', | ||
}, | ||
]); | ||
|
||
return caddyContainer.start(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { unlink } from 'fs/promises'; | ||
import { request } from 'http'; | ||
import { startActualContainer, startCaddyContainer } from './container-util.js'; | ||
|
||
// Requires testcontainers: | ||
// `yarn add -D testcontainers` | ||
|
||
// If using WSL, requires these steps: | ||
// https://java.testcontainers.org/supported_docker_environment/windows/#windows-subsystem-for-linux-wsl | ||
// - Expose the Docker for Windows daemon on tcp port 2375 without TLS. | ||
// (Right-click the Docker Desktop icon on the task bar > Change Settings). | ||
// - edit /etc/docker and add the following: | ||
// { | ||
// "hosts": [ | ||
// "tcp://0.0.0.0:2375", | ||
// "unix:///var/run/docker.sock" | ||
// ] | ||
// } | ||
// - Set the DOCKER_HOST environment variable inside the WSL shell to tcp://localhost:2375. | ||
// It is recommended to add this to your ~/.bashrc file, so it’s available every time you open your terminal. | ||
|
||
// debug with: | ||
// DEBUG=testcontainers* DOCKER_HOST=unix:///var/run/docker.sock yarn run e2e-test | ||
|
||
describe('Actual Server with Caddy', () => { | ||
let actualServerContainer; | ||
let caddyContainer; | ||
|
||
beforeAll(async () => { | ||
actualServerContainer = await startActualContainer(); | ||
caddyContainer = await startCaddyContainer( | ||
actualServerContainer.getMappedPort(5006), | ||
); | ||
}, 61 * 1000); | ||
|
||
it('should work with default config', async () => { | ||
const host = caddyContainer.getHost(); | ||
console.log('Caddy host: ' + host); | ||
request( | ||
{ | ||
hostname: host, | ||
port: caddyContainer.getMappedPort(80), | ||
method: 'get', | ||
path: '/health', | ||
}, | ||
(res) => { | ||
expect(res.statusCode).toBe(200); | ||
}, | ||
); | ||
}, 30000); | ||
|
||
afterAll(async () => { | ||
if (caddyContainer) await caddyContainer.stop(); | ||
if (actualServerContainer) await actualServerContainer.stop(); | ||
await unlink('./Caddyfile').catch((_err) => { | ||
// silence ENOENT | ||
return; | ||
}); | ||
}); | ||
}); | ||
|
||
// NGINX | ||
|
||
// TODO rename current implementation to allowedAuthCIDRs | ||
// - populate it by default with whatever folks have set in their trustedProxies | ||
// - we also need to fix the current implementation so it's not needed to be set if folks just want header auth, without restricting it | ||
// - it SHOULD only need to be set if someone wants to lock header auth to a specific endpoint. | ||
// TODO use trustedProxies for what you have here | ||
// |