diff --git a/README.md b/README.md index 114537c..e0ec513 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is a [plugin](https://arc.codes/docs/en/guides/plugins/overview) for [Architect](https://arc.codes/) that provisions managed [Amazon OpenSearch](https://aws.amazon.com/opensearch-service/) for the application. -When you are using Architect's [sandbox](https://arc.codes/docs/en/reference/cli/sandbox) mode, the plugin [downloads and runs Elasticsearch locally](https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html#elasticsearch-install-packages). +When you are using Architect's [sandbox](https://arc.codes/docs/en/reference/cli/sandbox) mode, the plugin [downloads and runs OpenSearch locally](https://opensearch.org/downloads.html#opensearch). Pair this pacakge with [@nasa-gcn/architect-functions-search](https://github.com/nasa-gcn/architect-functions-search) to connect to the service from your Node.js Lambda function code. @@ -31,7 +31,7 @@ Pair this pacakge with [@nasa-gcn/architect-functions-search](https://github.com dedicatedMasterCount 3 dedicatedMasterType t3.small.search -4. Optionally, create a file called `sandbox-search.json` or `sandbox-search.js` in your project and populate it with sample data to be passed to [`client.bulk()`](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/bulk_examples.html). Here are some examples. +4. Optionally, create a file called `sandbox-search.json` or `sandbox-search.js` in your project and populate it with sample data to be passed to [`client.bulk()`](https://github.com/opensearch-project/opensearch-js/blob/main/guides/bulk.md). Here are some examples. ## sandbox-search.json @@ -61,3 +61,41 @@ Pair this pacakge with [@nasa-gcn/architect-functions-search](https://github.com {"title": "Star Trek II: The Wrath of Khan"} ] } + +## Connecting to OpenSearch from your application + +In your Architect application, use the [@nasa-gcn/architect-functions-search](https://github.com/nasa-gcn/architect-functions-search) package to connect to your OpenSearch instance. To install the package, run: + +``` +npm i @nasa-gcn/architect-functions-search +``` + +Then add the following JavaScript code to your application: + +```ts +import { search } from '@nasa-gcn/architect-functions-search' + +const client = await search() +``` + +Now `client` is an instance of the [OpenSearch JavaScript client](https://opensearch.org/docs/latest/clients/javascript/index/), and you can call any client method on it — for example, [`client.index.create()`](https://opensearch.org/docs/latest/clients/javascript/index/#creating-an-index), [`client.index()`](https://opensearch.org/docs/latest/clients/javascript/index/#indexing-a-document), or [`client.search()`](https://opensearch.org/docs/latest/clients/javascript/index/#searching-for-documents). + +## Advanced usage from your application + +If you would like to manually connect to OpenSearch from your application, then you will need to sign your requests using [AWS SIG4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html); the OpenSearch client library provides the [`AwsSigv4Signer`](https://opensearch.org/docs/latest/clients/javascript/index/#authenticating-with-amazon-opensearch-service--aws-sigv4) helper to automate this. + +You can read the API endpoint information using [Architect service discovery](): + +```ts +import * as arc from '@architect/functions' + +const services = await arc.services() +const searchConfig = services.nasa_gcn - architect_plugin_search +``` + +The `searchConfig` object has the following two properties: + +- `searchConfig.node`: the URL of the API endpoint. +- `searchConfig.sig4service`: the value to pass for the `service` property in the `AwsSigv4Signer` constructor. + +See https://github.com/nasa-gcn/architect-functions-search/blob/main/index.ts for example code. diff --git a/index.ts b/index.ts index a3f8469..0192115 100644 --- a/index.ts +++ b/index.ts @@ -10,7 +10,7 @@ import { exists } from './paths' import { join } from 'path' import { pathToFileURL } from 'url' import { launch } from './run.js' -import type { LocalOpenSearch } from './run.js' +import type { LocalSearch } from './run.js' import { populate } from './data.js' import { cloudformationResources as serverlessCloudformationResources, @@ -54,12 +54,20 @@ async function executeSearchRequests(cwd: string) { } } +function getConfig(arc: { + search?: string[][] +}): Record { + if (arc.search) return Object.fromEntries(arc.search) + else return {} +} + export const deploy = { // @ts-expect-error: The Architect plugins API has no type definitions. start({ cloudformation, inventory, arc, stage }) { let resources - if (arc.search) { - resources = serviceCloudformationResources(Object.fromEntries(arc.search)) + const config = getConfig(arc) + if (config.availabilityZoneCount) { + resources = serviceCloudformationResources(config) } else { const { app } = inventory.inv const collectionName = toCollectionName(`${app}-${stage}`) @@ -84,7 +92,7 @@ export const deploy = { }, } -let local: LocalOpenSearch +let local: LocalSearch export const sandbox = { async start({ diff --git a/run.ts b/run.ts index dec69e2..075e233 100644 --- a/run.ts +++ b/run.ts @@ -21,7 +21,7 @@ import { import { pipeline } from 'stream/promises' import { createReadStream } from 'fs' -export class LocalOpenSearch { +export class LocalSearch { private readonly child!: ChildProcess private readonly tempDir!: string readonly port!: number @@ -93,8 +93,6 @@ export class LocalOpenSearch { } } -export async function launch( - ...args: Parameters -) { - return await LocalOpenSearch.launch(...args) +export async function launch(...args: Parameters) { + return await LocalSearch.launch(...args) }