Skip to content

Commit

Permalink
Implement top-level enabled support
Browse files Browse the repository at this point in the history
  • Loading branch information
eoinsha committed Oct 25, 2021
1 parent 38e0285 commit c942fac
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 98 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ You can customize the configuration:
Top-level plugin configuration can be specified in the `custom``slicWatch` section of `serverless.yml`

- The `topic` may be optionally provided as an SNS Topic destination for all alarms. If you omit the topic, alarms are still created but are not sent to any destination.
- Alarms or dashboards can be disabled at any level in the configuration by adding `enabled: false`
- Alarms or dashboards can be disabled at any level in the configuration by adding `enabled: false`. You can even disable all plugin functionality by specifying `enabled: false` at the top-level plugin configuration.

Supported options along with their defaults are shown below.

Expand All @@ -162,6 +162,7 @@ Supported options along with their defaults are shown below.
custom:
slicWatch:
topic: SNS_TOPIC_ARN # This is optional but recommended so you can receive alarms via email, Slack, etc.
enabled: true

alarms:
enabled: true
Expand Down
3 changes: 2 additions & 1 deletion serverless-plugin/config-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ const slicWatchSchema = {
properties: {
alarms: alarmsSchema,
dashboard: dashboardSchema,
topicArn: { type: 'string' }
topicArn: { type: 'string' },
enabled: { type: 'boolean' }
},
required: [],
additionalProperties: false
Expand Down
4 changes: 4 additions & 0 deletions serverless-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class ServerlessPlugin {

const alarmActions = []

if (slicWatchConfig.enabled === false) {
return
}

if (slicWatchConfig.topicArn) {
alarmActions.push(slicWatchConfig.topicArn)
}
Expand Down
221 changes: 125 additions & 96 deletions serverless-plugin/tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const testCfTemplate = {
}
}

const testState = {}
let testState = {}

const ServerlessPlugin = proxyrequire('../index', {
'./dashboard': () => {
Expand Down Expand Up @@ -77,120 +77,149 @@ const mockServerless = {
}
}

test('plugin fails if provider is not aws', (t) => {
t.throws(() => new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
provider: { name: 'azure' }
}
}))
t.end()
})

test('finalizeHook adds dashboard and alarms', (t) => {
const plugin = new ServerlessPlugin(mockServerless, {})
plugin.finalizeHook()

t.equal(testState.addDashboardCfTemplate.getSourceObject(), testCfTemplate)
t.equal(testState.addAlarmsCfTemplate.getSourceObject(), testCfTemplate)
t.end()
})

test('Plugin succeeds with no custom section', (t) => {
const plugin = new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
custom: undefined
}
test('index', t => {
t.beforeEach(t => {
testState = {}
})
plugin.finalizeHook()
t.end()
})

test('Plugin registers the configuration schema', (t) => {
const testData = {}
// eslint-disable-next-line no-new
new ServerlessPlugin({
...mockServerless,
configSchemaHandler: {
defineCustomProperties: (schema) => {
testData.schema = schema
},
defineFunctionProperties: (provider, schema) => {
testData.functionSchema = schema
t.test('plugin fails if provider is not aws', (t) => {
t.throws(() => new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
provider: { name: 'azure' }
}
}
}))
t.end()
})
t.equal(typeof testData.schema, 'object')
t.end()
})

test('Plugin execution succeeds with no slicWatch config', (t) => {
const plugin = new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
custom: {}
}
t.test('finalizeHook adds dashboard and alarms', (t) => {
const plugin = new ServerlessPlugin(mockServerless, {})
plugin.finalizeHook()

t.equal(testState.addDashboardCfTemplate.getSourceObject(), testCfTemplate)
t.equal(testState.addAlarmsCfTemplate.getSourceObject(), testCfTemplate)
t.end()
})
plugin.finalizeHook()
t.end()
})

test('Plugin execution succeeds if no SNS Topic is provided', (t) => {
const serviceYmlWithoutTopic = _.cloneDeep(slsYaml)
delete serviceYmlWithoutTopic.custom.slicWatch.topicArn
const plugin = new ServerlessPlugin(
{
t.test('Plugin succeeds with no custom section', (t) => {
const plugin = new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
...serviceYmlWithoutTopic
custom: undefined
}
},
{}
)
plugin.finalizeHook()
t.end()
})
})
plugin.finalizeHook()
t.end()
})

test('Plugin execution succeeds if resources are provided', (t) => {
const plugin = new ServerlessPlugin(
{
t.test('Plugin registers the configuration schema', (t) => {
const testData = {}
// eslint-disable-next-line no-new
new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
resources: {
Resources: {
queue: {
Type: 'AWS::SQS::Queue',
Properties: {}
}
}
configSchemaHandler: {
defineCustomProperties: (schema) => {
testData.schema = schema
},
defineFunctionProperties: (provider, schema) => {
testData.functionSchema = schema
}
}
},
{}
)
plugin.finalizeHook()
t.end()
})
})
t.equal(typeof testData.schema, 'object')
t.end()
})

test('Plugin execution fails if an invalid SLIC Watch is provided', (t) => {
const serviceYmlWithBadProperty = _.cloneDeep(slsYaml)
serviceYmlWithBadProperty.custom.slicWatch.topicArrrrn = 'pirateTopic'
const plugin = new ServerlessPlugin(
{
t.test('Plugin execution succeeds with no slicWatch config', (t) => {
const plugin = new ServerlessPlugin({
...mockServerless,
service: {
...mockServerless.service,
...serviceYmlWithBadProperty
custom: {}
}
},
{}
)
t.throws(() => plugin.finalizeHook(), ServerlessError)
})
plugin.finalizeHook()
t.ok(testState.alarmsCalled)
t.end()
})

t.test('Plugin execution succeeds if no SNS Topic is provided', (t) => {
const serviceYmlWithoutTopic = _.cloneDeep(slsYaml)
delete serviceYmlWithoutTopic.custom.slicWatch.topicArn
const plugin = new ServerlessPlugin(
{
...mockServerless,
service: {
...mockServerless.service,
...serviceYmlWithoutTopic
}
},
{}
)
plugin.finalizeHook()
t.ok(testState.alarmsCalled)
t.end()
})

t.test('Plugin execution succeeds if resources are provided', (t) => {
const plugin = new ServerlessPlugin(
{
...mockServerless,
service: {
...mockServerless.service,
resources: {
Resources: {
queue: {
Type: 'AWS::SQS::Queue',
Properties: {}
}
}
}
}
},
{}
)
plugin.finalizeHook()
t.ok(testState.alarmsCalled)
t.end()
})

t.test('Plugin execution fails if an invalid SLIC Watch config is provided', (t) => {
const serviceYmlWithBadProperty = _.cloneDeep(slsYaml)
serviceYmlWithBadProperty.custom.slicWatch.topicArrrrn = 'pirateTopic'
const plugin = new ServerlessPlugin(
{
...mockServerless,
service: {
...mockServerless.service,
...serviceYmlWithBadProperty
}
},
{}
)
t.throws(() => plugin.finalizeHook(), ServerlessError)
t.end()
})

t.test('Plugin skips SLIC Watch if top-level enabled==false', (t) => {
const serviceYmlWithDisabled = _.cloneDeep(slsYaml)
serviceYmlWithDisabled.custom.slicWatch.enabled = false
const plugin = new ServerlessPlugin(
{
...mockServerless,
service: {
...mockServerless.service,
...serviceYmlWithDisabled
}
},
{}
)
plugin.finalizeHook()
t.notOk(testState.alarmsCalled)
t.end()
})

t.end()
})

0 comments on commit c942fac

Please sign in to comment.