Skip to content

Commit

Permalink
got initial c++ grpc server up and running
Browse files Browse the repository at this point in the history
  • Loading branch information
Max-Gabriel-Susman committed Nov 4, 2023
1 parent bf32bd2 commit a082bf4
Show file tree
Hide file tree
Showing 8 changed files with 442 additions and 0 deletions.
56 changes: 56 additions & 0 deletions greeter-service/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#
# Copyright 2019 The Cloud Robotics Authors
#
# 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.
#

HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11 -I .
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

PROTOS_PATH = ./proto/

vpath %.proto $(PROTOS_PATH)

all: greeter-server greeter-client

greeter-server: helloworld.pb.o helloworld.grpc.pb.o server/server.o
$(CXX) $^ $(LDFLAGS) -o $@

greeter-client: helloworld.pb.o helloworld.grpc.pb.o client/client.o
$(CXX) $^ $(LDFLAGS) -o $@

.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<

.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
$(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<

clean:
rm -f *.o client/*.o server/*.o *.pb *.pb.cc *.pb.h
11 changes: 11 additions & 0 deletions greeter-service/client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM grpc/cxx:1.12.0

WORKDIR /data

COPY client/client.cc ./client/
COPY proto/helloworld.proto ./proto/
COPY Makefile ./

RUN make greeter-client && make clean

CMD ["./greeter-client"]
116 changes: 116 additions & 0 deletions greeter-service/client/client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
*
* Copyright 2019 The Cloud Robotics Authors
*
* 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.
*
*/

#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>

#include "helloworld.grpc.pb.h"

using grpc::Channel;
using grpc::ChannelCredentials;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;

class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}

// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);

// Container for the data we expect from the server.
HelloReply reply;

// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;

// The actual RPC.
Status status = stub_->SayHello(&context, request, &reply);

// Act upon its status.
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}

private:
std::unique_ptr<Greeter::Stub> stub_;
};

int main(int argc, char** argv) {
if (argc < 2) {
const std::string client_path(argv[0]);
std::cout << "Usage:" << std::endl;
std::cout << " " << client_path << " <address[:port]> [<name>]"
<< std::endl;
std::cout << "Example:" << std::endl;
std::cout << " " << client_path
<< " www.endpoints.${PROJECT_ID}.cloud.goog:443" << std::endl;
return 0;
}

// The first parameter is the server's address, optionally containing the
// port.
std::string grpc_endpoint(argv[1]);
if (grpc_endpoint.find(":") == std::string::npos) {
// Set the default port of the server.
grpc_endpoint += ":50051";
}

// The optional second parameter is the name to be sent to the server.
std::string name("world");
if (argc >= 3) {
name = argv[2];
}

std::cout << "Sending request to " << grpc_endpoint << " ..." << std::endl;

// We are communicating via SSL to the endpoint service using the credentials
// of the user or robot running the client.
// We don't use credentials when connecting to localhost for testing.
std::shared_ptr<ChannelCredentials> channel_creds;
if (grpc_endpoint.find("localhost:") == 0 ||
grpc_endpoint.find("127.0.0.1:") == 0) {
channel_creds = grpc::InsecureChannelCredentials();
} else {
channel_creds = grpc::GoogleDefaultCredentials();
}

GreeterClient greeter(grpc::CreateChannel(grpc_endpoint, channel_creds));
std::string user(name);
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;

return 0;
}
75 changes: 75 additions & 0 deletions greeter-service/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash
#
# Copyright 2019 The Cloud Robotics Authors
#
# 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 -o pipefail -o errexit
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd ${DIR}

function die {
echo "$1" >&2
exit 1
}

function push_image {
local target=$1

docker build -f "${target}/Dockerfile" -t "greeter-${target}" .
docker tag "greeter-${target}" "gcr.io/${PROJECT_ID}/greeter-${target}"
docker push "gcr.io/${PROJECT_ID}/greeter-${target}"
}

function create_config {
cat greeter-server.yaml.tmpl | envsubst >greeter-server.yaml
}

# public functions
function push_client {
push_image client
}

function update_config {
create_config
kubectl apply -f greeter-server.yaml
}

function update_server {
push_image server
kubectl delete pod -l 'app=greeter-server-app'
update_config
}

function create {
push_image server
push_client
update_config
}

function delete {
create_config
kubectl delete -f greeter-server.yaml
}

# main
if [[ -z ${PROJECT_ID} ]]; then
die "Set PROJECT_ID first: export PROJECT_ID=[GCP project id]"
fi

if [[ ! "$1" =~ ^(create|delete|update_config|update_server|push_client)$ ]]; then
die "Usage: $0 {create|delete|update_config|update_server|push_client}"
fi

# call arguments verbatim:
"$@"
58 changes: 58 additions & 0 deletions greeter-service/greeter-server.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: greeter-server-ingress
annotations:
nginx.ingress.kubernetes.io/backend-protocol: GRPC
nginx.ingress.kubernetes.io/auth-url: "http://token-vendor.default.svc.cluster.local/apis/core.token-vendor/v1/token.verify?robots=true"
spec:
ingressClassName: nginx
rules:
- host: "www.endpoints.${PROJECT_ID}.cloud.goog"
http:
paths: # must match the namespace and service name in the proto
- path: /helloworld.Greeter/
pathType: Prefix
backend:
service:
name: greeter-server-service
# must match the port used in server.cc
port:
number: 50051
---
apiVersion: v1
kind: Service
metadata:
name: greeter-server-service
spec:
ports:
- # optional descriptive name for the service port
name: grpc-port
# must match the service port specified in ingress
port: 50051
# the selector is used to link pods to services
selector:
app: greeter-server-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: greeter-server
spec:
replicas: 1
# all pods matching this selector belong to this deployment
selector:
matchLabels:
app: greeter-server-app
template:
metadata:
# the other side of the link between services and pods
labels:
app: greeter-server-app
spec:
containers:
- name: greeter-server
image: "gcr.io/${PROJECT_ID}/greeter-server:latest"
ports:
# must match the port of the service
- containerPort: 50051
33 changes: 33 additions & 0 deletions greeter-service/proto/helloworld.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2019 The Cloud Robotics Authors
//
// 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.

syntax = "proto3";

package helloworld;

// The greeting service definition.
service Greeter {
// Sends a greeting.
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings.
message HelloReply {
string message = 1;
}
11 changes: 11 additions & 0 deletions greeter-service/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM grpc/cxx:1.12.0

WORKDIR /data

COPY server/server.cc ./server/
COPY proto/helloworld.proto ./proto/
COPY Makefile ./

RUN make greeter-server && make clean

CMD ["./greeter-server"]
Loading

0 comments on commit a082bf4

Please sign in to comment.