Skip to content

Commit

Permalink
syncing up to fbe396f906bdfca9bb0d4510edcfa691f4919678
Browse files Browse the repository at this point in the history
Co-authored-by: Joey Greco <[email protected]>
Co-authored-by: Bruce Yu <[email protected]>
  • Loading branch information
3 people committed Oct 28, 2024
1 parent 228d15b commit 0d42a5f
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 122 deletions.
268 changes: 163 additions & 105 deletions postman/collection.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions workers/javascript/packages/plugins/s3/src/index.new.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,26 @@ function propsFromConfigs({
}

describe('execute', () => {
describe('list files', () => {
describe('list bucket objects', () => {
it.each([
{
description: 'happy path no prefix or delimiter',
datasourceConfiguration: { awsAuthType: AWSAuthType.ACCESS_KEY },
actionConfiguration: { action: S3ActionType.LIST_OBJECTS, resource: 'foo' },
actionConfiguration: { action: S3ActionType.LIST_BUCKET_OBJECTS, resource: 'foo' },
mockSendResponse: { Contents: { foo: 'bar' } },
expectedListRequest: { Bucket: 'foo' }
},
{
description: 'happy path with prefix and no delimiter',
datasourceConfiguration: { awsAuthType: AWSAuthType.ACCESS_KEY },
actionConfiguration: { action: S3ActionType.LIST_OBJECTS, resource: 'foo', listFilesConfig: { delimiter: 'd' } },
actionConfiguration: { action: S3ActionType.LIST_BUCKET_OBJECTS, resource: 'foo', listFilesConfig: { delimiter: 'd' } },
mockSendResponse: { Contents: { foo: 'bar' } },
expectedListRequest: { Bucket: 'foo', Delimiter: 'd' }
},
{
description: 'happy path with delimiter and no prefix',
datasourceConfiguration: { awsAuthType: AWSAuthType.ACCESS_KEY },
actionConfiguration: { action: S3ActionType.LIST_OBJECTS, resource: 'foo', listFilesConfig: { prefix: 'p' } },
actionConfiguration: { action: S3ActionType.LIST_BUCKET_OBJECTS, resource: 'foo', listFilesConfig: { prefix: 'p' } },
mockSendResponse: { Contents: { foo: 'bar' } },
expectedListRequest: { Bucket: 'foo', Prefix: 'p' }
}
Expand Down
19 changes: 17 additions & 2 deletions workers/javascript/packages/plugins/s3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
S3DatasourceConfiguration
} from '@superblocks/shared';

import { getS3ClientConfig, buildListObjectsV2Command } from './utils';
import { getS3ClientConfig, buildListObjectsV2Command, validateS3Action } from './utils';

export default class S3Plugin extends BasePlugin {
pluginName = 'S3';
Expand All @@ -47,20 +47,35 @@ export default class S3Plugin extends BasePlugin {
try {
const s3Client = await this.getS3Client(datasourceConfiguration);
const s3Action = actionConfiguration.action;
validateS3Action(s3Action);
const configuration = actionConfiguration;
const ret = new ExecutionOutput();
// TODO: Clean this up with a switch statement.
if (s3Action === S3ActionType.LIST_OBJECTS) {
ret.logWarn(
`${S3_ACTION_DISPLAY_NAMES[s3Action]} has been deprecated, use ${S3_ACTION_DISPLAY_NAMES[S3ActionType.LIST_BUCKET_OBJECTS]} instead`
);
if (!configuration.resource) {
throw new IntegrationError('Resource required for list objects', ErrorCode.INTEGRATION_MISSING_REQUIRED_FIELD, {
pluginName: this.pluginName
});
}
const data = await this.listObjects(s3Client, new ListObjectsV2Command(buildListObjectsV2Command(configuration)));
const data = await this.listObjects(s3Client, new ListObjectsV2Command({ Bucket: configuration.resource }));
ret.output = data.Contents;
} else if (s3Action === S3ActionType.LIST_BUCKETS) {
const data = await this.listBuckets(s3Client);
ret.output = data.Buckets;
} else if (s3Action === S3ActionType.LIST_BUCKET_OBJECTS) {
if (!configuration.resource) {
throw new IntegrationError(
`Resource required for ${S3_ACTION_DISPLAY_NAMES[s3Action]}`,
ErrorCode.INTEGRATION_MISSING_REQUIRED_FIELD,
{
pluginName: this.pluginName
}
);
}
ret.output = await this.listObjects(s3Client, new ListObjectsV2Command(buildListObjectsV2Command(configuration)));
} else if (s3Action === S3ActionType.GET_OBJECT) {
if (!configuration.resource) {
throw new IntegrationError('Resource required for get objects', ErrorCode.INTEGRATION_MISSING_REQUIRED_FIELD, {
Expand Down
27 changes: 25 additions & 2 deletions workers/javascript/packages/plugins/s3/src/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AWSAuthType } from '@superblocks/shared';
import { buildListObjectsV2Command, getS3ClientConfig } from './utils';
import { AWSAuthType, S3ActionType } from '@superblocks/shared';
import { buildListObjectsV2Command, getS3ClientConfig, validateS3Action } from './utils';

describe('getS3ClientConfig', () => {
it.each([
Expand Down Expand Up @@ -46,3 +46,26 @@ describe('buildListObjectsV2Command', () => {
expect(expectedResponse).toEqual(actualResponse);
});
});

describe('validateS3Action', () => {
const allActionsTestCases = Object.values(S3ActionType).map((action) => ({
description: `valid action: ${action}`,
action,
shouldError: false
}));

it.each([
...allActionsTestCases,
{
description: 'invalid action',
action: 'foo',
shouldError: true
}
])('$description', ({ action, shouldError }) => {
if (shouldError) {
expect(() => validateS3Action(action)).toThrow(`Invalid S3 action type: ${action}`);
} else {
expect(() => validateS3Action(action)).not.toThrow();
}
});
});
8 changes: 7 additions & 1 deletion workers/javascript/packages/plugins/s3/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { S3ClientConfig, ListObjectsV2CommandInput } from '@aws-sdk/client-s3';
import { S3ActionConfiguration, S3DatasourceConfiguration } from '@superblocks/shared';
import { S3ActionConfiguration, S3DatasourceConfiguration, S3ActionType } from '@superblocks/shared';
export function getS3ClientConfig(datasourceConfig: S3DatasourceConfiguration): S3ClientConfig {
const config: S3ClientConfig = {};
if (datasourceConfig?.endpoint) {
Expand All @@ -25,3 +25,9 @@ export function buildListObjectsV2Command(actionConfig: S3ActionConfiguration):
}
return commandInput;
}

export function validateS3Action(action: string) {
if (!Object.values(S3ActionType).includes(action as S3ActionType)) {
throw new Error(`Invalid S3 action type: ${action}`);
}
}
14 changes: 6 additions & 8 deletions workers/javascript/packages/shared/src/plugins/templates/s3.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
export const S3PluginVersions = {
V1: '0.0.1',
V5: '0.0.5',
V6: '0.0.6',
V10: '0.0.10'
};

export enum S3ActionType {
/**
* @deprecated Use LIST_BUCKET_OBJECTS instead.
*/
LIST_OBJECTS = 'LIST_OBJECTS',
LIST_BUCKET_OBJECTS = 'LIST_BUCKET_OBJECTS',
GET_OBJECT = 'GET_OBJECT',
DELETE_OBJECT = 'DELETE_OBJECT',
UPLOAD_OBJECT = 'UPLOAD_OBJECT',
Expand All @@ -17,7 +14,8 @@ export enum S3ActionType {
}

export const S3_ACTION_DISPLAY_NAMES: Record<S3ActionType, string> = {
[S3ActionType.LIST_OBJECTS]: 'List files',
[S3ActionType.LIST_OBJECTS]: 'List files (deprecated)',
[S3ActionType.LIST_BUCKET_OBJECTS]: 'List bucket objects',
[S3ActionType.GET_OBJECT]: 'Read file',
[S3ActionType.DELETE_OBJECT]: 'Delete files',
[S3ActionType.UPLOAD_OBJECT]: 'Upload file',
Expand Down

0 comments on commit 0d42a5f

Please sign in to comment.