Skip to content

Commit

Permalink
Merge branch 'main' into go-cognito-lambda-triggers
Browse files Browse the repository at this point in the history
  • Loading branch information
beqqrry-aws authored Apr 30, 2024
2 parents 28c6ce3 + 50b7b4c commit 98b6028
Show file tree
Hide file tree
Showing 71 changed files with 425 additions and 9,770 deletions.
9 changes: 4 additions & 5 deletions .git-hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/sh

set -e

tag="[PRE-COMMIT]"

log() {
Expand All @@ -21,11 +23,8 @@ for dir in * ; do
(cd "$dir" || exit

log "Working from $(pwd)..."
if ! "./hook_scripts/pre-commit.sh" ; then
log "$dir's pre-commit hook failed."
exit 1
fi)
./hook_scripts/pre-commit.sh)
fi
fi
fi
done
done
6 changes: 6 additions & 0 deletions javascriptv3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ You can run tests for a specific service, or for every service in this repositor

If you run tests using the preceding commands, output will be stored in `unit_test.log` or `integration_test.log`. Errors are still logged to the console.

## Linting
You can run ESLint to statically check for errors.

To run ESLint, use the following command:
`npm run ci-lint .`

## Docker image (Beta)

This example is available in a container image hosted on [Amazon Elastic Container Registry (ECR)](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html). This image will be pre-loaded with all JavaScript v3 examples with dependencies pre-resolved. It is used for running tests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,31 @@
import { log } from "../log.js";

/** snippet-start:[javascript.v3.glue.scenarios.basic.CleanUpDatabasesStep] */
/**
* @param {import('../../../actions/delete-database.js').deleteDatabase} deleteDatabase
* @param {string[]} databaseNames
*/
const deleteDatabases = (deleteDatabase, databaseNames) =>
Promise.all(
databaseNames.map((dbName) => deleteDatabase(dbName).catch(console.error))
databaseNames.map((dbName) => deleteDatabase(dbName).catch(console.error)),
);

/**
* @param {{
* getDatabases: import('../../../actions/get-databases.js').getDatabases
* deleteDatabase: import('../../../actions/delete-database.js').deleteDatabase
* }} config
*/
const makeCleanUpDatabasesStep =
({ getDatabases, deleteDatabase }) =>
/**
* @param {{ prompter: { prompt: () => Promise<any>}} context
*/
async (context) => {
const { DatabaseList } = await getDatabases();

if (DatabaseList.length > 0) {
/** @type {{ dbNames: string[] }} */
const { dbNames } = await context.prompter.prompt({
name: "dbNames",
type: "checkbox",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@
import { log } from "../log.js";

/** snippet-start:[javascript.v3.glue.scenarios.basic.CleanUpJobsStep] */
/**
*
* @param {import('../../../actions/delete-job.js').deleteJob} deleteJobFn
* @param {string[]} jobNames
* @param {{ prompter: { prompt: () => Promise<any> }}} context
*/
const handleDeleteJobs = async (deleteJobFn, jobNames, context) => {
/**
* @type {{ selectedJobNames: string[] }}
*/
const { selectedJobNames } = await context.prompter.prompt({
name: "selectedJobNames",
type: "checkbox",
Expand All @@ -17,12 +26,18 @@ const handleDeleteJobs = async (deleteJobFn, jobNames, context) => {
} else {
log("Deleting jobs.");
await Promise.all(
selectedJobNames.map((n) => deleteJobFn(n).catch(console.error))
selectedJobNames.map((n) => deleteJobFn(n).catch(console.error)),
);
log("Jobs deleted.", { type: "success" });
}
};

/**
* @param {{
* listJobs: import('../../../actions/list-jobs.js').listJobs,
* deleteJob: import('../../../actions/delete-job.js').deleteJob
* }} config
*/
const makeCleanUpJobsStep =
({ listJobs, deleteJob }) =>
async (context) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,38 @@
import { log } from "../log.js";

/** snippet-start:[javascript.v3.glue.scenarios.basic.CleanUpTablesStep] */
/**
* @param {import('../../../actions/delete-table.js').deleteTable} deleteTable
* @param {string} databaseName
* @param {string[]} tableNames
*/
const deleteTables = (deleteTable, databaseName, tableNames) =>
Promise.all(
tableNames.map((tableName) =>
deleteTable(databaseName, tableName).catch(console.error)
)
deleteTable(databaseName, tableName).catch(console.error),
),
);

/**
* @param {{
* getTables: import('../../../actions/get-tables.js').getTables,
* deleteTable: import('../../../actions/delete-table.js').deleteTable
* }} config
*/
const makeCleanUpTablesStep =
({ getTables, deleteTable }) =>
/**
* @param {{ prompter: { prompt: () => Promise<any>}}} context
*/
async (context) => {
const { TableList } = await getTables(process.env.DATABASE_NAME).catch(
() => ({ TableList: null })
() => ({ TableList: null }),
);

if (TableList && TableList.length > 0) {
/**
* @type {{ tableNames: string[] }}
*/
const { tableNames } = await context.prompter.prompt({
name: "tableNames",
type: "checkbox",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const crawlerExists = async ({ getCrawler }, crawlerName) => {
}
};

/**
* @param {{ createCrawler: import('../../../actions/create-crawler.js').createCrawler}} actions
*/
const makeCreateCrawlerStep = (actions) => async (context) => {
if (await crawlerExists(actions, process.env.CRAWLER_NAME)) {
log("Crawler already exists. Skipping creation.");
Expand All @@ -21,7 +24,7 @@ const makeCreateCrawlerStep = (actions) => async (context) => {
process.env.ROLE_NAME,
process.env.DATABASE_NAME,
process.env.TABLE_PREFIX,
process.env.S3_TARGET_PATH
process.env.S3_TARGET_PATH,
);

log("Crawler created successfully.", { type: "success" });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import { log } from "../log.js";

/** snippet-start:[javascript.v3.glue.scenarios.basic.GetTablesStep] */
/**
* @param {{ getTables: () => Promise<import('@aws-sdk/client-glue').GetTablesCommandOutput}} config
*/
const makeGetTablesStep =
({ getTables }) =>
async (context) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,36 @@
import { log } from "../log.js";

/** snippet-start:[javascript.v3.glue.scenarios.basic.PickJobRunStep] */
/**
* @typedef {{ prompter: { prompt: () => Promise<{jobName: string}> } }} Context
*/

/**
* @typedef {() => Promise<import('@aws-sdk/client-glue').GetJobRunCommandOutput>} getJobRun
*/

/**
* @typedef {() => Promise<import('@aws-sdk/client-glue').GetJobRunsCommandOutput} getJobRuns
*/

/**
*
* @param {getJobRun} getJobRun
* @param {string} jobName
* @param {string} jobRunId
*/
const logJobRunDetails = async (getJobRun, jobName, jobRunId) => {
const { JobRun } = await getJobRun(jobName, jobRunId);
log(JobRun, { type: "object" });
};

/**
*
* @param {{getJobRuns: getJobRuns, getJobRun: getJobRun }} funcs
*/
const makePickJobRunStep =
({ getJobRuns, getJobRun }) =>
async (context) => {
async (/** @type { Context } */ context) => {
if (context.selectedJobName) {
const { JobRuns } = await getJobRuns(context.selectedJobName);

Expand Down
11 changes: 9 additions & 2 deletions javascriptv3/example_code/glue/scenarios/basic/steps/pick-job.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

/**
* @typedef {() => Promise<import('@aws-sdk/client-glue').ListJobsCommandOutput>} listJobs
*/

/**
* @typedef {{ prompter: { prompt: () => Promise<{jobName: string}> } }} Context
*/

const makePickJobStep =
({ listJobs }) =>
async (context) => {
(/** @type { {listJobs: listJobs } } */ { listJobs }) =>
async (/** @type { Context } */ context) => {
const { JobNames } = await listJobs();

if (JobNames.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@ const keys = [
"JOB_NAME",
];

const validateEnv = async (context) => {
log("Checking if environment variables exist.");
const validateEnv = (context) => {
return new Promise((resolve, reject) => {
log("Checking if environment variables exist.");

if (!context || !process.env) {
throw new Error("Missing context.");
}

keys.forEach((key) => {
if (!process.env[key]) {
throw new Error(`Missing environment variable. No value for ${key}.`);
if (!context || !process.env) {
reject(new Error("Missing context."));
}
});

log("Variables exist.", { type: "success" });
return { ...context };
keys.forEach((key) => {
if (!process.env[key]) {
reject(new Error(`Missing environment variable. No value for ${key}.`));
}
});

log("Variables exist.", { type: "success" });
resolve({ ...context });
});
};

export { validateEnv, keys };
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@

import { log } from "../log.js";

const findPythonScript = async (s3ListObjects, bucketName) => {
/**
* @typedef {() => Promise<import('@aws-sdk/client-s3').ListObjectsCommandOutput>} listObjects
*/

const findPythonScript = async (
/** @type {listObjects} */ s3ListObjects,
bucketName,
) => {
try {
const { Contents } = await s3ListObjects(bucketName);
const script = Contents.find(
(obj) => obj.Key === process.env.PYTHON_SCRIPT_KEY
(obj) => obj.Key === process.env.PYTHON_SCRIPT_KEY,
);
return !!script;
} catch {
Expand All @@ -21,15 +28,15 @@ const makeValidatePythonScriptStep =
log("Checking if ETL python script exists.");
const scriptExists = await findPythonScript(
s3ListObjects,
process.env.BUCKET_NAME
process.env.BUCKET_NAME,
);

if (scriptExists) {
log("ETL python script exists.", { type: "success" });
return { ...context };
} else {
throw new Error(
"Missing ETL python script. Did you run the setup steps in the readme?"
"Missing ETL python script. Did you run the setup steps in the readme?",
);
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ describe("clean-up-crawler", () => {
});

it('should not throw an error if the delete fails with an "EntityNotFoundException"', () => {
vi.spyOn(GlueClient.prototype, "send").mockImplementationOnce(async () => {
vi.spyOn(GlueClient.prototype, "send").mockImplementationOnce(() => {
const err = new Error();
err.name = "EntityNotFoundException";
throw err;
return Promise.reject(err);
});

return expect(cleanUpCrawlerStep({})).resolves.toBeTruthy();
});

it('should throw an error if the delete fails with an error other than "EntityNotFoundException"', () => {
vi.spyOn(GlueClient.prototype, "send").mockImplementationOnce(async () => {
vi.spyOn(GlueClient.prototype, "send").mockImplementationOnce(() => {
const err = new Error();
err.name = "SomeOtherError";
throw err;
return Promise.reject(err);
});

return expect(cleanUpCrawlerStep({})).rejects.toBeTruthy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { mockPrompter } from "./mock-prompter.js";

describe("clean-up-databases", () => {
it("should not ask, or attempt, to delete, any databases if none are found", () => {
const getDatabases = vi.fn(async () => ({ DatabaseList: [] }));
const getDatabases = vi.fn(() => Promise.resolve({ DatabaseList: [] }));
const deleteDatabase = vi.fn(async (_dbName) => {});
const prompter = mockPrompter();
const cleanUpDatabasesStep = makeCleanUpDatabasesStep({
Expand All @@ -21,9 +21,11 @@ describe("clean-up-databases", () => {
});

it("should ask to delete, and delete, databases if any are found", async () => {
const getDatabases = vi.fn(async () => ({
DatabaseList: [{ Name: "db1" }],
}));
const getDatabases = vi.fn(() =>
Promise.resolve({
DatabaseList: [{ Name: "db1" }],
}),
);
const deleteDatabase = vi.fn(async (_dbName) => {});
const prompter = mockPrompter({ dbNames: ["db1"] });

Expand All @@ -38,7 +40,7 @@ describe("clean-up-databases", () => {
});

it("should return a context object", async () => {
const getDatabases = vi.fn(async () => ({ DatabaseList: [] }));
const getDatabases = vi.fn(() => Promise.resolve({ DatabaseList: [] }));
const deleteDatabase = vi.fn(async () => {});
const actions = { getDatabases, deleteDatabase };

Expand Down
Loading

0 comments on commit 98b6028

Please sign in to comment.