hosty
Version:
A code based opinionated way to self-host and manage web apps.
81 lines • 3.02 kB
JavaScript
import os from 'os';
import path from 'path';
import YAML from 'yaml';
import { spawn } from 'child_process';
import { mkdir, writeFile } from 'fs/promises';
import * as ansible from './ansible/index.js';
import { get_setup_tasks, server_to_host } from './server.js';
export const { deploy, destroy, playbook, write, run } = instance();
export function instance() {
const state = {
servers: {},
actions: [],
};
const deploy = (server, ...services) => {
state.servers[server.name] = server;
for (const service of services) {
state.actions.push({ type: 'deploy', server, service });
}
};
const destroy = (server, ...services) => {
state.servers[server.name] = server;
for (const service of services) {
state.actions.push({ type: 'destroy', server, service });
}
};
const playbook = () => {
const steps = [];
setup_servers(Object.values(state.servers), steps);
for (const action of state.actions) {
steps.push({ hosts: action.server.name, gather_facts: false, tasks: get_tasks(action) });
}
return steps;
};
const write = async (playbookPath) => {
await mkdir(path.dirname(playbookPath), { recursive: true });
await writeFile(playbookPath, YAML.stringify(playbook()));
};
const run = async (userOptions = {}) => {
const playbook_path = path.join(os.tmpdir(), [process.pid, Date.now(), Math.floor(1000 * Math.random())].join('_') + '.yaml');
const options = { ...defaultRunOptions, playbook_path, ...userOptions };
await write(options.playbook_path);
const args = [options.playbook_path];
if (options.ask_sudo_pass)
args.push('-K');
options.ansible_options.forEach((x) => args.push(x));
return spawn('ansible-playbook', args, options.spawn_options);
};
return { deploy, destroy, playbook, write, run };
}
const defaultRunOptions = {
ask_sudo_pass: true,
playbook_path: 'hosty-playbook.yaml',
spawn_options: {
stdio: 'inherit',
},
ansible_options: [],
};
function setup_servers(servers, steps) {
for (const server of servers) {
const host = server_to_host(server);
steps.push({
hosts: 'localhost',
gather_facts: false,
tasks: [ansible.tasks.builtin.add_host(`Define server ${server.name}`, host)],
});
steps.push({
hosts: server.name,
gather_facts: false,
tasks: [ansible.tasks.builtin.setup(`Gather facts of server ${server.name}`, {})],
});
steps.push({ hosts: server.name, gather_facts: false, tasks: get_setup_tasks(server) });
}
}
function get_tasks({ type, server, service }) {
if (type === 'deploy')
return service.get_deploy_tasks(server);
if (type === 'destroy')
return service.get_destroy_tasks(server);
return [];
}
//# sourceMappingURL=instance.js.map