Skip to content

Commit

Permalink
feat: add eventarc generic sample (#2003)
Browse files Browse the repository at this point in the history
- Adds a generic Eventarc sample
  - Re-uses same setup as other Eventarc samples
  - Logs and returns request headers and body. Deletes auth header (if present).
  - Tests that: headers and body are logged except auth header
- Tested locally

Fixes #1989
  • Loading branch information
grant authored Oct 12, 2020
1 parent 5914401 commit 68c1449
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 0 deletions.
4 changes: 4 additions & 0 deletions eventarc/generic/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Dockerfile
.dockerignore
node_modules
npm-debug.log
40 changes: 40 additions & 0 deletions eventarc/generic/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright 2020 Google, LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# [START eventarc_generic_dockerfile]

# Use the official lightweight Node.js 10 image.
# https://hub.docker.com/_/node
FROM node:12-slim

# Create and change to the app directory.
WORKDIR /usr/src/app

# Copy application dependency manifests to the container image.
# A wildcard is used to ensure both package.json AND package-lock.json are copied.
# Copying this separately prevents re-running npm install on every code change.
COPY package*.json ./

# Install dependencies.
# If you add a package-lock.json speed your build by switching to 'npm ci'.
# RUN npm ci --only=production
RUN npm install --production

# Copy local code to the container image.
COPY . .

# Run the web service on container startup.
CMD [ "npm", "start" ]

# [END eventarc_generic_dockerfile]
37 changes: 37 additions & 0 deletions eventarc/generic/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2020 Google, LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START eventarc_generic_handler]
const express = require('express');
const app = express();

app.use(express.json());
app.post('/', (req, res) => {
console.log('Event received!');

console.log('HEADERS:');
delete req.headers.Authorization; // do not log authorization header
console.log(JSON.stringify(req.headers));

console.log('BODY:');
console.log(JSON.stringify(req.body));

res.send({
headers: req.headers,
body: req.body,
});
});

module.exports = app;
// [END eventarc_generic_handler]
22 changes: 22 additions & 0 deletions eventarc/generic/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2020 Google, LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// [START eventarc_generic_server]
const app = require('./app.js');
const PORT = process.env.PORT || 8080;

app.listen(PORT, () =>
console.log(`nodejs-eventarc-generic listening on port ${PORT}`)
);
// [END eventarc_generic_server]
30 changes: 30 additions & 0 deletions eventarc/generic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "cloud-eventarc-generic",
"version": "1.0.0",
"private": true,
"main": "index.js",
"author": "Google LLC",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
},
"engines": {
"node": ">= 12.0.0"
},
"scripts": {
"start": "node index.js",
"test": "mocha test/app.test.js --check-leaks",
"system-test": "test/runner.sh mocha test/system.test.js --timeout=10000"
},
"dependencies": {
"express": "^4.16.4"
},
"devDependencies": {
"got": "^11.5.0",
"mocha": "^8.0.0",
"sinon": "^9.0.0",
"supertest": "^5.0.0",
"uuid": "^8.0.0"
}
}
51 changes: 51 additions & 0 deletions eventarc/generic/test/app.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2019, Google LLC.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// NOTE:
// This app can only be fully tested when deployed, because
// Pub/Sub requires a live endpoint URL to hit. Nevertheless,
// these tests mock it and partially test it locally.

'use strict';

const assert = require('assert');
const path = require('path');
const supertest = require('supertest');

let request;

describe('Unit Tests', () => {
before(() => {
const app = require(path.join(__dirname, '..', 'app'));
request = supertest(app);
});

describe('should succeed', () => {
it(`should relay the CloudEvent`, async () => {
await request
.post('/')
.type('json')
.set('ce-id', 1234)
.set('Authorization', 'MY-SECRET-VALUE') // never logged
.send({testkey: 'testvalue'})
.expect((res) => {
const responseBody = res.body;

assert.strictEqual(responseBody.headers.host.startsWith('127.0.0.1'), true);
assert.strictEqual(+responseBody.headers['ce-id'], 1234);
assert.strictEqual(responseBody.headers['Authorization'], undefined);
assert.deepStrictEqual(responseBody.body, {testkey: 'testvalue'});
});
});
});
});
38 changes: 38 additions & 0 deletions eventarc/generic/test/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

# Copyright 2020 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -eo pipefail;

requireEnv() {
test "${!1}" || (echo "Environment Variable '$1' not found" && exit 1)
}

requireEnv SERVICE_NAME
requireEnv CONTAINER_IMAGE

# Deploy the service
set -x
gcloud run deploy "${SERVICE_NAME}" \
--image="${CONTAINER_IMAGE}" \
--region="${REGION:-us-central1}" \
${FLAGS} \
--platform=managed \
--quiet
set +x

echo 'Cloud Run Links:'
echo "- Logs: https://console.cloud.google.com/logs/viewer?project=${GOOGLE_CLOUD_PROJECT}&resource=cloud_run_revision%2Fservice_name%2F${SERVICE_NAME}"
echo "- Console: https://console.cloud.google.com/run/detail/${REGION:-us-central1}/${SERVICE_NAME}/metrics?project=${GOOGLE_CLOUD_PROJECT}"
49 changes: 49 additions & 0 deletions eventarc/generic/test/runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bash

# Copyright 2020 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -eo pipefail;

requireEnv() {
test "${!1}" || (echo "Environment Variable '$1' not found" && exit 1)
}
requireEnv SERVICE_NAME

echo '---'
test/deploy.sh

echo
echo '---'
echo

# Register post-test cleanup.
# Only needed if deploy completed.
function cleanup {
set -x
gcloud run services delete ${SERVICE_NAME} \
--platform=managed \
--region="${REGION:-us-central1}" \
--quiet
}
trap cleanup EXIT

# TODO: Perform authentication inside the test.
export ID_TOKEN=$(gcloud auth print-identity-token)
export BASE_URL=$(test/url.sh)

test -z "$BASE_URL" && echo "BASE_URL value is empty" && exit 1

# Do not use exec to preserve trap behavior.
"$@"
50 changes: 50 additions & 0 deletions eventarc/generic/test/system.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const assert = require('assert');
const got = require('got');
const {resolve} = require('url');

const request = (method, route, base_url) => {
const {ID_TOKEN} = process.env;
if (!ID_TOKEN) {
throw Error('"ID_TOKEN" environment variable is required.');
}

return got(resolve(base_url.trim(), route), {
headers: {
Authorization: `Bearer ${ID_TOKEN.trim()}`,
},
method: method || 'get',
throwHttpErrors: false,
});
};

describe('End-to-End Tests', () => {
const {BASE_URL} = process.env;
if (!BASE_URL) {
throw Error(
'"BASE_URL" environment variable is required. For example: https://service-x8xabcdefg-uc.a.run.app'
);
}

it('post(/) without request parameters is a bad request', async () => {
const response = await request('post', '/', BASE_URL);
assert.strictEqual(
response.statusCode,
400,
'Bad Requests status not found'
);
});
});
30 changes: 30 additions & 0 deletions eventarc/generic/test/url.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash

# Copyright 2020 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -eo pipefail;

requireEnv() {
test "${!1}" || (echo "Environment Variable '$1' not found" && exit 1)
}

requireEnv SERVICE_NAME

set -x
gcloud run services \
describe "${SERVICE_NAME}" \
--region="${REGION:-us-central1}" \
--format='value(status.url)' \
--platform=managed

0 comments on commit 68c1449

Please sign in to comment.