Initial commit
Some checks failed
Continuous Integration - Pull Request / code-tests (pull_request) Has been cancelled
Continuous Integration - Pull Request / deployment-tests (local-code) (pull_request) Has been cancelled
helm-chart-ci / helm-chart-ci (pull_request) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (pull_request) Has been cancelled
kustomize-build-ci / kustomize-build-ci (pull_request) Has been cancelled
terraform-validate-ci / terraform-validate-ci (pull_request) Has been cancelled
Clean up deployment / cleanup-namespace (pull_request) Has been cancelled
Continuous Integration - Main/Release / code-tests (push) Has been cancelled
Continuous Integration - Main/Release / deployment-tests (local-code) (push) Has been cancelled
helm-chart-ci / helm-chart-ci (push) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (push) Has been cancelled
kustomize-build-ci / kustomize-build-ci (push) Has been cancelled
terraform-validate-ci / terraform-validate-ci (push) Has been cancelled
Some checks failed
Continuous Integration - Pull Request / code-tests (pull_request) Has been cancelled
Continuous Integration - Pull Request / deployment-tests (local-code) (pull_request) Has been cancelled
helm-chart-ci / helm-chart-ci (pull_request) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (pull_request) Has been cancelled
kustomize-build-ci / kustomize-build-ci (pull_request) Has been cancelled
terraform-validate-ci / terraform-validate-ci (pull_request) Has been cancelled
Clean up deployment / cleanup-namespace (pull_request) Has been cancelled
Continuous Integration - Main/Release / code-tests (push) Has been cancelled
Continuous Integration - Main/Release / deployment-tests (local-code) (push) Has been cancelled
helm-chart-ci / helm-chart-ci (push) Has been cancelled
kubevious-manifests-ci / kubevious-manifests-ci (push) Has been cancelled
kustomize-build-ci / kustomize-build-ci (push) Has been cancelled
terraform-validate-ci / terraform-validate-ci (push) Has been cancelled
This commit is contained in:
51
src/emailservice/Dockerfile
Normal file
51
src/emailservice/Dockerfile
Normal file
@@ -0,0 +1,51 @@
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
FROM --platform=$BUILDPLATFORM python:3.14.2-alpine@sha256:31da4cb527055e4e3d7e9e006dffe9329f84ebea79eaca0a1f1c27ce61e40ca5 AS base
|
||||
|
||||
FROM base AS builder
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
RUN apk update \
|
||||
&& apk add --no-cache g++ linux-headers \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
# get packages
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
FROM base
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# Enable Profiler
|
||||
ENV ENABLE_PROFILER=1
|
||||
|
||||
RUN apk update \
|
||||
&& apk add --no-cache libstdc++ \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
WORKDIR /email_server
|
||||
|
||||
# Grab packages from builder
|
||||
COPY --from=builder /usr/local/lib/python3.14/ /usr/local/lib/python3.14/
|
||||
|
||||
# Add the application
|
||||
COPY . .
|
||||
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT [ "python", "email_server.py" ]
|
||||
121
src/emailservice/demo_pb2.py
Executable file
121
src/emailservice/demo_pb2.py
Executable file
File diff suppressed because one or more lines are too long
822
src/emailservice/demo_pb2_grpc.py
Executable file
822
src/emailservice/demo_pb2_grpc.py
Executable file
@@ -0,0 +1,822 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# https://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.
|
||||
|
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
import demo_pb2 as demo__pb2
|
||||
|
||||
|
||||
class CartServiceStub(object):
|
||||
"""-----------------Cart service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.AddItem = channel.unary_unary(
|
||||
'/hipstershop.CartService/AddItem',
|
||||
request_serializer=demo__pb2.AddItemRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Empty.FromString,
|
||||
)
|
||||
self.GetCart = channel.unary_unary(
|
||||
'/hipstershop.CartService/GetCart',
|
||||
request_serializer=demo__pb2.GetCartRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Cart.FromString,
|
||||
)
|
||||
self.EmptyCart = channel.unary_unary(
|
||||
'/hipstershop.CartService/EmptyCart',
|
||||
request_serializer=demo__pb2.EmptyCartRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Empty.FromString,
|
||||
)
|
||||
|
||||
|
||||
class CartServiceServicer(object):
|
||||
"""-----------------Cart service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def AddItem(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetCart(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def EmptyCart(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_CartServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'AddItem': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.AddItem,
|
||||
request_deserializer=demo__pb2.AddItemRequest.FromString,
|
||||
response_serializer=demo__pb2.Empty.SerializeToString,
|
||||
),
|
||||
'GetCart': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetCart,
|
||||
request_deserializer=demo__pb2.GetCartRequest.FromString,
|
||||
response_serializer=demo__pb2.Cart.SerializeToString,
|
||||
),
|
||||
'EmptyCart': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.EmptyCart,
|
||||
request_deserializer=demo__pb2.EmptyCartRequest.FromString,
|
||||
response_serializer=demo__pb2.Empty.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.CartService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class CartService(object):
|
||||
"""-----------------Cart service-----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def AddItem(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/AddItem',
|
||||
demo__pb2.AddItemRequest.SerializeToString,
|
||||
demo__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetCart(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/GetCart',
|
||||
demo__pb2.GetCartRequest.SerializeToString,
|
||||
demo__pb2.Cart.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def EmptyCart(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CartService/EmptyCart',
|
||||
demo__pb2.EmptyCartRequest.SerializeToString,
|
||||
demo__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class RecommendationServiceStub(object):
|
||||
"""---------------Recommendation service----------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.ListRecommendations = channel.unary_unary(
|
||||
'/hipstershop.RecommendationService/ListRecommendations',
|
||||
request_serializer=demo__pb2.ListRecommendationsRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.ListRecommendationsResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class RecommendationServiceServicer(object):
|
||||
"""---------------Recommendation service----------
|
||||
|
||||
"""
|
||||
|
||||
def ListRecommendations(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_RecommendationServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'ListRecommendations': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ListRecommendations,
|
||||
request_deserializer=demo__pb2.ListRecommendationsRequest.FromString,
|
||||
response_serializer=demo__pb2.ListRecommendationsResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.RecommendationService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class RecommendationService(object):
|
||||
"""---------------Recommendation service----------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def ListRecommendations(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.RecommendationService/ListRecommendations',
|
||||
demo__pb2.ListRecommendationsRequest.SerializeToString,
|
||||
demo__pb2.ListRecommendationsResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class ProductCatalogServiceStub(object):
|
||||
"""---------------Product Catalog----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.ListProducts = channel.unary_unary(
|
||||
'/hipstershop.ProductCatalogService/ListProducts',
|
||||
request_serializer=demo__pb2.Empty.SerializeToString,
|
||||
response_deserializer=demo__pb2.ListProductsResponse.FromString,
|
||||
)
|
||||
self.GetProduct = channel.unary_unary(
|
||||
'/hipstershop.ProductCatalogService/GetProduct',
|
||||
request_serializer=demo__pb2.GetProductRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Product.FromString,
|
||||
)
|
||||
self.SearchProducts = channel.unary_unary(
|
||||
'/hipstershop.ProductCatalogService/SearchProducts',
|
||||
request_serializer=demo__pb2.SearchProductsRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.SearchProductsResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class ProductCatalogServiceServicer(object):
|
||||
"""---------------Product Catalog----------------
|
||||
|
||||
"""
|
||||
|
||||
def ListProducts(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetProduct(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def SearchProducts(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_ProductCatalogServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'ListProducts': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ListProducts,
|
||||
request_deserializer=demo__pb2.Empty.FromString,
|
||||
response_serializer=demo__pb2.ListProductsResponse.SerializeToString,
|
||||
),
|
||||
'GetProduct': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetProduct,
|
||||
request_deserializer=demo__pb2.GetProductRequest.FromString,
|
||||
response_serializer=demo__pb2.Product.SerializeToString,
|
||||
),
|
||||
'SearchProducts': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SearchProducts,
|
||||
request_deserializer=demo__pb2.SearchProductsRequest.FromString,
|
||||
response_serializer=demo__pb2.SearchProductsResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.ProductCatalogService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class ProductCatalogService(object):
|
||||
"""---------------Product Catalog----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def ListProducts(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/ListProducts',
|
||||
demo__pb2.Empty.SerializeToString,
|
||||
demo__pb2.ListProductsResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetProduct(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/GetProduct',
|
||||
demo__pb2.GetProductRequest.SerializeToString,
|
||||
demo__pb2.Product.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def SearchProducts(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.ProductCatalogService/SearchProducts',
|
||||
demo__pb2.SearchProductsRequest.SerializeToString,
|
||||
demo__pb2.SearchProductsResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class ShippingServiceStub(object):
|
||||
"""---------------Shipping Service----------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.GetQuote = channel.unary_unary(
|
||||
'/hipstershop.ShippingService/GetQuote',
|
||||
request_serializer=demo__pb2.GetQuoteRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.GetQuoteResponse.FromString,
|
||||
)
|
||||
self.ShipOrder = channel.unary_unary(
|
||||
'/hipstershop.ShippingService/ShipOrder',
|
||||
request_serializer=demo__pb2.ShipOrderRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.ShipOrderResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class ShippingServiceServicer(object):
|
||||
"""---------------Shipping Service----------
|
||||
|
||||
"""
|
||||
|
||||
def GetQuote(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def ShipOrder(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_ShippingServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'GetQuote': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetQuote,
|
||||
request_deserializer=demo__pb2.GetQuoteRequest.FromString,
|
||||
response_serializer=demo__pb2.GetQuoteResponse.SerializeToString,
|
||||
),
|
||||
'ShipOrder': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.ShipOrder,
|
||||
request_deserializer=demo__pb2.ShipOrderRequest.FromString,
|
||||
response_serializer=demo__pb2.ShipOrderResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.ShippingService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class ShippingService(object):
|
||||
"""---------------Shipping Service----------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def GetQuote(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.ShippingService/GetQuote',
|
||||
demo__pb2.GetQuoteRequest.SerializeToString,
|
||||
demo__pb2.GetQuoteResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def ShipOrder(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.ShippingService/ShipOrder',
|
||||
demo__pb2.ShipOrderRequest.SerializeToString,
|
||||
demo__pb2.ShipOrderResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class CurrencyServiceStub(object):
|
||||
"""-----------------Currency service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.GetSupportedCurrencies = channel.unary_unary(
|
||||
'/hipstershop.CurrencyService/GetSupportedCurrencies',
|
||||
request_serializer=demo__pb2.Empty.SerializeToString,
|
||||
response_deserializer=demo__pb2.GetSupportedCurrenciesResponse.FromString,
|
||||
)
|
||||
self.Convert = channel.unary_unary(
|
||||
'/hipstershop.CurrencyService/Convert',
|
||||
request_serializer=demo__pb2.CurrencyConversionRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Money.FromString,
|
||||
)
|
||||
|
||||
|
||||
class CurrencyServiceServicer(object):
|
||||
"""-----------------Currency service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def GetSupportedCurrencies(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def Convert(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_CurrencyServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'GetSupportedCurrencies': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetSupportedCurrencies,
|
||||
request_deserializer=demo__pb2.Empty.FromString,
|
||||
response_serializer=demo__pb2.GetSupportedCurrenciesResponse.SerializeToString,
|
||||
),
|
||||
'Convert': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.Convert,
|
||||
request_deserializer=demo__pb2.CurrencyConversionRequest.FromString,
|
||||
response_serializer=demo__pb2.Money.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.CurrencyService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class CurrencyService(object):
|
||||
"""-----------------Currency service-----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def GetSupportedCurrencies(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CurrencyService/GetSupportedCurrencies',
|
||||
demo__pb2.Empty.SerializeToString,
|
||||
demo__pb2.GetSupportedCurrenciesResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def Convert(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CurrencyService/Convert',
|
||||
demo__pb2.CurrencyConversionRequest.SerializeToString,
|
||||
demo__pb2.Money.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class PaymentServiceStub(object):
|
||||
"""-------------Payment service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.Charge = channel.unary_unary(
|
||||
'/hipstershop.PaymentService/Charge',
|
||||
request_serializer=demo__pb2.ChargeRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.ChargeResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class PaymentServiceServicer(object):
|
||||
"""-------------Payment service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def Charge(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_PaymentServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'Charge': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.Charge,
|
||||
request_deserializer=demo__pb2.ChargeRequest.FromString,
|
||||
response_serializer=demo__pb2.ChargeResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.PaymentService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class PaymentService(object):
|
||||
"""-------------Payment service-----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def Charge(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.PaymentService/Charge',
|
||||
demo__pb2.ChargeRequest.SerializeToString,
|
||||
demo__pb2.ChargeResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class EmailServiceStub(object):
|
||||
"""-------------Email service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.SendOrderConfirmation = channel.unary_unary(
|
||||
'/hipstershop.EmailService/SendOrderConfirmation',
|
||||
request_serializer=demo__pb2.SendOrderConfirmationRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.Empty.FromString,
|
||||
)
|
||||
|
||||
|
||||
class EmailServiceServicer(object):
|
||||
"""-------------Email service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def SendOrderConfirmation(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_EmailServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'SendOrderConfirmation': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SendOrderConfirmation,
|
||||
request_deserializer=demo__pb2.SendOrderConfirmationRequest.FromString,
|
||||
response_serializer=demo__pb2.Empty.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.EmailService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class EmailService(object):
|
||||
"""-------------Email service-----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def SendOrderConfirmation(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.EmailService/SendOrderConfirmation',
|
||||
demo__pb2.SendOrderConfirmationRequest.SerializeToString,
|
||||
demo__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class CheckoutServiceStub(object):
|
||||
"""-------------Checkout service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.PlaceOrder = channel.unary_unary(
|
||||
'/hipstershop.CheckoutService/PlaceOrder',
|
||||
request_serializer=demo__pb2.PlaceOrderRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.PlaceOrderResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class CheckoutServiceServicer(object):
|
||||
"""-------------Checkout service-----------------
|
||||
|
||||
"""
|
||||
|
||||
def PlaceOrder(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_CheckoutServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'PlaceOrder': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.PlaceOrder,
|
||||
request_deserializer=demo__pb2.PlaceOrderRequest.FromString,
|
||||
response_serializer=demo__pb2.PlaceOrderResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.CheckoutService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class CheckoutService(object):
|
||||
"""-------------Checkout service-----------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def PlaceOrder(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.CheckoutService/PlaceOrder',
|
||||
demo__pb2.PlaceOrderRequest.SerializeToString,
|
||||
demo__pb2.PlaceOrderResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
|
||||
class AdServiceStub(object):
|
||||
"""------------Ad service------------------
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.GetAds = channel.unary_unary(
|
||||
'/hipstershop.AdService/GetAds',
|
||||
request_serializer=demo__pb2.AdRequest.SerializeToString,
|
||||
response_deserializer=demo__pb2.AdResponse.FromString,
|
||||
)
|
||||
|
||||
|
||||
class AdServiceServicer(object):
|
||||
"""------------Ad service------------------
|
||||
|
||||
"""
|
||||
|
||||
def GetAds(self, request, context):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_AdServiceServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'GetAds': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetAds,
|
||||
request_deserializer=demo__pb2.AdRequest.FromString,
|
||||
response_serializer=demo__pb2.AdResponse.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'hipstershop.AdService', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class AdService(object):
|
||||
"""------------Ad service------------------
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def GetAds(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/hipstershop.AdService/GetAds',
|
||||
demo__pb2.AdRequest.SerializeToString,
|
||||
demo__pb2.AdResponse.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
39
src/emailservice/email_client.py
Executable file
39
src/emailservice/email_client.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
import grpc
|
||||
|
||||
import demo_pb2
|
||||
import demo_pb2_grpc
|
||||
|
||||
from logger import getJSONLogger
|
||||
logger = getJSONLogger('emailservice-client')
|
||||
|
||||
def send_confirmation_email(email, order):
|
||||
channel = grpc.insecure_channel('[::]:8080')
|
||||
stub = demo_pb2_grpc.EmailServiceStub(channel)
|
||||
try:
|
||||
response = stub.SendOrderConfirmation(demo_pb2.SendOrderConfirmationRequest(
|
||||
email = email,
|
||||
order = order
|
||||
))
|
||||
logger.info('Request sent.')
|
||||
except grpc.RpcError as err:
|
||||
logger.error(err.details())
|
||||
logger.error('{}, {}'.format(err.code().name, err.code().value))
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.info('Client for email service.')
|
||||
200
src/emailservice/email_server.py
Executable file
200
src/emailservice/email_server.py
Executable file
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
from concurrent import futures
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import grpc
|
||||
import traceback
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape, TemplateError
|
||||
from google.api_core.exceptions import GoogleAPICallError
|
||||
from google.auth.exceptions import DefaultCredentialsError
|
||||
|
||||
import demo_pb2
|
||||
import demo_pb2_grpc
|
||||
from grpc_health.v1 import health_pb2
|
||||
from grpc_health.v1 import health_pb2_grpc
|
||||
|
||||
from opentelemetry import trace
|
||||
from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
|
||||
from opentelemetry.sdk.trace import TracerProvider
|
||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
||||
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
||||
|
||||
# @TODO: Temporarily removed in https://github.com/GoogleCloudPlatform/microservices-demo/pull/3196
|
||||
# import googlecloudprofiler
|
||||
|
||||
from logger import getJSONLogger
|
||||
logger = getJSONLogger('emailservice-server')
|
||||
|
||||
# Loads confirmation email template from file
|
||||
env = Environment(
|
||||
loader=FileSystemLoader('templates'),
|
||||
autoescape=select_autoescape(['html', 'xml'])
|
||||
)
|
||||
template = env.get_template('confirmation.html')
|
||||
|
||||
class BaseEmailService(demo_pb2_grpc.EmailServiceServicer):
|
||||
def Check(self, request, context):
|
||||
return health_pb2.HealthCheckResponse(
|
||||
status=health_pb2.HealthCheckResponse.SERVING)
|
||||
|
||||
def Watch(self, request, context):
|
||||
return health_pb2.HealthCheckResponse(
|
||||
status=health_pb2.HealthCheckResponse.UNIMPLEMENTED)
|
||||
|
||||
class EmailService(BaseEmailService):
|
||||
def __init__(self):
|
||||
raise Exception('cloud mail client not implemented')
|
||||
super().__init__()
|
||||
|
||||
@staticmethod
|
||||
def send_email(client, email_address, content):
|
||||
response = client.send_message(
|
||||
sender = client.sender_path(project_id, region, sender_id),
|
||||
envelope_from_authority = '',
|
||||
header_from_authority = '',
|
||||
envelope_from_address = from_address,
|
||||
simple_message = {
|
||||
"from": {
|
||||
"address_spec": from_address,
|
||||
},
|
||||
"to": [{
|
||||
"address_spec": email_address
|
||||
}],
|
||||
"subject": "Your Confirmation Email",
|
||||
"html_body": content
|
||||
}
|
||||
)
|
||||
logger.info("Message sent: {}".format(response.rfc822_message_id))
|
||||
|
||||
def SendOrderConfirmation(self, request, context):
|
||||
email = request.email
|
||||
order = request.order
|
||||
|
||||
try:
|
||||
confirmation = template.render(order = order)
|
||||
except TemplateError as err:
|
||||
context.set_details("An error occurred when preparing the confirmation mail.")
|
||||
logger.error(err.message)
|
||||
context.set_code(grpc.StatusCode.INTERNAL)
|
||||
return demo_pb2.Empty()
|
||||
|
||||
try:
|
||||
EmailService.send_email(self.client, email, confirmation)
|
||||
except GoogleAPICallError as err:
|
||||
context.set_details("An error occurred when sending the email.")
|
||||
print(err.message)
|
||||
context.set_code(grpc.StatusCode.INTERNAL)
|
||||
return demo_pb2.Empty()
|
||||
|
||||
return demo_pb2.Empty()
|
||||
|
||||
class DummyEmailService(BaseEmailService):
|
||||
def SendOrderConfirmation(self, request, context):
|
||||
logger.info('A request to send order confirmation email to {} has been received.'.format(request.email))
|
||||
return demo_pb2.Empty()
|
||||
|
||||
class HealthCheck():
|
||||
def Check(self, request, context):
|
||||
return health_pb2.HealthCheckResponse(
|
||||
status=health_pb2.HealthCheckResponse.SERVING)
|
||||
|
||||
def start(dummy_mode):
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10),)
|
||||
service = None
|
||||
if dummy_mode:
|
||||
service = DummyEmailService()
|
||||
else:
|
||||
raise Exception('non-dummy mode not implemented yet')
|
||||
|
||||
demo_pb2_grpc.add_EmailServiceServicer_to_server(service, server)
|
||||
health_pb2_grpc.add_HealthServicer_to_server(service, server)
|
||||
|
||||
port = os.environ.get('PORT', "8080")
|
||||
logger.info("listening on port: "+port)
|
||||
server.add_insecure_port('[::]:'+port)
|
||||
server.start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(3600)
|
||||
except KeyboardInterrupt:
|
||||
server.stop(0)
|
||||
|
||||
def initStackdriverProfiling():
|
||||
project_id = None
|
||||
try:
|
||||
project_id = os.environ["GCP_PROJECT_ID"]
|
||||
except KeyError:
|
||||
# Environment variable not set
|
||||
pass
|
||||
|
||||
# @TODO: Temporarily removed in https://github.com/GoogleCloudPlatform/microservices-demo/pull/3196
|
||||
# for retry in range(1,4):
|
||||
# try:
|
||||
# if project_id:
|
||||
# googlecloudprofiler.start(service='email_server', service_version='1.0.0', verbose=0, project_id=project_id)
|
||||
# else:
|
||||
# googlecloudprofiler.start(service='email_server', service_version='1.0.0', verbose=0)
|
||||
# logger.info("Successfully started Stackdriver Profiler.")
|
||||
# return
|
||||
# except (BaseException) as exc:
|
||||
# logger.info("Unable to start Stackdriver Profiler Python agent. " + str(exc))
|
||||
# if (retry < 4):
|
||||
# logger.info("Sleeping %d to retry initializing Stackdriver Profiler"%(retry*10))
|
||||
# time.sleep (1)
|
||||
# else:
|
||||
# logger.warning("Could not initialize Stackdriver Profiler after retrying, giving up")
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.info('starting the email service in dummy mode.')
|
||||
|
||||
# Profiler
|
||||
try:
|
||||
if "DISABLE_PROFILER" in os.environ:
|
||||
raise KeyError()
|
||||
else:
|
||||
logger.info("Profiler enabled.")
|
||||
initStackdriverProfiling()
|
||||
except KeyError:
|
||||
logger.info("Profiler disabled.")
|
||||
|
||||
# Tracing
|
||||
try:
|
||||
if os.environ["ENABLE_TRACING"] == "1":
|
||||
otel_endpoint = os.getenv("COLLECTOR_SERVICE_ADDR", "localhost:4317")
|
||||
trace.set_tracer_provider(TracerProvider())
|
||||
trace.get_tracer_provider().add_span_processor(
|
||||
BatchSpanProcessor(
|
||||
OTLPSpanExporter(
|
||||
endpoint = otel_endpoint,
|
||||
insecure = True
|
||||
)
|
||||
)
|
||||
)
|
||||
grpc_server_instrumentor = GrpcInstrumentorServer()
|
||||
grpc_server_instrumentor.instrument()
|
||||
|
||||
except (KeyError, DefaultCredentialsError):
|
||||
logger.info("Tracing disabled.")
|
||||
except Exception as e:
|
||||
logger.warn(f"Exception on Cloud Trace setup: {traceback.format_exc()}, tracing disabled.")
|
||||
|
||||
start(dummy_mode = True)
|
||||
21
src/emailservice/genproto.sh
Executable file
21
src/emailservice/genproto.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash -eu
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
# [START gke_emailservice_genproto]
|
||||
|
||||
python -m grpc_tools.protoc -I../../protos --python_out=. --grpc_python_out=. ../../protos/demo.proto
|
||||
|
||||
# [END gke_emailservice_genproto]
|
||||
41
src/emailservice/logger.py
Executable file
41
src/emailservice/logger.py
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2018 Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from pythonjsonlogger import jsonlogger
|
||||
|
||||
# TODO(yoshifumi) this class is duplicated since other Python services are
|
||||
# not sharing the modules for logging.
|
||||
class CustomJsonFormatter(jsonlogger.JsonFormatter):
|
||||
def add_fields(self, log_record, record, message_dict):
|
||||
super(CustomJsonFormatter, self).add_fields(log_record, record, message_dict)
|
||||
if not log_record.get('timestamp'):
|
||||
log_record['timestamp'] = record.created
|
||||
if log_record.get('severity'):
|
||||
log_record['severity'] = log_record['severity'].upper()
|
||||
else:
|
||||
log_record['severity'] = record.levelname
|
||||
|
||||
def getJSONLogger(name):
|
||||
logger = logging.getLogger(name)
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
formatter = CustomJsonFormatter('%(timestamp)s %(severity)s %(name)s %(message)s')
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.propagate = False
|
||||
return logger
|
||||
10
src/emailservice/requirements.in
Normal file
10
src/emailservice/requirements.in
Normal file
@@ -0,0 +1,10 @@
|
||||
google-api-core==2.28.1
|
||||
grpcio-health-checking==1.76.0
|
||||
grpcio==1.76.0
|
||||
jinja2==3.1.6
|
||||
python-json-logger==4.0.0
|
||||
google-cloud-trace==1.17.0
|
||||
requests==2.32.5
|
||||
opentelemetry-distro==0.60b1
|
||||
opentelemetry-instrumentation-grpc==0.60b1
|
||||
opentelemetry-exporter-otlp-proto-grpc==1.39.1
|
||||
120
src/emailservice/requirements.txt
Normal file
120
src/emailservice/requirements.txt
Normal file
@@ -0,0 +1,120 @@
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile requirements.in -o requirements.txt
|
||||
cachetools==5.3.2
|
||||
# via google-auth
|
||||
certifi==2024.7.4
|
||||
# via requests
|
||||
charset-normalizer==3.3.2
|
||||
# via requests
|
||||
google-api-core[grpc]==2.28.1
|
||||
# via
|
||||
# -r requirements.in
|
||||
# google-cloud-trace
|
||||
google-auth==2.23.4
|
||||
# via
|
||||
# google-api-core
|
||||
# google-cloud-trace
|
||||
google-cloud-trace==1.17.0
|
||||
# via -r requirements.in
|
||||
googleapis-common-protos==1.72.0
|
||||
# via
|
||||
# google-api-core
|
||||
# grpcio-status
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
grpcio==1.76.0
|
||||
# via
|
||||
# -r requirements.in
|
||||
# google-api-core
|
||||
# google-cloud-trace
|
||||
# grpcio-health-checking
|
||||
# grpcio-status
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
grpcio-health-checking==1.76.0
|
||||
# via -r requirements.in
|
||||
grpcio-status==1.76.0
|
||||
# via google-api-core
|
||||
idna==3.7
|
||||
# via requests
|
||||
importlib-metadata==6.8.0
|
||||
# via opentelemetry-api
|
||||
jinja2==3.1.6
|
||||
# via -r requirements.in
|
||||
markupsafe==2.1.3
|
||||
# via jinja2
|
||||
opentelemetry-api==1.39.1
|
||||
# via
|
||||
# opentelemetry-distro
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
# opentelemetry-instrumentation
|
||||
# opentelemetry-instrumentation-grpc
|
||||
# opentelemetry-sdk
|
||||
# opentelemetry-semantic-conventions
|
||||
opentelemetry-distro==0.60b1
|
||||
# via -r requirements.in
|
||||
opentelemetry-exporter-otlp-proto-common==1.39.1
|
||||
# via opentelemetry-exporter-otlp-proto-grpc
|
||||
opentelemetry-exporter-otlp-proto-grpc==1.39.1
|
||||
# via -r requirements.in
|
||||
opentelemetry-instrumentation==0.60b1
|
||||
# via
|
||||
# opentelemetry-distro
|
||||
# opentelemetry-instrumentation-grpc
|
||||
opentelemetry-instrumentation-grpc==0.60b1
|
||||
# via -r requirements.in
|
||||
opentelemetry-proto==1.39.1
|
||||
# via
|
||||
# opentelemetry-exporter-otlp-proto-common
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
opentelemetry-sdk==1.39.1
|
||||
# via
|
||||
# opentelemetry-distro
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
opentelemetry-semantic-conventions==0.60b1
|
||||
# via
|
||||
# opentelemetry-instrumentation
|
||||
# opentelemetry-instrumentation-grpc
|
||||
# opentelemetry-sdk
|
||||
packaging==25.0
|
||||
# via opentelemetry-instrumentation
|
||||
proto-plus==1.27.0
|
||||
# via
|
||||
# google-api-core
|
||||
# google-cloud-trace
|
||||
protobuf==6.33.2
|
||||
# via
|
||||
# google-api-core
|
||||
# google-cloud-trace
|
||||
# googleapis-common-protos
|
||||
# grpcio-health-checking
|
||||
# grpcio-status
|
||||
# opentelemetry-proto
|
||||
# proto-plus
|
||||
pyasn1==0.5.0
|
||||
# via
|
||||
# pyasn1-modules
|
||||
# rsa
|
||||
pyasn1-modules==0.3.0
|
||||
# via google-auth
|
||||
python-json-logger==4.0.0
|
||||
# via -r requirements.in
|
||||
requests==2.32.5
|
||||
# via
|
||||
# -r requirements.in
|
||||
# google-api-core
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
typing-extensions==4.15.0
|
||||
# via
|
||||
# grpcio
|
||||
# opentelemetry-api
|
||||
# opentelemetry-exporter-otlp-proto-grpc
|
||||
# opentelemetry-sdk
|
||||
# opentelemetry-semantic-conventions
|
||||
urllib3==2.6.3
|
||||
# via requests
|
||||
wrapt==1.16.0
|
||||
# via
|
||||
# opentelemetry-instrumentation
|
||||
# opentelemetry-instrumentation-grpc
|
||||
zipp==3.19.1
|
||||
# via importlib-metadata
|
||||
53
src/emailservice/templates/confirmation.html
Normal file
53
src/emailservice/templates/confirmation.html
Normal file
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright 2020 Google LLC
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Your Order Confirmation</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<style>
|
||||
body{
|
||||
font-family: 'DM Sans', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h2>Your Order Confirmation</h2>
|
||||
<p>Thanks for shopping with us!<p>
|
||||
<h3>Order ID</h3>
|
||||
<p>#{{ order.order_id }}</p>
|
||||
<h3>Shipping</h3>
|
||||
<p>#{{ order.shipping_tracking_id }}</p>
|
||||
<p>{{ order.shipping_cost.units }}. {{ "%02d" | format(order.shipping_cost.nanos // 10000000) }} {{ order.shipping_cost.currency_code }}</p>
|
||||
<p>{{ order.shipping_address.street_address_1 }}, {{order.shipping_address.street_address_2}}, {{order.shipping_address.city}}, {{order.shipping_address.country}} {{order.shipping_address.zip_code}}</p>
|
||||
<h3>Items</h3>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<th>Item No.</th>
|
||||
<th>Quantity</th>
|
||||
<th>Price</th>
|
||||
</tr>
|
||||
{% for item in order.items %}
|
||||
<tr>
|
||||
<td>#{{ item.item.product_id }}</td>
|
||||
<td>{{ item.item.quantity }}</td>
|
||||
<td>{{ item.cost.units }}.{{ "%02d" | format(item.cost.nanos // 10000000) }} {{ item.cost.currency_code }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user