This repository has been archived by the owner on Mar 9, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mike Heffner
committed
Jul 22, 2019
1 parent
374947a
commit e0f96a9
Showing
10 changed files
with
404 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ tmp/ | |
node_modules/ | ||
.clasprc.json | ||
help_dialog.html | ||
src/functions/gen/*.ts | ||
src/functions/gen/*.ts | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { RDSDbEngine } from "../models/rds_db_engine"; | ||
import { InvocationSettings } from "../settings/invocation_settings"; | ||
import { RDSPrice } from "../rds_price"; | ||
import { PriceDuration } from "../price_converter"; | ||
import { _initContext } from "../context"; | ||
import { RDSSettingsValidator } from "../settings/rds_settings_validator"; | ||
|
||
function _rds(settings: InvocationSettings, dbEngine: RDSDbEngine, instanceType: string): number { | ||
if (dbEngine === undefined || dbEngine === null) { | ||
throw `Must specify DB engine` | ||
} | ||
|
||
if (!instanceType) { | ||
throw `Must specify a DB instance type` | ||
} | ||
|
||
let [ret, msg] = new RDSSettingsValidator(settings).validate() | ||
if (!ret) { | ||
throw msg | ||
} | ||
|
||
instanceType = instanceType.toString().toLowerCase() | ||
|
||
return new RDSPrice(settings, dbEngine, instanceType).get(PriceDuration.Hourly) | ||
} | ||
|
||
export function _rds_full(dbEngine: RDSDbEngine, instanceType: string, region: string, | ||
purchaseType: string, purchaseTerm?: string | number, paymentOption?: string) { | ||
_initContext() | ||
|
||
let settingsMap = { | ||
'region': region, | ||
'purchase_type': purchaseType | ||
} | ||
|
||
if (purchaseType === "reserved") { | ||
settingsMap['purchase_term'] = purchaseTerm | ||
settingsMap['payment_option'] = paymentOption | ||
} | ||
|
||
let settings = InvocationSettings.loadFromMap(settingsMap) | ||
|
||
return _rds(settings, dbEngine, instanceType) | ||
} | ||
|
||
export function _rds_settings(settingsRange: Array<Array<string>>, dbEngine: RDSDbEngine, instanceType: string, region?: string) { | ||
_initContext() | ||
|
||
if (!settingsRange) { | ||
throw `Must specify settings range` | ||
} | ||
|
||
let overrides = {} | ||
if (region) { | ||
overrides['region'] = region | ||
} | ||
|
||
let settings = InvocationSettings.loadFromRange(settingsRange, overrides) | ||
|
||
return _rds(settings, dbEngine, instanceType) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export enum RDSDbEngine { | ||
Aurora_Mysql, | ||
Aurora_Postgresql, | ||
Mysql, | ||
Postgresql, | ||
Mariadb | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { PriceDuration } from "../price_converter"; | ||
|
||
export class RDSInstancePrice { | ||
constructor(private readonly price, private readonly isReserved: boolean) { | ||
|
||
} | ||
|
||
totalPrice(duration: PriceDuration): number { | ||
if (this.isReserved) { | ||
return parseFloat(this.price.calculatedPrice.effectiveHourlyRate.USD) | ||
} else { | ||
return parseFloat(this.price.price.USD) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
import { InvocationSettings } from "./settings/invocation_settings"; | ||
import { RDSDbEngine } from "./models/rds_db_engine"; | ||
import { PriceDuration } from "./price_converter"; | ||
import { ctxt } from "./context"; | ||
import { RDSInstancePrice } from "./models/rds_instance_price"; | ||
|
||
export class RDSPrice { | ||
constructor(private readonly settings: InvocationSettings, private readonly dbEngine: RDSDbEngine, | ||
private readonly instanceType: string) { | ||
|
||
} | ||
|
||
get(duration: PriceDuration): number { | ||
let priceData = this.loadPriceData() | ||
|
||
return priceData.totalPrice(duration) | ||
} | ||
|
||
private loadPriceData() { | ||
if (this.isReserved() && this.settings.get("purchase_term") === "3" && | ||
this.settings.get("payment_option") === "no_upfront") { | ||
throw `The No-Upfront payment option is not supported for 3 year RDS RIs` | ||
} | ||
|
||
let pricePath = Utilities.formatString("/pricing/1.0/rds/%s/%s/%sindex.json", | ||
this.dbEngineUrlParam(), this.purchaseTypeUrlParam(), this.azUrlParam()) | ||
|
||
let body = ctxt().awsDataLoader.loadPath(pricePath) | ||
|
||
let resp = JSON.parse(body) | ||
|
||
let prices = this.filterPrices(resp.prices) | ||
|
||
if (prices.length == 0) { | ||
throw `Unable to find RDS instance ${this.instanceType} for DB engine ${this.dbEngineStr()}` | ||
} | ||
|
||
if (prices.length > 1) { | ||
throw `Too many matches found for ${this.instanceType} for DB engine ${this.dbEngineStr()}` | ||
} | ||
|
||
return new RDSInstancePrice(prices[0], this.isReserved()) | ||
} | ||
|
||
private filterPrices(prices) { | ||
return prices.filter(price => { | ||
let ret = price.attributes['aws:region'] == this.settings.get('region') && | ||
price.attributes['aws:rds:term'] === this.purchaseTypeAttr() && | ||
price.attributes['aws:rds:deploymentOption'] === 'Single-AZ' && | ||
price.attributes['aws:productFamily'] === 'Database Instance' && | ||
price.attributes['aws:rds:instanceType'] === this.instanceType | ||
if (!ret || !this.isReserved()) { | ||
return ret | ||
} | ||
|
||
return price.attributes['aws:offerTermLeaseLength'] === this.purchaseTermAttr() && | ||
// There are no convertible RDS RIs | ||
price.attributes['aws:offerTermOfferingClass'] === 'standard' && | ||
price.attributes['aws:offerTermPurchaseOption'] === this.paymentOptionAttr() | ||
}) | ||
} | ||
|
||
private isReserved(): boolean { | ||
return this.settings.get('purchase_type') === 'reserved' | ||
} | ||
|
||
private dbEngineUrlParam(): string { | ||
switch (this.dbEngine) { | ||
case RDSDbEngine.Aurora_Mysql: { | ||
return "aurora/mysql" | ||
} | ||
case RDSDbEngine.Aurora_Postgresql: { | ||
return "aurora/postgresql" | ||
} | ||
case RDSDbEngine.Mysql: { | ||
return "mysql" | ||
} | ||
case RDSDbEngine.Mariadb: { | ||
return "mariadb" | ||
} | ||
case RDSDbEngine.Postgresql: { | ||
return "postgresql" | ||
} | ||
} | ||
} | ||
|
||
private azUrlParam(): string { | ||
if (this.isAurora()) { | ||
return "" | ||
} else { | ||
return "single-az/" | ||
} | ||
} | ||
|
||
private isAurora(): boolean { | ||
return this.dbEngine === RDSDbEngine.Aurora_Mysql || this.dbEngine === RDSDbEngine.Aurora_Postgresql | ||
} | ||
|
||
private purchaseTypeUrlParam(): string { | ||
return this.isReserved() ? "reserved-instance" : "ondemand" | ||
} | ||
|
||
private purchaseTypeAttr(): string { | ||
return this.isReserved() ? "reserved" : "on-demand" | ||
} | ||
|
||
private purchaseTermAttr(): string { | ||
return Utilities.formatString("%syr", this.settings.get('purchase_term')) | ||
} | ||
|
||
private paymentOptionAttr(): string { | ||
switch(this.settings.get('payment_option')) { | ||
case 'no_upfront': { | ||
return 'No Upfront' | ||
} | ||
case 'partial_upfront': { | ||
return 'Partial Upfront' | ||
} | ||
case 'all_upfront': { | ||
return 'All Upfront' | ||
} | ||
default: { | ||
throw `Unknown payment option ${this.settings.get('payment_option')}` | ||
} | ||
} | ||
} | ||
|
||
private dbEngineStr(): string { | ||
return RDSDbEngine[this.dbEngine] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { SettingsValidator } from "./_settings_validator"; | ||
import { InvocationSettings } from "./invocation_settings"; | ||
import { SettingKeys } from "./setting_keys"; | ||
|
||
export class RDSSettingsValidator extends SettingsValidator { | ||
constructor(private readonly settings: InvocationSettings) { | ||
super() | ||
} | ||
|
||
validate(): [boolean, string] { | ||
let reqd = [SettingKeys.Region, SettingKeys.PurchaseType] | ||
|
||
let [ret, msg] = this.verifyOptions(reqd) | ||
if (!ret) { | ||
return [ret, msg] | ||
} | ||
|
||
let riOpts = [SettingKeys.PurchaseTerm, SettingKeys.PaymentOption] | ||
if (this.get(SettingKeys.PurchaseType) === "reserved") { | ||
[ret, msg] = this.verifyOptions(riOpts) | ||
if (!ret) { | ||
return [ret, msg] | ||
} | ||
} | ||
|
||
return [true, null] | ||
} | ||
|
||
protected get(key: string): string { | ||
return this.settings.get(key) | ||
} | ||
|
||
} |
Oops, something went wrong.