heroku
Version:
CLI to interact with Heroku
104 lines (102 loc) • 4.16 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@oclif/core");
const heroku_cli_util_1 = require("@heroku/heroku-cli-util");
const color_1 = require("@heroku-cli/color");
const command_1 = require("@heroku-cli/command");
const inquirer = require("inquirer");
const path = require("path");
const os = require("os");
const fs = require("fs-extra");
function sshKeygen(file, quiet) {
const spawn = require('child_process').spawn;
return new Promise(function (resolve, reject) {
spawn('ssh-keygen', ['-o', '-t', 'rsa', '-N', '', '-f', file], { stdio: quiet ? null : 'inherit' })
.on('close', (code) => code === 0 ? resolve(null) : reject(code));
});
}
async function confirmPrompt(message) {
if (process.stdin.isTTY) {
return inquirer.prompt([{
type: 'confirm',
name: 'yes',
message: message,
}]);
}
const data = await heroku_cli_util_1.hux.prompt(message + ' [Y/n]');
return { yes: /^y(es)?/i.test(data) };
}
class Add extends command_1.Command {
async run() {
const { flags, args } = await this.parse(Add);
const sshdir = path.join(os.homedir(), '.ssh');
const generate = async function () {
await fs.ensureDir(sshdir, { mode: 0o700 });
await sshKeygen(path.join(sshdir, 'id_rsa'), flags.quiet);
};
const findKey = async function () {
const defaultKeyPath = path.join(sshdir, 'id_rsa.pub');
const defaultKeyExists = await fs.pathExists(defaultKeyPath);
const keys = (await fs.readdir(sshdir))
.map(k => path.join(sshdir, k))
.filter(k => path.extname(k) === '.pub');
if (!defaultKeyExists && keys.length === 0) {
core_1.ux.warn('Could not find an existing SSH key at ' + path.join('~', '.ssh', 'id_rsa.pub'));
if (!flags.yes) {
const resp = await confirmPrompt('Would you like to generate a new one?');
if (!resp.yes)
return;
}
await generate();
return defaultKeyPath;
}
if (keys.length === 1) {
const key = keys[0];
core_1.ux.log(`Found an SSH public key at ${color_1.default.cyan(key)}`);
if (!flags.yes) {
const resp = await confirmPrompt('Would you like to upload it to Heroku?');
if (!resp.yes)
return;
}
return key;
}
const resp = await inquirer.prompt([{
type: 'list',
name: 'key',
choices: keys,
message: 'Which SSH key would you like to upload?',
}]);
return resp.key;
};
let key = args.key;
if (!key)
key = await findKey();
if (!key)
throw new Error('No key to upload');
core_1.ux.action.start(`Uploading ${color_1.default.cyan(key)} SSH key`);
const publicKey = await fs.readFile(key, { encoding: 'utf8' });
await this.heroku.post('/account/keys', {
body: {
public_key: publicKey,
},
});
core_1.ux.action.stop();
}
}
exports.default = Add;
Add.description = 'add an SSH key for a user';
Add.help = 'if no KEY is specified, will try to find ~/.ssh/id_rsa.pub';
Add.example = `$ heroku keys:add
Could not find an existing public key.
Would you like to generate one? [Yn] y
Generating new SSH public key.
Uploading SSH public key /.ssh/id_rsa.pub... done
$ heroku keys:add /my/key.pub
Uploading SSH public key /my/key.pub... done`;
Add.flags = {
quiet: command_1.flags.boolean({ hidden: true }),
yes: command_1.flags.boolean({ char: 'y', description: 'automatically answer yes for all prompts' }),
};
Add.args = {
key: core_1.Args.string({ description: 'absolute path to the key located on disk. If omitted, we use the default rsa key.' }),
};
;