Skip to content

Commit c598d77

Browse files
SAAS-steps - first typed step support (#338)
1 parent 7c9a716 commit c598d77

File tree

9 files changed

+596
-3
lines changed

9 files changed

+596
-3
lines changed

lib/interface/cli/commands/root/create.cmd.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const get = new Command({
99
root: true,
1010
command: 'create',
1111
description: 'Create a resource from a file or stdin',
12-
usage: 'Supported resources: \n\t\'context\'\n\t\'pipeline\'',
12+
usage: 'Supported resources: \n\t\'context\'\n\t\'pipeline\'\'\n\t\'step\'',
1313
webDocs: {
1414
description: 'Create a resource from a file, directory or url',
1515
category: 'Operate On Resources',
@@ -48,6 +48,10 @@ const get = new Command({
4848
await sdk.pipelines.create(data);
4949
console.log(`Pipeline '${name}' created`);
5050
break;
51+
case 'step':
52+
await sdk.steps.create(data);
53+
console.log(`Step '${name}' created`);
54+
break;
5155
default:
5256
throw new CFError(`Entity: ${entity} not supported`);
5357
}

lib/interface/cli/commands/root/replace.cmd.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const annotate = new Command({
99
root: true,
1010
command: 'replace',
1111
description: 'Replace a resource by filename',
12-
usage: 'Supported resources: \n\t\'Context\'\n\t\'Pipeline\'',
12+
usage: 'Supported resources: \n\t\'Context\'\n\t\'Pipeline\'\'\n\t\'Step\'',
1313
webDocs: {
1414
description: 'Replace a resource from a file, directory or url',
1515
category: 'Operate On Resources',
@@ -56,6 +56,12 @@ const annotate = new Command({
5656
}, data);
5757
console.log(`Pipeline '${name}' updated`);
5858
break;
59+
case 'step':
60+
await sdk.steps.replace({
61+
name,
62+
}, data);
63+
console.log(`Step '${name}' updated`);
64+
break;
5965
default:
6066
throw new CFError(`Entity: ${entity} not supported`);
6167
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const Command = require('../../Command');
2+
const deleteRoot = require('../root/delete.cmd');
3+
const { sdk } = require('../../../../logic');
4+
5+
6+
const command = new Command({
7+
command: 'step [name]',
8+
parent: deleteRoot,
9+
description: 'Delete a step',
10+
webDocs: {
11+
category: 'Steps',
12+
title: 'Delete Step',
13+
},
14+
builder: (yargs) => {
15+
return yargs
16+
.positional('name', {
17+
describe: 'Step name',
18+
});
19+
},
20+
handler: async (argv) => {
21+
const { name } = argv;
22+
23+
await sdk.steps.delete({ name });
24+
console.log(`Step '${name}' deleted.`);
25+
},
26+
});
27+
28+
29+
module.exports = command;
30+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
const debug = require('debug')('codefresh:cli:get:step');
2+
const Command = require('../../Command');
3+
const CFError = require('cf-errors');
4+
const _ = require('lodash');
5+
const DEFAULTS = require('../../defaults');
6+
const { prepareKeyValueFromCLIEnvOption } = require('../../helpers/general');
7+
const Output = require('../../../../output/Output');
8+
const { sdk } = require('../../../../logic');
9+
const Step = require('../../../../logic/entities/Step');
10+
11+
const getRoot = require('../root/get.cmd');
12+
13+
14+
const command = new Command({
15+
command: 'steps [id..]',
16+
aliases: ['step'],
17+
parent: getRoot,
18+
description: 'Get a specific step or an array of steps',
19+
webDocs: {
20+
category: 'Steps',
21+
title: 'Get Step',
22+
},
23+
builder: (yargs) => {
24+
return yargs
25+
.positional('id', {
26+
describe: 'Step name/id',
27+
})
28+
.option('name', {
29+
describe: 'Filter steps by name',
30+
})
31+
.option('label', {
32+
describe: 'Filter by a label',
33+
alias: 'l',
34+
default: [],
35+
})
36+
.option('limit', {
37+
describe: 'Limit amount of returned results',
38+
default: DEFAULTS.GET_LIMIT_RESULTS,
39+
})
40+
.option('page', {
41+
describe: 'Paginated page',
42+
default: DEFAULTS.GET_PAGINATED_PAGE,
43+
});
44+
},
45+
handler: async (argv) => {
46+
const { id: ids, name } = argv;
47+
const limit = argv.limit;
48+
const offset = (argv.page - 1) * limit;
49+
const labels = prepareKeyValueFromCLIEnvOption(argv.label);
50+
51+
if (!_.isEmpty(ids)) {
52+
const steps = [];
53+
for (const id of ids) {
54+
try {
55+
const currStep = await sdk.steps.get({ name: id });
56+
steps.push(Step.fromResponse(currStep));
57+
} catch (err) {
58+
if (steps.length) {
59+
Output.print(steps);
60+
}
61+
62+
debug(err.toString());
63+
const message = err.toString().includes('not find') ? `Step '${id}' was not found.` : 'Error occurred';
64+
throw new CFError({
65+
cause: err,
66+
message,
67+
});
68+
}
69+
}
70+
Output.print(steps);
71+
} else {
72+
const steps = await sdk.steps.list({
73+
limit,
74+
offset,
75+
id: name,
76+
labels,
77+
});
78+
Output.print(_.map(_.get(steps, 'docs'), Step.fromResponse));
79+
}
80+
},
81+
});
82+
83+
module.exports = command;
84+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const _ = require('lodash');
2+
const steps = () => require('../../../../logic').sdk.steps;
3+
const Step = require('../../../../logic/entities/Step');
4+
const { authContextWrapper } = require('../../completion/helpers');
5+
6+
const positionalHandler = async ({word, argv}) => {
7+
const stps = await steps().list({ limit: 25, offset: 0 });
8+
return _.map(_.get(stps, 'docs'), Step.fromResponse).map(p => p.name);
9+
};
10+
11+
module.exports = {
12+
positionalHandler: authContextWrapper(positionalHandler),
13+
};
14+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
const getCmd = require('./get.cmd').toCommand();
2+
const deleteCmd = require('./delete.cmd').toCommand();
3+
const { positionalHandler } = require('./get.completion');
4+
5+
jest.mock('../../helpers/validation'); // eslint-disable-line
6+
7+
jest.mock('../../completion/helpers', () => { // eslint-disable-line
8+
return {
9+
authContextWrapper: func => func,
10+
};
11+
});
12+
13+
jest.mock('../../../../logic/entities/Step', () => { // eslint-disable-line
14+
return {
15+
fromResponse: res => res,
16+
};
17+
});
18+
19+
const request = require('requestretry');
20+
21+
const DEFAULT_RESPONSE = request.__defaultResponse();
22+
23+
describe('step', () => {
24+
beforeEach(async () => {
25+
request.__reset();
26+
request.mockClear();
27+
await configureSdk(); // eslint-disable-line
28+
});
29+
30+
describe('commands', () => {
31+
describe('get', () => {
32+
it('should handle getting given id', async () => {
33+
const argv = { id: ['some id'] };
34+
await getCmd.handler(argv);
35+
await verifyResponsesReturned([DEFAULT_RESPONSE]); // eslint-disable-line
36+
});
37+
38+
it('should handle getting all', async () => {
39+
const argv = {};
40+
const response = { statusCode: 200, body: { docs: [DEFAULT_RESPONSE.body] } };
41+
request.__setResponse(response);
42+
await getCmd.handler(argv);
43+
await verifyResponsesReturned([response]); // eslint-disable-line
44+
});
45+
});
46+
47+
// decided to follow unit tests modularity concept
48+
describe('delete', () => {
49+
it('should handle deletion given name', async () => {
50+
const argv = { name: 'some name' };
51+
await deleteCmd.handler(argv);
52+
await verifyResponsesReturned([DEFAULT_RESPONSE]); // eslint-disable-line
53+
});
54+
});
55+
});
56+
57+
describe('completions', () => {
58+
describe('get', () => {
59+
it('should handle getting completion', async () => {
60+
const response = { statusCode: 200, body: { docs: [{ name: 'some pip' }] } };
61+
request.__setResponse(response);
62+
await positionalHandler({});
63+
await verifyResponsesReturned([response]); // eslint-disable-line
64+
});
65+
});
66+
});
67+
});

lib/logic/entities/Step.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const Entity = require('./Entity');
2+
const _ = require('lodash');
3+
4+
class Step extends Entity {
5+
constructor(data) {
6+
super();
7+
this.entityType = 'step';
8+
this.info = data;
9+
this.id = this.info.metadata.id;
10+
this.name = this.info.metadata.name;
11+
this.created = this.info.metadata.created_at ? new Date(this.info.metadata.created_at) : undefined;
12+
this.updated = this.info.metadata.updated_at ? new Date(this.info.metadata.updated_at) : undefined;
13+
this.defaultColumns = ['name', 'updated', 'created'];
14+
this.wideColumns = ['id'].concat(this.defaultColumns);
15+
}
16+
17+
static fromResponse(response) {
18+
return new Step(_.pick(response, 'id', 'version', 'kind', 'metadata', 'spec'));
19+
}
20+
}
21+
22+
module.exports = Step;

0 commit comments

Comments
 (0)