mirror of
https://github.com/vvsviridov/enm-cli.git
synced 2025-10-23 08:22:21 +00:00
203 lines
5.5 KiB
JavaScript
Executable File
203 lines
5.5 KiB
JavaScript
Executable File
const chalk = require('chalk')
|
|
const inquirer = require('inquirer')
|
|
|
|
const { statusPic } = require('../../../util/logJob')
|
|
const tableChoices = require('../../../util/tableChoices')
|
|
const { isEmpty } = require('../../../util/validation')
|
|
|
|
const jobsCommands = ['new', 'my', 'exit']
|
|
const jobsCommandsHelp = [
|
|
'[new] - Creates a new import job.',
|
|
'[my] - Toggle to show only user\'s jobs.',
|
|
'[exit] - Exit this app.',
|
|
'Or choose a job from list...',
|
|
]
|
|
|
|
|
|
async function newJob() {
|
|
const {
|
|
name,
|
|
validationPolicy,
|
|
executionPolicy,
|
|
unsynchNodes,
|
|
executionOrder
|
|
} = await inquirer.prompt([
|
|
{
|
|
type: 'input',
|
|
name: 'name',
|
|
message: 'Type a job\'s name:',
|
|
validate: isEmpty,
|
|
},
|
|
{
|
|
type: 'checkbox',
|
|
name: 'validationPolicy',
|
|
message: 'Validation Policy:',
|
|
choices: [
|
|
{
|
|
name: 'Skip MO Instance Validation',
|
|
value: 'no-instance-validation',
|
|
},
|
|
{
|
|
name: 'Skip Node Based Validation',
|
|
value: 'no-node-based-validation',
|
|
checked: true,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
type: 'list',
|
|
name: 'executionPolicy',
|
|
message: 'Execution Error Handling:',
|
|
choices: [
|
|
{
|
|
name: 'Stop',
|
|
value: 'stop-on-error',
|
|
},
|
|
{
|
|
name: 'Skip to next node',
|
|
value: 'continue-on-error-node',
|
|
},
|
|
{
|
|
name: 'Skip to next operation',
|
|
value: 'continue-on-error-operation',
|
|
},
|
|
],
|
|
default: 'stop-on-error',
|
|
},
|
|
{
|
|
type: 'list',
|
|
name: 'unsynchNodes',
|
|
message: 'Unsynchronized Nodes Policy:',
|
|
choices: [
|
|
{
|
|
name: 'Import skips operation execution on unsynchronized nodes. Recommended for faster performance.',
|
|
value: 'skip-unsync-nodes',
|
|
},
|
|
{
|
|
name: 'Import will be agnostic towards node synchronization state, implying import attempts operation execution on unsychronized nodes as well.',
|
|
value: 'exec-unsync-nodes',
|
|
},
|
|
],
|
|
default: 'skip-unsync-nodes',
|
|
},
|
|
{
|
|
type: 'list',
|
|
name: 'executionOrder',
|
|
message: 'Execution Order:',
|
|
choices: [
|
|
{
|
|
name: 'Sequential',
|
|
value: 'sequential',
|
|
},
|
|
{
|
|
name: 'Parallel',
|
|
value: 'parallel',
|
|
},
|
|
],
|
|
default: 'parallel',
|
|
when: input => !input.executionPolicy.includes('stop-on-error')
|
|
},
|
|
])
|
|
const axiosConfig = {
|
|
text: 'Creating job...',
|
|
method: 'post',
|
|
url: this.appUrl,
|
|
data: {
|
|
name,
|
|
validationPolicy: validationPolicy.length
|
|
? validationPolicy
|
|
: ['instance-validation', 'node-based-validation'],
|
|
executionPolicy: [
|
|
executionPolicy,
|
|
unsynchNodes,
|
|
executionOrder ?? 'sequential',
|
|
]
|
|
},
|
|
}
|
|
const { data } = await this.httpClient.request(axiosConfig)
|
|
this.jobs.unshift(data)
|
|
this.job(data.id)
|
|
}
|
|
|
|
|
|
async function getJobs() {
|
|
const params = new URLSearchParams()
|
|
params.append('offset', this.jobsOffset)
|
|
params.append('limit', this.jobsLimit)
|
|
params.append('expand', 'summary')
|
|
params.append('expand', 'files')
|
|
if (this.onlyMy) {
|
|
params.append('createdBy', this.username)
|
|
}
|
|
const axiosConfig = {
|
|
text: 'Getting jobs...',
|
|
method: 'get',
|
|
url: this.appUrl,
|
|
params,
|
|
}
|
|
let totalCount = 0
|
|
const { data } = await this.httpClient.request(axiosConfig)
|
|
if (data.jobs) {
|
|
this.jobs = data.jobs
|
|
this.jobId = null
|
|
this.jobsLinks = data._links
|
|
totalCount = data.totalCount
|
|
} else {
|
|
this.jobs = []
|
|
this.jobId = null
|
|
this.jobsLinks = []
|
|
}
|
|
const tableData = this.jobs.map(({ userId, status, name, summary }) => {
|
|
const nameValue = []
|
|
nameValue.push(`${statusPic(status)} ${name}`)
|
|
nameValue.push(chalk.dim(userId))
|
|
nameValue.push(chalk.dim.italic(status))
|
|
if (summary) {
|
|
const { executed, executionErrors, invalid, parsed, valid } = summary.total
|
|
nameValue.push(chalk.dim(`🍳 ${parsed}`))
|
|
nameValue.push(chalk.dim(`☑ ${valid}`))
|
|
nameValue.push(chalk.dim(`⚠ ${invalid}`))
|
|
nameValue.push(chalk.dim(`✅ ${executed}`))
|
|
nameValue.push(chalk.dim(`❌ ${executionErrors}`))
|
|
} else {
|
|
for (let index = 0; index < 5; index++) {
|
|
nameValue.push(chalk.dim('⏳'))
|
|
}
|
|
}
|
|
return nameValue
|
|
})
|
|
this.choices = tableChoices(tableData).map((row, i) => ({
|
|
name: row,
|
|
value: this.jobs[i].id,
|
|
short: this.jobs[i].id,
|
|
}))
|
|
Object.values(this.jobsLinks).forEach(item => item.rel !== 'self' && this.commands.push(item.rel))
|
|
this.commands = [...jobsCommands]
|
|
this.help = jobsCommandsHelp.join('\n ')
|
|
this.prompt = `${totalCount} jobs (${this.jobsOffset}-${Math.min(this.jobsOffset + this.jobsLimit, totalCount)})`
|
|
}
|
|
|
|
|
|
function setJobsPagination(href) {
|
|
const url = new URL(href)
|
|
const searchParams = new URLSearchParams(url.search)
|
|
this.jobsLimit = +searchParams.get('limit')
|
|
this.jobsOffset = +searchParams.get('offset')
|
|
}
|
|
|
|
|
|
async function pageJobs(command) {
|
|
const page = command.replace(/_/, '')
|
|
if (!this.jobsLinks[page]) {
|
|
throw new Error(`No ${page} jobs❗`)
|
|
}
|
|
setJobsPagination.call(this, this.jobsLinks[page].href)
|
|
await this.getJobs()
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
newJob,
|
|
getJobs,
|
|
pageJobs,
|
|
} |