Skip to content

Commit 139880d

Browse files
authored
Merge pull request #65 from oss-serverless/aws-sdk-v3
Migrate to AWS SDK V3 - Part 1
2 parents b3f58fb + 57ef13a commit 139880d

21 files changed

+1287
-110
lines changed

.github/workflows/integrate.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,24 @@ jobs:
5050
run: |
5151
npm update --no-save
5252
npm update --save-dev --no-save
53-
- name: Unit tests
53+
- name: Unit tests (AWS SDK v2)
5454
# Some tests depend on TTY support, which is missing in GA runner
5555
# Workaround taken from https://github.com/actions/runner/issues/241#issuecomment-577360161
5656
run: script -e -c "npm test -- -b"
57-
- name: Packaging tests
57+
env:
58+
SLS_AWS_SDK_V3: '0'
59+
- name: Unit tests (AWS SDK v3)
60+
run: script -e -c "npm test -- -b"
61+
env:
62+
SLS_AWS_SDK_V3: '1'
63+
- name: Packaging tests (AWS SDK v2)
5864
run: npm run integration-test-run-package
65+
env:
66+
SLS_AWS_SDK_V3: '0'
67+
- name: Packaging tests (AWS SDK v3)
68+
run: npm run integration-test-run-package
69+
env:
70+
SLS_AWS_SDK_V3: '1'
5971

6072
windowsNode16:
6173
name: '[Windows] Node 16: Unit tests'
@@ -122,7 +134,7 @@ jobs:
122134
integrate:
123135
name: Integrate
124136
runs-on: ubuntu-latest
125-
needs: [linuxNode22, windowsNode22, linuxNode16]
137+
needs: [linuxNode22, windowsNode16, linuxNode16]
126138
timeout-minutes: 30 # Default is 360
127139
env:
128140
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}

.github/workflows/validate.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,24 @@ jobs:
6363
then
6464
npx dump-release-notes-from-cc-changelog $NEW_VERSION
6565
fi
66-
- name: Unit tests
66+
- name: Unit tests (AWS SDK v2)
6767
# Some tests depend on TTY support, which is missing in GA runner
6868
# Workaround taken from https://github.com/actions/runner/issues/241#issuecomment-577360161
6969
run: script -e -c "npm test -- -b"
70-
- name: Packaging tests
70+
env:
71+
SLS_AWS_SDK_V3: '0'
72+
- name: Unit tests (AWS SDK v3)
73+
run: script -e -c "npm test -- -b"
74+
env:
75+
SLS_AWS_SDK_V3: '1'
76+
- name: Packaging tests (AWS SDK v2)
77+
run: npm run integration-test-run-package
78+
env:
79+
SLS_AWS_SDK_V3: '0'
80+
- name: Packaging tests (AWS SDK v3)
7181
run: npm run integration-test-run-package
82+
env:
83+
SLS_AWS_SDK_V3: '1'
7284

7385
windowsNode16:
7486
name: '[Windows] Node 16: Unit tests'

lib/aws/client-factory.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use strict';
2+
3+
const { APIGatewayClient } = require('@aws-sdk/client-api-gateway');
4+
const { ApiGatewayV2Client } = require('@aws-sdk/client-apigatewayv2');
5+
const { CloudFormationClient } = require('@aws-sdk/client-cloudformation');
6+
const { CloudWatchClient } = require('@aws-sdk/client-cloudwatch');
7+
const { CloudWatchLogsClient } = require('@aws-sdk/client-cloudwatch-logs');
8+
const { CognitoIdentityProviderClient } = require('@aws-sdk/client-cognito-identity-provider');
9+
const { ECRClient } = require('@aws-sdk/client-ecr');
10+
const { EventBridgeClient } = require('@aws-sdk/client-eventbridge');
11+
const { IAMClient } = require('@aws-sdk/client-iam');
12+
const { LambdaClient } = require('@aws-sdk/client-lambda');
13+
const { S3Client } = require('@aws-sdk/client-s3');
14+
const { SSMClient } = require('@aws-sdk/client-ssm');
15+
const { STSClient } = require('@aws-sdk/client-sts');
16+
17+
// Map service names to their client classes
18+
const CLIENT_MAP = {
19+
APIGateway: APIGatewayClient,
20+
ApiGatewayV2: ApiGatewayV2Client,
21+
CloudFormation: CloudFormationClient,
22+
CloudWatch: CloudWatchClient,
23+
CloudWatchLogs: CloudWatchLogsClient,
24+
CognitoIdentityProvider: CognitoIdentityProviderClient,
25+
ECR: ECRClient,
26+
EventBridge: EventBridgeClient,
27+
IAM: IAMClient,
28+
Lambda: LambdaClient,
29+
S3: S3Client,
30+
SSM: SSMClient,
31+
STS: STSClient,
32+
};
33+
34+
class AWSClientFactory {
35+
constructor(baseConfig = {}) {
36+
this.baseConfig = baseConfig;
37+
this.clients = new Map();
38+
}
39+
40+
/**
41+
* Get a configured AWS service client
42+
* @param {string} serviceName - Name of the AWS service (e.g., 'S3', 'CloudFormation')
43+
* @param {Object} overrideConfig - Configuration to override base config
44+
* @returns {Object} AWS SDK v3 client instance
45+
*/
46+
getClient(serviceName, overrideConfig = {}) {
47+
const ClientClass = CLIENT_MAP[serviceName];
48+
if (!ClientClass) {
49+
throw new Error(`Unknown AWS service: ${serviceName}`);
50+
}
51+
52+
// Create a cache key based on service and config
53+
const configKey = JSON.stringify({ serviceName, ...this.baseConfig, ...overrideConfig });
54+
55+
if (!this.clients.has(configKey)) {
56+
const clientConfig = { ...this.baseConfig, ...overrideConfig };
57+
this.clients.set(configKey, new ClientClass(clientConfig));
58+
}
59+
60+
return this.clients.get(configKey);
61+
}
62+
63+
/**
64+
* Send a command to an AWS service
65+
* @param {string} serviceName - Name of the AWS service
66+
* @param {Object} command - AWS SDK v3 command instance
67+
* @param {Object} clientConfig - Optional client configuration override
68+
* @returns {Promise} Result of the AWS API call
69+
*/
70+
async send(serviceName, command, clientConfig = {}) {
71+
const client = this.getClient(serviceName, clientConfig);
72+
return client.send(command);
73+
}
74+
}
75+
76+
module.exports = AWSClientFactory;

lib/aws/commands.js

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
'use strict';
2+
3+
// API Gateway Commands
4+
const {
5+
GetAccountCommand,
6+
UpdateAccountCommand,
7+
GetApiKeyCommand,
8+
CreateStageCommand,
9+
GetUsagePlansCommand,
10+
UpdateUsagePlanCommand,
11+
TagResourceCommand,
12+
UntagResourceCommand,
13+
UpdateStageCommand,
14+
} = require('@aws-sdk/client-api-gateway');
15+
16+
// API Gateway V2 Commands
17+
const { GetApiCommand } = require('@aws-sdk/client-apigatewayv2');
18+
19+
// CloudFormation Commands
20+
const {
21+
CreateStackCommand,
22+
CreateChangeSetCommand,
23+
DeleteChangeSetCommand,
24+
ExecuteChangeSetCommand,
25+
UpdateStackCommand,
26+
DeleteStackCommand,
27+
DescribeStacksCommand,
28+
ValidateTemplateCommand,
29+
SetStackPolicyCommand,
30+
GetTemplateCommand,
31+
ListStackResourcesCommand,
32+
DescribeStackResourceCommand,
33+
DescribeStackEventsCommand,
34+
ListExportsCommand,
35+
} = require('@aws-sdk/client-cloudformation');
36+
37+
// CloudWatch Commands
38+
const { GetMetricStatisticsCommand } = require('@aws-sdk/client-cloudwatch');
39+
40+
// CloudWatch Logs Commands
41+
const {
42+
DescribeLogStreamsCommand,
43+
FilterLogEventsCommand,
44+
DeleteSubscriptionFilterCommand,
45+
} = require('@aws-sdk/client-cloudwatch-logs');
46+
47+
// Cognito Identity Provider Commands
48+
const {
49+
ListUserPoolsCommand,
50+
DescribeUserPoolCommand,
51+
UpdateUserPoolCommand,
52+
} = require('@aws-sdk/client-cognito-identity-provider');
53+
54+
// ECR Commands
55+
const {
56+
DeleteRepositoryCommand,
57+
DescribeRepositoriesCommand,
58+
GetAuthorizationTokenCommand,
59+
CreateRepositoryCommand,
60+
DescribeImagesCommand,
61+
} = require('@aws-sdk/client-ecr');
62+
63+
// EventBridge Commands
64+
const {
65+
CreateEventBusCommand,
66+
DeleteEventBusCommand,
67+
PutRuleCommand,
68+
DeleteRuleCommand,
69+
PutTargetsCommand,
70+
RemoveTargetsCommand,
71+
} = require('@aws-sdk/client-eventbridge');
72+
73+
// IAM Commands
74+
const {
75+
GetRoleCommand,
76+
ListAttachedRolePoliciesCommand,
77+
CreateRoleCommand,
78+
AttachRolePolicyCommand,
79+
} = require('@aws-sdk/client-iam');
80+
81+
// Lambda Commands
82+
const {
83+
GetFunctionCommand,
84+
UpdateFunctionConfigurationCommand,
85+
UpdateFunctionCodeCommand,
86+
InvokeCommand,
87+
ListVersionsByFunctionCommand,
88+
GetLayerVersionCommand,
89+
AddPermissionCommand,
90+
RemovePermissionCommand,
91+
} = require('@aws-sdk/client-lambda');
92+
93+
// S3 Commands
94+
const {
95+
ListObjectsV2Command,
96+
ListObjectVersionsCommand,
97+
DeleteObjectsCommand,
98+
HeadObjectCommand,
99+
PutObjectCommand,
100+
GetObjectCommand,
101+
GetBucketLocationCommand,
102+
HeadBucketCommand,
103+
GetBucketNotificationConfigurationCommand,
104+
PutBucketNotificationConfigurationCommand,
105+
} = require('@aws-sdk/client-s3');
106+
107+
// SSM Commands
108+
const { GetParameterCommand } = require('@aws-sdk/client-ssm');
109+
110+
// STS Commands
111+
const { GetCallerIdentityCommand } = require('@aws-sdk/client-sts');
112+
113+
/**
114+
* Map v2 method names to v3 command classes
115+
* Format: { ServiceName: { methodName: CommandClass } }
116+
*/
117+
const COMMAND_MAP = {
118+
APIGateway: {
119+
getAccount: GetAccountCommand,
120+
updateAccount: UpdateAccountCommand,
121+
getApiKey: GetApiKeyCommand,
122+
createStage: CreateStageCommand,
123+
getUsagePlans: GetUsagePlansCommand,
124+
updateUsagePlan: UpdateUsagePlanCommand,
125+
tagResource: TagResourceCommand,
126+
untagResource: UntagResourceCommand,
127+
updateStage: UpdateStageCommand,
128+
},
129+
130+
ApiGatewayV2: {
131+
getApi: GetApiCommand,
132+
},
133+
134+
CloudFormation: {
135+
createStack: CreateStackCommand,
136+
createChangeSet: CreateChangeSetCommand,
137+
deleteChangeSet: DeleteChangeSetCommand,
138+
executeChangeSet: ExecuteChangeSetCommand,
139+
updateStack: UpdateStackCommand,
140+
deleteStack: DeleteStackCommand,
141+
describeStacks: DescribeStacksCommand,
142+
validateTemplate: ValidateTemplateCommand,
143+
setStackPolicy: SetStackPolicyCommand,
144+
getTemplate: GetTemplateCommand,
145+
listStackResources: ListStackResourcesCommand,
146+
describeStackResource: DescribeStackResourceCommand,
147+
describeStackEvents: DescribeStackEventsCommand,
148+
listExports: ListExportsCommand,
149+
},
150+
151+
CloudWatch: {
152+
getMetricStatistics: GetMetricStatisticsCommand,
153+
},
154+
155+
CloudWatchLogs: {
156+
describeLogStreams: DescribeLogStreamsCommand,
157+
filterLogEvents: FilterLogEventsCommand,
158+
deleteSubscriptionFilter: DeleteSubscriptionFilterCommand,
159+
},
160+
161+
CognitoIdentityProvider: {
162+
listUserPools: ListUserPoolsCommand,
163+
describeUserPool: DescribeUserPoolCommand,
164+
updateUserPool: UpdateUserPoolCommand,
165+
},
166+
167+
ECR: {
168+
deleteRepository: DeleteRepositoryCommand,
169+
describeRepositories: DescribeRepositoriesCommand,
170+
getAuthorizationToken: GetAuthorizationTokenCommand,
171+
createRepository: CreateRepositoryCommand,
172+
describeImages: DescribeImagesCommand,
173+
},
174+
175+
EventBridge: {
176+
createEventBus: CreateEventBusCommand,
177+
deleteEventBus: DeleteEventBusCommand,
178+
putRule: PutRuleCommand,
179+
deleteRule: DeleteRuleCommand,
180+
putTargets: PutTargetsCommand,
181+
removeTargets: RemoveTargetsCommand,
182+
},
183+
184+
IAM: {
185+
getRole: GetRoleCommand,
186+
listAttachedRolePolicies: ListAttachedRolePoliciesCommand,
187+
createRole: CreateRoleCommand,
188+
attachRolePolicy: AttachRolePolicyCommand,
189+
},
190+
191+
Lambda: {
192+
getFunction: GetFunctionCommand,
193+
updateFunctionConfiguration: UpdateFunctionConfigurationCommand,
194+
updateFunctionCode: UpdateFunctionCodeCommand,
195+
invoke: InvokeCommand,
196+
listVersionsByFunction: ListVersionsByFunctionCommand,
197+
getLayerVersion: GetLayerVersionCommand,
198+
addPermission: AddPermissionCommand,
199+
removePermission: RemovePermissionCommand,
200+
},
201+
202+
S3: {
203+
listObjectsV2: ListObjectsV2Command,
204+
listObjectVersions: ListObjectVersionsCommand,
205+
deleteObjects: DeleteObjectsCommand,
206+
headObject: HeadObjectCommand,
207+
putObject: PutObjectCommand,
208+
getObject: GetObjectCommand,
209+
getBucketLocation: GetBucketLocationCommand,
210+
headBucket: HeadBucketCommand,
211+
getBucketNotificationConfiguration: GetBucketNotificationConfigurationCommand,
212+
putBucketNotificationConfiguration: PutBucketNotificationConfigurationCommand,
213+
// Note: upload is handled separately as it's not a direct API call
214+
},
215+
216+
SSM: {
217+
getParameter: GetParameterCommand,
218+
},
219+
220+
STS: {
221+
getCallerIdentity: GetCallerIdentityCommand,
222+
},
223+
};
224+
225+
/**
226+
* Get command class for a service method
227+
* @param {string} serviceName - AWS service name
228+
* @param {string} methodName - Method name from v2 SDK
229+
* @returns {Function} Command class constructor
230+
*/
231+
function getCommand(serviceName, methodName) {
232+
const serviceCommands = COMMAND_MAP[serviceName];
233+
if (!serviceCommands) {
234+
throw new Error(`Unknown AWS service: ${serviceName}`);
235+
}
236+
237+
const CommandClass = serviceCommands[methodName];
238+
if (!CommandClass) {
239+
throw new Error(`Unknown method '${methodName}' for service '${serviceName}'`);
240+
}
241+
242+
return CommandClass;
243+
}
244+
245+
/**
246+
* Create a command instance for a service method
247+
* @param {string} serviceName - AWS service name
248+
* @param {string} methodName - Method name from v2 SDK
249+
* @param {Object} params - Parameters for the command
250+
* @returns {Object} Command instance
251+
*/
252+
function createCommand(serviceName, methodName, params = {}) {
253+
const CommandClass = getCommand(serviceName, methodName);
254+
return new CommandClass(params);
255+
}
256+
257+
module.exports = {
258+
createCommand,
259+
};

0 commit comments

Comments
 (0)