Skip to content

Apply Serverless v3 new API/design for CLI output #484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/deploy/stepFunctions/compileAlarms.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const _ = require('lodash');
const BbPromise = require('bluebird');
const Joi = require('@hapi/joi');
const schema = require('./compileAlarms.schema');
const logger = require('../../utils/logger');

const cloudWatchMetricNames = {
executionsTimedOut: 'ExecutionsTimedOut',
Expand Down Expand Up @@ -39,7 +40,7 @@ function getCloudWatchAlarms(
);

if (!_.isEmpty(invalid)) {
serverless.cli.consoleLog(
logger.log(
`state machine [${stateMachineName}] : alarms.metrics has invalid metrics `,
`[${invalid.join(',')}]. `
+ 'No CloudWatch Alarms would be created for these. '
Expand Down Expand Up @@ -96,7 +97,7 @@ function validateConfig(serverless, stateMachineName, alarmsObj) {
const { error } = Joi.validate(alarmsObj, schema, { allowUnknown: false });

if (error) {
serverless.cli.consoleLog(
logger.log(
`State machine [${stateMachineName}] : alarms config is malformed. `
+ 'Please see https://github.com/horike37/serverless-step-functions for examples. '
+ `${error}`,
Expand All @@ -109,6 +110,7 @@ function validateConfig(serverless, stateMachineName, alarmsObj) {

module.exports = {
compileAlarms() {
logger.config(this.serverless, this.v3Api);
const cloudWatchAlarms = _.flatMap(this.getAllStateMachines(), (name) => {
const stateMachineObj = this.getStateMachine(name);
const stateMachineLogicalId = this.getStateMachineLogicalId(name, stateMachineObj);
Expand Down
11 changes: 7 additions & 4 deletions lib/deploy/stepFunctions/compileIamRole.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const path = require('path');
const { isIntrinsic, translateLocalFunctionNames, trimAliasFromLambdaArn } = require('../../utils/aws');
const { getArnPartition } = require('../../utils/arn');

const logger = require('../../utils/logger');

function getTaskStates(states) {
return _.flatMap(states, (state) => {
switch (state.Type) {
Expand Down Expand Up @@ -49,7 +51,7 @@ function sqsQueueUrlToArn(serverless, queueUrl) {
// we need to use "*" as ARN
return '*';
}
serverless.cli.consoleLog(`Unable to parse SQS queue url [${queueUrl}]`);
logger.log(`Unable to parse SQS queue url [${queueUrl}]`);
return [];
}

Expand All @@ -62,7 +64,7 @@ function getSqsPermissions(serverless, state) {
: sqsQueueUrlToArn(serverless, state.Parameters.QueueUrl);
return [{ action: 'sqs:SendMessage', resource: queueArn }];
}
serverless.cli.consoleLog('SQS task missing Parameters.QueueUrl or Parameters.QueueUrl.$');
logger.log('SQS task missing Parameters.QueueUrl or Parameters.QueueUrl.$');
return [];
}

Expand All @@ -73,7 +75,7 @@ function getSnsPermissions(serverless, state) {
const topicArn = state.Parameters['TopicArn.$'] ? '*' : state.Parameters.TopicArn;
return [{ action: 'sns:Publish', resource: topicArn }];
}
serverless.cli.consoleLog('SNS task missing Parameters.TopicArn or Parameters.TopicArn.$');
logger.log('SNS task missing Parameters.TopicArn or Parameters.TopicArn.$');
return [];
}

Expand Down Expand Up @@ -478,7 +480,7 @@ function getIamPermissions(taskStates) {
],
}];
}
this.serverless.cli.consoleLog('Cannot generate IAM policy statement for Task state', state);
logger.log('Cannot generate IAM policy statement for Task state', state);
return [];
}
});
Expand All @@ -505,6 +507,7 @@ function getIamStatements(iamPermissions) {

module.exports = {
compileIamRole() {
logger.config(this.serverless, this.v3Api);
this.getAllStateMachines().forEach((stateMachineName) => {
const stateMachineObj = this.getStateMachine(stateMachineName);
if (stateMachineObj.role) {
Expand Down
6 changes: 4 additions & 2 deletions lib/deploy/stepFunctions/compileNotifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const Joi = require('@hapi/joi');
const crypto = require('crypto');
const BbPromise = require('bluebird');
const schema = require('./compileNotifications.schema');
const logger = require('../../utils/logger');

const executionStatuses = [
'ABORTED', 'FAILED', 'RUNNING', 'SUCCEEDED', 'TIMED_OUT',
Expand Down Expand Up @@ -318,7 +319,7 @@ function validateConfig(serverless, stateMachineName, stateMachineObj, notificat
}

if (stateMachineObj.type === 'EXPRESS') {
serverless.cli.consoleLog(
logger.log(
`State machine [${stateMachineName}] : notifications are not supported on Express Workflows. `
+ 'Please see https://docs.aws.amazon.com/step-functions/latest/dg/concepts-standard-vs-express.html for difference between Step Functions Standard and Express Workflow.',
);
Expand All @@ -330,7 +331,7 @@ function validateConfig(serverless, stateMachineName, stateMachineObj, notificat
);

if (error) {
serverless.cli.consoleLog(
logger.log(
`State machine [${stateMachineName}] : notifications config is malformed. `
+ 'Please see https://github.com/horike37/serverless-step-functions for examples. '
+ `${error}`,
Expand All @@ -343,6 +344,7 @@ function validateConfig(serverless, stateMachineName, stateMachineObj, notificat

module.exports = {
compileNotifications() {
logger.config(this.serverless, this.v3Api);
const newResourcePairs = _.flatMap(this.getAllStateMachines(), (name) => {
const stateMachineObj = this.getStateMachine(name);
const stateMachineLogicalId = this.getStateMachineLogicalId(name, stateMachineObj);
Expand Down
3 changes: 2 additions & 1 deletion lib/deploy/stepFunctions/compileStateMachines.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const BbPromise = require('bluebird');
const crypto = require('crypto');
const schema = require('./compileStateMachines.schema');
const { isIntrinsic, translateLocalFunctionNames, convertToFunctionVersion } = require('../../utils/aws');
const logger = require('../../utils/logger');

function generateSubVariableName(element) {
return crypto
Expand Down Expand Up @@ -119,7 +120,7 @@ module.exports = {
if (this.serverless.service.stepFunctions.validate) {
const { isValid, errorsText } = aslValidator(stateMachineObj.definition);
if (isValid) {
this.serverless.cli.consoleLog(`✓ State machine "${stateMachineName}" definition is valid`);
logger.log(`✓ State machine "${stateMachineName}" definition is valid`);
} else {
const errorMessage = [
`✕ State machine "${stateMachineName}" definition is invalid:`,
Expand Down
5 changes: 2 additions & 3 deletions lib/deploy/stepFunctions/compileStateMachines.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const _ = require('lodash');
const expect = require('chai').expect;
const Serverless = require('serverless/lib/Serverless');
const CLI = require('serverless/lib/classes/CLI');
const AwsProvider = require('serverless/lib/plugins/aws/provider');
const ServerlessStepFunctions = require('./../../index');

Expand All @@ -12,9 +13,7 @@ describe('#compileStateMachines', () => {

beforeEach(() => {
serverless = new Serverless();
serverless.cli = {
consoleLog: () => {},
};
serverless.cli = new CLI(serverless);
serverless.configSchemaHandler = {
// eslint-disable-next-line no-unused-vars
defineTopLevelProperty: (propertyName, propertySchema) => {},
Expand Down
27 changes: 20 additions & 7 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ const invoke = require('./invoke/invoke');
const yamlParser = require('./yamlParser');
const naming = require('./naming');

const logger = require('./utils/logger');

class ServerlessStepFunctions {
constructor(serverless, options) {
constructor(serverless, options, v3Api) {
this.serverless = serverless;
this.options = options || {};
this.v3Api = v3Api;

this.provider = this.serverless.getProvider('aws');
this.service = this.serverless.service.service;
this.region = this.provider.getRegion();
this.stage = this.provider.getStage();

logger.config(serverless, v3Api);
Object.assign(
this,
compileStateMachines,
Expand Down Expand Up @@ -171,17 +177,17 @@ class ServerlessStepFunctions {
.then(this.startExecution)
.then(this.describeExecution)
.then((result) => {
this.serverless.cli.consoleLog('');
logger.log('');
if (result.status === 'FAILED') {
return this.getExecutionHistory()
.then((error) => {
this.serverless.cli.consoleLog(_.merge(result, error.events[error.events.length - 1]
logger.log(_.merge(result, error.events[error.events.length - 1]
.executionFailedEventDetails));
process.exitCode = 1;
});
}

this.serverless.cli.consoleLog(result);
logger.log(result);
return BbPromise.resolve();
});
}
Expand All @@ -191,8 +197,15 @@ class ServerlessStepFunctions {
let stateMachineMessages = '';

const endpointInfo = this.endpointInfo;
message += `${chalk.yellow.underline('Serverless StepFunctions OutPuts')}\n`;
message += `${chalk.yellow('endpoints:')}`;

if (this.v3Api) {
const slsRed = chalk.hex('#fd5750');
message += `\n${slsRed('✔')} Serverless StepFunctions OutPuts\n`;
message += `${chalk.grey('endpoints:')}`;
} else {
message += `${chalk.yellow.underline('Serverless StepFunctions OutPuts')}\n`;
message += `${chalk.yellow('endpoints:')}`;
}

if (this.isStateMachines()) {
_.forEach(this.getAllStateMachines(), (stateMachineName) => {
Expand Down Expand Up @@ -225,7 +238,7 @@ class ServerlessStepFunctions {
message += stateMachineMessages;
message += '\n';

this.serverless.cli.consoleLog(message);
logger.log(message);

return message;
}
Expand Down
21 changes: 12 additions & 9 deletions lib/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const AwsProvider = require('serverless/lib/plugins/aws/provider');
const CLI = require('serverless/lib/classes/CLI');
const chalk = require('chalk');
const ServerlessStepFunctions = require('./index');
const logger = require('./utils/logger');

describe('#index', () => {
let serverless;
Expand Down Expand Up @@ -287,22 +288,24 @@ describe('#index', () => {
});

describe('#deploy()', () => {
let consoleLogStub;
let logSpy;

beforeEach(() => {
consoleLogStub = sinon.stub(serverless.cli, 'consoleLog').returns();
logger.config(serverless);
logSpy = sinon.spy(logger, 'log');
serverless.cli = { consoleLog: logSpy };
serverlessStepFunctions.endpointInfo = 'https://example.com';
});

afterEach(() => {
serverlessStepFunctions.serverless.cli.consoleLog.restore();
logSpy.restore();
});

it('should not display endpoints if http event not given', () => {
serverlessStepFunctions.serverless.service.stepFunctions = {};
const expectedMessage = '';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(false);
expect(logSpy.calledOnce).to.equal(false);
expect(message).to.equal(expectedMessage);
});

Expand All @@ -328,7 +331,7 @@ describe('#index', () => {
expectedMessage += '\n POST - https://example.com/foo/bar';
expectedMessage += '\n';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(true);
expect(logSpy.calledOnce).to.equal(true);
expect(message).to.equal(expectedMessage);
});

Expand All @@ -351,7 +354,7 @@ describe('#index', () => {
expectedMessage += '\n POST - https://example.com/foo/bar';
expectedMessage += '\n';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(true);
expect(logSpy.calledOnce).to.equal(true);
expect(message).to.equal(expectedMessage);
});

Expand All @@ -374,7 +377,7 @@ describe('#index', () => {
expectedMessage += '\n POST - https://example.com';
expectedMessage += '\n';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(true);
expect(logSpy.calledOnce).to.equal(true);
expect(message).to.equal(expectedMessage);
});

Expand All @@ -389,7 +392,7 @@ describe('#index', () => {
};
const expectedMessage = '';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(false);
expect(logSpy.calledOnce).to.equal(false);
expect(message).to.equal(expectedMessage);
});

Expand All @@ -408,7 +411,7 @@ describe('#index', () => {
};
const expectedMessage = '';
const message = serverlessStepFunctions.display();
expect(consoleLogStub.calledOnce).to.equal(false);
expect(logSpy.calledOnce).to.equal(false);
expect(message).to.equal(expectedMessage);
});
});
Expand Down
15 changes: 15 additions & 0 deletions lib/utils/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
'use strict';

class Logger {
config(serverless, v3Api) {
if (v3Api) {
this.log = v3Api.log;
} else {
this.log = serverless.cli && serverless.cli.consoleLog;
}

return this;
}
}

module.exports = new Logger();
39 changes: 39 additions & 0 deletions lib/utils/logger.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

const expect = require('chai').expect;
const sinon = require('sinon');
const Serverless = require('serverless/lib/Serverless');
const logger = require('../utils/logger');

describe('logger', () => {
let serverless;
let v3LogSpy;

beforeEach(() => {
serverless = new Serverless();
serverless.cli = { consoleLog: sinon.spy() };

v3LogSpy = sinon.spy();
});

afterEach(() => {
serverless.cli = null;
v3LogSpy = null;
});

it('should be assigned legacy logger (serverless.cli.consoleLog) if v3 log api is not supplied', () => {
const { log } = logger.config(serverless);
log('Testing purpose');

expect(serverless.cli.consoleLog.callCount).to.equal(1);
expect(v3LogSpy.callCount).to.equal(0);
});

it('should be assigned new log API if new log api is supplied', () => {
const { log } = logger.config(serverless, { log: v3LogSpy });
log('Testing purpose');

expect(serverless.cli.consoleLog.callCount).to.equal(0);
expect(v3LogSpy.callCount).to.equal(1);
});
});
Loading