Skip to content

Commit 266b1dd

Browse files
committed
v1.1.0
This release marks the beginning of the history of this repo. Prior to this, the repo was littered with test commits made when developing the CI pipeline. This really should have been in a different repo but, oh well, here we are. The PyPI and NPM packages have been published with prior versions and there's no undoing that. So here's to the future. 🌱
0 parents  commit 266b1dd

File tree

15 files changed

+15911
-0
lines changed

15 files changed

+15911
-0
lines changed

.devcontainer/devcontainer.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "VS Code DEV Container for AWS CDK development",
3+
"image": "jsii/superchain:1-buster-slim-node16"
4+
}

.github/workflows/distribute.yaml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
name: Distribute
2+
3+
on:
4+
release:
5+
types:
6+
- released
7+
8+
jobs:
9+
package:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v3
13+
14+
- uses: actions/setup-node@v3
15+
with:
16+
node-version: 16
17+
cache: "npm"
18+
19+
- name: Install Dependencies
20+
run: npm ci
21+
22+
- name: Compile project
23+
run: npm run build
24+
25+
- name: Generate distribution packages
26+
run: npm run package
27+
28+
- name: Generate documentation
29+
run: npm run docgen
30+
31+
- uses: actions/upload-artifact@v3
32+
with:
33+
name: docs
34+
path: docs
35+
36+
- uses: actions/upload-artifact@v3
37+
with:
38+
name: python
39+
path: dist/python/*
40+
41+
- uses: actions/upload-artifact@v3
42+
with:
43+
name: js
44+
path: dist/js/*
45+
46+
- uses: actions/upload-artifact@v3
47+
with:
48+
name: jsii
49+
path: .jsii
50+
51+
update-docs:
52+
runs-on: ubuntu-latest
53+
needs: package
54+
steps:
55+
- uses: actions/checkout@v3
56+
57+
- uses: actions/download-artifact@v3
58+
with:
59+
name: docs
60+
61+
- name: Deploy 🚀
62+
uses: JamesIves/github-pages-deploy-action@v4
63+
with:
64+
folder: docs
65+
66+
distribute-python:
67+
runs-on: ubuntu-latest
68+
needs: package
69+
steps:
70+
- uses: actions/download-artifact@v3
71+
with:
72+
name: python
73+
path: dist
74+
75+
- run: pip install twine
76+
77+
- run: twine upload dist/*
78+
env:
79+
github_token: ${{ secrets.GITHUB_TOKEN }}
80+
TWINE_USERNAME: __token__
81+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
82+
83+
distribute-js:
84+
runs-on: ubuntu-latest
85+
needs: package
86+
steps:
87+
- uses: actions/download-artifact@v3
88+
with:
89+
name: js
90+
path: dist
91+
92+
- uses: actions/setup-node@v3
93+
with:
94+
node-version: 16
95+
registry-url: 'https://registry.npmjs.org'
96+
97+
- run: npm publish dist/*
98+
env:
99+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.github/workflows/test.yaml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Test & Build
2+
3+
on:
4+
push:
5+
6+
jobs:
7+
test-build:
8+
runs-on: ubuntu-latest
9+
steps:
10+
# To make git commits made by semantic-release be made to our bot and not
11+
# "github-actions" user which doesn't trigger other Action Workflows.
12+
# https://github.com/semantic-release/semantic-release/discussions/1906#discussioncomment-656651
13+
- name: Checkout
14+
uses: actions/checkout@v3
15+
with:
16+
persist-credentials: false
17+
18+
- uses: actions/setup-node@v3
19+
with:
20+
node-version: 16
21+
cache: "npm"
22+
23+
- name: Install Dependencies
24+
run: npm ci
25+
26+
- name: Compile project
27+
run: npm run build
28+
29+
- name: Generate distribution packages
30+
run: npm run package
31+
32+
- name: Generate documentation
33+
run: npm run docgen
34+
35+
- uses: actions/upload-artifact@v3
36+
with:
37+
name: docs
38+
path: |
39+
docs
40+
41+
- uses: actions/upload-artifact@v3
42+
with:
43+
name: python
44+
path: |
45+
dist/python/*
46+
47+
- uses: actions/upload-artifact@v3
48+
with:
49+
name: js
50+
path: |
51+
dist/js/*
52+
53+
- uses: actions/upload-artifact@v3
54+
with:
55+
name: jsii
56+
path: |
57+
.jsii
58+
59+
- name: Get Release Bot Token
60+
id: get-token
61+
uses: getsentry/action-github-app-token@v1
62+
with:
63+
app_id: ${{ secrets.DS_RELEASE_BOT_ID }}
64+
private_key: ${{ secrets.DS_RELEASE_BOT_PRIVATE_KEY }}
65+
66+
- name: Maybe Release 🚀
67+
if: github.ref == 'refs/heads/main'
68+
run: |
69+
npm run semantic-release
70+
env:
71+
GITHUB_TOKEN: ${{ steps.get-token.outputs.token }}

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
tsconfig.*
3+
lib/**/*.js
4+
lib/**/*.d.ts
5+
.jsii
6+
dist
7+
docs

.npmignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
# Exclude typescript source and config
3+
*.ts
4+
tsconfig.json
5+
6+
# Include javascript files and typescript declarations
7+
!*.js
8+
!*.d.ts
9+
10+
# Exclude jsii outdir
11+
dist
12+
13+
# Include .jsii and .jsii.gz
14+
!.jsii
15+
!.jsii.gz

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18

CHANGELOG.md

Whitespace-only changes.

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# pgSTAC CDK construct
2+
3+
## Published Packages
4+
5+
- https://pypi.org/project/cdk-seed.pgstac-cdk-construct/
6+
- https://www.npmjs.com/package/pgstac-cdk-construct
7+
8+
## Release
9+
10+
Versioning is automatically handled via [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and [Semantic Release](https://semantic-release.gitbook.io/semantic-release/).
11+
12+
A warning: If you rebase `main`, you must ensure that the commits referenced by tags point to commits that are within the `main` branch. If a commit references a commit that is no longer on the `main` branch, Semantic Release will fail to detect the correct version of the project. [More information](https://github.com/semantic-release/semantic-release/issues/1121#issuecomment-517945233).

lib/bootstrap-pgstac/index.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {
2+
aws_ec2,
3+
aws_rds,
4+
aws_lambda,
5+
aws_logs,
6+
aws_secretsmanager,
7+
CustomResource,
8+
Duration,
9+
Stack,
10+
RemovalPolicy,
11+
} from "aws-cdk-lib";
12+
import { Construct } from "constructs";
13+
14+
function hasVpc(
15+
instance: aws_rds.DatabaseInstance | aws_rds.IDatabaseInstance
16+
): instance is aws_rds.DatabaseInstance {
17+
return (instance as aws_rds.DatabaseInstance).vpc !== undefined;
18+
}
19+
20+
/**
21+
* Bootstraps a database instance, installing pgSTAC onto the database.
22+
*/
23+
export class BootstrapPgStac extends Construct {
24+
secret: aws_secretsmanager.ISecret;
25+
26+
constructor(scope: Construct, id: string, props: BootstrapPgStacProps) {
27+
super(scope, id);
28+
29+
const handler = new aws_lambda.Function(this, "lambda", {
30+
handler: "handler.handler",
31+
runtime: aws_lambda.Runtime.PYTHON_3_8,
32+
code: aws_lambda.Code.fromDockerBuild(__dirname, {
33+
file: "runtime/Dockerfile",
34+
buildArgs: { PGSTAC_VERSION: props.pgstacVersion },
35+
}),
36+
timeout: Duration.minutes(2),
37+
vpc: hasVpc(props.database) ? props.database.vpc : props.vpc,
38+
logRetention: aws_logs.RetentionDays.ONE_WEEK,
39+
});
40+
41+
this.secret = new aws_secretsmanager.Secret(this, "secret", {
42+
secretName: [
43+
props.secretsPrefix || "pgstac",
44+
id,
45+
this.node.addr.slice(-8),
46+
].join("/"),
47+
generateSecretString: {
48+
secretStringTemplate: JSON.stringify({
49+
dbname: props.pgstacDbName || "pgstac",
50+
engine: "postgres",
51+
port: 5432,
52+
host: props.database.instanceEndpoint.hostname,
53+
username: props.pgstacUsername || "pgstac_user",
54+
}),
55+
generateStringKey: "password",
56+
excludePunctuation: true,
57+
},
58+
description: `PgSTAC database bootstrapped by ${
59+
Stack.of(this).stackName
60+
}`,
61+
});
62+
63+
// Allow lambda to...
64+
// read new user secret
65+
this.secret.grantRead(handler);
66+
// read database secret
67+
props.dbSecret.grantRead(handler);
68+
// connect to database
69+
props.database.connections.allowFrom(handler, aws_ec2.Port.tcp(5432));
70+
71+
// this.connections = props.database.connections;
72+
new CustomResource(this, "bootstrapper", {
73+
serviceToken: handler.functionArn,
74+
properties: {
75+
// By setting pgstac_version in the properties assures
76+
// that Create/Update events will be passed to the service token
77+
pgstac_version: props.pgstacVersion,
78+
conn_secret_arn: props.dbSecret.secretArn,
79+
new_user_secret_arn: this.secret.secretArn,
80+
},
81+
removalPolicy: RemovalPolicy.RETAIN, // This retains the custom resource (which doesn't really exist), not the database
82+
});
83+
}
84+
}
85+
86+
export interface BootstrapPgStacProps {
87+
/**
88+
* VPC in which the database resides.
89+
*
90+
* Note - Must be explicitely set if the `database` only conforms to the
91+
* `aws_rds.IDatabaseInstace` interface (ie it is a reference to a database instance
92+
* rather than a database instance.)
93+
*
94+
* @default - `vpc` property of the `database` instance provided.
95+
*/
96+
readonly vpc?: aws_ec2.IVpc;
97+
98+
/**
99+
* Database onto which pgSTAC should be installed.
100+
*/
101+
readonly database: aws_rds.DatabaseInstance | aws_rds.IDatabaseInstance;
102+
103+
/**
104+
* Secret containing valid connection details for the database instance. Secret must
105+
* conform to the format of CDK's `DatabaseInstance` (i.e. a JSON object containing a
106+
* `username`, `password`, `host`, `port`, and optionally a `dbname`). If a `dbname`
107+
* property is not specified within the secret, the bootstrapper will attempt to
108+
* connect to a database with the name of `"postgres"`.
109+
*/
110+
readonly dbSecret: aws_secretsmanager.ISecret;
111+
112+
/**
113+
* Name of database that is to be created and onto which pgSTAC will be installed.
114+
*
115+
* @default - "pgstac"
116+
*/
117+
readonly pgstacDbName?: string;
118+
119+
/**
120+
* Name of user that will be generated for connecting to the pgSTAC database.
121+
*
122+
* @default - "pgstac_user"
123+
*/
124+
readonly pgstacUsername?: string;
125+
126+
/**
127+
* pgSTAC version to be installed.
128+
*/
129+
readonly pgstacVersion: string;
130+
131+
/**
132+
* Prefix to assign to the generated `secrets_manager.Secret`
133+
*
134+
* @default - "pgstac"
135+
*/
136+
readonly secretsPrefix: string;
137+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM lambci/lambda:build-python3.8
2+
3+
ARG PGSTAC_VERSION
4+
RUN echo "Using PGSTAC Version ${PGSTAC_VERSION}"
5+
6+
WORKDIR /tmp
7+
8+
RUN pip install requests psycopg[binary,pool] pypgstac==${PGSTAC_VERSION} -t /asset
9+
10+
COPY runtime/handler.py /asset/handler.py
11+
12+
# https://stackoverflow.com/a/61746719
13+
# Tip from eoAPI: turns out, asyncio is part of python
14+
RUN rm -rf /asset/asyncio*

0 commit comments

Comments
 (0)