Skip to content
This repository has been archived by the owner on Feb 22, 2020. It is now read-only.

feat(proto): versioning protobuf and validating in recv_message #237

Merged
merged 4 commits into from
Sep 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions gnes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
# limitations under the License.


# do not change this line
# this is managed by git tag and replaced on every release
# do not change this line manually
# this is managed by git tag and updated on every release
__version__ = '0.0.38'
__proto_version__ = '20190905'

# do not change this line manually
# this is managed by shell/make-proto.sh and updated on every execution
__proto_version__ = '0.0.4'
3 changes: 3 additions & 0 deletions gnes/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ def set_service_parser(parser=None):
parser.add_argument('--parallel_type', type=ParallelType.from_string, choices=list(ParallelType),
default=ParallelType.PUSH_NONBLOCK,
help='parallel type of the concurrent services')
parser.add_argument('--check_version', action='store_true', default=False,
help='comparing the GNES and proto version of incoming message with local setup, '
'mismatch raise an exception')
return parser


Expand Down
2 changes: 1 addition & 1 deletion gnes/client/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ def send_message(self, message: "gnes_pb2.Message", timeout: int = -1):
send_message(self.sender, message, timeout=timeout)

def recv_message(self, timeout: int = -1) -> gnes_pb2.Message:
r = recv_message(self.receiver, timeout=timeout)
r = recv_message(self.receiver, timeout=timeout, check_version=self.args.check_version)
self.logger.info('recv a message: %s' % r.envelope)
return r
17 changes: 16 additions & 1 deletion gnes/proto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def send_message(sock: 'zmq.Socket', msg: 'gnes_pb2.Message', timeout: int = -1)
sock.setsockopt(zmq.SNDTIMEO, -1)


def recv_message(sock: 'zmq.Socket', timeout: int = -1) -> Optional['gnes_pb2.Message']:
def recv_message(sock: 'zmq.Socket', timeout: int = -1, check_version: bool = False) -> Optional['gnes_pb2.Message']:
response = []
try:
if timeout > 0:
Expand All @@ -144,6 +144,21 @@ def recv_message(sock: 'zmq.Socket', timeout: int = -1) -> Optional['gnes_pb2.Me
_, msg_data = sock.recv_multipart()
msg = gnes_pb2.Message()
msg.ParseFromString(msg_data)

if check_version and msg.envelope:
from .. import __version__, __proto_version__
if hasattr(msg.envelope, 'gnes_version') and __version__ != msg.envelope.gnes_version:
raise AttributeError('mismatched GNES version! '
'incoming message has GNES version %s, whereas local GNES version %s' % (
msg.envelope.gnes_version, __version__))
if hasattr(msg.envelope, 'proto_version') and __proto_version__ != msg.envelope.proto_version:
raise AttributeError('mismatched protobuf version! '
'incoming message has protobuf version %s, whereas local protobuf version %s' % (
msg.envelope.proto_version, __proto_version__))
if not hasattr(msg.envelope, 'proto_version') and not hasattr(msg.envelope, 'gnes_version'):
raise AttributeError('version_check=True locally, '
'but incoming message contains no version info in its envelope. '
'the message is probably sent from an outdated GNES service')
return msg

except ValueError:
Expand Down
4 changes: 4 additions & 0 deletions gnes/proto/gnes.proto
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ message Envelope {
google.protobuf.Timestamp timestamp = 2;
}
repeated route routes = 6;

string gnes_version = 7;

string proto_version = 8;
}

message Message {
Expand Down
86 changes: 50 additions & 36 deletions gnes/proto/gnes_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion gnes/service/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ def _run(self, ctx):
self.is_handler_done.clear()

# receive message
msg = recv_message(pull_sock)
msg = recv_message(pull_sock, check_version=self.args.check_version)

# choose output sock
if msg.request and msg.request.WhichOneof('body') and \
Expand Down
17 changes: 17 additions & 0 deletions shell/make-proto.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env bash

set -e

SRC_NAME=gnes.proto
SRC_DIR=../gnes/proto/
VER_FILE=../gnes/__init__.py

# generating test proto

Expand All @@ -11,7 +14,21 @@ SRC_DIR=../gnes/proto/
PLUGIN_PATH=/Volumes/TOSHIBA-4T/Documents/grpc/bins/opt/grpc_python_plugin
#PLUGIN_PATH=/user/local/grpc/bins/opt/grpc_python_plugin

printf "\e[1;33mgenerating protobuf and grpc python interface\e[0m\n"

protoc -I ${SRC_DIR} --python_out=${SRC_DIR} --grpc_python_out=${SRC_DIR} --plugin=protoc-gen-grpc_python=${PLUGIN_PATH} ${SRC_DIR}${SRC_NAME}

printf "\e[1;33mfixing grpc import\e[0m\n"
# fix import bug in google generator
sed -i '' -e '4s/.*/from\ \.\ import\ gnes_pb2\ as\ gnes__pb2/' ${SRC_DIR}gnes_pb2_grpc.py

# update protobuf version in gnes/__init__.py

OLDVER=$(sed -n 's/^__proto_version__ = '\''\(.*\)'\''$/\1/p' $VER_FILE)
printf "current proto version:\t\e[1;33m$OLDVER\e[0m\n"

NEWVER=$(echo $OLDVER | awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{$NF=sprintf("%0*d", length($NF), ($NF+1)); print}')
printf "bump proto version to:\t\e[1;32m$NEWVER\e[0m\n"

sed -i '' -e 's/^__proto_version__ = '\''\(.*\)'\''/__proto_version__ = '\'"$NEWVER"\''/' $VER_FILE
printf "\e[1;32mAll done!\e[0m\n"