Skip to content

Commit fe5c106

Browse files
Itai GendlerItai Gendler
authored andcommitted
Add support for retreiving workflow logs
1 parent 1c2f4ab commit fe5c106

File tree

7 files changed

+187
-2
lines changed

7 files changed

+187
-2
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const debug = require('debug')('codefresh:cli:logs');
2+
const Command = require('../../Command');
3+
const _ = require('lodash');
4+
const CFError = require('cf-errors');
5+
const { logs } = require('../../../../logic').api;
6+
7+
8+
const run = new Command({
9+
root: true,
10+
command: 'logs <id>',
11+
description: 'Show logs of a workflow',
12+
builder: (yargs) => {
13+
yargs
14+
.positional('id', {
15+
describe: 'Pipeline id',
16+
})
17+
.option('f', {
18+
describe: 'Continue showing workflow logs until it will finish',
19+
type: 'boolean',
20+
});
21+
22+
return yargs;
23+
},
24+
handler: async (argv) => {
25+
const workflowId = argv.id;
26+
const follow = argv.f;
27+
28+
await logs.showWorkflowLogs(workflowId, follow);
29+
// TODO fix this. its a workaround since something related to firebase in not properly closed
30+
process.exit(0);
31+
},
32+
});
33+
34+
module.exports = run;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ const run = new Command({
4848
describe: 'todo',
4949
type: 'number',
5050
default: 1,
51+
})
52+
.option('f', {
53+
describe: 'Show and follow the logs of the created workflow',
5154
});
5255

5356
crudFilenameOption(yargs, {

lib/logic/api/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
2-
31
const user = require('./user');
42
const pipeline = require('./pipeline');
53
const context = require('./context');
64
const image = require('./image');
75
const composition = require('./composition');
86
const environment = require('./environment');
97
const workflow = require('./workflow');
8+
const logs = require('./logs');
109

1110
module.exports = {
1211
user,
@@ -16,4 +15,5 @@ module.exports = {
1615
composition,
1716
environment,
1817
workflow,
18+
logs,
1919
};

lib/logic/api/logs.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
const debug = require('debug')('codefresh:api:logs');
2+
const Promise = require('bluebird');
3+
const _ = require('lodash');
4+
const CFError = require('cf-errors'); // eslint-disable-line
5+
const { sendHttpRequest } = require('./helper');
6+
const workflows = require('./workflow');
7+
const Firebase = require('firebase');
8+
const rp = require('request-promise');
9+
10+
const getFirebaseToken = async () => {
11+
const options = {
12+
url: '/api/user/firebaseAuth',
13+
method: 'GET',
14+
};
15+
16+
const firebaseAuth = await sendHttpRequest(options);
17+
return firebaseAuth;
18+
};
19+
20+
const connectToFirebase = async (firebaseAuth) => {
21+
const promise = new Promise((resolve, reject) => {
22+
const jobIdRef = new Firebase(firebaseAuth.url);
23+
jobIdRef.authWithCustomToken(firebaseAuth.accessToken, (err) => {
24+
if (err) {
25+
reject(new CFError({
26+
cause: err,
27+
message: 'Failed to login to Firebase',
28+
}));
29+
} else {
30+
debug('Firebase login succeeded');
31+
resolve();
32+
}
33+
});
34+
});
35+
return promise;
36+
};
37+
38+
const printLogsFromJson = (steps) => {
39+
_.forEach(steps, (step) => {
40+
const prefixSuffix = Array(step.name.length)
41+
.join('=');
42+
console.log(`${prefixSuffix}\nStep: ${step.name}\n${prefixSuffix}`);
43+
_.forEach(step.logs, (log) => {
44+
console.log(log);
45+
});
46+
});
47+
};
48+
49+
const printCurrentFirebaseLogs = async (firebaseAuth, progressJobId) => {
50+
const promise = new Promise((resolve, reject) => {
51+
const jobIdRef = new Firebase(`${firebaseAuth.url}/build-logs/${progressJobId}`);
52+
jobIdRef.once('value', (snapshot) => {
53+
const { steps } = snapshot.val();
54+
printLogsFromJson(steps);
55+
56+
resolve();
57+
}, (err) => {
58+
reject(new CFError({
59+
cause: err,
60+
message: 'Failed to get logs from firebase',
61+
}));
62+
});
63+
});
64+
return promise;
65+
};
66+
67+
// TODO implement
68+
const printFollowFirebaseLogs = async (firebaseAuth, progressJobId) => { // eslint-disable-line
69+
};
70+
71+
const getProgressJob = async (workflowId) => {
72+
const workflow = await workflows.getWorkflowById(workflowId);
73+
const progressJobId = workflow.info.progress;
74+
75+
const options = {
76+
url: `/api/progress/${progressJobId}`,
77+
method: 'GET',
78+
};
79+
80+
const progressJob = await sendHttpRequest(options);
81+
return progressJob;
82+
};
83+
84+
const showWorkflowLogsFromFirebase = async (progressJobId, follow) => {
85+
const firebaseAuth = await getFirebaseToken();
86+
await connectToFirebase(firebaseAuth);
87+
if (follow) { // eslint-disable-line
88+
// TODO implement
89+
} else {
90+
await printCurrentFirebaseLogs(firebaseAuth, progressJobId);
91+
}
92+
};
93+
94+
// when bringing logs from gcs, there is no meaning for workflow since the workflow has finished
95+
const showWorkflowLogsFromGCS = async (progressJob) => {
96+
const options = {
97+
url: progressJob.location.url,
98+
method: 'GET',
99+
json: true,
100+
};
101+
102+
103+
const { steps } = await rp(options);
104+
printLogsFromJson(steps);
105+
};
106+
107+
const showWorkflowLogs = async (workflowId, follow) => {
108+
const progressJob = await getProgressJob(workflowId);
109+
if (progressJob.location.type === 'firebase') {
110+
await showWorkflowLogsFromFirebase(progressJob._id, follow);
111+
} else {
112+
await showWorkflowLogsFromGCS(progressJob);
113+
}
114+
};
115+
116+
117+
module.exports = {
118+
showWorkflowLogs,
119+
};

lib/logic/api/workflow.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const _extractFieldsForWorkflowEntity = (workflow) => {
2222
repository: `${workflow.repoOwner}/${workflow.repoName}`,
2323
branch: workflow.branchName,
2424
trigger: workflow.trigger,
25+
progress: workflow.progress,
2526
};
2627
};
2728

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"scripts": "lib/**/*.js"
2222
},
2323
"dependencies": {
24+
"firebase": "git+https://github.com/codefresh-io/firebase.git#80b2ed883ff281cd67b53bd0f6a0bbd6f330fed5",
2425
"@codefresh-io/docker-reference": "^0.0.5",
2526
"bluebird": "^3.5.1",
2627
"cf-errors": "^0.1.11",

yarn.lock

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,12 @@ fast-levenshtein@~2.0.4:
12691269
version "2.0.6"
12701270
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
12711271

1272+
faye-websocket@>=0.6.0:
1273+
version "0.11.1"
1274+
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38"
1275+
dependencies:
1276+
websocket-driver ">=0.5.1"
1277+
12721278
fb-watchman@^2.0.0:
12731279
version "2.0.0"
12741280
resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58"
@@ -1337,6 +1343,12 @@ find-up@^2.0.0, find-up@^2.1.0:
13371343
dependencies:
13381344
locate-path "^2.0.0"
13391345

1346+
"firebase@git+https://github.com/codefresh-io/firebase.git#80b2ed883ff281cd67b53bd0f6a0bbd6f330fed5":
1347+
version "2.4.2"
1348+
resolved "git+https://github.com/codefresh-io/firebase.git#80b2ed883ff281cd67b53bd0f6a0bbd6f330fed5"
1349+
dependencies:
1350+
faye-websocket ">=0.6.0"
1351+
13401352
flat-cache@^1.2.1:
13411353
version "1.3.0"
13421354
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481"
@@ -1680,6 +1692,10 @@ html-encoding-sniffer@^1.0.1:
16801692
dependencies:
16811693
whatwg-encoding "^1.0.1"
16821694

1695+
http-parser-js@>=0.4.0:
1696+
version "0.4.9"
1697+
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.9.tgz#ea1a04fb64adff0242e9974f297dd4c3cad271e1"
1698+
16831699
http-signature@~1.1.0:
16841700
version "1.1.1"
16851701
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
@@ -4006,6 +4022,17 @@ webidl-conversions@^4.0.0:
40064022
version "4.0.2"
40074023
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
40084024

4025+
websocket-driver@>=0.5.1:
4026+
version "0.7.0"
4027+
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb"
4028+
dependencies:
4029+
http-parser-js ">=0.4.0"
4030+
websocket-extensions ">=0.1.1"
4031+
4032+
websocket-extensions@>=0.1.1:
4033+
version "0.1.3"
4034+
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29"
4035+
40094036
whatwg-encoding@^1.0.1:
40104037
version "1.0.3"
40114038
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3"

0 commit comments

Comments
 (0)