Skip to content

Commit

Permalink
fix: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ServerlessLife committed May 9, 2024
1 parent 5c6fd0f commit 98bfcdd
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 182 deletions.
2 changes: 1 addition & 1 deletion src/infraDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ export async function deployInfrastructure() {
await Promise.all(promises);
}

export async function destroyInfrastructure() {
export async function removeInfrastructure() {
const promises: Promise<void>[] = [];

promises.push(deleteLayer());
Expand Down
10 changes: 5 additions & 5 deletions src/lldebugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export let resources: ResourcesToDebug;
let debuggerId: string;

export let argOptions: {
destroy?: boolean;
remove?: boolean;
verbose?: boolean;
context?: string;
profile?: string;
Expand All @@ -43,7 +43,7 @@ async function run() {

program.name("lld").description("Lambda Live Debugger").version(version);

program.option("-d, --destroy", "Destroy the infrastructure");
program.option("-r, --remove", "Remove Lambda Live Debugger infrastructure");
program.option("-v, --verbose", "Verbose logs");
program.option("-c, --context <context>", "AWS CDK context");
program.option("--profile <profile>", "AWS profile to use");
Expand Down Expand Up @@ -72,9 +72,9 @@ async function run() {
);

console.log("ARGUMENTS", argOptions);
if (argOptions.destroy) {
console.log("Destroying infrastructure...");
await InfraDeploy.destroyInfrastructure();
if (argOptions.remove) {
console.log("Removing Lambda Live Debugger infrastructure...");
await InfraDeploy.removeInfrastructure();
return;
}

Expand Down
222 changes: 46 additions & 176 deletions test/cdk-simple.test.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,32 @@
import { expect, test, describe, beforeAll, afterAll } from "vitest";
import { ChildProcess, exec, execSync, spawn } from "child_process";
import { IAMClient, GetRolePolicyCommand } from "@aws-sdk/client-iam";
import { promisify } from "util";
import { ChildProcess } from "child_process";
import fs from "fs/promises";
import {
LambdaClient,
GetFunctionCommand,
InvokeCommand,
} from "@aws-sdk/client-lambda";
import { setTimeout } from "timers/promises";
import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";
import { startDebugger } from "./utils/startDebugger";
import { expectInfraIsRemoved } from "./utils/expectInfraIsRemoved";
import { expectInfraIsDeployed } from "./utils/expectInfraIsDeployed";
import { removeInfra } from "./utils/removeInfra";
import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);
export const execAsync = promisify(exec);

describe("cdk-simple", () => {
const sampleFolder = "test/cdk-simple";
const folder = "test/cdk-simple";
let lldProcess: ChildProcess | undefined;

beforeAll(async () => {
if (process.env.CI === "true" || process.env.RUN_TEST_FROM_CLI === "true") {
if (process.env.CI === "true") {
await execAsync("npm run destroy", {
cwd: sampleFolder,
cwd: folder,
});
}

await execAsync("npm run deploy", {
cwd: sampleFolder,
});

console.log("Starting LLD...");

lldProcess = spawn("node ../../dist/lldebugger.js -c=environment=test", {
cwd: sampleFolder,
shell: true,
cwd: folder,
});

// wait for the debugger to start

await new Promise((resolve, reject) => {
let errorWhileRunning = false;
if (!lldProcess) {
throw new Error("Failed to start LLD");
}

lldProcess.stdout?.on("data", (data) => {
console.log("LLD: " + data.toString());
const line = data.toString();
if (line.includes("IoT connected")) {
resolve(true);
}
});
lldProcess.stderr?.on("data", (data) => {
console.log("LLD ERROR: " + data.toString());
errorWhileRunning = true;
});
lldProcess.on("close", (error) => {
console.log(`LLD CLOSED: error=${errorWhileRunning}`);
if (error) {
reject(error);
} else {
resolve(true);
}
});
});
await setTimeout(5000);
lldProcess = await startDebugger(folder);
}
});

Expand All @@ -73,46 +36,18 @@ describe("cdk-simple", () => {
});

test("check infra", async () => {
if (process.env.CI === "true" || process.env.RUN_TEST_FROM_CLI === "true") {
const lambdaName = await getTestFunctionName(sampleFolder);
const lambdaConfiguration = await getFuntion(lambdaName);
const roleArn = lambdaConfiguration.Configuration?.Role;
const policyDocument = await getPolicyDocument(roleArn);

expect(
lambdaConfiguration.Configuration?.Environment?.Variables
).toMatchObject({
AWS_LAMBDA_EXEC_WRAPPER: "/opt/lld-wrapper",
LLD_DEBUGGER_ID: expect.any(String),
LLD_FUNCTION_ID: expect.any(String),
LLD_INITIAL_TIMEOUT: "3",
NODE_OPTIONS: "--enable-source-maps",
});

expect(lambdaConfiguration.Configuration?.Layers?.length).toEqual(1);

expect(lambdaConfiguration.Configuration?.Layers![0].Arn).toContain(
":layer:LambdaLiveDebugger:"
);
expect(policyDocument).toEqual({
Statement: [
{
Action: "iot:*",
Effect: "Allow",
Resource: "*",
},
],
Version: "2012-10-17",
});
}
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestTsCommonJs"
);
await expectInfraIsDeployed(lambdaName);
});

test("call Lambda - testTsCommon", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestTsCommonJs"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestTsCommonJs;

const now = new Date().toISOString();

Expand All @@ -136,11 +71,10 @@ describe("cdk-simple", () => {
});

test("call Lambda - testTsEsModule", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestTsEsModule"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestTsEsModule;

const now = new Date().toISOString();

Expand All @@ -164,11 +98,10 @@ describe("cdk-simple", () => {
});

test("call Lambda - testJsCommonJs", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestJsCommonJs"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestJsCommonJs;

const now = new Date().toISOString();

Expand All @@ -192,11 +125,10 @@ describe("cdk-simple", () => {
});

test("call Lambda - testJsEsModule", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestJsEsModule"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestJsEsModule;

const now = new Date().toISOString();

Expand All @@ -220,11 +152,10 @@ describe("cdk-simple", () => {
});

test("call Lambda - testJsCommonJsBase", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestJsCommonJsBase"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestJsCommonJsBase;

const now = new Date().toISOString();

Expand All @@ -247,13 +178,11 @@ describe("cdk-simple", () => {
expect(response.runningLocaly).toEqual("true");
});

//testJsEsModuleBase
test("call Lambda - testJsEsModuleBase", async () => {
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestJsEsModuleBase"
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestJsEsModuleBase;

const now = new Date().toISOString();

Expand All @@ -276,82 +205,23 @@ describe("cdk-simple", () => {
expect(response.runningLocaly).toEqual("true");
});

test("destroy infra", async () => {
test("remove infra", async () => {
if (process.env.CI === "true" || process.env.RUN_TEST_FROM_CLI === "true") {
lldProcess?.kill();

await execSync("node ../../dist/lldebugger.js --destroy", {
cwd: sampleFolder,
});

await setTimeout(6000);

const lambdaName = await getTestFunctionName(sampleFolder);
const lambdaConfiguration = await getFuntion(lambdaName);
const roleArn = lambdaConfiguration.Configuration?.Role;
const policyDocument = await getPolicyDocument(roleArn);

expect(lambdaConfiguration.Configuration?.Environment)
.toMatchInlineSnapshot(`
{
"Variables": {
"AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1",
},
}
`);
expect(lambdaConfiguration.Configuration?.Layers).toBeUndefined();
expect(policyDocument).toBeUndefined();
await removeInfra(lldProcess, folder);
const lambdaName = await getCdkFunctionName(
folder,
"FunctionNameTestTsCommonJs"
);
await expectInfraIsRemoved(lambdaName);
}
});
});

async function getTestFunctionName(sampleFolder: string) {
export async function getCdkFunctionName(folder: string, functionName: string) {
// read lambda configuration using LambdaClient
const cdkOutputs = JSON.parse(
await fs.readFile(`${sampleFolder}/cdk-outputs.json`, "utf-8")
await fs.readFile(`${folder}/cdk-outputs.json`, "utf-8")
);
const lambdaName =
cdkOutputs["test-lld-cdk-simple"].FunctionNameTestTsCommonJs;
const lambdaName = cdkOutputs["test-lld-cdk-simple"][functionName];
return lambdaName;
}

const iamClient = new IAMClient({});

async function getPolicyDocument(roleArn: string | undefined) {
try {
const roleName = roleArn!.split("/").pop();

const policy = await iamClient.send(
new GetRolePolicyCommand({
RoleName: roleName,
PolicyName: "LambdaLiveDebuggerPolicy",
})
);

if (policy.PolicyDocument) {
const policyDocument = JSON.parse(
decodeURIComponent(policy.PolicyDocument)
);
return policyDocument;
} else {
return undefined;
}
} catch (error: any) {
if (error.name === "NoSuchEntityException") {
return undefined;
} else {
throw error;
}
}
}

const lambdaClient = new LambdaClient({});

async function getFuntion(lambdaName: any) {
const lambdaConfiguration = await lambdaClient.send(
new GetFunctionCommand({
FunctionName: lambdaName,
})
);
return lambdaConfiguration;
}
37 changes: 37 additions & 0 deletions test/utils/expectInfraIsDeployed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect } from "vitest";
import { getFuntionConfiguration } from "./getFuntionConfiguration";
import { getPolicyDocument } from "./getPolicyDocument";

export async function expectInfraIsDeployed(lambdaName: any) {
if (process.env.CI === "true" || process.env.RUN_TEST_FROM_CLI === "true") {
const lambdaConfiguration = await getFuntionConfiguration(lambdaName);
const roleArn = lambdaConfiguration.Configuration?.Role;
const policyDocument = await getPolicyDocument(roleArn);

expect(
lambdaConfiguration.Configuration?.Environment?.Variables
).toMatchObject({
AWS_LAMBDA_EXEC_WRAPPER: "/opt/lld-wrapper",
LLD_DEBUGGER_ID: expect.any(String),
LLD_FUNCTION_ID: expect.any(String),
LLD_INITIAL_TIMEOUT: "3",
NODE_OPTIONS: "--enable-source-maps",
});

expect(lambdaConfiguration.Configuration?.Layers?.length).toEqual(1);

expect(lambdaConfiguration.Configuration?.Layers![0].Arn).toContain(
":layer:LambdaLiveDebugger:"
);
expect(policyDocument).toEqual({
Statement: [
{
Action: "iot:*",
Effect: "Allow",
Resource: "*",
},
],
Version: "2012-10-17",
});
}
}
Loading

0 comments on commit 98bfcdd

Please sign in to comment.