UNPKG

@adp-psych/container-tools

Version:

Tools for using containers for psychology experiments

134 lines (123 loc) 4 kB
/* * Copyright (C) 2021 Anthony Di Pietro * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ /** * @file Installs an experiment * to a [Kubernetes](https://kubernetes.io/) cluster * using [Helm](https://helm.sh/). * * @module module:install-experiment * @requires console-exec * @requires generate-selfsigned-certificate * @author Anthony Di Pietro <anthony.dipietro@research.uwa.edu.au> * @copyright © 2021 Anthony Di Pietro * @license AGPL-3.0-or-later */ const fs = require('node:fs/promises'); const {tmpdir} = require('node:os'); const path = require('node:path'); const pkgBasename = require('@adp-psych/pkg-basename'); const {consoleSpawn} = require('./console-exec.js'); const generateSelfsignedCertificate = require('./generate-selfsigned-certificate.js'); const {upgradeInstall} = require('./helm.js'); /** * The filename of the private key for the TLS certificate. * * @constant {String} * @static * @access protected */ const KEY_FILENAME = 'privkey.pem'; /** * The filename of the TLS certificate. * * @constant {String} * @static * @access protected */ const CERTIFICATE_FILENAME = 'cert.pem'; /** * Creates a * [Kubernetes TLS secret](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets). * * @static * @access protected * @param {String} keyFilename - The filename of the private key. * @param {String} certificateFilename - The filename of the certificate. * @example * createTlsSecret('tls/privkey.pem', 'tls/cert.pem'); */ const createTlsSecret = async (keyFilename, certificateFilename) => { const pkg = pkgBasename(); try { await consoleSpawn('kubectl', [ 'delete', 'secret', `${pkg}-tls`, ]); } catch { /* Ignore failure to delete secret, as it may not exist. */ } await consoleSpawn('kubectl', [ 'create', 'secret', 'tls', `${pkg}-tls`, `--cert=${certificateFilename}`, `--key=${keyFilename}`, ]); }; /** * Installs/upgrades the experiment using Helm. * * @static * @access protected * @param {String} chartDirectory - The path of the chart directory. * This should contain a directory named with the experiment's package * name that contains the chart files for the experiment. * @example * helmUpgradeExperiment('build/helm'); // Installs/upgrades the experiment. */ const helmUpgradeExperiment = async (chartDirectory) => { const pkg = pkgBasename(); await upgradeInstall(pkg, path.join(chartDirectory, pkg), []); }; /** * Installs/upgrades the experiment using Helm. * * @static * @param {String} chartDirectory - The path of the chart directory. * This should contain a directory named with the experiment's package * name that contains the chart files for the experiment. * @example * installExperiment('build/helm'); // Installs/upgrades the experiment. */ const installExperiment = async (chartDirectory) => { const pkg = pkgBasename(); const tlsDirectory = await fs.mkdtemp( path.join(tmpdir(), `${pkg}-tls-`), ); const keyFilename = path.join(tlsDirectory, KEY_FILENAME); const certificateFilename = path.join( tlsDirectory, CERTIFICATE_FILENAME, ); await generateSelfsignedCertificate(keyFilename, certificateFilename); await createTlsSecret(keyFilename, certificateFilename); await helmUpgradeExperiment(chartDirectory); await fs.rm(tlsDirectory, {'recursive': true}); }; module.exports = installExperiment;