Skip to content

Commit 6e7a1cb

Browse files
authoredJul 8, 2024··
Merge pull request #749 from danistrebel/feat/grpc-http-gateway-generator
Feat/grpc http gateway generator
2 parents 4665629 + 829ee4a commit 6e7a1cb

23 files changed

+798
-4
lines changed
 

‎CODEOWNERS

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
/tools/apigee-x-trial-provision @yuriylesyuk @danistrebel
3232
/tools/decrypt-hybrid-assets @yuriylesyuk
3333
/tools/endpoints-oas-importer @danistrebel
34+
/tools/grpc-http-gateway-generator @danistrebel @omidtahouri
3435
/tools/hybrid-quickstart @danistrebel
3536
/tools/oas-apigee-mock @markjkelly
3637
/tools/pipeline-linter @seymen @danistrebel
3738
/tools/pipeline-runner @seymen @danistrebel
38-
/tools/sf-dependency-list @yuriylesyuk
3939
/tools/proxy-endpoint-unifier @anaik91
40-
/tools/target-server-validator @anaik91
40+
/tools/sf-dependency-list @yuriylesyuk
41+
/tools/target-server-validator @anaik91

‎README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ Apigee products.
9292
A tool to unify/split proxy endpoints based on API basepath.
9393
- [Apigee Target Server Validator](tools/target-server-validator) -
9494
A tool to validate all targets in Target Servers & Apigee API Proxy Bundles.
95-
95+
- [gRPC to HTTP Gateway Generator](tools/grpc-http-gateway-generator) -
96+
Generate gateways to expose gRPC services with HTTP API management.
9697
## Labs
9798

9899
This folder contains raw assets used to generate content to teach a particular
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# gRPC to HTTP Gateway Generator
2+
3+
The purpose of this tool is to generate a gRPC to HTTP gateway based on a protocol buffer.
4+
It leverages the [gRPC Gateway](https://github.com/grpc-ecosystem/grpc-gateway) project to generate the gateway code.
5+
6+
The generated gRPC gateway can then be used to create HTTP adapters for gRPC services and use them in a classical HTTP REST-based API management environment.
7+
8+
![Architecture Overview](./img/architecture.png)
9+
10+
## Prerequisites
11+
12+
The generator assumed you have the protobuf compiler `protoc` installed.
13+
14+
Note that `protoc` is pre-installed on Cloud Shell.
15+
16+
To install `protoc` with `apt`, run the following command:
17+
18+
```sh
19+
apt install -y protobuf-compiler
20+
```
21+
22+
## Generate the Gateway Code
23+
24+
The gateway is generated based on a protocol buffer file that you supply with the `--proto-path` flag:
25+
26+
```sh
27+
./generate-gateway.sh --proto-path ./examples/currency.proto
28+
```
29+
30+
Optionally you can also specify the desired output directory with the `--output` flag. If no output directory is specified the output will be generated in the `./generated/gateway` folder.
31+
32+
## Run the Gateway
33+
34+
You can run the gateway locally with the following commands and point to a gRPC server endpoint that runs on localhost port 9090:
35+
36+
```sh
37+
(cd generated/gateway && go run main.go --grpc-server-endpoint localhost:9090)
38+
```
39+
40+
If you preffer to run the gateway as a container use the following commands to build and run the gateway container:
41+
42+
```sh
43+
(cd generated/gateway && docker build . -t gateway:latest)
44+
docker run -p 8080:8080 -e GRPC_SERVER_ENDPOINT=localhost:9090 gateway:latest
45+
```
46+
47+
## Try it out locally
48+
49+
With the gateway running you can call the automatically generated API endpoints of the gateway to consume your gRPC service.
50+
51+
With the gRPC Gateway pointing to an exposed currency service of the [microservice demo](https://github.com/GoogleCloudPlatform/microservices-demo) the currency conversion request would look like this:
52+
53+
```sh
54+
curl -X POST localhost:8080/hipstershop.CurrencyService/Convert -d '{"from": {"units": 3, "currency_code": "USD", "nanos": 0}, "to_code": "CHF"}'
55+
```
56+
57+
Whist the code to request supported currencies looks like this:
58+
59+
```sh
60+
curl -X POST localhost:8080/hipstershop.CurrencyService/GetSupportedCurrencies
61+
```
62+
63+
Note that the automatically generated API doesn't yet come in a RESTful format. This is one of the aspects that can be changed in an API management layer to improve the overall usability and security of the API.
64+
65+
### Deploy to Cloud Run
66+
67+
Once we've tested the gateway locally we can deploy it to Cloud Run for production use.
68+
69+
```sh
70+
(cd generated/gateway && gcloud run deploy currency-grpc-gw --source . --allow-unauthenticated --region europe-west1 --project $PROJECT_ID)
71+
```
72+
73+
## Expose the Cloud Run Service via Apigee
74+
75+
With the Gateway running in Cloud Run we can now expose it via Apigee.
76+
For detailed instructions on how to expose a cloud run service in Apigee please see [this reference implementation](https://github.com/apigee/devrel/tree/main/references/cloud-run).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
version: v1
16+
plugins:
17+
- plugin: go
18+
out: gen/go
19+
opt:
20+
- paths=source_relative
21+
- plugin: go-grpc
22+
out: gen/go
23+
opt:
24+
- paths=source_relative
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<!--
3+
Copyright 2024 Google LLC
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<APIProxy revision="1" name="currency-v1">
18+
</APIProxy>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<AssignMessage name="AM.SetConversionPath">
17+
<AssignVariable>
18+
<Name>flow.target.pathsuffix</Name>
19+
<Value>/hipstershop.CurrencyService/Convert</Value>
20+
</AssignVariable>
21+
</AssignMessage>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<AssignMessage name="AM.SetCurrenciesPath">
17+
<AssignVariable>
18+
<Name>flow.target.pathsuffix</Name>
19+
<Value>/hipstershop.CurrencyService/GetSupportedCurrencies</Value>
20+
</AssignVariable>
21+
</AssignMessage>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<HTTPModifier continueOnError="false" enabled="true" name="HM.SetTargetMethod">
17+
<Set>
18+
<Verb>POST</Verb>
19+
</Set>
20+
</HTTPModifier>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<Javascript timeLimit="200" name="JS.SetTargetPath">
17+
<ResourceURL>jsc://set-target-path.js</ResourceURL>
18+
</Javascript>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<ProxyEndpoint name="default">
17+
<Flows>
18+
<Flow>
19+
<Condition>request.verb = "GET" and proxy.pathsuffix = "/currencies"</Condition>
20+
<Request>
21+
<Step>
22+
<Name>AM.SetCurrenciesPath</Name>
23+
</Step>
24+
</Request>
25+
</Flow>
26+
<Flow>
27+
<Condition>request.verb = "POST" and proxy.pathsuffix = "/convert"</Condition>
28+
<Request>
29+
<Step>
30+
<Name>AM.SetConversionPath</Name>
31+
</Step>
32+
</Request>
33+
</Flow>
34+
</Flows>
35+
<PostFlow>
36+
<Request>
37+
<Step>
38+
<Name>HM.SetTargetMethod</Name>
39+
</Step>
40+
</Request>
41+
</PostFlow>
42+
<HTTPProxyConnection>
43+
<BasePath>/currency/v1</BasePath>
44+
</HTTPProxyConnection>
45+
<RouteRule name="default">
46+
<TargetEndpoint>default</TargetEndpoint>
47+
</RouteRule>
48+
</ProxyEndpoint>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
context.setVariable("target.copy.pathsuffix", false)
18+
19+
var existingTargetUrl = context.getVariable("target.url");
20+
var targetPath = context.getVariable("flow.target.pathsuffix") || ""; // retrieve custom path, set by AM policies
21+
var queryString = context.getVariable("request.querystring") || "";
22+
23+
var updatedTargetUrl = existingTargetUrl + targetPath + (queryString ? "?"+queryString : "");
24+
25+
context.setVariable("target.url",
26+
existingTargetUrl + // use target base URL
27+
targetPath + // append custom path
28+
(queryString ? "?"+queryString : "") // conditionally append query params
29+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<TargetEndpoint name="default">
17+
<PreFlow>
18+
<Request>
19+
<Step>
20+
<Name>JS.SetTargetPath</Name>
21+
</Step>
22+
</Request>
23+
</PreFlow>
24+
<HTTPTargetConnection>
25+
<Authentication>
26+
<GoogleIDToken>
27+
<Audience>CLOUD_RUN_URL</Audience>
28+
</GoogleIDToken>
29+
</Authentication>
30+
<URL>CLOUD_RUN_URL</URL>
31+
</HTTPTargetConnection>
32+
</TargetEndpoint>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright 2024 Google LLC
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: serving.knative.dev/v1
16+
kind: Service
17+
metadata:
18+
name: currency-service
19+
spec:
20+
template:
21+
spec:
22+
containers:
23+
- name: grpc-gateway
24+
image: GRPC_GATEWAY_IMAGE
25+
ports:
26+
- name: http1
27+
containerPort: 8080
28+
resources:
29+
limits:
30+
cpu: 1000m
31+
memory: 512Mi
32+
startupProbe:
33+
timeoutSeconds: 240
34+
periodSeconds: 240
35+
failureThreshold: 1
36+
tcpSocket:
37+
port: 8080
38+
- name: currencyservice-1
39+
image: gcr.io/google-samples/microservices-demo/currencyservice@sha256:e08a1f5d4e4b74fc3d6222d535a11615e8201e7075a090c1ba4436ef1f1cbe7b
40+
env:
41+
- name: PORT
42+
value: "9090"
43+
resources:
44+
limits:
45+
cpu: 1000m
46+
memory: 512Mi
47+
startupProbe:
48+
timeoutSeconds: 1
49+
periodSeconds: 10
50+
failureThreshold: 3
51+
grpc:
52+
port: 9090
53+
service: currencyservice-v1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
syntax = "proto3";
16+
17+
package hipstershop;
18+
19+
// -----------------Currency service-----------------
20+
21+
service CurrencyService {
22+
rpc GetSupportedCurrencies(Empty) returns (GetSupportedCurrenciesResponse) {}
23+
rpc Convert(CurrencyConversionRequest) returns (Money) {}
24+
}
25+
26+
message Empty {
27+
}
28+
29+
// Represents an amount of money with its currency type.
30+
message Money {
31+
// The 3-letter currency code defined in ISO 4217.
32+
string currency_code = 1;
33+
34+
// The whole units of the amount.
35+
// For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
36+
int64 units = 2;
37+
38+
// Number of nano (10^-9) units of the amount.
39+
// The value must be between -999,999,999 and +999,999,999 inclusive.
40+
// If `units` is positive, `nanos` must be positive or zero.
41+
// If `units` is zero, `nanos` can be positive, zero, or negative.
42+
// If `units` is negative, `nanos` must be negative or zero.
43+
// For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
44+
int32 nanos = 3;
45+
}
46+
47+
message GetSupportedCurrenciesResponse {
48+
// The 3-letter currency code defined in ISO 4217.
49+
repeated string currency_codes = 1;
50+
}
51+
52+
message CurrencyConversionRequest {
53+
Money from = 1;
54+
55+
// The 3-letter currency code defined in ISO 4217.
56+
string to_code = 2;
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/bin/bash
2+
# Copyright 2024 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
17+
set -e
18+
19+
# check if protoc is installed
20+
if ! command -v protoc &> /dev/null; then
21+
echo "[ERROR] protoc is not installed. Please install protoc before running this script."
22+
exit 1
23+
fi
24+
25+
proto_path=""
26+
out=""
27+
28+
while [[ $# -gt 0 ]]; do
29+
case $1 in
30+
--proto-path)
31+
proto_path="$2"
32+
shift 2
33+
;;
34+
--out)
35+
out="$2"
36+
shift 2
37+
;;
38+
--*|-*)
39+
echo "Unknown option $1"
40+
exit 1
41+
;;
42+
esac
43+
done
44+
45+
# check if proto path is provided
46+
if [ -z "$proto_path" ]; then
47+
echo "[ERROR] Proto path is required supply via variable --proto-path"
48+
exit 1
49+
fi
50+
51+
# check if proto path is a file
52+
if [ ! -f "$proto_path" ]; then
53+
echo "[ERROR] Proto path is not a file"
54+
exit 1
55+
fi
56+
57+
# check if output directory is provided
58+
if [ -z "$out" ]; then
59+
echo "[WARN] Output directory is not provided via variable --out. Using the default value ./generated/gateway"
60+
out="$(pwd)/generated/gateway"
61+
else
62+
mkdir -p "$out"
63+
out="$(cd "$out"; pwd -P)"
64+
fi
65+
66+
script_dir="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
67+
68+
temp_dir=$(mktemp -d)
69+
proto_file_name=$(basename "$proto_path")
70+
cp "$proto_path" "$temp_dir/$proto_file_name"
71+
72+
73+
# install tooling dependencies
74+
pushd "$script_dir/tools" &> /dev/null
75+
go mod tidy
76+
go install \
77+
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
78+
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
79+
google.golang.org/protobuf/cmd/protoc-gen-go \
80+
google.golang.org/grpc/cmd/protoc-gen-go-grpc
81+
PATH="$PATH:$(go env GOPATH)/bin"
82+
export PATH
83+
popd &> /dev/null
84+
85+
# Generate the gRPC adapter
86+
mkdir -p "$out/adapter"
87+
88+
pushd "$temp_dir" &> /dev/null
89+
protoc -I . \
90+
--go_out "$out/adapter" \
91+
--go_opt "M$proto_file_name=.;adapter" \
92+
--go-grpc_out "$out/adapter" \
93+
--go-grpc_opt "M$proto_file_name=.;adapter" \
94+
"./$proto_file_name"
95+
96+
protoc -I . --grpc-gateway_out "$out/adapter" \
97+
--grpc-gateway_opt "M$proto_file_name=.;adapter" \
98+
--grpc-gateway_opt generate_unbound_methods=true \
99+
"./$proto_file_name"
100+
popd &> /dev/null
101+
102+
cp "$script_dir/templates/main.go" "$out/main.go"
103+
cp "$script_dir/templates/Dockerfile" "$out/Dockerfile"
104+
105+
(cd "$out/adapter" && go mod init adapter &> /dev/null && go mod tidy &> /dev/null)
106+
(cd "$out" && go mod init gateway &> /dev/null && go mod edit -replace adapter=./adapter && go mod tidy &> /dev/null)
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/bin/bash
2+
3+
# Copyright 2024 Google LLC
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -e # exit on first error
18+
19+
SCRIPTPATH="$( cd "$(dirname "$0")" || exit >/dev/null 2>&1 ; pwd -P )"
20+
export PATH="$PATH:$SCRIPTPATH/../../tools/apigee-sackmesser/bin"
21+
22+
PROJECT_ID=$(gcloud config get-value project)
23+
GCP_REGION=europe-west2
24+
25+
# Generate the gRCP Gateway based on the proto file
26+
rm -rdf generated || true
27+
./generate-gateway.sh --proto-path ./examples/currency.proto
28+
29+
# Build the gRPC Gateway
30+
(cd generated/gateway && CGO_ENABLED=0 go build -o grpcgateway .)
31+
32+
# Build the grpc-gateway container and push it to Artifact Registry
33+
(cd generated/gateway && docker build -t grpc-gateway:latest .)
34+
35+
DOCKER_REPO="devrel"
36+
REPO_LOCATION="europe"
37+
38+
if [ -z "$(gcloud artifacts repositories describe $DOCKER_REPO \
39+
--location=$REPO_LOCATION \
40+
--project "$PROJECT_ID" \
41+
--format='get(name)')" ]; then \
42+
43+
gcloud artifacts repositories create $DOCKER_REPO \
44+
--repository-format=docker \
45+
--location=$REPO_LOCATION \
46+
--project="$PROJECT_ID"
47+
fi
48+
49+
IMAGE_PATH="$REPO_LOCATION-docker.pkg.dev/$PROJECT_ID/$DOCKER_REPO/grpc-gateway"
50+
docker tag grpc-gateway:latest "$IMAGE_PATH:latest"
51+
docker push "$IMAGE_PATH"
52+
53+
# Deploy grpc-gateway container to Cloud Run
54+
sed -i.bak "s|GRPC_GATEWAY_IMAGE|$IMAGE_PATH|g" "examples/currency-v1/cloud-run-service.yaml"
55+
56+
gcloud run services replace examples/currency-v1/cloud-run-service.yaml \
57+
--project "$PROJECT_ID" --region $GCP_REGION \
58+
--platform managed
59+
60+
# Generate and deploy an Apigee API proxy for the currency-service
61+
SA_EMAIL="apigee-test-cloudrun@$APIGEE_X_ORG.iam.gserviceaccount.com"
62+
63+
if [ -z "$(gcloud iam service-accounts list --filter "$SA_EMAIL" --format="value(email)" --project "$APIGEE_X_ORG")" ]; then
64+
gcloud iam service-accounts create apigee-test-cloudrun \
65+
--description="Apigee Test Cloud Run" --project "$APIGEE_X_ORG"
66+
fi
67+
68+
gcloud run services add-iam-policy-binding currency-service \
69+
--member="serviceAccount:$SA_EMAIL" \
70+
--role='roles/run.invoker' \
71+
--region=$GCP_REGION \
72+
--platform=managed --project "$PROJECT_ID"
73+
74+
CLOUD_RUN_URL=$(gcloud run services list --filter currency-service --format="value(status.url)" --limit 1)
75+
sed -i "s|CLOUD_RUN_URL|$CLOUD_RUN_URL|g" "examples/currency-v1/apiproxy/targets/default.xml"
76+
77+
TOKEN="$(gcloud config config-helper --force-auth-refresh --format json | jq -r '.credential.access_token')"
78+
sackmesser deploy -d "$SCRIPTPATH/examples/currency-v1" -o "$APIGEE_X_ORG" -e "$APIGEE_X_ENV" -t "$TOKEN" --deployment-sa "$SA_EMAIL"
79+
80+
# Test the Apigee API
81+
curl -X GET "https://$APIGEE_X_HOSTNAME/currency/v1/currencies"
82+
83+
curl -X POST "https://$APIGEE_X_HOSTNAME/currency/v1/convert" \
84+
-d '{"from": {"units": 3, "currency_code": "USD", "nanos": 0}, "to_code": "CHF"}'
85+
86+
# Clean up
87+
# undeploy and delete proxy
88+
# delete CR service
89+
# delete SA
90+
# delete AR registry
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2024 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
FROM golang:alpine as app-builder
16+
17+
WORKDIR /go/src/app
18+
COPY . .
19+
20+
RUN CGO_ENABLED=0 go build -o grpcgateway .
21+
22+
FROM scratch
23+
COPY --from=app-builder /go/src/app/grpcgateway /gateway
24+
25+
ENTRYPOINT ["/gateway"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package main
16+
17+
import (
18+
"context"
19+
"flag"
20+
"net/http"
21+
"os"
22+
23+
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
24+
"google.golang.org/grpc"
25+
"google.golang.org/grpc/credentials/insecure"
26+
"google.golang.org/grpc/grpclog"
27+
28+
gw "adapter" // needs to be replaced
29+
)
30+
31+
var (
32+
// command-line options:
33+
// gRPC server endpoint
34+
grpcServerEndpointFlag = flag.String("grpc-server-endpoint", "", "gRPC server endpoint")
35+
)
36+
37+
func run() error {
38+
ctx := context.Background()
39+
ctx, cancel := context.WithCancel(ctx)
40+
defer cancel()
41+
42+
// Register gRPC server endpoint
43+
mux := runtime.NewServeMux()
44+
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
45+
46+
grpcServerEndpoint := *grpcServerEndpointFlag
47+
if grpcServerEndpoint == "" {
48+
grpcServerEndpoint = os.Getenv("GRPC_SERVER_ENDPOINT")
49+
}
50+
if grpcServerEndpoint == "" {
51+
grpcServerEndpoint = "localhost:9090"
52+
}
53+
54+
grpclog.Infof("Upstream gRPC server endpoint = %s", grpcServerEndpoint)
55+
56+
err := gw.RegisterCurrencyServiceHandlerFromEndpoint(ctx, mux, grpcServerEndpoint, opts)
57+
if err != nil {
58+
return err
59+
}
60+
61+
// Start HTTP server (and proxy calls to gRPC server endpoint)
62+
port := os.Getenv("PORT")
63+
if port == "" {
64+
port = "8080"
65+
}
66+
grpclog.Infof("Serving gRPC-Gateway on http://0.0.0.0:%s", port)
67+
return http.ListenAndServe( ":" + port, mux)
68+
}
69+
70+
func main() {
71+
flag.Parse()
72+
73+
if err := run(); err != nil {
74+
grpclog.Fatal(err)
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module tools
2+
3+
go 1.22.4
4+
5+
require (
6+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
7+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0
8+
google.golang.org/protobuf v1.34.2
9+
)
10+
11+
require (
12+
github.com/kr/text v0.2.0 // indirect
13+
github.com/rogpeppe/go-internal v1.12.0 // indirect
14+
golang.org/x/text v0.15.0 // indirect
15+
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect
16+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect
17+
google.golang.org/grpc v1.64.0 // indirect
18+
gopkg.in/yaml.v3 v3.0.1 // indirect
19+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
3+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
4+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
5+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
6+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
7+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
8+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
9+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
10+
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
11+
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
12+
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
13+
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
14+
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
15+
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
16+
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
17+
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
18+
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No=
19+
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas=
20+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA=
21+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
22+
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
23+
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
24+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0 h1:9SxA29VM43MF5Z9dQu694wmY5t8E/Gxr7s+RSxiIDmc=
25+
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0/go.mod h1:yZOK5zhQMiALmuweVdIVoQPa6eIJyXn2B9g5dJDhqX4=
26+
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
27+
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
28+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
29+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
30+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
31+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
32+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// +build tools
16+
17+
package tools
18+
19+
import (
20+
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
21+
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
22+
_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
23+
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
24+
)

‎tools/pipeline-runner/Dockerfile

+4-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ RUN apk add --no-cache \
3535
ca-certificates \
3636
ttf-freefont \
3737
py-pip \
38-
zip
38+
zip \
39+
make \
40+
go \
41+
protobuf-dev
3942

4043
# Reduce nighly log (note: -ntp requires maven 3.6.1+)
4144
RUN mv /usr/bin/mvn /usr/bin/_mvn &&\

0 commit comments

Comments
 (0)
Please sign in to comment.