Skip to content

Commit 8a34b88

Browse files
authoredDec 30, 2020
fix: Authentication and Logs (#244)
BREAKING CHANGE: Node.js version 10 or later is required (dropped support for v6 and v8)
1 parent be817a2 commit 8a34b88

7 files changed

+84
-69
lines changed
 

‎logs/lib/retrieveLogs.js

+9-10
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ module.exports = {
1212

1313
getLogs() {
1414
const project = this.serverless.service.provider.project;
15-
const region = this.options.region;
1615
let func = this.options.function;
1716
const pageSize = this.options.count || 10;
1817

1918
func = getGoogleCloudFunctionName(this.serverless.service.functions, func);
2019

2120
return this.provider.request('logging', 'entries', 'list', {
22-
filter: `Function execution ${func} ${region}`,
21+
filter: `resource.labels.function_name="${func}" AND NOT textPayload=""`,
2322
orderBy: 'timestamp desc',
2423
resourceNames: [`projects/${project}`],
2524
pageSize,
@@ -29,7 +28,6 @@ module.exports = {
2928
printLogs(logs) {
3029
if (!logs.entries || !logs.entries.length) {
3130
logs = {
32-
//eslint-disable-line
3331
entries: [
3432
{
3533
timestamp: new Date().toISOString().slice(0, 10),
@@ -39,10 +37,13 @@ module.exports = {
3937
};
4038
}
4139

42-
let output = logs.entries.reduce(
43-
(p, c) => (p += `${chalk.grey(`${c.timestamp}:`)} ${c.textPayload}\n`),
44-
''
45-
); //eslint-disable-line
40+
let output = logs.entries.reduce((p, c) => {
41+
let message = '';
42+
message += `${chalk.grey(`${c.timestamp}:`)}\t`;
43+
message += c.labels && c.labels.execution_id ? `[${c.labels.execution_id}]\t` : '';
44+
message += `${c.textPayload}\n`;
45+
return p + message;
46+
}, '');
4647

4748
output = `Displaying the ${logs.entries.length} most recent log(s):\n\n${output}`; // prettify output
4849
output = output.slice(0, output.length - 1); // remove "\n---\n\n" for the last log entry
@@ -53,7 +54,6 @@ module.exports = {
5354
},
5455
};
5556

56-
// retrieve the functions name (Google uses our handler property as the function name)
5757
const getGoogleCloudFunctionName = (serviceFunctions, func) => {
5858
if (!serviceFunctions[func]) {
5959
const errorMessage = [
@@ -62,6 +62,5 @@ const getGoogleCloudFunctionName = (serviceFunctions, func) => {
6262
].join('');
6363
throw new Error(errorMessage);
6464
}
65-
66-
return serviceFunctions[func].handler;
65+
return serviceFunctions[func].name;
6766
};

‎logs/lib/retrieveLogs.test.js

+16-7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ describe('RetrieveLogs', () => {
2323
serverless.service.functions = {
2424
func1: {
2525
handler: 'foo',
26+
name: 'full-function-name',
2627
},
2728
};
2829
serverless.setProvider('google', new GoogleProvider(serverless));
@@ -71,7 +72,7 @@ describe('RetrieveLogs', () => {
7172
return googleLogs.getLogs().then(() => {
7273
expect(
7374
requestStub.calledWithExactly('logging', 'entries', 'list', {
74-
filter: 'Function execution foo us-central1',
75+
filter: 'resource.labels.function_name="full-function-name" AND NOT textPayload=""',
7576
orderBy: 'timestamp desc',
7677
resourceNames: ['projects/my-project'],
7778
pageSize: 10,
@@ -87,7 +88,7 @@ describe('RetrieveLogs', () => {
8788
return googleLogs.getLogs().then(() => {
8889
expect(
8990
requestStub.calledWithExactly('logging', 'entries', 'list', {
90-
filter: 'Function execution foo us-central1',
91+
filter: 'resource.labels.function_name="full-function-name" AND NOT textPayload=""',
9192
orderBy: 'timestamp desc',
9293
resourceNames: ['projects/my-project'],
9394
pageSize: googleLogs.options.count,
@@ -117,13 +118,21 @@ describe('RetrieveLogs', () => {
117118
it('should print the received execution result log on the console', () => {
118119
const logs = {
119120
entries: [
120-
{ timestamp: '1970-01-01 00:00', textPayload: 'Entry 1' },
121-
{ timestamp: '1970-01-01 00:01', textPayload: 'Entry 2' },
121+
{
122+
timestamp: '1970-01-01 00:00',
123+
textPayload: 'Entry 1',
124+
labels: { execution_id: 'foo' },
125+
},
126+
{
127+
timestamp: '1970-01-01 00:01',
128+
textPayload: 'Entry 2',
129+
labels: { execution_id: 'bar' },
130+
},
122131
],
123132
};
124133

125-
const logEntry1 = `${chalk.grey('1970-01-01 00:00:')} Entry 1`;
126-
const logEntry2 = `${chalk.grey('1970-01-01 00:01:')} Entry 2`;
134+
const logEntry1 = `${chalk.grey('1970-01-01 00:00:')}\t[foo]\tEntry 1`;
135+
const logEntry2 = `${chalk.grey('1970-01-01 00:01:')}\t[bar]\tEntry 2`;
127136
const expectedOutput = `Displaying the 2 most recent log(s):\n\n${logEntry1}\n${logEntry2}`;
128137

129138
return googleLogs.printLogs(logs).then(() => {
@@ -133,7 +142,7 @@ describe('RetrieveLogs', () => {
133142

134143
it('should print a default message to the console when no logs were received', () => {
135144
const date = `${new Date().toISOString().slice(0, 10)}:`;
136-
const logEntry = `${chalk.grey(date)} There is no log data to show...`;
145+
const logEntry = `${chalk.grey(date)}\tThere is no log data to show...`;
137146
const expectedOutput = `Displaying the 1 most recent log(s):\n\n${logEntry}`;
138147

139148
return googleLogs.printLogs({}).then(() => {

‎package.json

+3
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,8 @@
7474
"prettify:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier --write",
7575
"test": "jest"
7676
},
77+
"engines": {
78+
"node": ">=10.0"
79+
},
7780
"license": "MIT"
7881
}

‎package/lib/compileFunctions.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module.exports = {
4343
funcTemplate.properties.runtime =
4444
_.get(funcObject, 'runtime') ||
4545
_.get(this, 'serverless.service.provider.runtime') ||
46-
'nodejs8';
46+
'nodejs10';
4747
funcTemplate.properties.timeout =
4848
_.get(funcObject, 'timeout') || _.get(this, 'serverless.service.provider.timeout') || '60s';
4949
funcTemplate.properties.environmentVariables = _.merge(
@@ -165,7 +165,7 @@ const getFunctionTemplate = (funcObject, projectName, region, sourceArchiveUrl)
165165
properties: {
166166
parent: `projects/${projectName}/locations/${region}`,
167167
availableMemoryMb: 256,
168-
runtime: 'nodejs8',
168+
runtime: 'nodejs10',
169169
timeout: '60s',
170170
entryPoint: funcObject.handler,
171171
function: funcObject.name,

‎package/lib/compileFunctions.test.js

+22-22
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ describe('CompileFunctions', () => {
9898
func1: {
9999
handler: 'func1',
100100
memorySize: 1024,
101-
runtime: 'nodejs8',
101+
runtime: 'nodejs10',
102102
events: [{ http: 'foo' }],
103103
},
104104
};
@@ -109,7 +109,7 @@ describe('CompileFunctions', () => {
109109
name: 'my-service-dev-func1',
110110
properties: {
111111
parent: 'projects/myProject/locations/us-central1',
112-
runtime: 'nodejs8',
112+
runtime: 'nodejs10',
113113
function: 'my-service-dev-func1',
114114
entryPoint: 'func1',
115115
availableMemoryMb: 1024,
@@ -146,7 +146,7 @@ describe('CompileFunctions', () => {
146146
name: 'my-service-dev-func1',
147147
properties: {
148148
parent: 'projects/myProject/locations/us-central1',
149-
runtime: 'nodejs8',
149+
runtime: 'nodejs10',
150150
function: 'my-service-dev-func1',
151151
entryPoint: 'func1',
152152
availableMemoryMb: 1024,
@@ -183,7 +183,7 @@ describe('CompileFunctions', () => {
183183
name: 'my-service-dev-func1',
184184
properties: {
185185
parent: 'projects/myProject/locations/us-central1',
186-
runtime: 'nodejs8',
186+
runtime: 'nodejs10',
187187
function: 'my-service-dev-func1',
188188
entryPoint: 'func1',
189189
availableMemoryMb: 256,
@@ -220,7 +220,7 @@ describe('CompileFunctions', () => {
220220
name: 'my-service-dev-func1',
221221
properties: {
222222
parent: 'projects/myProject/locations/us-central1',
223-
runtime: 'nodejs8',
223+
runtime: 'nodejs10',
224224
function: 'my-service-dev-func1',
225225
entryPoint: 'func1',
226226
availableMemoryMb: 256,
@@ -259,7 +259,7 @@ describe('CompileFunctions', () => {
259259
name: 'my-service-dev-func1',
260260
properties: {
261261
parent: 'projects/myProject/locations/us-central1',
262-
runtime: 'nodejs8',
262+
runtime: 'nodejs10',
263263
function: 'my-service-dev-func1',
264264
entryPoint: 'func1',
265265
availableMemoryMb: 256,
@@ -300,7 +300,7 @@ describe('CompileFunctions', () => {
300300
name: 'my-service-dev-func1',
301301
properties: {
302302
parent: 'projects/myProject/locations/us-central1',
303-
runtime: 'nodejs8',
303+
runtime: 'nodejs10',
304304
function: 'my-service-dev-func1',
305305
entryPoint: 'func1',
306306
availableMemoryMb: 256,
@@ -345,7 +345,7 @@ describe('CompileFunctions', () => {
345345
name: 'my-service-dev-func1',
346346
properties: {
347347
parent: 'projects/myProject/locations/us-central1',
348-
runtime: 'nodejs8',
348+
runtime: 'nodejs10',
349349
function: 'my-service-dev-func1',
350350
entryPoint: 'func1',
351351
availableMemoryMb: 256,
@@ -387,7 +387,7 @@ describe('CompileFunctions', () => {
387387
name: 'my-service-dev-func1',
388388
properties: {
389389
parent: 'projects/myProject/locations/us-central1',
390-
runtime: 'nodejs8',
390+
runtime: 'nodejs10',
391391
function: 'my-service-dev-func1',
392392
entryPoint: 'func1',
393393
availableMemoryMb: 256,
@@ -429,7 +429,7 @@ describe('CompileFunctions', () => {
429429
name: 'my-service-dev-func1',
430430
properties: {
431431
parent: 'projects/myProject/locations/us-central1',
432-
runtime: 'nodejs8',
432+
runtime: 'nodejs10',
433433
function: 'my-service-dev-func1',
434434
entryPoint: 'func1',
435435
availableMemoryMb: 256,
@@ -476,7 +476,7 @@ describe('CompileFunctions', () => {
476476
name: 'my-service-dev-func1',
477477
properties: {
478478
parent: 'projects/myProject/locations/us-central1',
479-
runtime: 'nodejs8',
479+
runtime: 'nodejs10',
480480
function: 'my-service-dev-func1',
481481
entryPoint: 'func1',
482482
availableMemoryMb: 256,
@@ -521,7 +521,7 @@ describe('CompileFunctions', () => {
521521
name: 'my-service-dev-func1',
522522
properties: {
523523
parent: 'projects/myProject/locations/us-central1',
524-
runtime: 'nodejs8',
524+
runtime: 'nodejs10',
525525
function: 'my-service-dev-func1',
526526
entryPoint: 'func1',
527527
availableMemoryMb: 256,
@@ -576,7 +576,7 @@ describe('CompileFunctions', () => {
576576
name: 'my-service-dev-func1',
577577
properties: {
578578
parent: 'projects/myProject/locations/us-central1',
579-
runtime: 'nodejs8',
579+
runtime: 'nodejs10',
580580
function: 'my-service-dev-func1',
581581
entryPoint: 'func1',
582582
availableMemoryMb: 256,
@@ -595,7 +595,7 @@ describe('CompileFunctions', () => {
595595
name: 'my-service-dev-func2',
596596
properties: {
597597
parent: 'projects/myProject/locations/us-central1',
598-
runtime: 'nodejs8',
598+
runtime: 'nodejs10',
599599
function: 'my-service-dev-func2',
600600
entryPoint: 'func2',
601601
availableMemoryMb: 256,
@@ -623,7 +623,7 @@ describe('CompileFunctions', () => {
623623
func1: {
624624
handler: 'func1',
625625
memorySize: 128,
626-
runtime: 'nodejs8',
626+
runtime: 'nodejs10',
627627
vpc: 'projects/pg-us-n-app-123456/locations/us-central1/connectors/my-vpc',
628628
events: [{ http: 'foo' }],
629629
},
@@ -635,7 +635,7 @@ describe('CompileFunctions', () => {
635635
name: 'my-service-dev-func1',
636636
properties: {
637637
parent: 'projects/myProject/locations/us-central1',
638-
runtime: 'nodejs8',
638+
runtime: 'nodejs10',
639639
function: 'my-service-dev-func1',
640640
entryPoint: 'func1',
641641
availableMemoryMb: 128,
@@ -663,7 +663,7 @@ describe('CompileFunctions', () => {
663663
func1: {
664664
handler: 'func1',
665665
memorySize: 128,
666-
runtime: 'nodejs8',
666+
runtime: 'nodejs10',
667667
maxInstances: 10,
668668
vpc: 'projects/pg-us-n-app-123456/locations/us-central1/connectors/my-vpc',
669669
events: [{ http: 'foo' }],
@@ -676,7 +676,7 @@ describe('CompileFunctions', () => {
676676
name: 'my-service-dev-func1',
677677
properties: {
678678
parent: 'projects/myProject/locations/us-central1',
679-
runtime: 'nodejs8',
679+
runtime: 'nodejs10',
680680
function: 'my-service-dev-func1',
681681
entryPoint: 'func1',
682682
availableMemoryMb: 128,
@@ -705,14 +705,14 @@ describe('CompileFunctions', () => {
705705
func1: {
706706
handler: 'func1',
707707
memorySize: 128,
708-
runtime: 'nodejs8',
708+
runtime: 'nodejs10',
709709
vpc: 'projects/pg-us-n-app-123456/locations/us-central1/connectors/my-vpc',
710710
events: [{ http: 'foo' }],
711711
},
712712
func2: {
713713
handler: 'func2',
714714
memorySize: 128,
715-
runtime: 'nodejs8',
715+
runtime: 'nodejs10',
716716
maxInstances: 10,
717717
vpc: 'projects/pg-us-n-app-123456/locations/us-central1/connectors/my-vpc',
718718
events: [{ http: 'bar' }],
@@ -725,7 +725,7 @@ describe('CompileFunctions', () => {
725725
name: 'my-service-dev-func1',
726726
properties: {
727727
parent: 'projects/myProject/locations/us-central1',
728-
runtime: 'nodejs8',
728+
runtime: 'nodejs10',
729729
function: 'my-service-dev-func1',
730730
entryPoint: 'func1',
731731
availableMemoryMb: 128,
@@ -743,7 +743,7 @@ describe('CompileFunctions', () => {
743743
name: 'my-service-dev-func2',
744744
properties: {
745745
parent: 'projects/myProject/locations/us-central1',
746-
runtime: 'nodejs8',
746+
runtime: 'nodejs10',
747747
function: 'my-service-dev-func2',
748748
entryPoint: 'func2',
749749
availableMemoryMb: 128,

‎provider/googleProvider.js

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const path = require('path');
4-
const fs = require('fs');
54
const os = require('os');
65

76
const _ = require('lodash');
@@ -77,7 +76,7 @@ class GoogleProvider {
7776

7877
const authClient = this.getAuthClient();
7978

80-
return authClient.authorize().then(() => {
79+
return authClient.getClient().then(() => {
8180
const requestParams = { auth: authClient };
8281

8382
// merge the params from the request call into the base functionParams
@@ -105,21 +104,24 @@ class GoogleProvider {
105104
}
106105

107106
getAuthClient() {
108-
let credentials =
109-
this.serverless.service.provider.credentials || process.env.GOOGLE_APPLICATION_CREDENTIALS;
110-
const credParts = credentials.split(path.sep);
111-
112-
if (credParts[0] === '~') {
113-
credParts[0] = os.homedir();
114-
credentials = credParts.reduce((memo, part) => path.join(memo, part), '');
107+
let credentials = this.serverless.service.provider.credentials;
108+
109+
if (credentials) {
110+
const credParts = this.serverless.service.provider.credentials.split(path.sep);
111+
if (credParts[0] === '~') {
112+
credParts[0] = os.homedir();
113+
credentials = credParts.reduce((memo, part) => path.join(memo, part), '');
114+
}
115+
116+
return new google.auth.GoogleAuth({
117+
keyFile: credentials.toString(),
118+
scopes: 'https://www.googleapis.com/auth/cloud-platform',
119+
});
115120
}
116121

117-
const keyFileContent = fs.readFileSync(credentials).toString();
118-
const key = JSON.parse(keyFileContent);
119-
120-
return new google.auth.JWT(key.client_email, null, key.private_key, [
121-
'https://www.googleapis.com/auth/cloud-platform',
122-
]);
122+
return new google.auth.GoogleAuth({
123+
scopes: 'https://www.googleapis.com/auth/cloud-platform',
124+
});
123125
}
124126

125127
isServiceSupported(service) {

‎provider/googleProvider.test.js

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22

3-
const fs = require('fs');
43
const os = require('os');
54

65
const sinon = require('sinon');
@@ -10,7 +9,6 @@ const GoogleProvider = require('./googleProvider');
109
const Serverless = require('../test/serverless');
1110

1211
describe('GoogleProvider', () => {
13-
let readFileSyncStub;
1412
let googleProvider;
1513
let serverless;
1614
let setProviderStub;
@@ -22,20 +20,15 @@ describe('GoogleProvider', () => {
2220
serverless.service = {
2321
provider: {
2422
project: 'example-project',
25-
credentials: '/root/.gcloud/project-1234.json',
2623
},
2724
};
2825
setProviderStub = sinon.stub(serverless, 'setProvider').returns();
29-
readFileSyncStub = sinon
30-
.stub(fs, 'readFileSync')
31-
.returns('{"client_email": "foo@bar.de","private_key": "wasdqwerty"}');
3226
homedirStub = sinon.stub(os, 'homedir').returns('/root');
3327
googleProvider = new GoogleProvider(serverless);
3428
});
3529

3630
afterEach(() => {
3731
serverless.setProvider.restore();
38-
fs.readFileSync.restore();
3932
os.homedir.restore();
4033
});
4134

@@ -94,7 +87,7 @@ describe('GoogleProvider', () => {
9487
},
9588
};
9689
sinon.stub(googleProvider, 'getAuthClient').returns({
97-
authorize: sinon.stub().resolves(),
90+
getClient: sinon.stub().resolves(),
9891
});
9992
sinon.stub(googleProvider, 'isServiceSupported').returns();
10093
});
@@ -134,11 +127,20 @@ describe('GoogleProvider', () => {
134127
});
135128

136129
describe('#getAuthClient()', () => {
137-
it('should return a new authClient', () => {
130+
it('should return a new authClient when using default credentials', () => {
138131
const authClient = googleProvider.getAuthClient();
139132

140-
expect(readFileSyncStub.calledWithExactly('/root/.gcloud/project-1234.json')).toEqual(true);
141-
expect(authClient).toBeInstanceOf(google.auth.JWT);
133+
expect(authClient.keyFilename).toEqual(undefined);
134+
expect(authClient).toBeInstanceOf(google.auth.GoogleAuth);
135+
});
136+
137+
it('should return a new authClient when using a credentials file', () => {
138+
googleProvider.serverless.service.provider.credentials = '/root/.gcloud/project-1234.json';
139+
140+
const authClient = googleProvider.getAuthClient();
141+
142+
expect(authClient.keyFilename).toEqual('/root/.gcloud/project-1234.json');
143+
expect(authClient).toBeInstanceOf(google.auth.GoogleAuth);
142144
});
143145

144146
it('should expand tilde characters in credentials file paths', () => {
@@ -147,8 +149,8 @@ describe('GoogleProvider', () => {
147149
const authClient = googleProvider.getAuthClient();
148150

149151
expect(homedirStub.calledOnce).toEqual(true);
150-
expect(readFileSyncStub.calledWithExactly('/root/.gcloud/project-1234.json')).toEqual(true);
151-
expect(authClient).toBeInstanceOf(google.auth.JWT);
152+
expect(authClient.keyFilename).toEqual('/root/.gcloud/project-1234.json');
153+
expect(authClient).toBeInstanceOf(google.auth.GoogleAuth);
152154
});
153155
});
154156

0 commit comments

Comments
 (0)
Please sign in to comment.