diff --git a/package.json b/package.json index f8610175..39b37b98 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "@istanbuljs/nyc-config-typescript": "^0.1.3", "@types/jest": "^24.0.18", "@types/node": "^12.7.5", + "@types/prettier": "^1.18.3", "@types/table": "^4.0.7", "@types/yargs": "^13.0.3", "@typescript-eslint/eslint-plugin": "^2.3.0", diff --git a/src/ec2-types.ts b/src/ec2-types.ts index 179f23f4..da3308b1 100644 --- a/src/ec2-types.ts +++ b/src/ec2-types.ts @@ -1,21 +1,9 @@ export const instanceFamilies = [ 'a1', - 'c1', - 'c3', - 'c4', - 'c5', - 'c5d', - 'c5n', - 'd2', - 'f1', - 'g2', - 'g3', - 'g3s', - 'g4dn', - 'h1', - 'i2', - 'i3', - 'i3en', + 't1', + 't2', + 't3', + 't3a', 'm1', 'm2', 'm3', @@ -26,9 +14,12 @@ export const instanceFamilies = [ 'm5d', 'm5dn', 'm5n', - 'p2', - 'p3', - 'p3dn', + 'c1', + 'c3', + 'c4', + 'c5', + 'c5d', + 'c5n', 'r3', 'r4', 'r5', @@ -37,290 +28,304 @@ export const instanceFamilies = [ 'r5d', 'r5dn', 'r5n', - 't1', - 't2', - 't3', - 't3a', 'x1', 'x1e', 'z1d', + 'd2', + 'h1', + 'i2', + 'i3', + 'i3en', + 'f1', + 'g2', + 'g3', + 'g3s', + 'g4dn', + 'p2', + 'p3', + 'p3dn', ] as const; + export type InstanceFamily = typeof instanceFamilies[number]; + export const instanceSizes = [ - '10xlarge', - '12xlarge', - '16xlarge', - '18xlarge', - '24xlarge', + 'nano', + 'micro', + 'small', + 'medium', + 'large', + 'xlarge', '2xlarge', - '32xlarge', '3xlarge', '4xlarge', '6xlarge', '8xlarge', '9xlarge', - 'large', - 'medium', + '10xlarge', + '12xlarge', + '16xlarge', + '18xlarge', + '24xlarge', + '32xlarge', 'metal', - 'micro', - 'nano', - 'small', - 'xlarge', ] as const; + export type InstanceSize = typeof instanceSizes[number]; + export const allInstances = [ + 'a1.medium', + 'a1.large', + 'a1.xlarge', 'a1.2xlarge', 'a1.4xlarge', - 'a1.large', - 'a1.medium', 'a1.metal', - 'a1.xlarge', - 'c1.medium', - 'c1.xlarge', - 'c3.2xlarge', - 'c3.4xlarge', - 'c3.8xlarge', - 'c3.large', - 'c3.xlarge', - 'c4.2xlarge', - 'c4.4xlarge', - 'c4.8xlarge', - 'c4.large', - 'c4.xlarge', - 'c5.12xlarge', - 'c5.18xlarge', - 'c5.24xlarge', - 'c5.2xlarge', - 'c5.4xlarge', - 'c5.9xlarge', - 'c5.large', - 'c5.metal', - 'c5.xlarge', - 'c5d.18xlarge', - 'c5d.2xlarge', - 'c5d.4xlarge', - 'c5d.9xlarge', - 'c5d.large', - 'c5d.xlarge', - 'c5n.18xlarge', - 'c5n.2xlarge', - 'c5n.4xlarge', - 'c5n.9xlarge', - 'c5n.large', - 'c5n.metal', - 'c5n.xlarge', - 'd2.2xlarge', - 'd2.4xlarge', - 'd2.8xlarge', - 'd2.xlarge', - 'f1.16xlarge', - 'f1.2xlarge', - 'f1.4xlarge', - 'g2.2xlarge', - 'g2.8xlarge', - 'g3.16xlarge', - 'g3.4xlarge', - 'g3.8xlarge', - 'g3s.xlarge', - 'g4dn.12xlarge', - 'g4dn.16xlarge', - 'g4dn.2xlarge', - 'g4dn.4xlarge', - 'g4dn.8xlarge', - 'g4dn.xlarge', - 'h1.16xlarge', - 'h1.2xlarge', - 'h1.4xlarge', - 'h1.8xlarge', - 'i2.2xlarge', - 'i2.4xlarge', - 'i2.8xlarge', - 'i2.xlarge', - 'i3.16xlarge', - 'i3.2xlarge', - 'i3.4xlarge', - 'i3.8xlarge', - 'i3.large', - 'i3.metal', - 'i3.xlarge', - 'i3en.12xlarge', - 'i3en.24xlarge', - 'i3en.2xlarge', - 'i3en.3xlarge', - 'i3en.6xlarge', - 'i3en.large', - 'i3en.metal', - 'i3en.xlarge', - 'm1.large', - 'm1.medium', + 't1.micro', + 't2.micro', + 't2.small', + 't2.medium', + 't2.large', + 't2.xlarge', + 't2.2xlarge', + 't3.nano', + 't3.micro', + 't3.small', + 't3.medium', + 't3.large', + 't3.xlarge', + 't3.2xlarge', + 't3a.nano', + 't3a.micro', + 't3a.small', + 't3a.medium', + 't3a.large', + 't3a.xlarge', + 't3a.2xlarge', 'm1.small', + 'm1.medium', + 'm1.large', 'm1.xlarge', + 'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge', - 'm2.xlarge', - 'm3.2xlarge', - 'm3.large', 'm3.medium', + 'm3.large', 'm3.xlarge', - 'm4.10xlarge', - 'm4.16xlarge', - 'm4.2xlarge', - 'm4.4xlarge', + 'm3.2xlarge', 'm4.large', 'm4.xlarge', - 'm5.12xlarge', - 'm5.16xlarge', - 'm5.24xlarge', + 'm4.2xlarge', + 'm4.4xlarge', + 'm4.10xlarge', + 'm4.16xlarge', + 'm5.large', + 'm5.xlarge', 'm5.2xlarge', 'm5.4xlarge', 'm5.8xlarge', - 'm5.large', + 'm5.12xlarge', + 'm5.16xlarge', + 'm5.24xlarge', 'm5.metal', - 'm5.xlarge', - 'm5a.12xlarge', - 'm5a.16xlarge', - 'm5a.24xlarge', + 'm5a.large', + 'm5a.xlarge', 'm5a.2xlarge', 'm5a.4xlarge', 'm5a.8xlarge', - 'm5a.large', - 'm5a.xlarge', - 'm5ad.12xlarge', - 'm5ad.16xlarge', - 'm5ad.24xlarge', + 'm5a.12xlarge', + 'm5a.16xlarge', + 'm5a.24xlarge', + 'm5ad.large', + 'm5ad.xlarge', 'm5ad.2xlarge', 'm5ad.4xlarge', 'm5ad.8xlarge', - 'm5ad.large', - 'm5ad.xlarge', - 'm5d.12xlarge', - 'm5d.16xlarge', - 'm5d.24xlarge', + 'm5ad.12xlarge', + 'm5ad.16xlarge', + 'm5ad.24xlarge', + 'm5d.large', + 'm5d.xlarge', 'm5d.2xlarge', 'm5d.4xlarge', 'm5d.8xlarge', - 'm5d.large', + 'm5d.12xlarge', + 'm5d.16xlarge', + 'm5d.24xlarge', 'm5d.metal', - 'm5d.xlarge', - 'm5dn.12xlarge', - 'm5dn.16xlarge', - 'm5dn.24xlarge', + 'm5dn.large', + 'm5dn.xlarge', 'm5dn.2xlarge', 'm5dn.4xlarge', 'm5dn.8xlarge', - 'm5dn.large', - 'm5dn.xlarge', - 'm5n.12xlarge', - 'm5n.16xlarge', - 'm5n.24xlarge', + 'm5dn.12xlarge', + 'm5dn.16xlarge', + 'm5dn.24xlarge', + 'm5n.large', + 'm5n.xlarge', 'm5n.2xlarge', 'm5n.4xlarge', 'm5n.8xlarge', - 'm5n.large', - 'm5n.xlarge', - 'p2.16xlarge', - 'p2.8xlarge', - 'p2.xlarge', - 'p3.16xlarge', - 'p3.2xlarge', - 'p3.8xlarge', - 'p3dn.24xlarge', + 'm5n.12xlarge', + 'm5n.16xlarge', + 'm5n.24xlarge', + 'c1.medium', + 'c1.xlarge', + 'c3.large', + 'c3.xlarge', + 'c3.2xlarge', + 'c3.4xlarge', + 'c3.8xlarge', + 'c4.large', + 'c4.xlarge', + 'c4.2xlarge', + 'c4.4xlarge', + 'c4.8xlarge', + 'c5.large', + 'c5.xlarge', + 'c5.2xlarge', + 'c5.4xlarge', + 'c5.9xlarge', + 'c5.12xlarge', + 'c5.18xlarge', + 'c5.24xlarge', + 'c5.metal', + 'c5d.large', + 'c5d.xlarge', + 'c5d.2xlarge', + 'c5d.4xlarge', + 'c5d.9xlarge', + 'c5d.18xlarge', + 'c5n.large', + 'c5n.xlarge', + 'c5n.2xlarge', + 'c5n.4xlarge', + 'c5n.9xlarge', + 'c5n.18xlarge', + 'c5n.metal', + 'r3.large', + 'r3.xlarge', 'r3.2xlarge', 'r3.4xlarge', 'r3.8xlarge', - 'r3.large', - 'r3.xlarge', - 'r4.16xlarge', + 'r4.large', + 'r4.xlarge', 'r4.2xlarge', 'r4.4xlarge', 'r4.8xlarge', - 'r4.large', - 'r4.xlarge', - 'r5.12xlarge', - 'r5.16xlarge', - 'r5.24xlarge', + 'r4.16xlarge', + 'r5.large', + 'r5.xlarge', 'r5.2xlarge', 'r5.4xlarge', 'r5.8xlarge', - 'r5.large', + 'r5.12xlarge', + 'r5.16xlarge', + 'r5.24xlarge', 'r5.metal', - 'r5.xlarge', - 'r5a.12xlarge', - 'r5a.16xlarge', - 'r5a.24xlarge', + 'r5a.large', + 'r5a.xlarge', 'r5a.2xlarge', 'r5a.4xlarge', 'r5a.8xlarge', - 'r5a.large', - 'r5a.xlarge', - 'r5ad.12xlarge', - 'r5ad.16xlarge', - 'r5ad.24xlarge', + 'r5a.12xlarge', + 'r5a.16xlarge', + 'r5a.24xlarge', + 'r5ad.large', + 'r5ad.xlarge', 'r5ad.2xlarge', 'r5ad.4xlarge', 'r5ad.8xlarge', - 'r5ad.large', - 'r5ad.xlarge', - 'r5d.12xlarge', - 'r5d.16xlarge', - 'r5d.24xlarge', + 'r5ad.12xlarge', + 'r5ad.16xlarge', + 'r5ad.24xlarge', + 'r5d.large', + 'r5d.xlarge', 'r5d.2xlarge', 'r5d.4xlarge', 'r5d.8xlarge', - 'r5d.large', + 'r5d.12xlarge', + 'r5d.16xlarge', + 'r5d.24xlarge', 'r5d.metal', - 'r5d.xlarge', - 'r5dn.12xlarge', - 'r5dn.16xlarge', - 'r5dn.24xlarge', + 'r5dn.large', + 'r5dn.xlarge', 'r5dn.2xlarge', 'r5dn.4xlarge', 'r5dn.8xlarge', - 'r5dn.large', - 'r5dn.xlarge', - 'r5n.12xlarge', - 'r5n.16xlarge', - 'r5n.24xlarge', + 'r5dn.12xlarge', + 'r5dn.16xlarge', + 'r5dn.24xlarge', + 'r5n.large', + 'r5n.xlarge', 'r5n.2xlarge', 'r5n.4xlarge', 'r5n.8xlarge', - 'r5n.large', - 'r5n.xlarge', - 't1.micro', - 't2.2xlarge', - 't2.large', - 't2.medium', - 't2.micro', - 't2.small', - 't2.xlarge', - 't3.2xlarge', - 't3.large', - 't3.medium', - 't3.micro', - 't3.nano', - 't3.small', - 't3.xlarge', - 't3a.2xlarge', - 't3a.large', - 't3a.medium', - 't3a.micro', - 't3a.nano', - 't3a.small', - 't3a.xlarge', + 'r5n.12xlarge', + 'r5n.16xlarge', + 'r5n.24xlarge', 'x1.16xlarge', 'x1.32xlarge', - 'x1e.16xlarge', + 'x1e.xlarge', 'x1e.2xlarge', - 'x1e.32xlarge', 'x1e.4xlarge', 'x1e.8xlarge', - 'x1e.xlarge', - 'z1d.12xlarge', + 'x1e.16xlarge', + 'x1e.32xlarge', + 'z1d.large', + 'z1d.xlarge', 'z1d.2xlarge', 'z1d.3xlarge', 'z1d.6xlarge', - 'z1d.large', + 'z1d.12xlarge', 'z1d.metal', - 'z1d.xlarge', + 'd2.xlarge', + 'd2.2xlarge', + 'd2.4xlarge', + 'd2.8xlarge', + 'h1.2xlarge', + 'h1.4xlarge', + 'h1.8xlarge', + 'h1.16xlarge', + 'i2.xlarge', + 'i2.2xlarge', + 'i2.4xlarge', + 'i2.8xlarge', + 'i3.large', + 'i3.xlarge', + 'i3.2xlarge', + 'i3.4xlarge', + 'i3.8xlarge', + 'i3.16xlarge', + 'i3.metal', + 'i3en.large', + 'i3en.xlarge', + 'i3en.2xlarge', + 'i3en.3xlarge', + 'i3en.6xlarge', + 'i3en.12xlarge', + 'i3en.24xlarge', + 'i3en.metal', + 'f1.2xlarge', + 'f1.4xlarge', + 'f1.16xlarge', + 'g2.2xlarge', + 'g2.8xlarge', + 'g3.4xlarge', + 'g3.8xlarge', + 'g3.16xlarge', + 'g3s.xlarge', + 'g4dn.xlarge', + 'g4dn.2xlarge', + 'g4dn.4xlarge', + 'g4dn.8xlarge', + 'g4dn.12xlarge', + 'g4dn.16xlarge', + 'p2.xlarge', + 'p2.8xlarge', + 'p2.16xlarge', + 'p3.2xlarge', + 'p3.8xlarge', + 'p3.16xlarge', + 'p3dn.24xlarge', ] as const; + export type InstanceType = typeof allInstances[number]; diff --git a/util/generate-ec2-types.ts b/util/generate-ec2-types.ts index 291fb76c..01646918 100644 --- a/util/generate-ec2-types.ts +++ b/util/generate-ec2-types.ts @@ -1,12 +1,100 @@ -import { spawn } from 'child_process'; import { writeFileSync } from 'fs'; import { resolve } from 'path'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as prettier from 'prettier'; import { getGlobalSpotPrices } from '../src/lib'; +import { defaultRegions } from '../src/regions'; +import { nockEndpoint } from '../test/test-utils'; -const targetPath = resolve(__dirname, '../src/ec2-types.ts'); +const familyGeneral = ['a', 't', 'm']; + +const familyCompute = ['c']; + +const familyMemory = ['r', 'x', 'z']; + +const familyStorage = ['d', 'h', 'i']; + +const familyAcceleratedComputing = ['f', 'g', 'p']; + +const familyOrder = [ + ...familyGeneral, + ...familyCompute, + ...familyMemory, + ...familyStorage, + ...familyAcceleratedComputing, +]; + +const sizeOrder = [ + 'nano', + 'micro', + 'small', + 'medium', + 'large', + 'xlarge', + '2xlarge', + '3xlarge', + '4xlarge', + '6xlarge', + '8xlarge', + '9xlarge', + '10xlarge', + '12xlarge', + '16xlarge', + '18xlarge', + '24xlarge', + '32xlarge', + 'metal', +]; + +const sortFamilies = (f1: string, f2: string) => { + let rtn = 0; + if (f1[0] === f2[0]) { + if (f1 < f2) rtn = -1; + if (f1 > f2) rtn = 1; + return rtn; + } + const i1 = familyOrder.indexOf(f1[0]); + const i2 = familyOrder.indexOf(f2[0]); + if (i1 < 0) throw new Error(`unexpected instance family ${f1}`); + if (i2 < 0) throw new Error(`unexpected instance family ${f2}`); + if (i1 < i2) rtn = -1; + if (i1 > i2) rtn = 1; + return rtn; +}; + +const sortSizes = (s1: string, s2: string) => { + let rtn = 0; + const i1 = sizeOrder.indexOf(s1); + const i2 = sizeOrder.indexOf(s2); + if (i1 < 0) throw new Error(`unexpected instance size ${s1}`); + if (i2 < 0) throw new Error(`unexpected instance size ${s2}`); + if (i1 < i2) rtn = -1; + if (i1 > i2) rtn = 1; + return rtn; +}; + +const sortInstances = (i1: string, i2: string) => { + let rtn = 0; + const [f1, s1] = i1.split('.'); + const [f2, s2] = i2.split('.'); + let sc1 = sizeOrder.indexOf(s1); + let sc2 = sizeOrder.indexOf(s2); + if (f1[0] === f2[0]) { + if (f1 < f2) sc1 -= 100; + if (f1 > f2) sc1 += 100; + } else { + sc1 += familyOrder.indexOf(f1[0]) * 100; + sc2 += familyOrder.indexOf(f2[0]) * 100; + } + if (sc1 < sc2) rtn = -1; + if (sc1 > sc2) rtn = 1; + return rtn; +}; + +export const getEc2Types = async () => { + defaultRegions.forEach(region => nockEndpoint({ region })); // TEMP FOR TESTING -const getEc2Types = async () => { const allInstances = (await getGlobalSpotPrices({ quiet: true })).reduce( (list, cur) => { if (cur.InstanceType && list.indexOf(cur.InstanceType) < 0) list.push(cur.InstanceType); @@ -27,35 +115,32 @@ const getEc2Types = async () => { if (instanceSizes.indexOf(size) < 0) instanceSizes.push(size); }); - // console.log(list); let output = ''; output += `export const instanceFamilies = [ '${instanceFamilies - .sort() - .join("', '")}' ] as const;`; - output += `export type InstanceFamily = typeof instanceFamilies[number];`; - output += `export const instanceSizes = [ '${instanceSizes.sort().join("', '")}' ] as const;`; - output += `export type InstanceSize = typeof instanceSizes[number];`; - output += `export const allInstances = [ '${allInstances.sort().join("', '")}' ] as const;`; + .sort(sortFamilies) + .join("', '")}' ] as const;\n\n`; + output += `export type InstanceFamily = typeof instanceFamilies[number];\n\n`; + output += `export const instanceSizes = [ '${instanceSizes + .sort(sortSizes) + .join("', '")}' ] as const;\n\n`; + output += `export type InstanceSize = typeof instanceSizes[number];\n\n`; + output += `export const allInstances = [ '${allInstances + .sort(sortInstances) + .join("', '")}' ] as const;\n\n`; output += `export type InstanceType = typeof allInstances[number];`; - writeFileSync(targetPath, output); - - await new Promise(res => { - console.log('prettier starting...'); - const prettierPath = resolve(__dirname, '../node_modules/.bin/prettier'); - const prettierArgs = [targetPath, '--write']; - const prettier = spawn(prettierPath, prettierArgs); - prettier.on('close', () => { - console.log('prettier complete'); - res(); - }); - prettier.stderr.on('data', (data: Buffer) => { - console.log(data.toString()); - }); - prettier.stderr.on('data', (data: Buffer) => { - console.log('prettier error', data.toString()); - }); + output = prettier.format(output, { + printWidth: 100, + trailingComma: 'all', + singleQuote: true, + parser: 'typescript', }); + return output; }; -getEc2Types(); +if (require.main && require.main.filename === module.filename) { + (async () => { + const targetPath = resolve(__dirname, '../src/ec2-types.ts'); + writeFileSync(targetPath, await getEc2Types()); + })(); +} diff --git a/yarn.lock b/yarn.lock index ff761c1d..b4bd5a6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -525,6 +525,11 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== +"@types/prettier@^1.18.3": + version "1.18.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.18.3.tgz#64ff53329ce16139f17c3db9d3e0487199972cd8" + integrity sha512-48rnerQdcZ26odp+HOvDGX8IcUkYOCuMc2BodWYTe956MqkHlOGAG4oFQ83cjZ0a4GAgj7mb4GUClxYd2Hlodg== + "@types/semver@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.2.tgz#5e8b09f0e4af53034b1d0fb9977a277847836205"