Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save vchudnov-g/c3badc32c5a3aa4fba86e04f75fbea04 to your computer and use it in GitHub Desktop.
Save vchudnov-g/c3badc32c5a3aa4fba86e04f75fbea04 to your computer and use it in GitHub Desktop.
Simplest gRPC API with working generated client libraries & samples – # codelab

🦑 G.A.P.I.C 🖥 codelab 🎓

.
├── artman_dogs.yaml
├── dogs.proto
├── dogs_gapic.yaml
├── dogs_server.js
├── dogs_service.yaml
└── generate-and-run.sh

{{ potential source material for a simple gRPC/GAPIC codelab }}

common:
api_name: dogs
api_version: v1
organization_name: codelabs
service_yaml: dogs_service.yaml
gapic_yaml: dogs_gapic.yaml
src_proto_paths:
- dogs.proto
proto_deps:
- name: google-common-protos
artifacts:
- name: python_gapic
type: GAPIC
language: PYTHON
- name: php_gapic
type: GAPIC
language: PHP
syntax = "proto3";
package codelabs.dogs.v1;
service DogsService {
rpc ListDogs(Empty) returns (DogList) {}
rpc AddDog(Dog) returns (Empty) {}
rpc RemoveDog(Dog) returns (Empty) {}
}
message Empty {}
message Dog { string name = 1; }
message DogList { repeated Dog dogs = 1; }
type: com.google.api.codegen.ConfigProto
config_schema_version: 1.0.0
language_settings:
python:
package_name: codelabs.dogs_v1.gapic
php:
package_name: Codelabs\Dogs\V1
interfaces:
- name: codelabs.dogs.v1.DogsService
methods:
- name: ListDogs
samples:
standalone:
- calling_forms: ".*"
value_sets: list_dogs
region_tag: list_dogs
sample_value_sets:
- id: list_dogs
description: "List Dogs"
on_success:
- loop:
variable: dog
collection: $resp.dogs
body:
- print:
- "Dog name: %s"
- dog.name
- name: AddDog
samples:
standalone:
- calling_forms: ".*"
value_sets: add_dog
region_tag: add_dog
sample_value_sets:
- id: add_dog
description: "Add Dog"
parameters:
defaults:
- name="Your dog’s name, e.g. Rover"
attributes:
- parameter: name
sample_argument_name: name
on_success:
- print:
- "Dog added"
- name: RemoveDog
samples:
standalone:
- calling_forms: ".*"
value_sets: remove_dog
region_tag: remove_dog
sample_value_sets:
- id: remove_dog
description: "Remove Dog"
parameters:
defaults:
- name="Your dog’s name, e.g. Rover"
attributes:
- parameter: name
sample_argument_name: name
on_success:
- print:
- "Dog removed"
// To run: npm install grpc && node dogs_server.js
const grpc = require('grpc')
const proto = grpc.load('dogs.proto')
const service = proto.codelabs.dogs.v1.DogsService.service
const server = new grpc.Server()
const dogs = [{ name: "Rover" }, { name: "Spot" }]
server.addService(service, {
listDogs: function(call, callback) {
callback(null, dogs)
},
addDog: function(call, callback) {
const dog = call.request
dogs.push(dog)
callback(null, {})
},
removeDog: function(call, callback) {
const dog = call.request
const dogIndex = dogs.findIndex(d => d.name == dog.name)
if (dogIndex > -1) {
dogs.splice(dogIndex, 1)
callback(null, {})
} else {
callback({ code: grpc.status.NOT_FOUND, details: 'Not found' })
}
}
})
console.log('gRPC listening on localhost:2222')
server.bind('localhost:2222', grpc.ServerCredentials.createInsecure())
server.start()
type: google.api.Service
config_version: 3
name: localhost:2222
apis:
- name: codelabs.dogs.v1.DogsService
#! /bin/bash
language=python
artman_yaml=artman_dogs.yaml
echo "–> –> –> Deleting previous artman-genfiles artifacts"
rm_genfiles_output="`rm -rfv ./artman-genfiles`"
echo "–> –> –> Deleted `echo -e "$rm_genfiles_output" | wc -l` files/dirs"
root="`pwd`"
# Required dependencies (or it blows up)
googleapis_dir="$(samplegen --info | grep "googleapis =" | awk '{print $3}')"
mkdir -pv ./google/{api,rpc,type,longrunning,iam/v1}
for filepath in google/api/{http,annotations}.proto; do
cp -v "$googleapis_dir/$filepath" "./$filepath"
done
echo "–> –> –> Generating Python Library"
gapicgenerator_dir="$(samplegen --info | grep "gapic_generator =" | awk '{print $3}')"
output=`docker run --rm -e RUNNING_IN_ARTMAN_DOCKER=True -v "$(pwd):/googleapis" \
-v "$gapicgenerator_dir:/toolkit" -w /googleapis googleapis/artman /bin/bash -c \
"artman --local --config $artman_yaml generate ${language}_gapic" 2>&1`
docker_exit_code=$?
echo -e $output
if [ $docker_exit_code -ne 0 ]; then
if [[ "$output" =~ "Path gapic not found in" ]]; then
echo "–> –> –> Generation may have failed ($docker_exit_code)"
echo "–> –> –> 'dogs' related directories created:"
find $root/artman-genfiles -type d -name "*dog*"
else
echo "–> –> –> Generating $language failed ($docker_exit_code)"
exit $docker_exit_code
fi
fi
python_library_root="artman-genfiles/python/dogs-v1"
python_samples_path="samples/codelabs/dogs_v1/gapic/list_dogs"
cd "$root/$python_library_root"
echo "–> –> –> FIX standardize import namespaces"
grep -rl "from codelabs.dogs\.v1" codelabs | xargs -n1 sed -i.bak -e "s/from codelabs.dogs.v1/from codelabs.dogs_v1/"
find codelabs/ -name "*.py.bak" -exec rm {} \;
echo "–> –> –> Copy pb2 proto files into package"
mv ../grpc-codelabs-dogs-v1/codelabs/dogs_v1/proto codelabs/dogs_v1/
touch codelabs/dogs_v1/proto/__init__.py
echo "–> –> –> FIX pb2 proto imports"
grep -rl "from codelabs.dogs_v1 import dogs_pb2" . | xargs -n1 sed -i.bak -e "s/dogs_v1 import dogs_pb2/dogs_v1.proto import dogs_pb2/"
find codelabs/ -name "*.py.bak" -exec rm {} \;
echo "–> –> –> FIX samples to use localhost server (without auth)"
for sample in `find samples/codelabs/dogs_v1/gapic -name "*.py"`; do
sed -i.bak -e $'s/import sys/import sys\\\nfrom grpc import insecure_channel/' "$sample"
find samples/ -name "*.py.bak" -exec rm {} \;
sed -i.bak -e 's/\.DogsServiceClient()/.DogsServiceClient(channel=insecure_channel("localhost:2222"))/' "$sample"
find samples/ -name "*.py.bak" -exec rm {} \;
done
echo "–> –> –> FIX setup.py"
for replacement in "s/^.*namespace.*$//" \
"s/if 'google.cloud'.*$//" \
"s/startswith('google')/startswith('codelabs')/"
do
sed -i.bak -e "$replacement" setup.py
done
echo "–> –> –> Install Generated Library"
virtualenv --python python3 env
source env/bin/activate
pip install .
echo "–> –> –> Running Python Samples"
echo "–> –> –> Sample: List Dogs"
python samples/codelabs/dogs_v1/gapic/list_dogs/list_dogs_request_list_dogs.py
echo "–> –> –> Sample: Add Dog"
python samples/codelabs/dogs_v1/gapic/add_dog/add_dog_request_add_dog.py --name "Rex"
echo "–> –> –> Sample: List Dogs"
python samples/codelabs/dogs_v1/gapic/list_dogs/list_dogs_request_list_dogs.py
echo "–> –> –> Sample: Remove Dogs"
python samples/codelabs/dogs_v1/gapic/remove_dog/remove_dog_request_remove_dog.py --name "Rex"
echo "–> –> –> Sample: List Dogs"
python samples/codelabs/dogs_v1/gapic/list_dogs/list_dogs_request_list_dogs.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment