Skip to content

Commit

Permalink
Merge pull request #20 from icgood/check
Browse files Browse the repository at this point in the history
Add health check client command
  • Loading branch information
icgood authored Dec 5, 2021
2 parents d57a24b + 019c67a commit 6cde908
Show file tree
Hide file tree
Showing 16 changed files with 322 additions and 194 deletions.
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pymapadmin/grpc/admin_grpc.py -diff
pymapadmin/grpc/admin_pb2.py -diff
pymapadmin/grpc/admin_pb2.pyi -diff
4 changes: 2 additions & 2 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9]
python-version: ['3.10']

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel twine
Expand All @@ -35,7 +35,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
Expand Down
75 changes: 47 additions & 28 deletions pymapadmin/commands/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

from .. import __version__ as client_version
from ..local import token_file
from ..typing import StubT, RequestT, ResponseT, MethodProtocol
from ..typing import StubT, MethodProtocol, RequestT, ResponseT, \
AdminRequestT, AdminResponseT
from ..grpc.admin_pb2 import SUCCESS

try:
Expand All @@ -23,7 +24,7 @@
except ImportError: # pragma: no cover
pass

__all__ = ['Command', 'ClientCommand']
__all__ = ['Command', 'ClientCommand', 'AdminCommand']


class Command(metaclass=ABCMeta):
Expand Down Expand Up @@ -106,6 +107,7 @@ def build_request(self) -> RequestT:
"""Build the request."""
...

@abstractmethod
def handle_response(self, response: ResponseT, outfile: TextIO) -> int:
"""Handle each response. For streaming responses, this will be
called once for each streamed response as long as ``0`` is returned.
Expand All @@ -118,32 +120,7 @@ def handle_response(self, response: ResponseT, outfile: TextIO) -> int:
outfile: The file object to print the output to.
"""
if response.result.code == SUCCESS:
self.handle_success(response, outfile)
return 0
else:
self.handle_failure(response, outfile)
return 1

def handle_success(self, response: ResponseT, outfile: TextIO) -> None:
"""Print a successful response.
Args:
response: The response from the server.
outfile: The file object to print the output to.
"""
print(response, file=outfile)

def handle_failure(self, response: ResponseT, outfile: TextIO) -> None:
"""Print a failure response.
Args:
response: The response from the server.
outfile: The file object to print the output to.
"""
print(response.result, file=sys.stderr)
...

def handle_exception(self, exc: Exception, outfile: TextIO) -> int:
"""Handle an exception that occurred while calling the RPC function.
Expand All @@ -170,3 +147,45 @@ async def __call__(self, outfile: TextIO) -> int:
return self.handle_exception(exc, outfile)
else:
return 0


class AdminCommand(ClientCommand[StubT, AdminRequestT, AdminResponseT],
metaclass=ABCMeta):
"""Interface for client command implementations.
Args:
args: The command line arguments.
client: The client object.
"""

def handle_response(self, response: AdminResponseT,
outfile: TextIO) -> int:
if response.result.code == SUCCESS:
self.handle_success(response, outfile)
return 0
else:
self.handle_failure(response, outfile)
return 1

def handle_success(self, response: AdminResponseT,
outfile: TextIO) -> None:
"""Print a successful response.
Args:
response: The response from the server.
outfile: The file object to print the output to.
"""
print(response, file=outfile)

def handle_failure(self, response: AdminResponseT,
outfile: TextIO) -> None:
"""Print a failure response.
Args:
response: The response from the server.
outfile: The file object to print the output to.
"""
print(response.result, file=sys.stderr)
49 changes: 49 additions & 0 deletions pymapadmin/commands/health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

from __future__ import annotations

from argparse import ArgumentParser
from typing import Any, TextIO

from grpclib.health.v1.health_grpc import HealthStub
from grpclib.health.v1.health_pb2 import \
HealthCheckRequest, HealthCheckResponse

from .base import ClientCommand
from ..typing import RequestT, ResponseT, MethodProtocol

__all__ = ['CheckCommand']


class HealthCommand(ClientCommand[HealthStub, RequestT, ResponseT]):

@property
def client(self) -> HealthStub:
return HealthStub(self.channel)


class CheckCommand(HealthCommand[HealthCheckRequest,
HealthCheckResponse]):
"""Check the health of the server."""

@classmethod
def add_subparser(cls, name: str, subparsers: Any) \
-> ArgumentParser: # pragma: no cover
return subparsers.add_parser(
name, description=cls.__doc__,
help='check the server health')

@property
def method(self) -> MethodProtocol[HealthCheckRequest,
HealthCheckResponse]:
return self.client.Check

def build_request(self) -> HealthCheckRequest:
return HealthCheckRequest()

def _is_serving(self, response: HealthCheckResponse) -> bool:
return response.status == HealthCheckResponse.ServingStatus.SERVING

def handle_response(self, response: HealthCheckResponse,
outfile: TextIO) -> int:
print(response, file=outfile)
return 0 if self._is_serving(response) else 1
6 changes: 3 additions & 3 deletions pymapadmin/commands/mailbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
from argparse import ArgumentParser, FileType
from typing import Any, TextIO

from .base import ClientCommand
from ..typing import RequestT, ResponseT, MethodProtocol
from .base import AdminCommand
from ..typing import AdminRequestT, AdminResponseT, MethodProtocol
from ..grpc.admin_grpc import MailboxStub
from ..grpc.admin_pb2 import AppendRequest, AppendResponse

__all__ = ['AppendCommand']


class MailboxCommand(ClientCommand[MailboxStub, RequestT, ResponseT]):
class MailboxCommand(AdminCommand[MailboxStub, AdminRequestT, AdminResponseT]):

@property
def client(self) -> MailboxStub:
Expand Down
6 changes: 3 additions & 3 deletions pymapadmin/commands/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
from contextlib import closing
from typing import Any, Optional, TextIO

from .base import Command, ClientCommand
from .base import Command, AdminCommand
from ..config import Config
from ..local import config_file, token_file
from ..typing import RequestT, ResponseT, MethodProtocol
from ..typing import AdminRequestT, AdminResponseT, MethodProtocol
from ..grpc.admin_grpc import SystemStub
from ..grpc.admin_pb2 import LoginRequest, LoginResponse, \
PingRequest, PingResponse

__all__ = ['SaveArgsCommand', 'LoginCommand', 'PingCommand']


class SystemCommand(ClientCommand[SystemStub, RequestT, ResponseT]):
class SystemCommand(AdminCommand[SystemStub, AdminRequestT, AdminResponseT]):

@property
def client(self) -> SystemStub:
Expand Down
6 changes: 3 additions & 3 deletions pymapadmin/commands/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from collections.abc import Mapping, Sequence
from typing import Any, Optional

from .base import ClientCommand
from ..typing import RequestT, ResponseT, MethodProtocol
from .base import AdminCommand
from ..typing import AdminRequestT, AdminResponseT, MethodProtocol
from ..grpc.admin_grpc import UserStub
from ..grpc.admin_pb2 import \
UserData, UserResponse, GetUserRequest, SetUserRequest, DeleteUserRequest

__all__ = ['GetUserCommand', 'SetUserCommand', 'DeleteUserCommand']


class UserCommand(ClientCommand[UserStub, RequestT, ResponseT]):
class UserCommand(AdminCommand[UserStub, AdminRequestT, AdminResponseT]):

@property
def client(self) -> UserStub:
Expand Down
22 changes: 11 additions & 11 deletions pymapadmin/grpc/admin.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ message Result {
message LoginRequest {
string authcid = 1;
string secret = 2;
oneof optional_authzid { string authzid = 3; }
oneof optional_token_expiration { double token_expiration = 4; }
optional string authzid = 3;
optional double token_expiration = 4;
}

message LoginResponse {
Result result = 1;
oneof optional_bearer_token { string bearer_token = 2; }
optional string bearer_token = 2;
}

message PingRequest {}
Expand All @@ -35,9 +35,9 @@ message PingResponse {

message AppendRequest {
string user = 1;
oneof optional_sender { string sender = 2; }
oneof optional_recipient { string recipient = 3; }
oneof optional_mailbox { string mailbox = 4; }
optional string sender = 2;
optional string recipient = 3;
optional string mailbox = 4;
bytes data = 5;
repeated string flags = 6;
uint64 when = 7;
Expand All @@ -46,12 +46,12 @@ message AppendRequest {
message AppendResponse {
Result result = 1;
string mailbox = 2;
uint32 validity = 3;
uint32 uid = 4;
optional uint32 validity = 3;
optional uint32 uid = 4;
}

message UserData {
oneof optional_password { string password = 1; }
optional string password = 1;
map<string, string> params = 2;
}

Expand All @@ -70,8 +70,8 @@ message DeleteUserRequest {

message UserResponse {
Result result = 1;
string username = 2;
oneof optional_data { UserData data = 3; }
optional string username = 2;
UserData data = 3;
}

service System {
Expand Down
Loading

0 comments on commit 6cde908

Please sign in to comment.