From 8183adc15ea4cd24757afca12bb7ea63b0ba4de9 Mon Sep 17 00:00:00 2001 From: Erki Aas Date: Mon, 12 Dec 2022 22:56:14 +0200 Subject: [PATCH] Initial commit --- .dockerignore | 18 +++++ .drone.yml | 2 + .gitignore | 174 ++++++++++++++++++++++++++++++++++++++++ Dockerfile | 19 +++++ README.md | 19 +++++ index.ts | 59 ++++++++++++++ k8s/dev/deployment.yaml | 48 +++++++++++ package.json | 17 ++++ skaffold.yaml | 28 +++++++ tsconfig.json | 20 +++++ 10 files changed, 404 insertions(+) create mode 100644 .dockerignore create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 index.ts create mode 100644 k8s/dev/deployment.yaml create mode 100644 package.json create mode 100644 skaffold.yaml create mode 100644 tsconfig.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..5a2a92b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +.kpt-pipeline/ +k8s/ +skaffold.yaml +README.md +.git/ +node_modules/ +.drone.yml + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +*.kpt-pipeline diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e7b5dfa --- /dev/null +++ b/.drone.yml @@ -0,0 +1,2 @@ +kind: template +load: docker.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc39021 --- /dev/null +++ b/.gitignore @@ -0,0 +1,174 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +\*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +\*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +\*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +\*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.cache +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +.cache/ + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp +.cache + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.\* + + +.vscode +.idea/ +node_nodules/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1a03162 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +# pull official node image +FROM harbor.k-space.ee/docker.io/library/node:19 + +# define /app as working directory +WORKDIR /app + +# copy package.json and package-lock.json to /app +COPY package.json /app +# COPY bun.lockb /app + +# install node dependencies +# RUN bun install +RUN yarn install --production +COPY . /app + +# bun install doesnt work in Docker for some reason: https://github.com/oven-sh/bun/issues/1590 +FROM jarredsumner/bun:0.2.0 AS run +COPY --from=0 /app /app +ENTRYPOINT bun run index.ts diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b8b9f0 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# camtiler-event-broker + +Microservice to alter Camtiler log rows by creating presigned screenshot URLs. + +Based on the novel, but experimental Bun runtime: https://github.com/oven-sh/bun/ + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v0.3.0. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..64c5834 --- /dev/null +++ b/index.ts @@ -0,0 +1,59 @@ +import {HttpRequest} from "@aws-sdk/protocol-http"; +import {S3RequestPresigner} from "@aws-sdk/s3-request-presigner"; +import {parseUrl} from "@aws-sdk/url-parser"; +import {Hash} from "@aws-sdk/hash-node"; +import {fromEnv} from "@aws-sdk/credential-provider-env"; +import {formatUrl} from "@aws-sdk/util-format-url"; + +// Minio set-up variables +const minioSchema = process.env.MINIO_SCHEMA; +const minioHostname = process.env.MINIO_HOSTNAME; +const minioPort = process.env.MINIO_PORT; +const minioBucket = process.env.MINIO_BUCKET; + +const signer = async function (asset: string) { + const baseUrl = minioSchema + '://' + minioHostname + ((minioPort === '443' || minioPort === '80') ? '' : `:${minioPort}`) + + '/' + minioBucket + '/' + const s3ObjectUrl = parseUrl(baseUrl + asset); + const presigner = new S3RequestPresigner({ + credentials: fromEnv(), // AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are read here. + region: 'us-east-1', + sha256: Hash.bind(null, "sha256"), // In Node.js + }); + // Create a GET request from S3 url. + return await presigner.presign(new HttpRequest(s3ObjectUrl)); +} + +const getPromises = async function (resp: object, path: string): Promise { + const screenshots = resp.screenshots ? resp.screenshots : [] + if (path === '/details/') { + return screenshots.map(async (x) => { + return { + thumb: formatUrl(await signer(`thumb/${x}`)), + orig: formatUrl(await signer(`${x}`)) + } + }); + } else if (path === '/initial/' || path === '/query/' || path === '/streaming/') { + return screenshots.splice(0, 5).map(async (x) => { + return { + thumb: formatUrl(await signer(`thumb/${x}`)), + } + }); + } +} + +export default { + port: 3000, + async fetch(request: Request) { + let reqUrl = await parseUrl(request.url) + let req = await request.json(); + + return Promise.all(await getPromises(req, reqUrl.path)).then((r) => { + let resp = Object.assign({}, req) + resp.screenshots = r + return resp + }).then((resp) => { + return new Response(JSON.stringify(resp)) + }); + }, +}; diff --git a/k8s/dev/deployment.yaml b/k8s/dev/deployment.yaml new file mode 100644 index 0000000..80bf7be --- /dev/null +++ b/k8s/dev/deployment.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: camtiler-event-broker +spec: + type: ClusterIP + selector: + app: camtiler-event-broker + ports: + - protocol: TCP + port: 80 + targetPort: 3000 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: camtiler-event-broker +spec: + selector: + matchLabels: + app: camtiler-event-broker + template: + metadata: + labels: + app: camtiler-event-broker + spec: + containers: + - name: camtiler-event-broker + image: harbor.k-space.ee/playground/camtiler-event-broker + ports: + - containerPort: 3000 + env: + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: minio-access-secret + key: secret + - name: AWS_ACCESS_KEY_ID + value: 'eventsource' + - name: MINIO_BUCKET + value: 'application' + - name: MINIO_HOSTNAME + value: 'cams-s3.k-space.ee' + - name: MINIO_PORT + value: '443' + - name: MINIO_SCHEMA + value: 'https' diff --git a/package.json b/package.json new file mode 100644 index 0000000..bba75fb --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "camtiler-event-broker", + "module": "index.ts", + "devDependencies": { + "bun-types": "^0.3.0" + }, + "type": "module", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.226.0", + "@aws-sdk/hash-node": "^3.226.0", + "@aws-sdk/protocol-http": "^3.226.0", + "@aws-sdk/s3-request-presigner": "^3.226.0", + "@aws-sdk/url-parser": "^3.226.0", + "@aws-sdk/util-format-url": "^3.226.0", + "http2": "^3.3.7" + } +} diff --git a/skaffold.yaml b/skaffold.yaml new file mode 100644 index 0000000..52613b6 --- /dev/null +++ b/skaffold.yaml @@ -0,0 +1,28 @@ +apiVersion: skaffold/v3 +kind: Config +metadata: + name: camtiler-event-broker + +build: + artifacts: + - image: harbor.k-space.ee/playground/camtiler-event-broker + docker: + dockerfile: Dockerfile + +deploy: + kubectl: {} + +manifests: + rawYaml: + - k8s/dev/deployment.yaml + +profiles: + - name: dev + activation: + - command: dev + build: + artifacts: + - image: harbor.k-space.ee/playground/camtiler-event-broker + manifests: + rawYaml: + - k8s/dev/deployment.yaml diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d2a16de --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "lib": [ + "ESNext" + ], + "module": "esnext", + "target": "esnext", + "moduleResolution": "nodenext", + "strict": true, + "downlevelIteration": true, + "skipLibCheck": true, + "jsx": "preserve", + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "types": [ + "bun-types" // add Bun global + ] + } +}