From 1f81496374b75844f711f499dee50a32655f4040 Mon Sep 17 00:00:00 2001 From: Omid Tahouri Date: Thu, 4 Jul 2024 08:18:53 +0000 Subject: [PATCH] feat: deploy grpc gateway to cloud run with an apigee proxy --- tools/grpc-http-gateway-generator/pipeline.sh | 63 ++++++++++++++++++- .../templates/apiproxy/currency-v1.xml | 18 ++++++ .../policies/AM.SetConversionPath.xml | 21 +++++++ .../policies/AM.SetCurrenciesPath.xml | 21 +++++++ .../apiproxy/policies/HM.SetTargetMethod.xml | 20 ++++++ .../apiproxy/policies/JS.SetTargetPath.xml | 18 ++++++ .../templates/apiproxy/proxies/default.xml | 48 ++++++++++++++ .../apiproxy/resources/jsc/set-target-path.js | 29 +++++++++ .../templates/apiproxy/targets/default.xml | 32 ++++++++++ .../templates/cloud-run-service.yaml | 53 ++++++++++++++++ 10 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/currency-v1.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetConversionPath.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetCurrenciesPath.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/policies/HM.SetTargetMethod.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/policies/JS.SetTargetPath.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/proxies/default.xml create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/resources/jsc/set-target-path.js create mode 100644 tools/grpc-http-gateway-generator/templates/apiproxy/targets/default.xml create mode 100644 tools/grpc-http-gateway-generator/templates/cloud-run-service.yaml diff --git a/tools/grpc-http-gateway-generator/pipeline.sh b/tools/grpc-http-gateway-generator/pipeline.sh index 44867c03..136f7db8 100755 --- a/tools/grpc-http-gateway-generator/pipeline.sh +++ b/tools/grpc-http-gateway-generator/pipeline.sh @@ -16,9 +16,15 @@ set -e # exit on first error +SCRIPTPATH="$( cd "$(dirname "$0")" || exit >/dev/null 2>&1 ; pwd -P )" +export PATH="$PATH:$SCRIPTPATH/../../tools/apigee-sackmesser/bin" + +GCP_REGION=europe-west2 + # Run a currency mock service docker run --name grpc-mock --detach \ -p 9090:9090 -e PORT=9090 \ + -e DISABLE_PROFILER=1 -e DISABLE_DEBUGGER=1 \ gcr.io/google-samples/microservices-demo/currencyservice:v0.10.0 &> /dev/null # Trap for cleanup @@ -37,7 +43,60 @@ GATEWAY_PID=$! trap 'docker kill grpc-mock &> /dev/null || true; docker rm grpc-mock &> /dev/null || true; kill $GATEWAY_PID || true' EXIT INT TERM # Smoke test the gRPC Gateway -curl --fail -X POST localhost:8080/hipstershop.CurrencyService/Convert \ +curl -X POST localhost:8080/hipstershop.CurrencyService/Convert \ -d '{"from": {"units": 3, "currency_code": "USD", "nanos": 0}, "to_code": "CHF"}' -curl --fail -X POST localhost:8080/hipstershop.CurrencyService/GetSupportedCurrencies +curl -X POST localhost:8080/hipstershop.CurrencyService/GetSupportedCurrencies + +# Build the grpc-gateway container and push it to Artifact Registry +(cd generated/gateway && docker build -t grpc-gateway:latest .) + +DOCKER_REPO="docker" +if [ -z "$(gcloud artifacts repositories describe $DOCKER_REPO --location=$GCP_REGION --format='get(name)')" ]; then \ + gcloud artifacts repositories create $DOCKER_REPO \ + --repository-format=docker \ + --location=$GCP_REGION \ + --project=$APIGEE_X_ORG +fi + +IMAGE_PATH="$GCP_REGION-docker.pkg.dev/$APIGEE_X_ORG/$DOCKER_REPO/grpc-gateway" +docker tag grpc-gateway:latest "$IMAGE_PATH:latest" +docker push "$IMAGE_PATH" + +sed -i.bak "s|GRPC_GATEWAY_IMAGE|$IMAGE_PATH|g" "templates/cloud-run-service.yaml" + +gcloud run services replace templates/cloud-run-service.yaml \ + --project $APIGEE_X_ORG --region $GCP_REGION \ + --platform managed + +# Generate and deploy an Apigee API proxy for the currency-service +SA_EMAIL="apigee-runtime@$APIGEE_X_ORG.iam.gserviceaccount.com" + +if [ -z "$(gcloud iam service-accounts list --filter "$SA_EMAIL" --format="value(email)" --project "$APIGEE_X_ORG")" ]; then + gcloud iam service-accounts create apigee-runtime \ + --description="Apigee Runtime" --project "$APIGEE_X_ORG" +fi + +gcloud run services add-iam-policy-binding currency-service \ + --member="serviceAccount:$SA_EMAIL" \ + --role='roles/run.invoker' \ + --region=$GCP_REGION \ + --platform=managed --project "$APIGEE_X_ORG" + +CLOUD_RUN_URL=$(gcloud run services list --filter currency-service --format="value(status.url)" --limit 1) +sed -i "s|CLOUD_RUN_URL|$CLOUD_RUN_URL|g" "templates/apiproxy/targets/default.xml" + +TOKEN="$(gcloud config config-helper --force-auth-refresh --format json | jq -r '.credential.access_token')" +sackmesser deploy -d "$SCRIPTPATH/templates" -o "$APIGEE_X_ORG" -e "$APIGEE_X_ENV" -t "$TOKEN" --deployment-sa "$SA_EMAIL" + +# Test the Apigee API +curl -X GET "https://$APIGEE_X_HOSTNAME/currency/v1/currencies" + +curl -X POST "https://$APIGEE_X_HOSTNAME/currency/v1/convert" \ + -d '{"from": {"units": 3, "currency_code": "USD", "nanos": 0}, "to_code": "CHF"}' + +# Clean up + # undeploy and delete proxy + # delete CR service + # delete SA + # delete AR registry diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/currency-v1.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/currency-v1.xml new file mode 100644 index 00000000..f0acd847 --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/currency-v1.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetConversionPath.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetConversionPath.xml new file mode 100644 index 00000000..5d745abd --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetConversionPath.xml @@ -0,0 +1,21 @@ + + + + flow.target.pathsuffix + /hipstershop.CurrencyService/Convert + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetCurrenciesPath.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetCurrenciesPath.xml new file mode 100644 index 00000000..43cf6ef4 --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/AM.SetCurrenciesPath.xml @@ -0,0 +1,21 @@ + + + + flow.target.pathsuffix + /hipstershop.CurrencyService/GetSupportedCurrencies + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/policies/HM.SetTargetMethod.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/HM.SetTargetMethod.xml new file mode 100644 index 00000000..ff59942a --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/HM.SetTargetMethod.xml @@ -0,0 +1,20 @@ + + + + POST + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/policies/JS.SetTargetPath.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/JS.SetTargetPath.xml new file mode 100644 index 00000000..b7fd841d --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/policies/JS.SetTargetPath.xml @@ -0,0 +1,18 @@ + + + jsc://set-target-path.js + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/proxies/default.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/proxies/default.xml new file mode 100644 index 00000000..5195c438 --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/proxies/default.xml @@ -0,0 +1,48 @@ + + + + + request.verb = "GET" and proxy.pathsuffix = "/currencies" + + + AM.SetCurrenciesPath + + + + + request.verb = "POST" and proxy.pathsuffix = "/convert" + + + AM.SetConversionPath + + + + + + + + HM.SetTargetMethod + + + + + /currency/v1 + + + default + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/resources/jsc/set-target-path.js b/tools/grpc-http-gateway-generator/templates/apiproxy/resources/jsc/set-target-path.js new file mode 100644 index 00000000..1e426c44 --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/resources/jsc/set-target-path.js @@ -0,0 +1,29 @@ +/* + Copyright 2024 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. +*/ + +context.setVariable("target.copy.pathsuffix", false) + +var existingTargetUrl = context.getVariable("target.url"); +var targetPath = context.getVariable("flow.target.pathsuffix") || ""; // retrieve custom path, set by AM policies +var queryString = context.getVariable("request.querystring") || ""; + +var updatedTargetUrl = existingTargetUrl + targetPath + (queryString ? "?"+queryString : ""); + +context.setVariable("target.url", + existingTargetUrl + // use target base URL + targetPath + // append custom path + (queryString ? "?"+queryString : "") // conditionally append query params +); diff --git a/tools/grpc-http-gateway-generator/templates/apiproxy/targets/default.xml b/tools/grpc-http-gateway-generator/templates/apiproxy/targets/default.xml new file mode 100644 index 00000000..064848df --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/apiproxy/targets/default.xml @@ -0,0 +1,32 @@ + + + + + + JS.SetTargetPath + + + + + + + CLOUD_RUN_URL + + + CLOUD_RUN_URL + + \ No newline at end of file diff --git a/tools/grpc-http-gateway-generator/templates/cloud-run-service.yaml b/tools/grpc-http-gateway-generator/templates/cloud-run-service.yaml new file mode 100644 index 00000000..0eae3cfa --- /dev/null +++ b/tools/grpc-http-gateway-generator/templates/cloud-run-service.yaml @@ -0,0 +1,53 @@ +# Copyright 2024 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. + +apiVersion: serving.knative.dev/v1 +kind: Service +metadata: + name: currency-service +spec: + template: + spec: + containers: + - name: grpc-gateway + image: GRPC_GATEWAY_IMAGE + ports: + - name: http1 + containerPort: 8080 + resources: + limits: + cpu: 1000m + memory: 512Mi + startupProbe: + timeoutSeconds: 240 + periodSeconds: 240 + failureThreshold: 1 + tcpSocket: + port: 8080 + - name: currencyservice-1 + image: gcr.io/google-samples/microservices-demo/currencyservice@sha256:e08a1f5d4e4b74fc3d6222d535a11615e8201e7075a090c1ba4436ef1f1cbe7b + env: + - name: PORT + value: '9090' + resources: + limits: + cpu: 1000m + memory: 512Mi + startupProbe: + timeoutSeconds: 1 + periodSeconds: 10 + failureThreshold: 3 + grpc: + port: 9090 + service: currencyservice-v1 \ No newline at end of file