Skip to content

Commit

Permalink
Include serviceName in generated names (#15)
Browse files Browse the repository at this point in the history
* Prepare everything to include serviceName in generated names

* Use service name to generate names

* Pass service name to Role, Policy and Target
  • Loading branch information
sbstjn authored Jul 31, 2017
1 parent b014bca commit a2a472c
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 58 deletions.
20 changes: 12 additions & 8 deletions src/aws/names.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ function truncate (input) {
return input.length <= 64 ? input : input.substr(0, 32) + md5(input)
}

function policyScale (table, read, index, stage) {
function policyScale (service, table, read, index, stage) {
return clean(
util.format(
'Table%sScalingPolicy-%s%s%s',
'%sTable%sScalingPolicy-%s%s%s',
service || '',
read ? 'Read' : 'Write',
table,
index || '',
Expand All @@ -21,10 +22,11 @@ function policyScale (table, read, index, stage) {
)
}

function policyRole (table, index, stage) {
function policyRole (service, table, index, stage) {
return clean(
util.format(
'DynamoDBAutoscalePolicy-%s%s%s',
'%sDynamoDBAutoscalePolicy-%s%s%s',
service || '',
table,
index || '',
stage || ''
Expand All @@ -40,10 +42,11 @@ function dimension (read, index) {
)
}

function target (table, read, index, stage) {
function target (service, table, read, index, stage) {
return clean(
util.format(
'AutoScalingTarget%s-%s%s%s',
'%sAutoScalingTarget%s-%s%s%s',
service || '',
read ? 'Read' : 'Write',
table,
index || '',
Expand All @@ -61,10 +64,11 @@ function metric (read) {
)
}

function role (table, index, stage) {
function role (service, table, index, stage) {
return clean(
util.format(
'DynamoDBAutoscaleRole-%s%s%s',
'%sDynamoDBAutoscaleRole-%s%s%s',
service || '',
table,
index || '',
stage || ''
Expand Down
11 changes: 6 additions & 5 deletions src/aws/policy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const names = require('./names')

class Policy {
constructor (table, value, read, scaleIn, scaleOut, index, stage) {
constructor (service, table, value, read, scaleIn, scaleOut, index, stage) {
this.service = service
this.table = table
this.index = index
this.stage = stage
Expand All @@ -20,13 +21,13 @@ class Policy {

toJSON () {
return {
[names.policyScale(this.table, this.read, this.index, this.stage)]: {
[names.policyScale(this.service, this.table, this.read, this.index, this.stage)]: {
'Type': 'AWS::ApplicationAutoScaling::ScalingPolicy',
'DependsOn': [ this.table, names.target(this.table, this.read, this.index, this.stage) ].concat(this.dependencies),
'DependsOn': [ this.table, names.target(this.service, this.table, this.read, this.index, this.stage) ].concat(this.dependencies),
'Properties': {
'PolicyName': names.policyScale(this.table, this.read, this.index, this.stage),
'PolicyName': names.policyScale(this.service, this.table, this.read, this.index, this.stage),
'PolicyType': 'TargetTrackingScaling',
'ScalingTargetId': { 'Ref': names.target(this.table, this.read, this.index, this.stage) },
'ScalingTargetId': { 'Ref': names.target(this.service, this.table, this.read, this.index, this.stage) },
'TargetTrackingScalingPolicyConfiguration': {
'PredefinedMetricSpecification': {
'PredefinedMetricType': names.metric(this.read)
Expand Down
9 changes: 5 additions & 4 deletions src/aws/role.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const names = require('./names')

class Role {
constructor (table, index, stage) {
constructor (service, table, index, stage) {
this.service = service
this.table = table
this.index = index
this.stage = stage
Expand All @@ -16,11 +17,11 @@ class Role {

toJSON () {
return {
[names.role(this.table, this.index, this.stage)]: {
[names.role(this.service, this.table, this.index, this.stage)]: {
'Type': 'AWS::IAM::Role',
'DependsOn': [ this.table ].concat(this.dependencies),
'Properties': {
'RoleName': names.role(this.table, this.index, this.stage),
'RoleName': names.role(this.service, this.table, this.index, this.stage),
'AssumeRolePolicyDocument': {
'Version': '2012-10-17',
'Statement': [
Expand All @@ -35,7 +36,7 @@ class Role {
},
'Policies': [
{
'PolicyName': names.policyRole(this.table, this.index, this.stage),
'PolicyName': names.policyRole(this.service, this.table, this.index, this.stage),
'PolicyDocument': {
'Version': '2012-10-17',
'Statement': [
Expand Down
9 changes: 5 additions & 4 deletions src/aws/target.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const names = require('./names')

class Target {
constructor (table, min, max, read, index, stage) {
constructor (service, table, min, max, read, index, stage) {
this.service = service
this.table = table
this.index = index
this.stage = stage
Expand All @@ -25,14 +26,14 @@ class Target {
}

return {
[names.target(this.table, this.read, this.index, this.stage)]: {
[names.target(this.service, this.table, this.read, this.index, this.stage)]: {
'Type': 'AWS::ApplicationAutoScaling::ScalableTarget',
'DependsOn': [ this.table, names.role(this.table, this.index, this.stage) ].concat(this.dependencies),
'DependsOn': [ this.table, names.role(this.service, this.table, this.index, this.stage) ].concat(this.dependencies),
'Properties': {
'MaxCapacity': this.max,
'MinCapacity': this.min,
'ResourceId': { 'Fn::Join': [ '', resource ] },
'RoleARN': { 'Fn::GetAtt': [ names.role(this.table, this.index, this.stage), 'Arn' ] },
'RoleARN': { 'Fn::GetAtt': [ names.role(this.service, this.table, this.index, this.stage), 'Arn' ] },
'ScalableDimension': names.dimension(this.read, this.index),
'ServiceNamespace': 'dynamodb'
}
Expand Down
20 changes: 15 additions & 5 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ class Plugin {
return this.serverless.getProvider('aws').getStage()
}

/**
* Get the current service name
*
* @return {string}
*/
getServiceName () {
return this.serverless.service.getServiceName()
}

/**
* Validate the request and check if configuration is available
*/
Expand Down Expand Up @@ -81,6 +90,7 @@ class Plugin {
*/
resources (table, index, config) {
const resources = []
const service = this.getServiceName()
const stage = this.getStage()
const data = this.defaults(config)

Expand All @@ -90,23 +100,23 @@ class Plugin {
)

// Add role to manage Auto Scaling policies
resources.push(new Role(table, index, stage))
resources.push(new Role(service, table, index, stage))

// Only add Auto Scaling for read capacity if configuration set is available
if (config.read) {
resources.push(
// ScaleIn/ScaleOut values are fix to 60% usage
new Policy(table, data.read.usage, true, 60, 60, index, stage),
new Target(table, data.read.minimum, data.read.maximum, true, index, stage)
new Policy(service, table, data.read.usage, true, 60, 60, index, stage),
new Target(service, table, data.read.minimum, data.read.maximum, true, index, stage)
)
}

// Only add Auto Scaling for write capacity if configuration set is available
if (config.write) {
resources.push(
// ScaleIn/ScaleOut values are fix to 60% usage
new Policy(table, data.write.usage, false, 60, 60, index, stage),
new Target(table, data.write.minimum, data.write.maximum, false, index, stage)
new Policy(service, table, data.write.usage, false, 60, 60, index, stage),
new Target(service, table, data.write.minimum, data.write.maximum, false, index, stage)
)
}

Expand Down
14 changes: 7 additions & 7 deletions test/aws/names.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ describe('Clean', () => {

describe('Names', () => {
it('creates name for Role', () => {
expect(names.role('test-with-invalid-characters')).toBe('DynamoDBAutoscaleRoletestwithinvalidcharacters')
expect(names.role('service', 'test-with-invalid-characters')).toBe('serviceDynamoDBAutoscaleRoletestwithinvalidcharacters')
})

it('creates name for Role with index and stage', () => {
expect(names.role('test-with-invalid-characters', 'index', 'stage')).toBe('DynamoDBAutoscaleRoletestwithinvalidcharactersindexstage')
expect(names.role('service', 'test-with-invalid-characters', 'index', 'stage')).toBe('serviceDynamoDBAutoscaleRoletestwithinvalidcharactersindexstage')
})

it('creates name for Metric (read)', () => {
Expand All @@ -36,22 +36,22 @@ describe('Names', () => {
})

it('creates name for PolicyRole', () => {
expect(names.policyRole('test-with-invalid-characters')).toBe('DynamoDBAutoscalePolicytestwithinvalidcharacters')
expect(names.policyRole('', 'test-with-invalid-characters')).toBe('DynamoDBAutoscalePolicytestwithinvalidcharacters')
})

it('creates name for PolicyScale (read)', () => {
expect(names.policyScale('test-with-invalid-characters', true)).toBe('TableReadScalingPolicytestwithinvalidcharacters')
expect(names.policyScale('', 'test-with-invalid-characters', true)).toBe('TableReadScalingPolicytestwithinvalidcharacters')
})

it('creates name for PolicyScale (write)', () => {
expect(names.policyScale('test-with-invalid-characters', false)).toBe('TableWriteScalingPolicytestwithinvalidcharacters')
expect(names.policyScale('', 'test-with-invalid-characters', false)).toBe('TableWriteScalingPolicytestwithinvalidcharacters')
})

it('creates name for Target (read)', () => {
expect(names.target('test-with-invalid-characters', true)).toBe('AutoScalingTargetReadtestwithinvalidcharacters')
expect(names.target('', 'test-with-invalid-characters', true)).toBe('AutoScalingTargetReadtestwithinvalidcharacters')
})

it('creates name for Target (write)', () => {
expect(names.target('test-with-invalid-characters', false)).toBe('AutoScalingTargetWritetestwithinvalidcharacters')
expect(names.target('', 'test-with-invalid-characters', false)).toBe('AutoScalingTargetWritetestwithinvalidcharacters')
})
})
20 changes: 10 additions & 10 deletions test/aws/policy.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ const Policy = require('../../src/aws/policy')

describe('Policy', () => {
it('creates CF resource for read capacity', () => {
const p = new Policy('my-table-name', 0.75, true, 60, 70)
const p = new Policy('', 'my-table-name', 0.75, true, 60, 70)
const j = p.toJSON()

expect(j).toHaveProperty(names.policyScale('my-table-name', true))
expect(j).toHaveProperty(names.policyScale('', 'my-table-name', true))

const d = j[names.policyScale('my-table-name', true)]
const d = j[names.policyScale('', 'my-table-name', true)]

expect(d).toHaveProperty('Type', 'AWS::ApplicationAutoScaling::ScalingPolicy')
expect(d).toHaveProperty('Properties.PolicyName', names.policyScale('my-table-name', true))
expect(d).toHaveProperty('Properties.PolicyName', names.policyScale('', 'my-table-name', true))
expect(d).toHaveProperty('Properties.PolicyType', 'TargetTrackingScaling')
expect(d).toHaveProperty('Properties.ScalingTargetId', { 'Ref': names.target('my-table-name', true) })
expect(d).toHaveProperty('Properties.ScalingTargetId', { 'Ref': names.target('', 'my-table-name', true) })
expect(d).toHaveProperty('Properties.TargetTrackingScalingPolicyConfiguration.PredefinedMetricSpecification.PredefinedMetricType', names.metric(true))

const c = d.Properties.TargetTrackingScalingPolicyConfiguration
Expand All @@ -24,17 +24,17 @@ describe('Policy', () => {
})

it('creates CF resource for write capacity', () => {
const p = new Policy('my-table-name', 0.15, false, 60, 70)
const p = new Policy('', 'my-table-name', 0.15, false, 60, 70)
const j = p.toJSON()

expect(j).toHaveProperty(names.policyScale('my-table-name', false))
expect(j).toHaveProperty(names.policyScale('', 'my-table-name', false))

const d = j[names.policyScale('my-table-name', false)]
const d = j[names.policyScale('', 'my-table-name', false)]

expect(d).toHaveProperty('Type', 'AWS::ApplicationAutoScaling::ScalingPolicy')
expect(d).toHaveProperty('Properties.PolicyName', names.policyScale('my-table-name', false))
expect(d).toHaveProperty('Properties.PolicyName', names.policyScale('', 'my-table-name', false))
expect(d).toHaveProperty('Properties.PolicyType', 'TargetTrackingScaling')
expect(d).toHaveProperty('Properties.ScalingTargetId', { 'Ref': names.target('my-table-name', false) })
expect(d).toHaveProperty('Properties.ScalingTargetId', { 'Ref': names.target('', 'my-table-name', false) })
expect(d).toHaveProperty('Properties.TargetTrackingScalingPolicyConfiguration.PredefinedMetricSpecification.PredefinedMetricType', names.metric(false))

const c = d.Properties.TargetTrackingScalingPolicyConfiguration
Expand Down
16 changes: 9 additions & 7 deletions test/aws/role.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ const Role = require('../../src/aws/role')

describe('Role', () => {
it('creates CF resource', () => {
const r = new Role('my-table-name')
const r = new Role('', 'my-table-name')
const j = r.toJSON()

expect(j).toHaveProperty(names.role('my-table-name'))
expect(j).toHaveProperty(names.role('', 'my-table-name'))

const d = j[names.role('my-table-name')]
const d = j[names.role('', 'my-table-name')]

expect(d).toHaveProperty('Type', 'AWS::IAM::Role')
expect(d).toHaveProperty('Properties.RoleName', 'DynamoDBAutoscaleRolemytablename')
})

it('truncates role name if needed', () => {
const r = new Role('my-table-name-with-some-extra-long-string-information-added-to-the-end')
const r = new Role('service', 'my-table-name-with-some-extra-long-string-information-added-to-the-end')
const j = r.toJSON()

expect(j).toHaveProperty(names.role('my-table-name-with-some-extra-long-string-information-added-to-the-end'))
const n = 'serviceDynamoDBAutoscaleRolemyta941c3679150ea9fa409846dd3c00ec13'

const d = j[names.role('my-table-name-with-some-extra-long-string-information-added-to-the-end')]
expect(j).toHaveProperty(n)

const d = j[n]

expect(d.Properties.RoleName.length).toBe(64)
expect(d).toHaveProperty('Properties.RoleName', 'DynamoDBAutoscaleRolemytablename0cde19b63d7d9f9b35cd41a979fd72a2')
expect(d).toHaveProperty('Properties.RoleName', n)
})
})
16 changes: 8 additions & 8 deletions test/aws/target.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,36 @@ const Target = require('../../src/aws/target')

describe('Target', () => {
it('creates CF resource for read capacity', () => {
const t = new Target('my-table-name', 4, 100, true)
const t = new Target('', 'my-table-name', 4, 100, true)
const j = t.toJSON()

expect(j).toHaveProperty(names.target('my-table-name', true))
expect(j).toHaveProperty(names.target('', 'my-table-name', true))

const d = j[names.target('my-table-name', true)]
const d = j[names.target('', 'my-table-name', true)]

expect(d).toHaveProperty('Type', 'AWS::ApplicationAutoScaling::ScalableTarget')
expect(d).toHaveProperty('Properties.MinCapacity', 4)
expect(d).toHaveProperty('Properties.MaxCapacity', 100)
expect(d).toHaveProperty('Properties.ScalableDimension', names.dimension(true))
expect(d).toHaveProperty('Properties.ServiceNamespace', 'dynamodb')
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt')
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt', [ names.role('my-table-name'), 'Arn' ])
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt', [ names.role('', 'my-table-name'), 'Arn' ])
})

it('creates CF resource for write capacity', () => {
const t = new Target('my-table-name', 100, 2000, false)
const t = new Target('', 'my-table-name', 100, 2000, false)
const j = t.toJSON()

expect(j).toHaveProperty(names.target('my-table-name', false))
expect(j).toHaveProperty(names.target('', 'my-table-name', false))

const d = j[names.target('my-table-name', false)]
const d = j[names.target('', 'my-table-name', false)]

expect(d).toHaveProperty('Type', 'AWS::ApplicationAutoScaling::ScalableTarget')
expect(d).toHaveProperty('Properties.MinCapacity', 100)
expect(d).toHaveProperty('Properties.MaxCapacity', 2000)
expect(d).toHaveProperty('Properties.ScalableDimension', names.dimension(false))
expect(d).toHaveProperty('Properties.ServiceNamespace', 'dynamodb')
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt')
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt', [ names.role('my-table-name'), 'Arn' ])
expect(d).toHaveProperty('Properties.RoleARN.Fn::GetAtt', [ names.role('', 'my-table-name'), 'Arn' ])
})
})

0 comments on commit a2a472c

Please sign in to comment.