Skip to content

Commit

Permalink
Merge pull request #81 from gino247/80-base-price-selection-step-func…
Browse files Browse the repository at this point in the history
…tions

Implement regional base price selection for AWS Step Functions
  • Loading branch information
alexcasalboni committed Jun 8, 2020
2 parents e774724 + 3f44735 commit 3bc6308
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 14 deletions.
3 changes: 2 additions & 1 deletion lambda/executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ module.exports.handler = async(event, context) => {
}

// get base cost
const baseCost = utils.baseCostForRegion(utils.regionFromARN(lambdaARN));
const prices = JSON.parse(process.env.baseCosts);
const baseCost = utils.baseCostForRegion(prices, utils.regionFromARN(lambdaARN));

return computeStatistics(baseCost, results, value);
};
Expand Down
20 changes: 12 additions & 8 deletions lambda/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ const AWS = require('aws-sdk');
const utils = module.exports;

// cost of 6+N state transitions (AWS Step Functions)
module.exports.stepFunctionsCost = (nPower) => +(0.000025 * (6 + nPower)).toFixed(5);
module.exports.stepFunctionsCost = (nPower) => +(this.stepFunctionsBaseCost() * (6 + nPower)).toFixed(5);

module.exports.stepFunctionsBaseCost = () => {
const prices = JSON.parse(process.env.sfCosts);
// assume the AWS_REGION variable is set for this function
return this.baseCostForRegion(prices, process.env.AWS_REGION);
};

module.exports.allPowerValues = () => {
const increment = 64;
Expand Down Expand Up @@ -311,15 +316,14 @@ module.exports.buildVisualizationURL = (stats, baseURL) => {
};

/**
* Using the prices supplied via prices.json,
* Using the prices supplied,
* to figure what the base price is for the
* supplied lambda's region
*/
module.exports.baseCostForRegion = (region) => {
const prices = JSON.parse(process.env.baseCosts);
if (prices[region]) {
return prices[region];
module.exports.baseCostForRegion = (priceMap, region) => {
if (priceMap[region]) {
return priceMap[region];
}
console.log(region + ' not found in base price map, using default: ' + prices['default']);
return prices['default'];
console.log(region + ' not found in base price map, using default: ' + priceMap['default']);
return priceMap['default'];
};
1 change: 1 addition & 0 deletions template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Globals:
defaultPowerValues: !Join [ ",", !Ref PowerValues ]
minRAM: '128'
baseCosts: '{"ap-east-1":2.865e-7,"af-south-1":2.763e-7,"me-south-1":2.583e-7,"eu-south-1":2.440e-7,"default":2.083e-7}'
sfCosts: '{"default": 0.000025,"us-gov-west-1": 0.00003,"ap-northeast-2": 0.0000271,"eu-south-1": 0.00002625,"af-south-1": 0.00002975,"us-west-1": 0.0000279,"eu-west-3": 0.0000297,"ap-east-1": 0.0000275,"me-south-1": 0.0000275,"ap-south-1": 0.0000285,"us-gov-east-1": 0.00003,"sa-east-1": 0.0000375}'
visualizationURL: !Ref visualizationURL

Resources:
Expand Down
3 changes: 2 additions & 1 deletion test/unit/test-lambda.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ AWS.mock('Lambda', 'invoke', {});
const powerValues = [128, 256, 512, 1024];
process.env.defaultPowerValues = powerValues.join(',');
process.env.minRAM = 128;
process.env.baseCosts = '{"eu-west-1":0.00000003, "af-south-1": 0.0000002763, "default": 0.00000028}';
const fakeContext = {};

// variables used during tests
Expand Down Expand Up @@ -84,7 +85,7 @@ describe('Lambda Functions', async() => {
return arn;
});
sandBox.stub(utils, 'baseCostForRegion')
.callsFake((region) => {
.callsFake((_priceMap, region) => {
return region === 'af-south-1' ? 0.0000002763 : 0.0000002083;
});
getLambdaAliasStub = sandBox.stub(utils, 'getLambdaAlias')
Expand Down
46 changes: 42 additions & 4 deletions test/unit/test-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ const expect = require('expect.js');

// const AWS = require('aws-sdk');
var AWS = require('aws-sdk-mock');

process.env.sfCosts = `{"us-gov-west-1": 0.00003,"eu-north-1": 0.000025,
"eu-central-1": 0.000025,"us-east-1": 0.000025,"ap-northeast-1": 0.000025,
"ap-northeast-2": 0.0000271,"eu-south-1": 0.00002625,"af-south-1": 0.00002975,
"us-west-1": 0.0000279,"eu-west-3": 0.0000297,"ap-southeast-2": 0.000025,
"ap-east-1": 0.0000275,"eu-west-2": 0.000025,"me-south-1": 0.0000275,
"us-east-2": 0.000025,"ap-south-1": 0.0000285,"ap-southeast-1": 0.000025,
"us-gov-east-1": 0.00003,"ca-central-1": 0.000025,"eu-west-1": 0.000025,
"us-west-2": 0.000025,"sa-east-1": 0.0000375}`;

process.env.AWS_REGION = 'af-south-1';

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

// AWS SDK mocks
Expand Down Expand Up @@ -54,6 +66,32 @@ describe('Lambda Utils', () => {
});
});

describe('stepFunctionsCost', () => {
it('should return expected step base cost', () => {
process.env.sfCosts = '{"us-gov-west-1": 0.00003, "default": 0.000025}';
process.env.AWS_REGION = 'us-gov-west-1';
const result = utils.stepFunctionsBaseCost();
expect(result).to.be.equal(0.00003);
});
it('should return default step base cost', () => {
process.env.sfCosts = '{"us-gov-west-1": 0.00003, "default": 0.000025}';
process.env.AWS_REGION = 'af-south-1';
const result = utils.stepFunctionsBaseCost();
expect(result).to.be.equal(0.000025);
});
});

describe('stepFunctionsBaseCost', () => {
it('should return expected step total cost', () => {
process.env.sfCosts = '{"us-gov-west-1": 0.00003, "default": 0.000025}';
process.env.AWS_REGION = 'us-gov-west-1';
const nPower = 10;
const expectedCost = +(0.00003 * (6 + nPower)).toFixed(5);
const result = utils.stepFunctionsCost(nPower);
expect(result).to.be.equal(expectedCost);
});
});

describe('getLambdaPower', () => {
it('should return the memory value', async() => {
const value = await getLambdaPower('arn:aws:lambda:us-east-1:XXX:function:YYY');
Expand Down Expand Up @@ -262,19 +300,19 @@ describe('Lambda Utils', () => {
});

describe('baseCostForRegion', () => {
process.env.baseCosts = JSON.stringify({
const prices = {
'ap-east-1': 0.0000002865,
'af-south-1': 0.0000002763,
'me-south-1': 0.0000002583,
default: 0.0000002083,
});
};

it('should return ap-east-1 base price', () => {
expect(utils.baseCostForRegion('ap-east-1')).to.be(0.0000002865);
expect(utils.baseCostForRegion(prices, 'ap-east-1')).to.be(0.0000002865);
});

it('should return default base price', () => {
expect(utils.baseCostForRegion('eu-west-1')).to.be(0.0000002083);
expect(utils.baseCostForRegion(prices, 'eu-west-1')).to.be(0.0000002083);
});
});
});

0 comments on commit 3bc6308

Please sign in to comment.