Skip to content

feat: add eventarc generic sample #2003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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