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(servicequotas): add dynamodb quotas #63

Merged
merged 22 commits into from
Jan 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
08bcd5f
chore: upgraded saml provider to new commonAws
OlafConijn Jan 13, 2021
53337ab
fix: updated installation instructions
OlafConijn Jan 13, 2021
73f4819
fix: oidc-provider bump rpdk dependency
OlafConijn Jan 13, 2021
d7aeffb
feat(servicequotas-dynamodb): initial commit, version 0.1.0
OlafConijn Jan 18, 2021
add8bd1
fix: updated installation instructions
OlafConijn Jan 13, 2021
f6083d5
fix: oidc-provider bump rpdk dependency
OlafConijn Jan 13, 2021
1ec9b11
feat(servicequotas-dynamodb): initial commit, version 0.1.0
OlafConijn Jan 18, 2021
bcabcf2
Merge branch 'feat/service-quotas-dynamodb' of github.com:org-formati…
OlafConijn Jan 18, 2021
70b416f
chore(service-quotas-dynamodb): linting
OlafConijn Jan 18, 2021
5f56784
Merge branch 'master' into feat/service-quotas-dynamodb
OlafConijn Jan 18, 2021
ba36151
fix: review changes
OlafConijn Feb 15, 2021
97d9014
chore(service-quotas-ddb): empty read handler
OlafConijn Feb 15, 2021
4732a23
revert unintended change in saml provider
OlafConijn Feb 15, 2021
067f431
fix: cicd
OlafConijn Feb 15, 2021
10aa39e
ci: re-trigger build
PatMyron Sep 23, 2021
645bcab
Merge branch 'master' into feat/service-quotas-dynamodb
PatMyron Sep 23, 2021
aa341e6
Merge branch 'master' into feat/service-quotas-dynamodb
eduardomourar Jan 22, 2022
5c98230
chore: keep saml-provider documentation as before
eduardomourar Jan 22, 2022
d998f60
chore: update package dependencies
eduardomourar Jan 22, 2022
937a334
chore: add unit tests
eduardomourar Jan 22, 2022
59ca43c
chore: use cfn cli typescript plugin from aws
eduardomourar Jan 22, 2022
d5e09e4
chore: add jest config to folder
eduardomourar Jan 22, 2022
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
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
id: install_python
run: |
mkdir "$LOG_PATH"
pip install --upgrade pip git+https://github.com/eduardomourar/cloudformation-cli-typescript-plugin.git#egg=cloudformation-cli-typescript-plugin
pip install --upgrade pip cloudformation-cli-typescript-plugin
curl -s -L https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -o sam.zip
unzip -q sam.zip -d ../sam-install
sudo ../sam-install/install --update
Expand Down
2 changes: 2 additions & 0 deletions service-quotas/dynamodb/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
optional = false
save = false
17 changes: 17 additions & 0 deletions service-quotas/dynamodb/.rpdk-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"typeName": "Community::ServiceQuotas::DynamoDB",
OlafConijn marked this conversation as resolved.
Show resolved Hide resolved
"language": "typescript",
"runtime": "nodejs12.x",
"artifact_type": "RESOURCE",
"entrypoint": "dist/handlers.entrypoint",
"testEntrypoint": "dist/handlers.testEntrypoint",
"settings": {
"version": false,
"subparser_name": null,
"verbose": 0,
"force": false,
"type_name": null,
"useDocker": false,
"protocolVersion": "2.0.0"
}
}
39 changes: 39 additions & 0 deletions service-quotas/dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Community::ServiceQuotas::DynamoDB

Congratulations on starting development! Next steps:

1. Write the JSON schema describing your resource, [community-servicequotas-dynamodb.json](./community-servicequotas-dynamodb.json)
2. Implement your resource handlers in [handlers.ts](./community-servicequotas-dynamodb/handlers.ts)

> Don't modify [models.ts](./community-servicequotas-dynamodb/models.ts) by hand, any modifications will be overwritten when the `generate` or `package` commands are run.

Implement CloudFormation resource here. Each function must always return a ProgressEvent.

```typescript
const progress = ProgressEvent.builder<ProgressEvent<ResourceModel>>()

// Required
// Must be one of OperationStatus.InProgress, OperationStatus.Failed, OperationStatus.Success
.status(OperationStatus.InProgress)
// Required on SUCCESS (except for LIST where resourceModels is required)
// The current resource model after the operation; instance of ResourceModel class
.resourceModel(model)
.resourceModels(null)
// Required on FAILED
// Customer-facing message, displayed in e.g. CloudFormation stack events
.message('')
// Required on FAILED a HandlerErrorCode
.errorCode(HandlerErrorCode.InternalFailure)
// Optional
// Use to store any state between re-invocation via IN_PROGRESS
.callbackContext({})
// Required on IN_PROGRESS
// The number of seconds to delay before re-invocation
.callbackDelaySeconds(0)

.build()
```

While importing the [cfn-rpdk](https://github.com/eduardomourar/cloudformation-cli-typescript-plugin) library, failures can be passed back to CloudFormation by either raising an exception from `exceptions`, or setting the ProgressEvent's `status` to `OperationStatus.Failed` and `errorCode` to one of `HandlerErrorCode`. There is a static helper function, `ProgressEvent.failed`, for this common case.

Keep in mind, during runtime all logs will be delivered to CloudWatch if you use the `log()` method from `LoggerProxy` class.
52 changes: 52 additions & 0 deletions service-quotas/dynamodb/__tests__/handlers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { ServiceQuotas } from 'aws-sdk';
import { on, AwsServiceMockBuilder } from '@jurijzahn8019/aws-promise-jest-mock';
import { Action, exceptions, SessionProxy } from '@amazon-web-services-cloudformation/cloudformation-cli-typescript-lib';
import createFixture from '../sam-tests/create.json';
import deleteFixture from '../sam-tests/delete.json';
import readFixture from '../sam-tests/read.json';
import updateFixture from '../sam-tests/update.json';
import { resource } from '../src/handlers';

jest.mock('aws-sdk');

describe('when calling handler', () => {
let testEntrypointPayload: any;
let spySession: jest.SpyInstance;
let spySessionClient: jest.SpyInstance;
let serviceQuotas: AwsServiceMockBuilder<ServiceQuotas>;
let fixtureMap: Map<Action, Record<string, any>>;

beforeAll(() => {
fixtureMap = new Map<Action, Record<string, any>>();
fixtureMap.set(Action.Create, createFixture);
fixtureMap.set(Action.Read, readFixture);
fixtureMap.set(Action.Update, updateFixture);
fixtureMap.set(Action.Delete, deleteFixture);
});

beforeEach(async () => {
serviceQuotas = on(ServiceQuotas, { snapshot: false });
spySession = jest.spyOn(SessionProxy, 'getSession');
spySessionClient = jest.spyOn<any, any>(SessionProxy.prototype, 'client');
spySessionClient.mockReturnValue(serviceQuotas.instance);
testEntrypointPayload = {
credentials: { accessKeyId: '', secretAccessKey: '', sessionToken: '' },
region: 'us-east-1',
action: 'CREATE',
};
});

afterEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
});

test('all operations fail without session - service quotas cloudformation', async () => {
expect.assertions(fixtureMap.size);
spySession.mockReturnValue(null);
for (const [action, request] of fixtureMap) {
const progress = await resource.testEntrypoint({ ...testEntrypointPayload, action, request }, null);
expect(progress.errorCode).toBe(exceptions.InvalidCredentials.name);
}
});
});
55 changes: 55 additions & 0 deletions service-quotas/dynamodb/community-servicequotas-dynamodb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"typeName": "Community::ServiceQuotas::DynamoDB",
"description": "Custom Service Quota limits for DynamoDB resources. e.g: to increase the maximum number of tables per region.",
"sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-rpdk.git",
"definitions": {
},
"properties": {
"Tables": {
"description":"The maximum number of tables that can be created per region. (default = 256).",
"type": "integer",
"default": 256,
"minimum": 256
},
"Arn": {
"type": "string"
}
},
"additionalProperties": false,
"readOnlyProperties": [
"/properties/Arn"
],
"primaryIdentifier": [
"/properties/Arn"
],
"handlers": {
"create": {
"permissions": [
"servicequotas:requestServiceQuotaIncrease",
"servicequotas:listRequestedServiceQuotaChangeHistoryByQuota",
"servicequotas:getServiceQuota",
"cloudformation:DescribeAccountLimits",
"servicequotas:GetAWSDefaultServiceQuota",
"iam:CreateServiceLinkedRole"
]
},
"read": {
"permissions": [
]
},
"update": {
"permissions": [
"servicequotas:requestServiceQuotaIncrease",
"servicequotas:listRequestedServiceQuotaChangeHistoryByQuota",
"servicequotas:getServiceQuota",
"cloudformation:DescribeAccountLimits",
"servicequotas:GetAWSDefaultServiceQuota",
"iam:CreateServiceLinkedRole"
]
},
"delete": {
"permissions": [
]
}
}
}
55 changes: 55 additions & 0 deletions service-quotas/dynamodb/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Community::ServiceQuotas::DynamoDB

Custom Service Quota limits for DynamoDB resources. e.g: to increase the maximum number of tables per region.

## Syntax

To declare this entity in your AWS CloudFormation template, use the following syntax:

### JSON

<pre>
{
"Type" : "Community::ServiceQuotas::DynamoDB",
"Properties" : {
"<a href="#tables" title="Tables">Tables</a>" : <i>Integer</i>,
}
}
</pre>

### YAML

<pre>
Type: Community::ServiceQuotas::DynamoDB
Properties:
<a href="#tables" title="Tables">Tables</a>: <i>Integer</i>
</pre>

## Properties

#### Tables

The maximum number of tables that can be created per region. (default = 256).

_Required_: No

_Type_: Integer

_Update requires_: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)

## Return Values

### Ref

When you pass the logical ID of this resource to the intrinsic `Ref` function, Ref returns the Arn.

### Fn::GetAtt

The `Fn::GetAtt` intrinsic function returns a value for a specified attribute of this type. The following are the available attributes and sample return values.

For more information about using the `Fn::GetAtt` intrinsic function, see [Fn::GetAtt](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html).

#### Arn

Returns the <code>Arn</code> value.

6 changes: 6 additions & 0 deletions service-quotas/dynamodb/example.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
AWSTemplateFormatVersion: 2010-09-09
Resources:
DynamoDB:
Type: 'Community::ServiceQuotas::DynamoDB'
Properties:
Tables: 256
10 changes: 10 additions & 0 deletions service-quotas/dynamodb/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable @typescript-eslint/no-require-imports */
const base = require('../../jest.config.base.js');
const package = require('./package');

module.exports = {
...base,
displayName: package.name,
name: package.name,
};
Loading