Skip to content

Commit

Permalink
Add --diff option teraslice-cli (#3710)
Browse files Browse the repository at this point in the history
This PR makes the following changes: 

- Adds `--diff` option to `teraslice cli view` that will compare the
local `json` job file with what teraslice has on the state cluster
- Bumps `teraslice-cli` from `v2.1.0` to `v2.2.0`

Ref to issue #3694
  • Loading branch information
sotojn authored Aug 8, 2024
1 parent 9f9d820 commit 20511ae
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 3 deletions.
4 changes: 3 additions & 1 deletion packages/teraslice-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "teraslice-cli",
"displayName": "Teraslice CLI",
"version": "2.1.0",
"version": "2.2.0",
"description": "Command line manager for teraslice jobs, assets, and cluster references.",
"keywords": [
"teraslice"
Expand Down Expand Up @@ -42,6 +42,7 @@
"@terascope/utils": "^0.60.0",
"chalk": "^4.1.2",
"cli-table3": "^0.6.4",
"diff": "^5.2.0",
"easy-table": "^1.2.0",
"ejs": "^3.1.10",
"esbuild": "^0.21.5",
Expand All @@ -62,6 +63,7 @@
},
"devDependencies": {
"@types/decompress": "^4.2.7",
"@types/diff": "^5.2.1",
"@types/easy-table": "^1.2.0",
"@types/ejs": "^3.1.5",
"@types/js-yaml": "^4.0.9",
Expand Down
2 changes: 2 additions & 0 deletions packages/teraslice-cli/src/cmds/tjm/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ export default {
yargs.option('src-dir', yargsOptions.buildOption('src-dir'));
yargs.option('config-dir', yargsOptions.buildOption('config-dir'));
yargs.options('status', yargsOptions.buildOption('jobs-status'));
yargs.option('diff', yargsOptions.buildOption('diff'));
yargs
.example('$0 tjm view JOB_FILE.json', 'displays job config on job cluster')
.example('$0 tjm view JOB_FILE.json --diff', 'Shows diff between the local json file and whats currently on the cluster')
.example('$0 tjm view JOB_FILE1.json JOB_FILE2.json', 'displays config for multiple job files');
return yargs;
},
Expand Down
91 changes: 90 additions & 1 deletion packages/teraslice-cli/src/helpers/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import {
has, toString, pDelay, pMap,
} from '@terascope/utils';
import { Teraslice } from '@terascope/types';
import chalk from 'chalk';
import * as diff from 'diff';
import path from 'node:path';
import { Job } from 'teraslice-client-js';
import TerasliceUtil from './teraslice-util.js';
import Display from './display.js';
Expand Down Expand Up @@ -669,6 +672,88 @@ export default class Jobs {
}
}

formatJobConfig(jobConfig: JobConfigFile) {
const finalJobConfig: Partial<Teraslice.JobConfig> = {};
Object.keys(jobConfig).forEach((key) => {
if (key === '__metadata') {
finalJobConfig.job_id = jobConfig[key].cli.job_id;
finalJobConfig._updated = jobConfig[key].cli.updated;
} else {
finalJobConfig[key] = jobConfig[key];
}
});
return finalJobConfig;
}

getLocalJSONConfigs(srcDir: string, files: string[]) {
const localJobConfigs = {};
for (const file of files) {
const filePath = path.join(srcDir, file);
const jobConfig: JobConfigFile = JSON.parse(fs.readFileSync(filePath, { encoding: 'utf-8' }));
const formattedJobConfig = this.formatJobConfig(jobConfig);
localJobConfigs[formattedJobConfig.job_id as string] = formattedJobConfig;
}
return localJobConfigs;
}

printDiff(diffResult: Diff.Change[], showUpdateField: boolean) {
diffResult.forEach((part) => {
let color: chalk.Chalk;
let symbol: string;
let pointer: string;
if (part.added) {
color = chalk.green;
symbol = '+';
pointer = ' <--- local job file value';
} else if (part.removed) {
color = chalk.red;
symbol = '-';
pointer = ' <--- state cluster value';
} else {
color = chalk.grey;
symbol = ' ';
pointer = '';
}
const lines = part.value.split('\n');
lines.forEach((line) => {
/// Don't print blank lines
if (line.length !== 0) {
/// These fields aren't in the job file so don't compare in diff
if (!line.includes('"_created":') && !line.includes('"_context":')) {
/// Check to see if we want to display _updated field
if (line.includes('"_updated":')) {
if (showUpdateField) {
process.stdout.write(color(`${symbol} ${line}${pointer}\n`));
}
} else {
process.stdout.write(color(`${symbol} ${line}${pointer}\n`));
}
}
}
});
});
}

getJobDiff(job: JobMetadata) {
const localJobConfigs = this.getLocalJSONConfigs(
this.config.args.srcDir,
this.config.args.jobFile
);
const diffObject = diff.diffJson(job.config, localJobConfigs[job.id]);

/// "_update" fields on the job file are always off by a couple milliseconds
/// We only want to display a diff of this field if it's greater than a minute
let showUpdateField = false;
const jobConfigUpdateTime = new Date(job.config._updated).getTime();
const localConfigUpdateTime = new Date(localJobConfigs[job.id]._updated).getTime();
const timeDiff = Math.abs(localConfigUpdateTime - jobConfigUpdateTime);
if (timeDiff > (1000 * 60)) {
showUpdateField = true;
}

this.printDiff(diffObject, showUpdateField);
}

/**
* @param args action and final property, final indicates if it is part of a series of commands
* @param job job metadata
Expand All @@ -692,7 +777,11 @@ export default class Jobs {
({ message, final } = this.getUpdateMessage(action, job));
}

reply.yellow(`> ${message}`);
if (this.config.args.diff && action === 'view') {
this.getJobDiff(job);
} else {
reply.yellow(`> ${message}`);
}

if (final) {
reply.green(`${jobInfoString}`);
Expand Down
5 changes: 5 additions & 0 deletions packages/teraslice-cli/src/helpers/yargs-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ export default class Options {
describe: 'Silence non-error logging.',
type: 'boolean'
}),
diff: () => ({
describe: 'Shows diff on a job in a cluster and a job file',
default: false,
type: 'boolean'
})
};

private positionals: Record<string, (...args: any[]) => yargs.PositionalOptions> = {
Expand Down
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2682,6 +2682,11 @@
dependencies:
"@types/node" "*"

"@types/diff@^5.2.1":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@types/diff/-/diff-5.2.1.tgz#cceae9c4b2dae5c6b8ab1ce1263601c255d87fb3"
integrity sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==

"@types/easy-table@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/easy-table/-/easy-table-1.2.0.tgz#d7153551a2c3f6571dddff974b05aa2fb1a4a948"
Expand Down Expand Up @@ -5214,7 +5219,7 @@ diff-sequences@^29.6.3:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==

diff@^5.0.0:
diff@^5.0.0, diff@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531"
integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==
Expand Down

0 comments on commit 20511ae

Please sign in to comment.