Skip to content

Commit

Permalink
Fix integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rddimon committed Jan 4, 2024
1 parent d73b004 commit 35538f1
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 41 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [3.2.0] - 2024-01-04

### Fixed

- Added plugin schema to fix serverless warning. Thank you @crunchie84 ([74](https://github.com/amplify-education/serverless-log-forwarding/pull/74))
- Refactored integration tests
- Updated linting
- Updated packages

## [3.1.0] - 2023-02-17

### Added
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serverless-log-forwarding",
"version": "3.1.0",
"version": "3.2.0",
"description": "a serverless plugin to forward logs to given lambda function",
"keywords": [
"serverless",
Expand Down
36 changes: 18 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,42 +46,42 @@ class LogForwardingPlugin {
}

// schema for the function section of serverless.yml
this.serverless.configSchemaHandler.defineFunctionProperties('aws', {
this.serverless.configSchemaHandler.defineFunctionProperties("aws", {
properties: {
logForwarding: {
type: 'object',
type: "object",
properties: {
enabled: {
type: 'boolean',
},
type: "boolean"
}
},
required: ['enabled'],
},
required: ["enabled"]
}
},
required: [],
required: []
});

// schema for the custom props section of serverless.yml
this.serverless.configSchemaHandler.defineCustomProperties({
properties: {
logForwarding: {
type: 'object',
type: "object",
properties: {
destinationARN: { type: 'string' },
roleArn: { type: 'string' },
filterPattern: { type: 'string' },
normalizedFilterID: { type: 'string' },
destinationARN: { type: "string" },
roleArn: { type: "string" },
filterPattern: { type: "string" },
normalizedFilterID: { type: "string" },
stages: {
type: 'array',
type: "array",
uniqueItems: true,
items: { type: 'string' },
items: { type: "string" }
},
createLambdaPermission: { type: 'boolean' },
createLambdaPermission: { type: "boolean" }
},
required: ['destinationARN'],
},
required: ["destinationARN"]
}
},
required: ['logForwarding'],
required: ["logForwarding"]
});
}

Expand Down
58 changes: 57 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,62 @@ export interface PluginConfig {
destinationARN: string;
}

/**
* If your plugin adds new properties to any level in the serverless.yml
* you can use these functions to add JSON ajv based schema validation for
* those properties
*
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration
*/
export interface ConfigSchemaHandler {
/**
* If your plugin requires additional top-level properties (like provider, custom, service...)
* you can use the defineTopLevelProperty helper to add their definition.
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#top-level-properties-via-definetoplevelproperty
*/
defineTopLevelProperty(
providerName: string,
schema: Record<string, unknown>
): void;
/**
* If your plugin depends on properties defined in the custom: section, you can use the
* defineCustomProperties helper
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#properties-in-custom-via-definecustomproperties
*/
defineCustomProperties(jsonSchema: object): void;
/**
* If your plugin adds support to a new function event, you can use the
* defineFunctionEvent helper
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#function-events-via-definefunctionevent
*/
defineFunctionEvent(
providerName: string,
event: string,
jsonSchema: Record<string, object>
): void;
/**
* If your plugin adds new properties to a function event, you can use the
* defineFunctionEventProperties helper
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#function-event-properties-via-definefunctioneventproperties
*/
defineFunctionEventProperties(
providerName: string,
existingEvent: string,
jsonSchema: object
): void;
/**
* If your plugin adds new properties to functions, you can use the
* defineFunctionProperties helper.
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#function-properties-via-definefunctionproperties
*/
defineFunctionProperties(providerName: string, schema: object): void;
/**
* If your plugin provides support for a new provider, register it via defineProvider
* @see https://www.serverless.com/framework/docs/guides/plugins/custom-configuration#new-provider-via-defineprovider
*/
defineProvider(providerName: string, options?: Record<string, unknown>): void;
}

export interface ServerlessInstance {
service: {
service: string
Expand All @@ -55,7 +111,7 @@ export interface ServerlessInstance {
},

getProvider (name: string): AWSProvider,

configSchemaHandler: ConfigSchemaHandler;
cli: {
log (str: string, entity?: string): void,
consoleLog (str: string): void,
Expand Down
12 changes: 10 additions & 2 deletions test/integration-tests/utils/aws/lambda-wrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import {
GetPolicyResponse,
LambdaClient, RemovePermissionCommand
} from "@aws-sdk/client-lambda";
import { sleep } from "../test-utilities";

const FUNC_ZIP_PATH = "test/integration-tests/fixtures/logs-receiver.zip";
const MAX_FUNC_ACTIVE_RETRY = 3;
const FUNC_ACTIVE_TIMEOUT_SEC = 10;

export default class LambdaWrap {
private lambdaClient: LambdaClient;
Expand All @@ -37,13 +40,18 @@ export default class LambdaWrap {
}));
}

async ensureFunctionActive (funcName: string): Promise<void> {
async ensureFunctionActive (funcName: string, retry: number = 1): Promise<void> {
if (retry > MAX_FUNC_ACTIVE_RETRY) {
throw new Error("Max retry reached");
}

const resp: GetFunctionResponse = await this.lambdaClient.send(new GetFunctionCommand({
FunctionName: funcName
}));

if (resp.Configuration.State !== "Active") {
throw new Error("retry");
await sleep(FUNC_ACTIVE_TIMEOUT_SEC * 1000);
await this.ensureFunctionActive(funcName, retry + 1);
}
}

Expand Down
7 changes: 0 additions & 7 deletions test/integration-tests/utils/aws/log-wrap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
CloudWatchLogsClient,
DeleteLogGroupCommand,
DescribeSubscriptionFiltersCommand,
SubscriptionFilter
} from "@aws-sdk/client-cloudwatch-logs";
Expand All @@ -12,12 +11,6 @@ export default class LogWrap {
this.cwlClient = new CloudWatchLogsClient({ region });
}

async removeLambdaLogs (logGroupName: string) {
await this.cwlClient.send(new DeleteLogGroupCommand({
logGroupName: logGroupName
}));
}

async getSubscriptionFilter (logGroupName: string, destinationArn: string): Promise<SubscriptionFilter | null> {
const { subscriptionFilters } = await this.cwlClient.send(new DescribeSubscriptionFiltersCommand({
logGroupName: logGroupName
Expand Down
16 changes: 4 additions & 12 deletions test/integration-tests/utils/log-receiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import IamWrap from "./aws/iam-wrap";
import LambdaWrap from "./aws/lambda-wrap";
import LogWrap from "./aws/log-wrap";
import { sleep } from "./test-utilities";

/**
* Interface for the immutable objects with information about
Expand Down Expand Up @@ -37,11 +38,11 @@ export default class LogReceiver {
* that it's active. Returns the information about objects.
*/
public async setUpLogsReceiver (): Promise<LogsReceiverData> {
// setup lambda role
const role = await this.iamWrap.setupLambdaRole(this.resourceName);
// eslint-disable-next-line no-promise-executor-return,promise/param-names
// await new Promise((r) => setTimeout(r, 10000));
// we need to wait around 10 seconds to use the role
await sleep(10 * 1000);
const funcData = await this.lambdaWrap.createDummyFunction(this.resourceName, role.Arn);

await this.lambdaWrap.ensureFunctionActive(funcData.FunctionName);

return {
Expand All @@ -59,21 +60,12 @@ export default class LogReceiver {
await this.lambdaWrap.removeFunction(this.resourceName);
console.debug("Logs receiver lambda was deleted");
} catch (e) {
console.error(e);
console.debug("Failed to delete a logs receiver");
}
try {
await this.logWrap.removeLambdaLogs(`/aws/lambda/${this.resourceName}`);
console.log("Log receiver's log group was deleted");
} catch (e) {
console.error(e);
console.debug("Failed to delete a logs receiver's log group");
}
try {
await this.iamWrap.removeLambdaRole(this.resourceName);
console.log("Log receiver's role was deleted");
} catch (e) {
console.error(e);
console.debug("Failed to delete the execution role");
}
}
Expand Down
4 changes: 4 additions & 0 deletions test/integration-tests/utils/test-utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ export function getLogGroup (testName: string, stage: string, functionId: string
return `/aws/lambda/${functionName}`;
}

export function sleep (ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

export async function runTest (testName: string, assertFunc): Promise<void> {
try {
const configFolder = `configs/${testName}`;
Expand Down

0 comments on commit 35538f1

Please sign in to comment.