Skip to content

Commit de16efa

Browse files
author
Oleg Sucharevich
authored
report installation progress to codefresh to support idiomatic instal… (#459)
* report installation progress to codefresh to support idiomatic installation * report failures
1 parent 779b013 commit de16efa

File tree

5 files changed

+232
-56
lines changed

5 files changed

+232
-56
lines changed

lib/interface/cli/commands/hybrid/init.cmd.js

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const colors = require('colors');
1313
const DEFAULTS = require('../../defaults');
1414
const sdk = require('../../../../logic/sdk');
1515
const _ = require('lodash');
16+
const installationProgress = require('./installation-process');
17+
const { to } = require('./../../../../logic/cli-config/errors/awaitTo');
1618

1719
const INSTALLATION_DEFAULTS = {
1820
NAMESPACE: 'codefresh',
@@ -40,7 +42,18 @@ function prettyError(error) {
4042
}
4143
}
4244

43-
async function createDemoPipeline(runtimeName) {
45+
async function handleError(error, message, progressReporter, event) {
46+
if (!error) {
47+
return;
48+
}
49+
if (progressReporter) {
50+
await to(progressReporter.report(event, installationProgress.status.FAILURE));
51+
}
52+
console.log(`${colors.red('Error: ')} ${message}: ${prettyError(error)}`);
53+
process.exit(1);
54+
}
55+
56+
async function createDemoPipeline(runtimeName, progressReporter) {
4457
const pipeline = await sdk.pipelines.create({ metadata: { name: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME } });
4558
pipeline.spec.runtimeEnvironment = {
4659
name: runtimeName,
@@ -63,37 +76,37 @@ async function createDemoPipeline(runtimeName) {
6376
version: pipeline.version,
6477
},
6578
);
79+
80+
await to(progressReporter.report(installationProgress.events.PIPELINE_CREATED, installationProgress.status.SUCCESS));
6681
}
6782

68-
async function createAndExecuteDemoPipeline(runtimeName) {
83+
async function createAndExecuteDemoPipeline(runtimeName, progressReporter) {
6984
let demoPipelineExists = false;
7085

71-
try {
72-
const pipelines = await sdk.pipelines.list({ id: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME });
73-
if (_.get(pipelines, 'docs.length')) {
74-
demoPipelineExists = true;
75-
}
76-
} catch (error) {
77-
console.log(`Failed to fetch account pipelines, cause: ${error.message}`);
86+
const [getPipelinesError, pipelines] = await to(sdk.pipelines.list({ id: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME }));
87+
if (getPipelinesError) {
88+
console.log(`Failed to fetch account pipelines, cause: ${getPipelinesError.message}`);
89+
} else if (_.get(pipelines, 'docs.length')) {
90+
demoPipelineExists = true;
7891
}
7992

8093
if (!demoPipelineExists) {
8194
console.log(`Creating demo pipeline with the name: "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}"`);
82-
try {
83-
await createDemoPipeline(runtimeName);
84-
} catch (error) {
85-
console.log(`${colors.red('Error: ')} Failed to create demo pipeline, cause: ${prettyError(error)}`);
86-
}
95+
const [createDemoPipelineError] = await to(createDemoPipeline(runtimeName, progressReporter));
96+
await handleError(createDemoPipelineError, 'Failed to create demo pipeline', progressReporter, installationProgress.events.PIPELINE_CREATED);
8797
} else {
8898
console.log(`Demo pipeline with the name: "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}" already exists`);
8999
}
90100

91101
console.log(`${colors.yellow('*NOTE* Running a pipeline for the first time might take longer than usual.')}`);
92102
console.log(`Executing pipeline "${colors.cyan(INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME)}"`);
93-
await pipelinesRunCmd.handler({
103+
const [pipelineExecutionError] = await to(pipelinesRunCmd.handler({
94104
name: INSTALLATION_DEFAULTS.DEMO_PIPELINE_NAME,
95105
exitProcess: false,
96-
});
106+
}));
107+
await handleError(pipelineExecutionError, 'Failed to run demo pipeline', progressReporter, installationProgress.events.PIPELINE_EXECUTED);
108+
109+
await to(progressReporter.report(installationProgress.events.PIPELINE_EXECUTED, installationProgress.status.SUCCESS));
97110
}
98111

99112
async function getRecommendedKubeNamespace(kubeconfigPath, kubeContextName) {
@@ -215,7 +228,6 @@ const initCmd = new Command({
215228
'exec-demo-pipeline': shouldExecutePipeline,
216229
token,
217230
} = argv;
218-
219231
if (_.get(sdk, 'config.context.isNoAuth') && !token) {
220232
console.log('Not authenticated as a Codefresh account: ');
221233
console.log('In order to install a Codefresh Runner you need to provide ' +
@@ -292,48 +304,55 @@ const initCmd = new Command({
292304
4. Execute demo pipeline after install: ${colors.cyan(!!shouldExecutePipeline)}
293305
`);
294306

307+
const [, progress] = await to(async () => installationProgress.create(sdk['runner-installation'], {
308+
options: {
309+
kubeContextName,
310+
kubeNamespace,
311+
shouldMakeDefaultRe,
312+
shouldExecutePipeline,
313+
},
314+
}));
315+
316+
const progressReporter = installationProgress.buildReporter(sdk['runner-installation'], progress);
317+
318+
295319
if (token) { // Add context
296-
try {
297-
await createContext.handler({
298-
apiKey: token,
299-
name: INSTALLATION_DEFAULTS.CF_CONTEXT_NAME,
300-
url,
301-
});
302-
const config = await getConfigForSdk();
303-
await sdk.configure(config);
304-
console.log(`A Codefresh context named '${INSTALLATION_DEFAULTS.CF_CONTEXT_NAME}' was added to your "cfconfig" file.`);
305-
} catch (error) {
306-
console.log(`${colors.red('Error:')} Could not use the provided token, failed with error: ${prettyError(error)}`);
307-
process.exit(1);
308-
}
320+
const createContextOptions = {
321+
apiKey: token,
322+
name: INSTALLATION_DEFAULTS.CF_CONTEXT_NAME,
323+
url,
324+
};
325+
const [err] = await to(createContext.handler(createContextOptions));
326+
await handleError(err, 'Failed to use the provided token');
327+
const config = await getConfigForSdk();
328+
await sdk.configure(config);
329+
console.log(`A Codefresh context named '${INSTALLATION_DEFAULTS.CF_CONTEXT_NAME}' was added to your "cfconfig" file.`);
309330
} else {
310331
token = _.get(sdk, 'config.context.token');
311332
}
312333

313334
// Install runner and runtime
314-
let runtimeName;
315-
try {
316-
runtimeName = await installAgent.handler({
317-
name,
318-
'kube-context-name': kubeContextName,
319-
'kube-node-selector': kubeNodeSelector,
320-
'dry-run': dryRun,
321-
'in-cluster': inCluster,
322-
'kube-namespace': kubeNamespace,
323-
'kubernetes-runner-type': kubernetesRunnerType,
324-
tolerations,
325-
'venona-version': venonaVersion,
326-
'kube-config-path': kubeConfigPath,
327-
'skip-version-check': skipVersionCheck,
328-
'install-runtime': true,
329-
verbose,
330-
'make-default-runtime': shouldMakeDefaultRe,
331-
terminateProcess: false,
332-
});
333-
} catch (error) {
334-
console.log(`${colors.red('Error: ')} Runner installation failed with error: ${prettyError(error)}`);
335-
process.exit(1);
336-
}
335+
const agentInstallOptions = {
336+
name,
337+
'kube-context-name': kubeContextName,
338+
'kube-node-selector': kubeNodeSelector,
339+
'dry-run': dryRun,
340+
'in-cluster': inCluster,
341+
'kube-namespace': kubeNamespace,
342+
'kubernetes-runner-type': kubernetesRunnerType,
343+
tolerations,
344+
'venona-version': venonaVersion,
345+
'kube-config-path': kubeConfigPath,
346+
'skip-version-check': skipVersionCheck,
347+
'install-runtime': true,
348+
verbose,
349+
'make-default-runtime': shouldMakeDefaultRe,
350+
terminateProcess: false,
351+
};
352+
const [err, runtimeName] = await to(installAgent.handler(agentInstallOptions));
353+
await handleError(err, 'Runner installation failed', progressReporter, installationProgress.events.RUNNER_INSTALLED);
354+
355+
await to(progressReporter.report(installationProgress.events.RUNNER_INSTALLED, installationProgress.status.SUCCESS));
337356

338357
// Install monitoring
339358
await installMonitoring.handler({
@@ -345,16 +364,18 @@ const initCmd = new Command({
345364
verbose,
346365
noExit: true, // to prevent if from calling: process.exit()
347366
});
367+
await to(progressReporter.report(installationProgress.events.MONITOR_INSTALLED, installationProgress.status.SUCCESS));
348368

349369
// Post Installation
350370
if (shouldExecutePipeline) {
351-
await createAndExecuteDemoPipeline(runtimeName);
371+
await createAndExecuteDemoPipeline(runtimeName, progressReporter);
352372
}
353373

354374
console.log(colors.green('\nRunner Status:'));
355375
await getAgents.handler({});
356376
console.log(colors.green(`\nDocumenation link: ${colors.blue('https://codefresh.io/docs/docs/enterprise/codefresh-runner/#codefresh-runner-preview-release')}`));
357377
console.log(colors.green(`If you had any issues with the installation please report them at: ${colors.blue('https://github.com/codefresh-io/cli/issues/new')}`));
378+
await to(progressReporter.report(installationProgress.events.FINISHED, installationProgress.status.SUCCESS));
358379
process.exit(); // TODO : This is not needed - needed to be fixed
359380
},
360381
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
async function create(installer, event) {
2+
const res = await installer.createNewInstallationProgress(event);
3+
return res.progress;
4+
}
5+
6+
function buildReporter(installer, progress) {
7+
return {
8+
report: (event, status, options = {}) => {
9+
const data = {
10+
event,
11+
content: {
12+
status,
13+
...options,
14+
},
15+
};
16+
return installer.reportInstallationProgressEvent({ id: progress.id }, data);
17+
},
18+
};
19+
}
20+
21+
module.exports = {
22+
create,
23+
buildReporter,
24+
events: {
25+
RUNNER_INSTALLED: 'runner-installed',
26+
MONITOR_INSTALLED: 'monitor-installed',
27+
PIPELINE_EXECUTED: 'demo-pipeline-executed',
28+
PIPELINE_CREATED: 'demo-pipeline-created',
29+
FINISHED: 'finished',
30+
},
31+
status: {
32+
SUCCESS: 'success',
33+
FAILURE: 'failure',
34+
},
35+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
async function to(fn) {
2+
try {
3+
let res;
4+
if (typeof fn === 'function') {
5+
res = await fn();
6+
} else {
7+
res = await fn;
8+
}
9+
return [null, res];
10+
} catch (err) {
11+
return [err, null];
12+
}
13+
}
14+
module.exports = {
15+
to,
16+
};

openapi.json

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7945,7 +7945,102 @@
79457945
"agents"
79467946
]
79477947
}
7948-
}
7948+
},
7949+
"/runner-installation": {
7950+
"post": {
7951+
"x-endpoint": {
7952+
"isEndpoint": false,
7953+
"auth": {
7954+
"middleware": [
7955+
"auth.isAuthenticated"
7956+
]
7957+
},
7958+
"postMiddleware": [
7959+
"global.iseMiddleware"
7960+
],
7961+
"handler": "runner-installation.createNewInstallationProgress"
7962+
},
7963+
"responses": {
7964+
"201": {
7965+
"$ref": "#/components/responses/Json"
7966+
}
7967+
},
7968+
"tags": [
7969+
"runner-installation"
7970+
],
7971+
"operationId": "runner-installation-create",
7972+
"summary": "Create new runner installation progress",
7973+
"x-sdk-interface": "runner-installation.createNewInstallationProgress",
7974+
"requestBody": {
7975+
"$ref": "#/components/requestBodies/Json"
7976+
}
7977+
}
7978+
},
7979+
"/runner-installation/{id}": {
7980+
"get": {
7981+
"x-endpoint": {
7982+
"isEndpoint": false,
7983+
"auth": {
7984+
"middleware": [
7985+
"auth.isAuthenticated"
7986+
]
7987+
},
7988+
"postMiddleware": [
7989+
"global.iseMiddleware"
7990+
],
7991+
"handler": "runner-installation.getInstallationProgress"
7992+
},
7993+
"parameters": [
7994+
{
7995+
"$ref": "#/components/parameters/id"
7996+
}
7997+
],
7998+
"responses": {
7999+
"200": {
8000+
"$ref": "#/components/responses/Json"
8001+
}
8002+
},
8003+
"tags": [
8004+
"runner-installation"
8005+
],
8006+
"operationId": "runner-installation-get",
8007+
"summary": "Get new session of runner installation progress",
8008+
"x-sdk-interface": "runner-installation.getInstallationProgress"
8009+
},
8010+
"patch": {
8011+
"parameters": [
8012+
{
8013+
"$ref": "#/components/parameters/id"
8014+
}
8015+
],
8016+
"x-endpoint": {
8017+
"isEndpoint": false,
8018+
"auth": {
8019+
"middleware": [
8020+
"auth.isAuthenticated"
8021+
]
8022+
},
8023+
"postMiddleware": [
8024+
"global.iseMiddleware"
8025+
],
8026+
"handler": "runner-installation.reportInstallationProgressEvent"
8027+
},
8028+
"responses": {
8029+
"200": {
8030+
"$ref": "#/components/responses/Json"
8031+
}
8032+
},
8033+
"tags": [
8034+
"runner-installation"
8035+
],
8036+
"operationId": "runner-installation-update",
8037+
"summary": "Update runner-installation progress",
8038+
"x-sdk-interface": "runner-installation.reportInstallationProgressEvent",
8039+
"requestBody": {
8040+
"$ref": "#/components/requestBodies/Json"
8041+
}
8042+
}
8043+
}
79498044
},
79508045
"components": {
79518046
"parameters": {
@@ -8204,6 +8299,15 @@
82048299
}
82058300
}
82068301
}
8302+
},
8303+
"Json": {
8304+
"content": {
8305+
"application/json": {
8306+
"schema": {
8307+
"$ref": "#/components/schemas/requestBody"
8308+
}
8309+
}
8310+
}
82078311
}
82088312
},
82098313
"securitySchemes": {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codefresh",
3-
"version": "0.62.4",
3+
"version": "0.63.0",
44
"description": "Codefresh command line utility",
55
"main": "index.js",
66
"preferGlobal": true,

0 commit comments

Comments
 (0)