Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: service quota construct #33

Merged
merged 8 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"sonarlint.connectedMode.project": {
"connectionId": "reapit",
"projectKey": "reapit_ts-cdk-constructs"
}
},
"deepscan.enable": true
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
],
"scripts": {
"test": "jest --passWithNoTests --ignoreProjects 'integration tests' --coverage",
"check": "tsc packages/**/*.ts --noEmit",
"check": "tsc --noEmit",
"build": "yarn workspaces foreach --all -v run build",
"lint": "yarn workspaces foreach --all -v run lint",
"integ": "jest --passWithNoTests --ignoreProjects 'unit tests' --silent false",
"root:test": "jest --passWithNoTests --ignoreProjects 'integration tests'",
"root:integ": "jest --passWithNoTests --ignoreProjects 'unit tests' --silent false",
"root:check": "tsc",
"root:check": "tsc --noEmit",
"generate-readme": "reapit-cdk-generate-readme"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/constructs/cross-region-stack-export/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

![npm version](https://img.shields.io/npm/v/@reapit-cdk/cross-region-stack-export)
![npm downloads](https://img.shields.io/npm/dm/@reapit-cdk/cross-region-stack-export)
![coverage: 74.02%25](https://img.shields.io/badge/coverage-74.02%25-orange)
![coverage: 71.85%25](https://img.shields.io/badge/coverage-71.85%25-orange)
![Integ Tests: X](https://img.shields.io/badge/Integ%20Tests-X-red)

Allows you to share values between stack across regions and accounts.
Expand Down
1 change: 1 addition & 0 deletions packages/constructs/edge-api/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ api.addEndpoint({

// optional
customMiddlewares: [
// @ts-expect-error
(req, mapping) => {
// req is CloudfrontRequest https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/common/cloudfront.d.ts#L44
// mapping is destination['user requested domain name'] e.g. mapping['example.org']
Expand Down
1 change: 1 addition & 0 deletions packages/constructs/edge-api/tests/construct.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ describe('edge-api', () => {
pathPattern: '/google',
destination,
customMiddlewares: [
// @ts-expect-error
(req, mapping) => {
if (req.uri === '/authorize' || req.uri === '/login') {
if (typeof mapping !== 'string') {
Expand Down
1 change: 1 addition & 0 deletions packages/constructs/edge-api/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ api.addEndpoint({

// optional
customMiddlewares: [
// @ts-expect-error
(req, mapping) => {
// req is CloudfrontRequest https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/aws-lambda/common/cloudfront.d.ts#L44
// mapping is destination['user requested domain name'] e.g. mapping['example.org']
Expand Down
1 change: 1 addition & 0 deletions packages/constructs/service-quotas/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quotas.json
4 changes: 4 additions & 0 deletions packages/constructs/service-quotas/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src
tests
.eslintrc.js
tsconfig.json
53 changes: 53 additions & 0 deletions packages/constructs/service-quotas/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "@reapit-cdk/service-quotas",
"version": "0.0.0",
"description": "This construct allows you to IaC your service quotas",
"homepage": "https://github.com/reapit/ts-cdk-constructs/blob/main/packages/modules/service-quotas",
"readme": "https://github.com/reapit/ts-cdk-constructs/blob/main/packages/modules/service-quotas/readme.md",
"bugs": {
"url": "https://github.com/reapit/ts-cdk-constructs/issues"
},
"license": "MIT",
"author": {
"name": "Josh Balfour",
"email": "jbalfour@reapit.com"
},
"repository": {
"url": "https://github.com/reapit/ts-cdk-constructs.git"
},
"scripts": {
"build": "reapit-cdk-tsup --lambda",
"check": "yarn run root:check -p $(pwd)",
"lint": "echo 'skipping'",
"test": "yarn run root:test -- $(pwd)",
"prepack": "yarn build",
"integ": "yarn run root:integ -- $(pwd)",
"jsii:build": "rpt-cdk-jsii",
"jsii:publish": "rpt-cdk-jsii --publish",
"gen-types": "ts-node src/generate-types.ts"
},
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"types": "dist/index.d.ts"
},
"peerDependencies": {
"aws-cdk-lib": "^2.96.2",
"constructs": "^10.2.70"
},
"devDependencies": {
"@aws-sdk/client-service-quotas": "3.414.0",
"@reapit-cdk/custom-resource-wrapper": "workspace:^",
"@reapit-cdk/eslint-config": "workspace:^",
"@reapit-cdk/integration-tests": "workspace:^",
"@reapit-cdk/jsii": "workspace:^",
"@reapit-cdk/tsup": "workspace:^",
"aws-cdk-lib": "^2.96.2",
"aws-lambda": "^1.0.7",
"aws-sdk-client-mock": "^3.0.0",
"constructs": "^10.2.70",
"ts-node": "^10.9.2",
"varname": "^6.0.0"
}
}
44 changes: 44 additions & 0 deletions packages/constructs/service-quotas/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# @reapit-cdk/service-quotas


![npm version](https://img.shields.io/npm/v/@reapit-cdk/service-quotas)
![npm downloads](https://img.shields.io/npm/dm/@reapit-cdk/service-quotas)
![coverage: 0%25](https://img.shields.io/badge/coverage-0%25-red)
![Integ Tests: X](https://img.shields.io/badge/Integ%20Tests-X-red)

This construct allows you to IaC your service quotas

## Package Installation:

```sh
yarn add --dev @reapit-cdk/service-quotas
# or
npm install @reapit-cdk/service-quotas --save-dev
```

## Usage
```ts
import { Stack, App } from 'aws-cdk-lib'
import { AWSService, AmazonCloudFrontQuota, ServiceQuotas } from '@reapit-cdk/service-quotas'

const app = new App()
const stack = new Stack(app, 'stack-name')
const quotas = new ServiceQuotas(stack, 'service-quotas', {
// Fail the stack if your requests aren't granted yet
failIfNotGranted: true,
// Make another request if an existing one is denied
rerequestWhenDenied: true,
})

quotas.requestQuota(
// region
'us-east-1',
// service (use the AWSService.${Service} helper or specify the e.g. 'cloudfront' string as any)
AWSService.AmazonCloudFront,
// quota (use the ${Service}Quota e.g. AmazonCloudFrontQuota helper or specify the 'LL-' string as any)
AmazonCloudFrontQuota.CacheBehaviorsPerDistribution,
// desired value
100,
)

```
70 changes: 70 additions & 0 deletions packages/constructs/service-quotas/src/construct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Construct } from 'constructs'
import { Code, Function, Runtime } from 'aws-cdk-lib/aws-lambda'
import * as path from 'path'
import { CustomResource, Duration, Lazy } from 'aws-cdk-lib'
import { PolicyStatement } from 'aws-cdk-lib/aws-iam'
import { Provider } from 'aws-cdk-lib/custom-resources'
import { Config, Quota } from './types'

import { AWSService, ServiceQuotaMap } from './quotas'

export class ServiceQuotas extends Construct {
private quotas: Quota[] = []
config: Config

constructor(scope: Construct, id: string, config: Config) {
super(scope, id)

this.config = config

const lambda = new Function(this, 'lambda', {
code: Code.fromAsset(path.join(__dirname, '..', 'dist', 'lambda')),
handler: 'lambda.onEvent',
runtime: Runtime.NODEJS_18_X,
timeout: Duration.minutes(15),
})

lambda.addToRolePolicy(
new PolicyStatement({
actions: [
'servicequotas:ListRequestedServiceQuotaChangeHistoryByQuota',
'servicequotas:GetServiceQuota',
'servicequotas:RequestServiceQuotaIncrease',
],
resources: ['*'],
}),
)

const provider = new Provider(this, 'provider', {
onEventHandler: lambda,
})

const self = this

new CustomResource(this, 'custom-resource', {
serviceToken: provider.serviceToken,
properties: {
config: this.config,
quotas: Lazy.any({
produce() {
return self.quotas
},
}),
},
})
}

requestQuota<S extends AWSService, Q extends ServiceQuotaMap[S]>(
region: string,
service: S,
quota: Q,
desiredValue: number,
) {
this.quotas.push({
desiredValue,
quota: quota as string,
region,
service,
})
}
}
Loading
Loading