Skip to content
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

run: add hello-broken sample #1480

Merged
merged 11 commits into from
Sep 23, 2019
17 changes: 10 additions & 7 deletions run/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

| Sample | Description | Deploy |
| --------------------------------------- | ------------------------ | ------------- |
|[Hello World][helloworld]&nbsp;&#10149; | Quickstart | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30">][run_button_helloworld] |
| [Image Processing][image_processing] | Event-driven image analysis & transformation | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30">][run_button_image_processing] |
|[Manual Logging][manual_logging] | Structured logging without client library | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30">][run_button_manual_logging] |
|[Pub/Sub][pubsub] | Event-driven service with a Pub/Sub push subscription | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30">][run_button_pubsub] |
|[Hello World][helloworld]&nbsp;&#10149; | Quickstart | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30"/>][run_button_helloworld] |
|[Hello Broken][hello_broken] | Something is wrong, how do you fix it? | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30"/>][run_button_hello_broken] |
|[Pub/Sub][pubsub] | Event-driven service with a Pub/Sub push subscription | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30"/>][run_button_pubsub] |
|[Image Processing][image_processing] | Event-driven image analysis & transformation | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30"/>][run_button_image_processing] |
|[Manual Logging][manual_logging] | Structured logging without client library | [<img src="https://storage.googleapis.com/cloudrun/button.svg" alt="Run on Google Cloud" height="30"/>][run_button_manual_logging] |

For more Cloud Run samples beyond Node.js, see the main list in the [Cloud Run Samples repository](https://github.com/GoogleCloudPlatform/cloud-run-samples).

Expand Down Expand Up @@ -99,7 +100,7 @@ For more Cloud Run samples beyond Node.js, see the main list in the [Cloud Run S
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SAMPLE}
gcloud beta run deploy $SAMPLE \
# Needed for Manual Logging sample.
--set-env-var GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT}
--set-env-var GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT} \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SAMPLE}
```

Expand All @@ -110,10 +111,12 @@ for more information.
[run_build]: https://cloud.google.com/run/docs/building/containers
[run_deploy]: https://cloud.google.com/run/docs/deploying
[helloworld]: https://github.com/knative/docs/tree/master/docs/serving/samples/hello-world/helloworld-nodejs
[hello_broken]: hello-broken/
[pubsub]: pubsub/
[image_processing]: image-processing/
[manual_logging]: logging-manual/
[pubsub]: pubsub/
[run_button_helloworld]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/knative/docs&cloudshell_working_dir=docs/serving/samples/hello-world/helloworld-nodejs
[run_button_hello_broken]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/nodejs-docs-samples&cloudshell_working_dir=run/hello-broken
[run_button_pubsub]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/nodejs-docs-samples&cloudshell_working_dir=run/pubsub
[run_button_image_processing]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/nodejs-docs-samples&cloudshell_working_dir=run/image-processing
[run_button_manual_logging]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/nodejs-docs-samples&cloudshell_working_dir=run/logging-manual
[run_button_pubsub]: https://console.cloud.google.com/cloudshell/editor?shellonly=true&cloudshell_image=gcr.io/cloudrun/button&cloudshell_git_repo=https://github.com/GoogleCloudPlatform/nodejs-docs-samples&cloudshell_working_dir=run/pubsub
40 changes: 40 additions & 0 deletions run/hello-broken/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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.

# [START run_broken_dockerfile]

# Use the official lightweight Node.js 10 image.
# https://hub.docker.com/_/node
FROM node:10-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 copying both package.json AND package-lock.json (when available).
# Copying this first prevents re-running npm install on every code change.
COPY package*.json ./

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

# Copy local code to the container image.
COPY . ./
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need a forward slash here.

Copy link
Collaborator Author

@grayside grayside Sep 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the previous practice was to use COPY . ., this is a newer practice I think we should use in COPY statements. The issue is COPY supports having multiple source arguments and one destination argument, but if the source arguments are:

  • A directory
  • More than one file

Then the destination needs to have the trailing slash otherwise it will error.

This is intended to future proof the use of the Dockerfile should a developer use it as a template.


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

# [END run_broken_dockerfile]
68 changes: 68 additions & 0 deletions run/hello-broken/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Cloud Run Broken Sample

This sample presents broken code in need of troubleshooting. An alternate
resource at `/improved` shows a more stable implementation with more informative
errors and default values.

Use it with the [Local Container Troubleshooting tutorial](http://cloud.google.com/run/docs/tutorials/local-troubleshooting).

For more details on how to work with this sample read the [Google Cloud Run Node.js Samples README](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/run).

## Local Development

### `npm run e2e-test`

```
export SERVICE_NAME=broken
export CONTAINER_IMAGE=gcr.io/${GOOGLE_CLOUD_PROJECT}/broken
npm run e2e-test
```

## Using Testing Scripts

### url.sh

The `url.sh` script derives the automatically provisioned URL of a deployed
Cloud Run service.

```sh
export SERVICE_NAME=broken
export REGION=us-central1
test/url.sh
```

### deploy.sh

The `deploy.sh` script deploys a Cloud Run service.

```sh
export SERVICE_NAME=broken
export CONTAINER_IMAGE=gcr.io/${GOOGLE_CLOUD_PROJECT}/broken
export REGION=us-central1
test/deploy.sh
```

### runner.sh

The `runner.sh` script:

* Deploys the service to Cloud Run based on the `deploy.sh` script.
* Sets the `BASE_URL` and `ID_TOKEN` environment variables.
* Runs any arguments passed to the `runner.sh` script.
* Tears down the Cloud Run service on completion.

```sh
test/runner.sh sleep 20
```

## Environment Variables (Testing)

* `BASE_URL`: Specifies the Cloud Run service URL for end-to-end tests.
* `ID_TOKEN`: JWT token used to authenticate with Cloud Run's IAM-based authentication.
* `REGION`: [`us-central1`] Optional override region for the location of the Cloud Run service.
* `SERVICE_NAME`: The name of the deployed service, used in some API calls and test assertions.

## Dependencies

* **express**: Web server framework.
* **got**: [Testing] Used to make HTTP requests of the running service in end-to-end testing.
57 changes: 57 additions & 0 deletions run/hello-broken/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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.

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

app.get('/', (req, res) => {
console.log('hello: received request.');

// [START run_broken_service_problem]
const {NAME} = process.env;
if (!NAME) {
// Plain error logs do not appear in Stackdriver Error Reporting.
console.error('Environment validation failed.');
console.error(new Error('Missing required server parameter'));
return res.status(500).send('Internal Server Error');
}
// [END run_broken_service_problem]
res.send(`Hello ${NAME}!`);
});
// [END run_broken_service]

app.get('/improved', (req, res) => {
console.log('hello: received request.');

// [START run_broken_service_upgrade]
const NAME = process.env.NAME || 'World';
if (!process.env.NAME) {
console.log(
JSON.stringify({
severity: 'WARNING',
message: `NAME not set, default to '${NAME}'`,
})
);
}
// [END run_broken_service_upgrade]
res.send(`Hello ${NAME}!`);
});

// [START run_broken_service]
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`hello: listening on port ${port}`);
});
// [END run_broken_service]
22 changes: 22 additions & 0 deletions run/hello-broken/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "hello-broken",
"description": "Broken Cloud Run service for troubleshooting practice",
"version": "1.0.0",
"private": true,
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 0",
"e2e-test": "TARGET=Cloud test/runner.sh mocha test/system.test.js --timeout=20000",
"lint": "eslint '**/*.js'",
"fix": "eslint --fix '**/*.js'"
},
"author": "Google LLC",
"license": "Apache-2.0",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"got": "^9.6.0"
}
}
37 changes: 37 additions & 0 deletions run/hello-broken/test/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash

# 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.

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 beta run deploy "${SERVICE_NAME}" \
--image="${CONTAINER_IMAGE}" \
--region="${REGION:-us-central1}" \
${FLAGS} \
--platform=managed \
--quiet

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}"
56 changes: 56 additions & 0 deletions run/hello-broken/test/runner.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env bash

# 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.

set -eo pipefail;

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

# The hello-broken sample needs to be tested with the NAME environment variable
# both set and unset.
SERVICE_OVERRIDE="${SERVICE_NAME}-override"

echo '---'
test/deploy.sh
FLAGS="--set-env-vars NAME=$NAME" SERVICE_NAME=${SERVICE_OVERRIDE} test/deploy.sh

echo
echo '---'
echo

# Register post-test cleanup.
# Only needed if deploy completed.
function cleanup {
set -x
gcloud beta run services delete ${SERVICE_NAME} \
--platform=managed \
--region="${REGION:-us-central1}" \
--quiet
gcloud beta run services delete ${SERVICE_OVERRIDE} \
--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)
export BASE_URL_OVERRIDE=$(SERVICE_NAME=${SERVICE_OVERRIDE} test/url.sh)
# Do not use exec to preserve trap behavior.
"$@"
Loading