UNPKG

@liara/cli

Version:

The command line interface for Liara

359 lines (358 loc) 11.9 kB
import ora from 'ora'; import inquirer from 'inquirer'; import Command from '../../../base.js'; import { Flags, Args } from '@oclif/core'; import { createDebugLogger } from '../../../utils/output.js'; import { RecordType, } from '../../../types/dns-records.js'; const promptRecordContent = { A: async (flags) => { // @ts-ignore let result = []; if (flags.ip) { flags.ip.map((ip) => { result.push({ ip: ip }); }); } else { let done = false; let i = 1; do { const { ip } = (await inquirer.prompt({ name: 'ip', type: 'input', message: `Enter ip${i} (leave empty to finish):`, validate: (input) => input.length >= 0 || done === true, })); if (ip.length > 0) { result.push({ ip: ip }); } else { done = true; } i++; } while (!done); } return result; }, AAAA: async (flags) => { // @ts-ignore let result = []; if (flags.ip) { flags.ip.map((ip) => { result.push({ ip: ip }); }); } else { let done = false; let i = 1; do { const { ip } = (await inquirer.prompt({ name: 'ip', type: 'input', message: `Enter ip${i} (leave empty to finish):`, validate: (input) => input.length >= 0 || done === true, })); if (ip.length > 0) { result.push({ ip: ip }); } else { done = true; } i++; } while (!done); } return result; }, ALIAS: async (flags) => { // @ts-ignore let result = []; if (flags.host) { result.push({ host: flags.host }); } else { let done = true; let i = 1; do { const { host } = (await inquirer.prompt({ name: 'host', type: 'input', message: `Enter host${i} (leave empty to finish):`, validate: (input) => input.length >= 0 || done === true, })); if (host.length > 0) { result.push({ host: host }); } else { done = true; } i++; } while (!done); } return result; }, CNAME: async (flags) => { // @ts-ignore let result = []; if (flags.host) { result.push({ host: flags.host }); } else { let done = true; let i = 1; do { const { host } = (await inquirer.prompt({ name: 'host', type: 'input', message: `Enter host${i} (leave empty to finish):`, validate: (input) => input.length >= 0 || done === true, })); if (host.length > 0) { result.push({ host: host }); } else { done = true; } i++; } while (!done); } return result; }, MX: async (flags) => { // @ts-ignore let result = []; if (flags.mx) { flags.mx.map((combineInput) => { const parsed = combineInput.split(','); if (parsed.length != 2) { throw Error('mx flag should be like this: <hostname>,<priority>'); } result.push({ host: parsed[0], priority: parsed[1] }); }); } else { let done = false; let i = 1; do { const { combineInput } = (await inquirer.prompt({ name: 'combineInput', type: 'input', message: `Enter hostname and priority ${i} (<hostname> <priority>. leave empty to finish):`, validate: (input) => input.length == 0 || input.split(' ').length == 2 || done === true, })); if (combineInput.length > 0) { const parsed = combineInput.split(' '); if (parsed.length != 2) { throw Error('mx inputs should be like this: <hostname> <priority>'); } result.push({ host: parsed[0], priority: parsed[1] }); } else { done = true; } i++; } while (!done); } return result; }, SRV: async (flags) => { // @ts-ignore let result = []; if (flags.srv) { flags.srv.map((combineInput) => { const parsed = combineInput.split(','); if (parsed.length != 4) { throw Error('srv flag should be like this: <hostname>,<port>,<priority>,<weight>'); } result.push({ host: parsed[0], port: parsed[1], priority: parsed[2], weight: parsed[3], }); }); } else { let done = false; let i = 1; do { const { combineInput } = (await inquirer.prompt({ name: 'combineInput', type: 'input', message: `Enter hostname, port, priority and weight ${i} (<hostname> <port> <priority> <weight>. leave empty to finish):`, validate: (input) => input.length == 0 || input.split(' ').length == 4 || done === true, })); if (combineInput.length > 0) { const parsed = combineInput.split(' '); if (parsed.length != 4) { throw Error('srv inputs should be like this: <hostname> <port> <priority> <weight>'); } result.push({ host: parsed[0], port: parsed[1], priority: parsed[2], weight: parsed[3], }); } else { done = true; } i++; } while (!done); } return result; }, TXT: async (flags) => { // @ts-ignore let result = []; if (flags.txt) { flags.txt.map((txt) => { result.push({ text: txt }); }); } else { let done = false; let i = 1; do { const { text } = (await inquirer.prompt({ name: 'text', type: 'input', message: `Enter text${i} (leave empty to finish):`, validate: (input) => input.length >= 0 || done === true, })); if (text.length > 0) { result.push({ text: text }); } else { done = true; } i++; } while (!done); } return result; }, }; class Create extends Command { async run() { this.spinner = ora(); const { flags, args } = await this.parse(Create); const debug = createDebugLogger(flags.debug); await this.setGotConfig(flags); const account = await this.getCurrentAccount(); ((account && account.region === 'germany') || flags.region === 'germany') && this.error('We do not support germany any more.'); const name = flags.name || (await this.promptName()); const _type = flags.type || (await this.promptType()); const ttl = flags.ttl || (await this.promptTTL()); const zone = args.zone; const DNSRecord = { name: name, type: _type, ttl: ttl, // @ts-ignore contents: await promptRecordContent[_type](flags), }; try { await this.got.post(Create.PATH.replace('{zone}', zone), { json: { ...DNSRecord }, }); this.log(`Record ${name} created.`); } catch (error) { debug(error.message); if (error.response && error.response.body) { debug(JSON.stringify(error.response.body)); } if (error.response && error.response.statusCode === 400) { this.error(`Enter correct infortmation.`); } if (error.response && error.response.statusCode === 404) { this.error(`Zone does not exist.`); } if (error.response && error.response.statusCode === 409) { this.error(`This record already exists.`); } this.error(`Could not create the record. Please try again.`); } } async promptName() { const { name } = (await inquirer.prompt({ name: 'name', type: 'input', message: 'Enter record name:', validate: (input) => input.length > 2, })); return name; } async promptType() { const { type } = (await inquirer.prompt({ name: 'type', type: 'input', message: 'Enter record type:', validate: (input) => Object.values(RecordType).includes(input), })); return type; } async promptTTL() { const { ttl } = (await inquirer.prompt({ name: 'ttl', type: 'input', message: 'Enter record ttl:', validate: (input) => { const parsed = parseInt(input); return !isNaN(parsed); }, })); return ttl; } async setGotConfig(config) { await super.setGotConfig(config); const new_got = this.got.extend({ prefixUrl: Create.baseURL }); this.got = new_got; // baseURL is different for zone api } } Create.description = 'create a new dns record'; Create.baseURL = 'https://dns-service.iran.liara.ir'; Create.PATH = 'api/v1/zones/{zone}/dns-records'; Create.flags = { ...Command.flags, name: Flags.string({ char: 'n', description: 'record name', }), type: Flags.string({ char: 't', description: 'record type', }), ttl: Flags.integer({ char: 'l', description: 'time to live', }), ip: Flags.string({ char: 'i', description: 'ip value for record A and AAAA', multiple: true, }), host: Flags.string({ char: 's', description: 'host value for record ALIAS and CNAME', }), mx: Flags.string({ char: 'm', description: 'host and priority values for MX record. mx flag should be like this: --mx <hostname>,<priority>', multiple: true, }), srv: Flags.string({ char: 'r', description: 'hostname, port, priority and weight values for SRV record. srv flag should be like this: <hostname>,<port>,<priority>,<weight>', multiple: true, }), txt: Flags.string({ char: 'x', description: 'text value for record TXT', multiple: true, }), }; Create.args = { zone: Args.string({ description: 'zone name (domain)', required: true }), }; export default Create;