merge upstream
This commit is contained in:
commit
be14c98846
108 changed files with 4703 additions and 4395 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,8 +5,7 @@ pkg/
|
||||||
*.swp
|
*.swp
|
||||||
*~
|
*~
|
||||||
.vscode/
|
.vscode/
|
||||||
.vs/slnx.sqlite
|
.vs/
|
||||||
.vs/microservices-demo/v15/.suo
|
|
||||||
.idea
|
.idea
|
||||||
.skaffold-*.yaml
|
.skaffold-*.yaml
|
||||||
.kubernetes-manifests-*/
|
.kubernetes-manifests-*/
|
||||||
|
|
|
@ -4,7 +4,7 @@ services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/v0.12.0/skaffold-linux-amd64
|
- curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/v0.20.0/skaffold-linux-amd64
|
||||||
- chmod +x skaffold
|
- chmod +x skaffold
|
||||||
- sudo mv skaffold /usr/local/bin
|
- sudo mv skaffold /usr/local/bin
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
We'd love to accept your patches and contributions to this project. There are
|
We'd love to accept your patches and contributions to this project. There are
|
||||||
just a few small guidelines you need to follow.
|
just a few small guidelines you need to follow.
|
||||||
|
|
||||||
|
## Development Principles (for Googlers)
|
||||||
|
|
||||||
|
There are a few principles for developing or refactoring the service
|
||||||
|
implementations. Read the [Development Principles
|
||||||
|
Guide](./docs/development-principles.md).
|
||||||
|
|
||||||
## Contributor License Agreement
|
## Contributor License Agreement
|
||||||
|
|
||||||
Contributions to this project must be accompanied by a Contributor License
|
Contributions to this project must be accompanied by a Contributor License
|
||||||
|
|
200
README.md
200
README.md
|
@ -4,14 +4,22 @@ This project contains a 10-tier microservices application. The application is a
|
||||||
web-based e-commerce app called **“Hipster Shop”** where users can browse items,
|
web-based e-commerce app called **“Hipster Shop”** where users can browse items,
|
||||||
add them to the cart, and purchase them.
|
add them to the cart, and purchase them.
|
||||||
|
|
||||||
**Google uses this application to demonstrate Kubernetes, GKE, Istio,
|
**Google uses this application to demonstrate use of technologies like
|
||||||
Stackdriver, gRPC** and similar cloud-native technologies nowadays.
|
Kubernetes/GKE, Istio, Stackdriver, gRPC and OpenCensus**. This application
|
||||||
|
works on any Kubernetes cluster (such as a local one), as well as Google
|
||||||
|
Kubernetes Engine. It’s **easy to deploy with little to no configuration**.
|
||||||
|
|
||||||
|
If you’re using this demo, please **★Star** this repository to show your interest!
|
||||||
|
|
||||||
|
> 👓**Note to Googlers:** Please fill out the form at
|
||||||
|
> [go/microservices-demo](http://go/microservices-demo) if you are using this
|
||||||
|
> application.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
| Home Page | Checkout Screen |
|
| Home Page | Checkout Screen |
|
||||||
|-----------|-----------------|
|
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
| [](./img/hipster-shop-frontend-1.png) | [](./img/hipster-shop-frontend-2.png) |
|
| [](./docs/img/hipster-shop-frontend-1.png) | [](./docs/img/hipster-shop-frontend-2.png) |
|
||||||
|
|
||||||
## Service Architecture
|
## Service Architecture
|
||||||
|
|
||||||
|
@ -19,25 +27,24 @@ Stackdriver, gRPC** and similar cloud-native technologies nowadays.
|
||||||
languages that talk to each other over gRPC.
|
languages that talk to each other over gRPC.
|
||||||
|
|
||||||
[](./img/architecture-diagram.png)
|
microservices](./docs/img/architecture-diagram.png)](./docs/img/architecture-diagram.png)
|
||||||
|
|
||||||
Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
|
Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
|
||||||
|
|
||||||
| Service | Language | Description |
|
| Service | Language | Description |
|
||||||
|---------|----------|-------------|
|
| ---------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| [frontend](./src/frontend) | Go | Exposes an HTTP server to serve the website. Does not require signup/login and generates session IDs for all users automatically. |
|
| [frontend](./src/frontend) | Go | Exposes an HTTP server to serve the website. Does not require signup/login and generates session IDs for all users automatically. |
|
||||||
| [cartservice](./src/cartservice) | C# | Stores the items in the user's shipping cart in Redis and retrieves it. |
|
| [cartservice](./src/cartservice) | C# | Stores the items in the user's shipping cart in Redis and retrieves it. |
|
||||||
| [productcatalogservice](./src/productcatalogservice) | Go | Provides the list of products from a JSON file and ability to search products and get individual products. |
|
| [productcatalogservice](./src/productcatalogservice) | Go | Provides the list of products from a JSON file and ability to search products and get individual products. |
|
||||||
| [currencyservice](./src/currencyservice) | Node.js | Converts one money amount to another currency. Uses real values fetched from European Central Bank. It's the highest QPS service. |
|
| [currencyservice](./src/currencyservice) | Node.js | Converts one money amount to another currency. Uses real values fetched from European Central Bank. It's the highest QPS service. |
|
||||||
| [paymentservice](./src/paymentservice) | Node.js | Charges the given credit card info (hypothetically😇) with the given amount and returns a transaction ID. |
|
| [paymentservice](./src/paymentservice) | Node.js | Charges the given credit card info (mock) with the given amount and returns a transaction ID. |
|
||||||
| [shippingservice](./src/shippingservice) | Go | Gives shipping cost estimates based on the shopping cart. Ships items to the given address (hypothetically😇) |
|
| [shippingservice](./src/shippingservice) | Go | Gives shipping cost estimates based on the shopping cart. Ships items to the given address (mock) |
|
||||||
| [emailservice](./src/emailservice) | Python | Sends users an order confirmation email (hypothetically😇). |
|
| [emailservice](./src/emailservice) | Python | Sends users an order confirmation email (mock). |
|
||||||
| [checkoutservice](./src/checkoutservice) | Go | Retrieves user cart, prepares order and orchestrates the payment, shipping and the email notification. |
|
| [checkoutservice](./src/checkoutservice) | Go | Retrieves user cart, prepares order and orchestrates the payment, shipping and the email notification. |
|
||||||
| [recommendationservice](./src/recommendationservice) | Python | Recommends other products based on what's given in the cart. |
|
| [recommendationservice](./src/recommendationservice) | Python | Recommends other products based on what's given in the cart. |
|
||||||
| [adservice](./src/adservice) | Java | Provides text ads based on given context words. |
|
| [adservice](./src/adservice) | Java | Provides text ads based on given context words. |
|
||||||
| [loadgenerator](./src/loadgenerator) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
|
| [loadgenerator](./src/loadgenerator) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **[Kubernetes](https://kubernetes.io)/[GKE](https://cloud.google.com/kubernetes-engine/):**
|
- **[Kubernetes](https://kubernetes.io)/[GKE](https://cloud.google.com/kubernetes-engine/):**
|
||||||
|
@ -53,7 +60,7 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
|
||||||
addition to these, using Istio enables features like Request/Response
|
addition to these, using Istio enables features like Request/Response
|
||||||
**Metrics** and **Context Graph** out of the box. When it is running out of
|
**Metrics** and **Context Graph** out of the box. When it is running out of
|
||||||
Google Cloud, this code path remains inactive.
|
Google Cloud, this code path remains inactive.
|
||||||
- **[Skaffold](https://github.com/GoogleContainerTools/skaffold):** Application
|
- **[Skaffold](https://skaffold.dev):** Application
|
||||||
is deployed to Kubernetes with a single command using Skaffold.
|
is deployed to Kubernetes with a single command using Skaffold.
|
||||||
- **Synthetic Load Generation:** The application demo comes with a background
|
- **Synthetic Load Generation:** The application demo comes with a background
|
||||||
job that creates realistic usage patterns on the website using
|
job that creates realistic usage patterns on the website using
|
||||||
|
@ -61,27 +68,45 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
> **Note:** that the first build can take up to 20-30 minutes. Consequent builds
|
We offer three installation methods:
|
||||||
> will be faster.
|
|
||||||
|
1. **Running locally with “Docker for Desktop”** (~20 minutes) You will build
|
||||||
|
and deploy microservices images to a single-node Kubernetes cluster running
|
||||||
|
on your development machine.
|
||||||
|
|
||||||
|
2. **Running on Google Kubernetes Engine (GKE)”** (~30 minutes) You will build,
|
||||||
|
upload and deploy the container images to a Kubernetes cluster on Google
|
||||||
|
Cloud.
|
||||||
|
|
||||||
|
3. **Using pre-built container images:** (~10 minutes, you will still need to
|
||||||
|
follow one of the steps above up until `skaffold run` command). With this
|
||||||
|
option, you will use pre-built container images that are available publicly,
|
||||||
|
instead of building them yourself, which takes a long time).
|
||||||
|
|
||||||
### Option 1: Running locally with “Docker for Desktop”
|
### Option 1: Running locally with “Docker for Desktop”
|
||||||
|
|
||||||
> 💡 Recommended if you're planning to develop the application.
|
> 💡 Recommended if you're planning to develop the application or giving it a
|
||||||
|
> try on your local cluster.
|
||||||
|
|
||||||
1. Install tools to run a Kubernetes cluster locally:
|
1. Install tools to run a Kubernetes cluster locally:
|
||||||
|
|
||||||
- kubectl (can be installed via `gcloud components install kubectl`)
|
- kubectl (can be installed via `gcloud components install kubectl`)
|
||||||
- Docker for Desktop (Mac/Windows): It provides Kubernetes support as [noted
|
- Docker for Desktop (Mac/Windows): It provides Kubernetes support as [noted
|
||||||
here](https://docs.docker.com/docker-for-mac/kubernetes/).
|
here](https://docs.docker.com/docker-for-mac/kubernetes/).
|
||||||
- [skaffold](https://github.com/GoogleContainerTools/skaffold/#installation)
|
- [skaffold](https://skaffold.dev/docs/getting-started/#installing-skaffold)
|
||||||
|
(ensure version ≥v0.20)
|
||||||
|
|
||||||
1. Launch “Docker for Desktop”. Go to Preferences and choose “Enable Kubernetes”.
|
1. Launch “Docker for Desktop”. Go to Preferences:
|
||||||
|
|
||||||
|
- choose “Enable Kubernetes”,
|
||||||
|
- set CPUs to at least 3, and Memory to at least 6.0 GiB
|
||||||
|
- on the "Disk" tab, set at least 32 GB disk space
|
||||||
|
|
||||||
1. Run `kubectl get nodes` to verify you're connected to “Kubernetes on Docker”.
|
1. Run `kubectl get nodes` to verify you're connected to “Kubernetes on Docker”.
|
||||||
|
|
||||||
1. Run `skaffold run` (first time will be slow, it can take ~20-30 minutes).
|
1. Run `skaffold run` (first time will be slow, it can take ~20 minutes).
|
||||||
This will build and deploy the application. If you need to rebuild the images
|
This will build and deploy the application. If you need to rebuild the images
|
||||||
automatically as you refactor he code, run `skaffold dev` command.
|
automatically as you refactor the code, run `skaffold dev` command.
|
||||||
|
|
||||||
1. Run `kubectl get pods` to verify the Pods are ready and running. The
|
1. Run `kubectl get pods` to verify the Pods are ready and running. The
|
||||||
application frontend should be available at http://localhost:80 on your
|
application frontend should be available at http://localhost:80 on your
|
||||||
|
@ -89,86 +114,165 @@ Find **Protocol Buffers Descriptions** at the [`./pb` directory](./pb).
|
||||||
|
|
||||||
### Option 2: Running on Google Kubernetes Engine (GKE)
|
### Option 2: Running on Google Kubernetes Engine (GKE)
|
||||||
|
|
||||||
> 💡 Recommended for demos and making it available publicly.
|
> 💡 Recommended if you're using Google Cloud Platform and want to try it on
|
||||||
|
> a realistic cluster.
|
||||||
|
|
||||||
1. Install tools specified in the previous section (Docker, kubectl, skaffold)
|
1. Install tools specified in the previous section (Docker, kubectl, skaffold)
|
||||||
|
|
||||||
1. Create a Google Kubernetes Engine cluster and make sure `kubectl` is pointing
|
1. Create a Google Kubernetes Engine cluster and make sure `kubectl` is pointing
|
||||||
to the cluster.
|
to the cluster.
|
||||||
|
|
||||||
|
```sh
|
||||||
gcloud services enable container.googleapis.com
|
gcloud services enable container.googleapis.com
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
gcloud container clusters create demo --enable-autoupgrade \
|
gcloud container clusters create demo --enable-autoupgrade \
|
||||||
--enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5
|
--enable-autoscaling --min-nodes=3 --max-nodes=10 --num-nodes=5 --zone=us-central1-a
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
kubectl get nodes
|
kubectl get nodes
|
||||||
|
```
|
||||||
|
|
||||||
2. Enable Google Container Registry (GCR) on your GCP project and configure the
|
1. Enable Google Container Registry (GCR) on your GCP project and configure the
|
||||||
`docker` CLI to authenticate to GCR:
|
`docker` CLI to authenticate to GCR:
|
||||||
|
|
||||||
|
```sh
|
||||||
gcloud services enable containerregistry.googleapis.com
|
gcloud services enable containerregistry.googleapis.com
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
gcloud auth configure-docker -q
|
gcloud auth configure-docker -q
|
||||||
|
```
|
||||||
|
|
||||||
3. Set your project ID on image names:
|
1. In the root of this repository, run `skaffold run --default-repo=gcr.io/[PROJECT_ID]`,
|
||||||
|
where [PROJECT_ID] is your GCP project ID.
|
||||||
|
|
||||||
- Edit `skaffold.yaml`, update the `imageName:` fields that look like
|
This command:
|
||||||
`gcr.io/[PROJECT_ID]` with your own GCP project ID.
|
|
||||||
|
|
||||||
- Similarly, edit all Kubernetes Deployment manifests in the
|
|
||||||
[`./kubernetes-manifests`](./kubernetes-manifests) directory. Find the
|
|
||||||
`image:` fields with `gcr.io/[...]` and change them to your own GCP project
|
|
||||||
ID.
|
|
||||||
|
|
||||||
5. Run `skaffold run` from the root of this repository. This command:
|
|
||||||
- builds the container images
|
- builds the container images
|
||||||
- pushes them to GCR
|
- pushes them to GCR
|
||||||
- applies the `./kubernetes-manifests` deploying the application to
|
- applies the `./kubernetes-manifests` deploying the application to
|
||||||
Kubernetes.
|
Kubernetes.
|
||||||
|
|
||||||
6. Find the IP address of your application, then visit the application on your
|
**Troubleshooting:** If you get "No space left on device" error on Google
|
||||||
|
Cloud Shell, you can build the images on Google Cloud Build: [Enable the
|
||||||
|
Cloud Build
|
||||||
|
API](https://console.cloud.google.com/flows/enableapi?apiid=cloudbuild.googleapis.com),
|
||||||
|
then run `skaffold run -p gcb --default-repo=gcr.io/[PROJECT_ID]` instead.
|
||||||
|
|
||||||
|
1. Find the IP address of your application, then visit the application on your
|
||||||
browser to confirm installation.
|
browser to confirm installation.
|
||||||
|
|
||||||
kubectl get service frontend-external
|
kubectl get service frontend-external
|
||||||
|
|
||||||
### (Optional) Deploying on a Istio-installed cluster
|
**Troubleshooting:** A Kubernetes bug (will be fixed in 1.12) combined with
|
||||||
|
a Skaffold [bug](https://github.com/GoogleContainerTools/skaffold/issues/887)
|
||||||
|
causes load balancer to not to work even after getting an IP address. If you
|
||||||
|
are seeing this, run `kubectl get service frontend-external -o=yaml | kubectl apply -f-`
|
||||||
|
to trigger load balancer reconfiguration.
|
||||||
|
|
||||||
|
### Option 3: Using Pre-Built Container Images
|
||||||
|
|
||||||
|
> 💡 Recommended if you want to deploy the app faster in fewer steps to an
|
||||||
|
> existing cluster.
|
||||||
|
|
||||||
|
**NOTE:** If you need to create a Kubernetes cluster locally or on the cloud,
|
||||||
|
follow "Option 1" or "Option 2" until you reach the `skaffold run` step.
|
||||||
|
|
||||||
|
This option offers you pre-built public container images that are easy to deploy
|
||||||
|
by deploying the [release manifest](./release) directly to an existing cluster.
|
||||||
|
|
||||||
|
**Prerequisite**: a running Kubernetes cluster (either local or on cloud).
|
||||||
|
|
||||||
|
1. Clone this repository, and go to the repository directory
|
||||||
|
1. Run `kubectl apply -f ./release/kubernetes-manifests.yaml` to deploy the app.
|
||||||
|
1. Run `kubectl get pods` to see pods are in a Ready state.
|
||||||
|
1. Find the IP address of your application, then visit the application on your
|
||||||
|
browser to confirm installation.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
kubectl get service/frontend-external
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional) Deploying on a Istio-installed GKE cluster
|
||||||
|
|
||||||
> **Note:** you followed GKE deployment steps above, run `skaffold delete` first
|
> **Note:** you followed GKE deployment steps above, run `skaffold delete` first
|
||||||
> to delete what's deployed.
|
> to delete what's deployed.
|
||||||
|
|
||||||
1. Create a GKE cluster.
|
1. Create a GKE cluster (described in "Option 2").
|
||||||
|
|
||||||
2. Install Istio **without mutual TLS** option. (Istio mTLS is not yet supported
|
1. Use [Istio on GKE add-on](https://cloud.google.com/istio/docs/istio-on-gke/installing)
|
||||||
on this demo.)
|
to install Istio to your existing GKE cluster.
|
||||||
|
|
||||||
3. Install the automatic sidecar injection (annotate the `default` namespace
|
```sh
|
||||||
|
gcloud beta container clusters update demo \
|
||||||
|
--zone=us-central1-a \
|
||||||
|
--update-addons=Istio=ENABLED \
|
||||||
|
--istio-config=auth=MTLS_PERMISSIVE
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE: If you need to enable `MTLS_STRICT` mode, you will need to update
|
||||||
|
> several manifest files:
|
||||||
|
>
|
||||||
|
> - `kubernetes-manifests/frontend.yaml`: delete "livenessProbe" and
|
||||||
|
> "readinessProbe" fields.
|
||||||
|
> - `kubernetes-manifests/loadgenerator.yaml`: delete "initContainers" field.
|
||||||
|
|
||||||
|
1. (Optional) Enable Stackdriver Tracing/Logging with Istio Stackdriver Adapter
|
||||||
|
by [following this guide](https://cloud.google.com/istio/docs/istio-on-gke/installing#enabling_tracing_and_logging).
|
||||||
|
|
||||||
|
1. Install the automatic sidecar injection (annotate the `default` namespace
|
||||||
with the label):
|
with the label):
|
||||||
|
|
||||||
|
```sh
|
||||||
kubectl label namespace default istio-injection=enabled
|
kubectl label namespace default istio-injection=enabled
|
||||||
|
```
|
||||||
|
|
||||||
4. Apply the manifests in [`./istio-manifests`](./istio-manifests) directory.
|
1. Apply the manifests in [`./istio-manifests`](./istio-manifests) directory.
|
||||||
|
(This is required only once.)
|
||||||
|
|
||||||
|
```sh
|
||||||
kubectl apply -f ./istio-manifests
|
kubectl apply -f ./istio-manifests
|
||||||
|
```
|
||||||
|
|
||||||
This is required only once.
|
1. Deploy the application with `skaffold run --default-repo=gcr.io/[PROJECT_ID]`.
|
||||||
|
|
||||||
5. Deploy the application with `skaffold run`.
|
1. Run `kubectl get pods` to see pods are in a healthy and ready state.
|
||||||
|
|
||||||
6. Run `kubectl get pods` to see pods are in a healthy and ready state.
|
1. Find the IP address of your Istio gateway Ingress or Service, and visit the
|
||||||
|
|
||||||
7. Find the IP address of your istio gateway Ingress or Service, and visit the
|
|
||||||
application.
|
application.
|
||||||
|
|
||||||
INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
|
```sh
|
||||||
|
INGRESS_HOST="$(kubectl -n istio-system get service istio-ingressgateway \
|
||||||
|
-o jsonpath='{.status.loadBalancer.ingress[0].ip}')"
|
||||||
echo "$INGRESS_HOST"
|
echo "$INGRESS_HOST"
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
curl -v "http://$INGRESS_HOST"
|
curl -v "http://$INGRESS_HOST"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cleanup
|
||||||
|
|
||||||
|
If you've deployed the application with `skaffold run` command, you can run
|
||||||
|
`skaffold delete` to clean up the deployed resources.
|
||||||
|
|
||||||
|
If you've deployed the application with `kubectl apply -f [...]`, you can
|
||||||
|
run `kubectl delete -f [...]` with the same argument to clean up the deployed
|
||||||
|
resources.
|
||||||
|
|
||||||
|
## Conferences featuring Hipster Shop
|
||||||
|
|
||||||
|
- [Google Cloud Next'18 London – Keynote](https://youtu.be/nIq2pkNcfEI?t=3071)
|
||||||
|
showing Stackdriver Incident Response Management
|
||||||
|
- Google Cloud Next'18 SF
|
||||||
|
- [Day 1 Keynote](https://youtu.be/vJ9OaAqfxo4?t=2416) showing GKE On-Prem
|
||||||
|
- [Day 3 – Keynote](https://youtu.be/JQPOPV_VH5w?t=815) showing Stackdriver
|
||||||
|
APM (Tracing, Code Search, Profiler, Google Cloud Build)
|
||||||
|
- [Introduction to Service Management with Istio](https://www.youtube.com/watch?v=wCJrdKdD6UM&feature=youtu.be&t=586)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Note to fellow Googlers:** Please fill out the form at
|
|
||||||
[go/microservices-demo](http://go/microservices-demo) if you are using this
|
|
||||||
application.
|
|
||||||
|
|
||||||
This is not an official Google project.
|
This is not an official Google project.
|
||||||
|
|
25
cloudbuild.yaml
Normal file
25
cloudbuild.yaml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# This configuration file is used to build and deploy the app into a
|
||||||
|
# GKE cluster using Google Cloud Build.
|
||||||
|
#
|
||||||
|
# PREREQUISITES:
|
||||||
|
# - Cloud Build service account must have role: "Kubernetes Engine Developer"
|
||||||
|
|
||||||
|
# USAGE:
|
||||||
|
# GCP zone and GKE target cluster must be specified as substitutions
|
||||||
|
# Example invocation:
|
||||||
|
# `gcloud builds submit --config=cloudbuild.yaml --substitutions=_ZONE=us-central1-b,_CLUSTER=demo-app-staging .`
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- id: 'Deploy application to cluster'
|
||||||
|
name: 'gcr.io/k8s-skaffold/skaffold:v0.20.0'
|
||||||
|
entrypoint: 'bash'
|
||||||
|
args:
|
||||||
|
- '-c'
|
||||||
|
- >
|
||||||
|
gcloud container clusters get-credentials --zone=$_ZONE $_CLUSTER;
|
||||||
|
skaffold run -f=skaffold.yaml --default-repo=gcr.io/$PROJECT_ID;
|
||||||
|
|
||||||
|
# Add more power, and more time, for heavy Skaffold build
|
||||||
|
timeout: '3600s'
|
||||||
|
options:
|
||||||
|
machineType: 'N1_HIGHCPU_8'
|
44
docs/development-principles.md
Normal file
44
docs/development-principles.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Development Principles
|
||||||
|
|
||||||
|
> **Note:** This document outlines guidances behind some development decisions
|
||||||
|
> behind the Hipster Shop demo application.
|
||||||
|
|
||||||
|
### Minimal configuration
|
||||||
|
|
||||||
|
Running the demo locally or on GCP should require minimal to no
|
||||||
|
configuration unless absolutely necessary to run critical parts of the demo.
|
||||||
|
|
||||||
|
Configuration that takes multiple steps, especially such as creating service
|
||||||
|
accounts should be avoided.
|
||||||
|
|
||||||
|
### App must work well outside GCP
|
||||||
|
|
||||||
|
Demo application should work reasonably well when it is not deployed to GCP
|
||||||
|
services. The experience of running the application locally or on GCP should
|
||||||
|
be close.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
- OpenCensus prints the traces to stdout when it cannot connect to GCP.
|
||||||
|
- Stackdriver Debugging tries connecting to GCP multiple times, eventually gives
|
||||||
|
up.
|
||||||
|
|
||||||
|
### Running on GCP must not reduce functionality
|
||||||
|
|
||||||
|
Running the demo on the GCP must not reduce/lose any of the capabilities
|
||||||
|
developers have when running locally.
|
||||||
|
|
||||||
|
For example: Logs should still be printed to stdout/stderr even though logs are
|
||||||
|
uploaded to Stackdriver Logging when on GCP, so that developers can use "kubectl
|
||||||
|
logs" to diagnose each container.
|
||||||
|
|
||||||
|
### Microservice implementations should not be complex
|
||||||
|
|
||||||
|
Each service should provide a minimal implementation and try to avoid
|
||||||
|
unnecessary code and logic that's not executed.
|
||||||
|
|
||||||
|
Keep in mind that any service implementation is a decent example of “a GRPC
|
||||||
|
application that runs on Kubernetes”. Keeping the source code short and
|
||||||
|
navigable will serve this purpose.
|
||||||
|
|
||||||
|
It is okay to have intentional inefficiencies in the code as they help
|
||||||
|
illustrate the capabilities of profiling and diagnostics offerings.
|
BIN
docs/img/architecture-diagram.png
Normal file
BIN
docs/img/architecture-diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 776 KiB |
Before Width: | Height: | Size: 358 KiB After Width: | Height: | Size: 358 KiB |
18
hack/README.md
Executable file
18
hack/README.md
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
## `hack/`
|
||||||
|
|
||||||
|
This directory provides scripts for building and pushing Docker images, and tagging new demo
|
||||||
|
releases.
|
||||||
|
|
||||||
|
### env variables
|
||||||
|
|
||||||
|
- `TAG` - git release tag / Docker tag.
|
||||||
|
- `REPO_PREFIX` - Docker repo prefix to push images. Format: `$user/$project`. Resulting images will be of the
|
||||||
|
format `$user/$project/$svcname:$tag` (where `svcname` = `adservice`, `cartservice`,
|
||||||
|
etc.)
|
||||||
|
|
||||||
|
### scripts
|
||||||
|
|
||||||
|
1. `./make-docker-images.sh`: builds and pushes images to the specified Docker repository.
|
||||||
|
2. `./make-release-artifacts.sh`: generates a combined YAML file with image $TAG at:
|
||||||
|
`./release/kubernetes-manifests/demo.yaml`.
|
||||||
|
3. `./make-release.sh`: runs scripts 1 and 2, then runs `git tag` / pushes updated manifests to master.
|
9
src/cartservice/probe/genproto.sh → hack/license_header.txt
Executable file → Normal file
9
src/cartservice/probe/genproto.sh → hack/license_header.txt
Executable file → Normal file
|
@ -1,5 +1,3 @@
|
||||||
#!/bin/bash -eu
|
|
||||||
#
|
|
||||||
# Copyright 2018 Google LLC
|
# Copyright 2018 Google LLC
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -13,10 +11,3 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
#!/bin/bash -e
|
|
||||||
|
|
||||||
PATH=$PATH:$GOPATH/bin
|
|
||||||
protodir=../../../pb
|
|
||||||
|
|
||||||
protoc --go_out=plugins=grpc:genproto -I $protodir $protodir/demo.proto
|
|
41
hack/make-docker-images.sh
Executable file
41
hack/make-docker-images.sh
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2019 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.
|
||||||
|
|
||||||
|
# Builds and pushes docker image for each demo microservice.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
log() { echo "$1" >&2; }
|
||||||
|
|
||||||
|
TAG="${TAG:?TAG env variable must be specified}"
|
||||||
|
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified}"
|
||||||
|
|
||||||
|
while IFS= read -d $'\0' -r dir; do
|
||||||
|
# build image
|
||||||
|
svcname="$(basename "${dir}")"
|
||||||
|
image="${REPO_PREFIX}/$svcname:$TAG"
|
||||||
|
(
|
||||||
|
cd "${dir}"
|
||||||
|
log "Building: ${image}"
|
||||||
|
docker build -t "${image}" .
|
||||||
|
|
||||||
|
log "Pushing: ${image}"
|
||||||
|
docker push "${image}"
|
||||||
|
)
|
||||||
|
done < <(find "${SCRIPTDIR}/../src" -mindepth 1 -maxdepth 1 -type d -print0)
|
||||||
|
|
||||||
|
log "Successfully built and pushed all images."
|
101
hack/make-release-artifacts.sh
Executable file
101
hack/make-release-artifacts.sh
Executable file
|
@ -0,0 +1,101 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2019 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.
|
||||||
|
|
||||||
|
# This script compiles manifest files with the image tags and places them in
|
||||||
|
# /release/...
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
[[ -n "${DEBUG:-}" ]] && set -x
|
||||||
|
|
||||||
|
log() { echo "$1" >&2; }
|
||||||
|
|
||||||
|
TAG="${TAG:?TAG env variable must be specified}"
|
||||||
|
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified}"
|
||||||
|
OUT_DIR="${OUT_DIR:-${SCRIPTDIR}/../release}"
|
||||||
|
|
||||||
|
print_license_header() {
|
||||||
|
cat "${SCRIPTDIR}/license_header.txt"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
print_autogenerated_warning() {
|
||||||
|
cat<<EOF
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# WARNING: This file is autogenerated. Do not manually edit.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# define gsed as a function on Linux for compatibility
|
||||||
|
[ "$(uname -s)" == "Linux" ] && gsed() {
|
||||||
|
sed "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
read_manifests() {
|
||||||
|
local dir
|
||||||
|
dir="$1"
|
||||||
|
|
||||||
|
while IFS= read -d $'\0' -r file; do
|
||||||
|
# strip license headers (pattern "^# ")
|
||||||
|
awk '
|
||||||
|
/^[^# ]/ { found = 1 }
|
||||||
|
found { print }' "${file}"
|
||||||
|
|
||||||
|
echo "---"
|
||||||
|
done < <(find "${dir}" -name '*.yaml' -type f -print0)
|
||||||
|
}
|
||||||
|
|
||||||
|
mk_kubernetes_manifests() {
|
||||||
|
out_manifest="$(read_manifests "${SCRIPTDIR}/../kubernetes-manifests")"
|
||||||
|
|
||||||
|
# replace "image" repo, tag for each service
|
||||||
|
for dir in ./src/*/
|
||||||
|
do
|
||||||
|
svcname="$(basename "${dir}")"
|
||||||
|
image="$REPO_PREFIX/$svcname:$TAG"
|
||||||
|
|
||||||
|
pattern="^(\s*)image:\s.*$svcname(.*)(\s*)"
|
||||||
|
replace="\1image: $image\3"
|
||||||
|
out_manifest="$(gsed -r "s|$pattern|$replace|g" <(echo "${out_manifest}") )"
|
||||||
|
done
|
||||||
|
|
||||||
|
print_license_header
|
||||||
|
print_autogenerated_warning
|
||||||
|
echo "${out_manifest}"
|
||||||
|
}
|
||||||
|
|
||||||
|
mk_istio_manifests() {
|
||||||
|
print_license_header
|
||||||
|
print_autogenerated_warning
|
||||||
|
read_manifests "${SCRIPTDIR}/../istio-manifests"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
mkdir -p "${OUT_DIR}"
|
||||||
|
local k8s_manifests_file istio_manifests_file
|
||||||
|
|
||||||
|
k8s_manifests_file="${OUT_DIR}/kubernetes-manifests.yaml"
|
||||||
|
mk_kubernetes_manifests > "${k8s_manifests_file}"
|
||||||
|
log "Written ${k8s_manifests_file}"
|
||||||
|
|
||||||
|
istio_manifests_file="${OUT_DIR}/istio-manifests.yaml"
|
||||||
|
mk_istio_manifests > "${istio_manifests_file}"
|
||||||
|
log "Written ${istio_manifests_file}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
51
hack/make-release.sh
Executable file
51
hack/make-release.sh
Executable file
|
@ -0,0 +1,51 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Copyright 2019 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.
|
||||||
|
|
||||||
|
# This script creates a new release by:
|
||||||
|
# - 1. building/pushing images
|
||||||
|
# - 2. injecting tags into YAML manifests
|
||||||
|
# - 3. creating a new git tag
|
||||||
|
# - 4. pushing the tag/commit to master.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
[[ -n "${DEBUG:-}" ]] && set -x
|
||||||
|
|
||||||
|
log() { echo "$1" >&2; }
|
||||||
|
fail() { log "$1"; exit 1; }
|
||||||
|
|
||||||
|
TAG="${TAG:?TAG env variable must be specified}"
|
||||||
|
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified e.g. gcr.io\/google-samples\/microservices-demo}"
|
||||||
|
|
||||||
|
if [[ "$TAG" != v* ]]; then
|
||||||
|
fail "\$TAG must start with 'v', e.g. v0.1.0 (got: $TAG)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# build and push images
|
||||||
|
"${SCRIPTDIR}"/make-docker-images.sh
|
||||||
|
|
||||||
|
# update yaml
|
||||||
|
"${SCRIPTDIR}"/make-release-artifacts.sh
|
||||||
|
|
||||||
|
# create git release / push to master
|
||||||
|
git add "${SCRIPTDIR}/../release/"
|
||||||
|
git commit --allow-empty -m "Release $TAG"
|
||||||
|
log "Pushing k8s manifests to master..."
|
||||||
|
git tag "$TAG"
|
||||||
|
git push --tags
|
||||||
|
git push origin master
|
||||||
|
|
||||||
|
log "Successfully tagged release $TAG."
|
Binary file not shown.
Before Width: | Height: | Size: 78 KiB |
|
@ -1,28 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
||||||
apiVersion: networking.istio.io/v1alpha3
|
|
||||||
kind: ServiceEntry
|
|
||||||
metadata:
|
|
||||||
name: currency-provider-external
|
|
||||||
spec:
|
|
||||||
hosts:
|
|
||||||
- www.ecb.europa.eu
|
|
||||||
ports:
|
|
||||||
- number: 80
|
|
||||||
name: http
|
|
||||||
protocol: HTTP
|
|
||||||
- number: 443
|
|
||||||
name: https
|
|
||||||
protocol: HTTPS
|
|
|
@ -18,9 +18,6 @@ metadata:
|
||||||
name: whitelist-egress-googleapis
|
name: whitelist-egress-googleapis
|
||||||
spec:
|
spec:
|
||||||
hosts:
|
hosts:
|
||||||
- "169.254.169.254" # GCE metadata server
|
|
||||||
- "metadata.google" # GCE metadata server
|
|
||||||
- "metadata.google.internal" # GCE metadata server
|
|
||||||
- "accounts.google.com" # Used to get token
|
- "accounts.google.com" # Used to get token
|
||||||
- "*.googleapis.com"
|
- "*.googleapis.com"
|
||||||
ports:
|
ports:
|
||||||
|
@ -30,3 +27,20 @@ spec:
|
||||||
- number: 443
|
- number: 443
|
||||||
protocol: HTTPS
|
protocol: HTTPS
|
||||||
name: https
|
name: https
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: ServiceEntry
|
||||||
|
metadata:
|
||||||
|
name: whitelist-egress-google-metadata
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- metadata.google.internal
|
||||||
|
addresses:
|
||||||
|
- 169.254.169.254 # GCE metadata server
|
||||||
|
ports:
|
||||||
|
- number: 80
|
||||||
|
name: http
|
||||||
|
protocol: HTTP
|
||||||
|
- number: 443
|
||||||
|
name: https
|
||||||
|
protocol: HTTPS
|
||||||
|
|
8
kubernetes-manifests/README.md
Normal file
8
kubernetes-manifests/README.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# ./kubernetes-manifests
|
||||||
|
|
||||||
|
:warning: Kubernetes manifests provided in this directory are not directly
|
||||||
|
deployable to a cluster. They are meant to be used with `skaffold` command to
|
||||||
|
insert the correct `image:` tags.
|
||||||
|
|
||||||
|
Use the manifests in [/release](/release) directory which are configured with
|
||||||
|
pre-built public images.
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: adservice
|
name: adservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: adservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,12 +28,14 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/adservice
|
image: adservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 9555
|
- containerPort: 9555
|
||||||
env:
|
env:
|
||||||
- name: PORT
|
- name: PORT
|
||||||
value: "9555"
|
value: "9555"
|
||||||
|
#- name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 200m
|
cpu: 200m
|
||||||
|
@ -40,12 +45,12 @@ spec:
|
||||||
memory: 300Mi
|
memory: 300Mi
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
initialDelaySeconds: 20
|
initialDelaySeconds: 20
|
||||||
periodSeconds: 5
|
periodSeconds: 15
|
||||||
exec:
|
exec:
|
||||||
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
initialDelaySeconds: 20
|
initialDelaySeconds: 20
|
||||||
periodSeconds: 5
|
periodSeconds: 15
|
||||||
exec:
|
exec:
|
||||||
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
||||||
---
|
---
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: cartservice
|
name: cartservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cartservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/cartservice
|
image: cartservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 7070
|
- containerPort: 7070
|
||||||
env:
|
env:
|
||||||
|
@ -45,12 +48,12 @@ spec:
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
initialDelaySeconds: 15
|
initialDelaySeconds: 15
|
||||||
exec:
|
exec:
|
||||||
command: ["/cartservice_probe"]
|
command: ["/bin/grpc_health_probe", "-addr=:7070"]
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
initialDelaySeconds: 15
|
initialDelaySeconds: 15
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
exec:
|
exec:
|
||||||
command: ["/cartservice_probe"]
|
command: ["/bin/grpc_health_probe", "-addr=:7070"]
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: checkoutservice
|
name: checkoutservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: checkoutservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -24,7 +27,7 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/checkoutservice
|
image: checkoutservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 5050
|
- containerPort: 5050
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -46,6 +49,8 @@ spec:
|
||||||
value: "currencyservice:7000"
|
value: "currencyservice:7000"
|
||||||
- name: CART_SERVICE_ADDR
|
- name: CART_SERVICE_ADDR
|
||||||
value: "cartservice:7070"
|
value: "cartservice:7070"
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: currencyservice
|
name: currencyservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: currencyservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/currencyservice
|
image: currencyservice
|
||||||
ports:
|
ports:
|
||||||
- name: grpc
|
- name: grpc
|
||||||
containerPort: 7000
|
containerPort: 7000
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: emailservice
|
name: emailservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: emailservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/emailservice
|
image: emailservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -36,6 +39,9 @@ spec:
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
exec:
|
exec:
|
||||||
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
||||||
|
env:
|
||||||
|
- name: ENABLE_PROFILER
|
||||||
|
value: "0"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: frontend
|
name: frontend
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: frontend
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -24,7 +27,7 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/frontend
|
image: frontend
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -38,7 +41,7 @@ spec:
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/"
|
path: "/_healthz"
|
||||||
port: 8080
|
port: 8080
|
||||||
httpHeaders:
|
httpHeaders:
|
||||||
- name: "Cookie"
|
- name: "Cookie"
|
||||||
|
@ -58,6 +61,8 @@ spec:
|
||||||
value: "checkoutservice:5050"
|
value: "checkoutservice:5050"
|
||||||
- name: AD_SERVICE_ADDR
|
- name: AD_SERVICE_ADDR
|
||||||
value: "adservice:9555"
|
value: "adservice:9555"
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: loadgenerator
|
name: loadgenerator
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: loadgenerator
|
||||||
replicas: 1
|
replicas: 1
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -28,7 +31,7 @@ spec:
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: wait-frontend
|
- name: wait-frontend
|
||||||
image: alpine:3.6
|
image: alpine:3.6
|
||||||
command: ['sh', '-c', 'set -x; apk add --no-cache curl;
|
command: ['sh', '-c', 'set -x; apk add --no-cache curl &&
|
||||||
until timeout -t 2 curl -f "http://${FRONTEND_ADDR}"; do
|
until timeout -t 2 curl -f "http://${FRONTEND_ADDR}"; do
|
||||||
echo "waiting for http://${FRONTEND_ADDR}";
|
echo "waiting for http://${FRONTEND_ADDR}";
|
||||||
sleep 2;
|
sleep 2;
|
||||||
|
@ -38,7 +41,7 @@ spec:
|
||||||
value: "frontend:80"
|
value: "frontend:80"
|
||||||
containers:
|
containers:
|
||||||
- name: main
|
- name: main
|
||||||
image: gcr.io/microservices-demo-app/loadgenerator
|
image: loadgenerator
|
||||||
env:
|
env:
|
||||||
- name: FRONTEND_ADDR
|
- name: FRONTEND_ADDR
|
||||||
value: "frontend:80"
|
value: "frontend:80"
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: paymentservice
|
name: paymentservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: paymentservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/paymentservice
|
image: paymentservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 50051
|
- containerPort: 50051
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: productcatalogservice
|
name: productcatalogservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: productcatalogservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/productcatalogservice
|
image: productcatalogservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 3550
|
- containerPort: 3550
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -34,6 +37,9 @@ spec:
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
exec:
|
exec:
|
||||||
command: ["/bin/grpc_health_probe", "-addr=:3550"]
|
command: ["/bin/grpc_health_probe", "-addr=:3550"]
|
||||||
|
# env:
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: recommendationservice
|
name: recommendationservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: recommendationservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -25,7 +28,7 @@ spec:
|
||||||
terminationGracePeriodSeconds: 5
|
terminationGracePeriodSeconds: 5
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/recommendationservice
|
image: recommendationservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8080
|
- containerPort: 8080
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -39,6 +42,8 @@ spec:
|
||||||
env:
|
env:
|
||||||
- name: PRODUCT_CATALOG_SERVICE_ADDR
|
- name: PRODUCT_CATALOG_SERVICE_ADDR
|
||||||
value: "productcatalogservice:3550"
|
value: "productcatalogservice:3550"
|
||||||
|
- name: ENABLE_PROFILER
|
||||||
|
value: "0"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: redis-cart
|
name: redis-cart
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: redis-cart
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
|
|
@ -12,11 +12,14 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: shippingservice
|
name: shippingservice
|
||||||
spec:
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: shippingservice
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
|
@ -24,7 +27,7 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: server
|
- name: server
|
||||||
image: gcr.io/microservices-demo-app/shippingservice
|
image: shippingservice
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 50051
|
- containerPort: 50051
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
|
@ -34,6 +37,9 @@ spec:
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
exec:
|
exec:
|
||||||
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
||||||
|
# env:
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|
|
@ -64,6 +64,10 @@ message Product {
|
||||||
string description = 3;
|
string description = 3;
|
||||||
string picture = 4;
|
string picture = 4;
|
||||||
Money price_usd = 5;
|
Money price_usd = 5;
|
||||||
|
|
||||||
|
// Categories such as "vintage" or "gardening" that can be used to look up
|
||||||
|
// other related products.
|
||||||
|
repeated string categories = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductsResponse {
|
message ListProductsResponse {
|
||||||
|
|
111
release/istio-manifests.yaml
Normal file
111
release/istio-manifests.yaml
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# WARNING: This file is autogenerated. Do not manually edit.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: Gateway
|
||||||
|
metadata:
|
||||||
|
name: frontend-gateway
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
istio: ingressgateway # use Istio default gateway implementation
|
||||||
|
servers:
|
||||||
|
- port:
|
||||||
|
number: 80
|
||||||
|
name: http
|
||||||
|
protocol: HTTP
|
||||||
|
hosts:
|
||||||
|
- "*"
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: frontend-ingress
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- "*"
|
||||||
|
gateways:
|
||||||
|
- frontend-gateway
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: ServiceEntry
|
||||||
|
metadata:
|
||||||
|
name: currency-provider-external
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- www.ecb.europa.eu
|
||||||
|
ports:
|
||||||
|
- number: 80
|
||||||
|
name: http
|
||||||
|
protocol: HTTP
|
||||||
|
- number: 443
|
||||||
|
name: https
|
||||||
|
protocol: HTTPS
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: VirtualService
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- "frontend.default.svc.cluster.local"
|
||||||
|
http:
|
||||||
|
- route:
|
||||||
|
- destination:
|
||||||
|
host: frontend
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: ServiceEntry
|
||||||
|
metadata:
|
||||||
|
name: whitelist-egress-googleapis
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- "accounts.google.com" # Used to get token
|
||||||
|
- "*.googleapis.com"
|
||||||
|
ports:
|
||||||
|
- number: 80
|
||||||
|
protocol: HTTP
|
||||||
|
name: http
|
||||||
|
- number: 443
|
||||||
|
protocol: HTTPS
|
||||||
|
name: https
|
||||||
|
---
|
||||||
|
apiVersion: networking.istio.io/v1alpha3
|
||||||
|
kind: ServiceEntry
|
||||||
|
metadata:
|
||||||
|
name: whitelist-egress-google-metadata
|
||||||
|
spec:
|
||||||
|
hosts:
|
||||||
|
- metadata.google.internal
|
||||||
|
addresses:
|
||||||
|
- 169.254.169.254 # GCE metadata server
|
||||||
|
ports:
|
||||||
|
- number: 80
|
||||||
|
name: http
|
||||||
|
protocol: HTTP
|
||||||
|
- number: 443
|
||||||
|
name: https
|
||||||
|
protocol: HTTPS
|
||||||
|
---
|
660
release/kubernetes-manifests.yaml
Normal file
660
release/kubernetes-manifests.yaml
Normal file
|
@ -0,0 +1,660 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# WARNING: This file is autogenerated. Do not manually edit.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: emailservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: emailservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: emailservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/emailservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
readinessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
||||||
|
livenessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: emailservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: emailservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 5000
|
||||||
|
targetPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: checkoutservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: checkoutservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: checkoutservice
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/checkoutservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 5050
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:5050"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:5050"]
|
||||||
|
env:
|
||||||
|
- name: PRODUCT_CATALOG_SERVICE_ADDR
|
||||||
|
value: "productcatalogservice:3550"
|
||||||
|
- name: SHIPPING_SERVICE_ADDR
|
||||||
|
value: "shippingservice:50051"
|
||||||
|
- name: PAYMENT_SERVICE_ADDR
|
||||||
|
value: "paymentservice:50051"
|
||||||
|
- name: EMAIL_SERVICE_ADDR
|
||||||
|
value: "emailservice:5000"
|
||||||
|
- name: CURRENCY_SERVICE_ADDR
|
||||||
|
value: "currencyservice:7000"
|
||||||
|
- name: CART_SERVICE_ADDR
|
||||||
|
value: "cartservice:7070"
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: checkoutservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: checkoutservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 5050
|
||||||
|
targetPort: 5050
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: recommendationservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: recommendationservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: recommendationservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/recommendationservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
readinessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
||||||
|
livenessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:8080"]
|
||||||
|
env:
|
||||||
|
- name: PRODUCT_CATALOG_SERVICE_ADDR
|
||||||
|
value: "productcatalogservice:3550"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 220Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 450Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: recommendationservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: recommendationservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 8080
|
||||||
|
targetPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: frontend
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: frontend
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/frontend:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
httpGet:
|
||||||
|
path: "/_healthz"
|
||||||
|
port: 8080
|
||||||
|
httpHeaders:
|
||||||
|
- name: "Cookie"
|
||||||
|
value: "shop_session-id=x-readiness-probe"
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
httpGet:
|
||||||
|
path: "/_healthz"
|
||||||
|
port: 8080
|
||||||
|
httpHeaders:
|
||||||
|
- name: "Cookie"
|
||||||
|
value: "shop_session-id=x-liveness-probe"
|
||||||
|
env:
|
||||||
|
- name: PRODUCT_CATALOG_SERVICE_ADDR
|
||||||
|
value: "productcatalogservice:3550"
|
||||||
|
- name: CURRENCY_SERVICE_ADDR
|
||||||
|
value: "currencyservice:7000"
|
||||||
|
- name: CART_SERVICE_ADDR
|
||||||
|
value: "cartservice:7070"
|
||||||
|
- name: RECOMMENDATION_SERVICE_ADDR
|
||||||
|
value: "recommendationservice:8080"
|
||||||
|
- name: SHIPPING_SERVICE_ADDR
|
||||||
|
value: "shippingservice:50051"
|
||||||
|
- name: CHECKOUT_SERVICE_ADDR
|
||||||
|
value: "checkoutservice:5050"
|
||||||
|
- name: AD_SERVICE_ADDR
|
||||||
|
value: "adservice:9555"
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: frontend
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: frontend
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: frontend-external
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: frontend
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: paymentservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: paymentservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: paymentservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/paymentservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 50051
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: paymentservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: paymentservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 50051
|
||||||
|
targetPort: 50051
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: productcatalogservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: productcatalogservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: productcatalogservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/productcatalogservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 3550
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:3550"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:3550"]
|
||||||
|
# env:
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: productcatalogservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: productcatalogservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 3550
|
||||||
|
targetPort: 3550
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: cartservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: cartservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cartservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/cartservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 7070
|
||||||
|
env:
|
||||||
|
- name: REDIS_ADDR
|
||||||
|
value: "redis-cart:6379"
|
||||||
|
- name: PORT
|
||||||
|
value: "7070"
|
||||||
|
- name: LISTEN_ADDR
|
||||||
|
value: "0.0.0.0"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 300m
|
||||||
|
memory: 128Mi
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:7070"]
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:7070"]
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: cartservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: cartservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 7070
|
||||||
|
targetPort: 7070
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: loadgenerator
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: loadgenerator
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: loadgenerator
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
restartPolicy: Always
|
||||||
|
initContainers:
|
||||||
|
- name: wait-frontend
|
||||||
|
image: alpine:3.6
|
||||||
|
command: ['sh', '-c', 'set -x; apk add --no-cache curl &&
|
||||||
|
until timeout -t 2 curl -f "http://${FRONTEND_ADDR}"; do
|
||||||
|
echo "waiting for http://${FRONTEND_ADDR}";
|
||||||
|
sleep 2;
|
||||||
|
done;']
|
||||||
|
env:
|
||||||
|
- name: FRONTEND_ADDR
|
||||||
|
value: "frontend:80"
|
||||||
|
containers:
|
||||||
|
- name: main
|
||||||
|
image: gcr.io/google-samples/microservices-demo/loadgenerator:v0.1.0
|
||||||
|
env:
|
||||||
|
- name: FRONTEND_ADDR
|
||||||
|
value: "frontend:80"
|
||||||
|
- name: USERS
|
||||||
|
value: "10"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 300m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 512Mi
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: currencyservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: currencyservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: currencyservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/currencyservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
containerPort: 7000
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:7000"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:7000"]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: currencyservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: currencyservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 7000
|
||||||
|
targetPort: 7000
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: shippingservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: shippingservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: shippingservice
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/shippingservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 50051
|
||||||
|
readinessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:50051"]
|
||||||
|
# env:
|
||||||
|
# - name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 128Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: shippingservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: shippingservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 50051
|
||||||
|
targetPort: 50051
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: redis-cart
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: redis-cart
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: redis-cart
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: redis
|
||||||
|
image: redis:alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 6379
|
||||||
|
readinessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
tcpSocket:
|
||||||
|
port: 6379
|
||||||
|
livenessProbe:
|
||||||
|
periodSeconds: 5
|
||||||
|
tcpSocket:
|
||||||
|
port: 6379
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /data
|
||||||
|
name: redis-data
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 256Mi
|
||||||
|
cpu: 125m
|
||||||
|
requests:
|
||||||
|
cpu: 70m
|
||||||
|
memory: 200Mi
|
||||||
|
volumes:
|
||||||
|
- name: redis-data
|
||||||
|
emptyDir: {}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: redis-cart
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: redis-cart
|
||||||
|
ports:
|
||||||
|
- name: redis
|
||||||
|
port: 6379
|
||||||
|
targetPort: 6379
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: adservice
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: adservice
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: adservice
|
||||||
|
spec:
|
||||||
|
terminationGracePeriodSeconds: 5
|
||||||
|
containers:
|
||||||
|
- name: server
|
||||||
|
image: gcr.io/google-samples/microservices-demo/adservice:v0.1.0
|
||||||
|
ports:
|
||||||
|
- containerPort: 9555
|
||||||
|
env:
|
||||||
|
- name: PORT
|
||||||
|
value: "9555"
|
||||||
|
#- name: JAEGER_SERVICE_ADDR
|
||||||
|
# value: "jaeger-collector:14268"
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 200m
|
||||||
|
memory: 180Mi
|
||||||
|
limits:
|
||||||
|
cpu: 300m
|
||||||
|
memory: 300Mi
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
||||||
|
livenessProbe:
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
periodSeconds: 15
|
||||||
|
exec:
|
||||||
|
command: ["/bin/grpc_health_probe", "-addr=:9555"]
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: adservice
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: adservice
|
||||||
|
ports:
|
||||||
|
- name: grpc
|
||||||
|
port: 9555
|
||||||
|
targetPort: 9555
|
||||||
|
---
|
|
@ -12,57 +12,60 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
apiVersion: skaffold/v1alpha2
|
apiVersion: skaffold/v1beta2
|
||||||
kind: Config
|
kind: Config
|
||||||
build:
|
build:
|
||||||
|
artifacts:
|
||||||
|
# image tags are relative; to specify an image repo (e.g. GCR), you
|
||||||
|
# must provide a "default repo" using one of the methods described
|
||||||
|
# here:
|
||||||
|
# https://skaffold.dev/docs/concepts/#image-repository-handling
|
||||||
|
- image: emailservice
|
||||||
|
context: src/emailservice
|
||||||
|
- image: productcatalogservice
|
||||||
|
context: src/productcatalogservice
|
||||||
|
- image: recommendationservice
|
||||||
|
context: src/recommendationservice
|
||||||
|
- image: shippingservice
|
||||||
|
context: src/shippingservice
|
||||||
|
- image: checkoutservice
|
||||||
|
context: src/checkoutservice
|
||||||
|
- image: paymentservice
|
||||||
|
context: src/paymentservice
|
||||||
|
- image: currencyservice
|
||||||
|
context: src/currencyservice
|
||||||
|
- image: cartservice
|
||||||
|
context: src/cartservice
|
||||||
|
- image: frontend
|
||||||
|
context: src/frontend
|
||||||
|
- image: loadgenerator
|
||||||
|
context: src/loadgenerator
|
||||||
|
- image: adservice
|
||||||
|
context: src/adservice
|
||||||
tagPolicy:
|
tagPolicy:
|
||||||
gitCommit: {}
|
gitCommit: {}
|
||||||
artifacts:
|
|
||||||
- imageName: gcr.io/microservices-demo-app/emailservice
|
|
||||||
workspace: src/emailservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/productcatalogservice
|
|
||||||
workspace: src/productcatalogservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/recommendationservice
|
|
||||||
workspace: src/recommendationservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/shippingservice
|
|
||||||
workspace: src/shippingservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/checkoutservice
|
|
||||||
workspace: src/checkoutservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/paymentservice
|
|
||||||
workspace: src/paymentservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/currencyservice
|
|
||||||
workspace: src/currencyservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/cartservice
|
|
||||||
workspace: src/cartservice
|
|
||||||
- imageName: gcr.io/microservices-demo-app/frontend
|
|
||||||
workspace: src/frontend
|
|
||||||
- imageName: gcr.io/microservices-demo-app/loadgenerator
|
|
||||||
workspace: src/loadgenerator
|
|
||||||
- imageName: gcr.io/microservices-demo-app/adservice
|
|
||||||
workspace: src/adservice
|
|
||||||
deploy:
|
deploy:
|
||||||
kubectl:
|
kubectl:
|
||||||
manifests:
|
manifests:
|
||||||
- ./kubernetes-manifests/**.yaml
|
- ./kubernetes-manifests/**.yaml
|
||||||
|
|
||||||
|
|
||||||
profiles:
|
profiles:
|
||||||
# "travis-ci" profile is used to build the images without
|
# "travis-ci" profile is used to build the images without
|
||||||
# pushing them.
|
# pushing them.
|
||||||
- name: travis-ci
|
- name: travis-ci
|
||||||
build:
|
build:
|
||||||
local:
|
local:
|
||||||
skipPush: true
|
push: false
|
||||||
# "gcb" profile allows building and pushing the images
|
# "gcb" profile allows building and pushing the images
|
||||||
# on Google Container Builder without requiring docker
|
# on Google Container Builder without requiring docker
|
||||||
# installed on the developer machine. However, note that
|
# installed on the developer machine. However, note that
|
||||||
# since GCB does not cache the builds, each build will
|
# since GCB does not cache the builds, each build will
|
||||||
# start from scratch and therefore take a long time.
|
# start from scratch and therefore take a long time.
|
||||||
#
|
#
|
||||||
# This is not used by default. To use it, run:
|
# This is not used by default. To use it, run:
|
||||||
# skaffold run -p gcb
|
# skaffold run -p gcb
|
||||||
- name: gcb
|
- name: gcb
|
||||||
build:
|
build:
|
||||||
googleCloudBuild:
|
googleCloudBuild:
|
||||||
diskSizeGb: 300
|
diskSizeGb: 300
|
||||||
machineType: "N1_HIGHCPU_32"
|
machineType: N1_HIGHCPU_32
|
||||||
|
timeout: 4000s
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
FROM openjdk:8
|
FROM openjdk:8-slim as builder
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
|
||||||
chmod +x /bin/grpc_health_probe
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Next three steps are for caching dependency downloads
|
|
||||||
# to improve subsequent docker build.
|
|
||||||
COPY ["build.gradle", "gradlew", "./"]
|
COPY ["build.gradle", "gradlew", "./"]
|
||||||
COPY gradle gradle
|
COPY gradle gradle
|
||||||
|
RUN chmod +x gradlew
|
||||||
RUN ./gradlew downloadRepos
|
RUN ./gradlew downloadRepos
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN chmod +x gradlew
|
||||||
RUN ./gradlew installDist
|
RUN ./gradlew installDist
|
||||||
|
|
||||||
|
FROM openjdk:8-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
|
||||||
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.1 && \
|
||||||
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app .
|
||||||
|
|
||||||
EXPOSE 9555
|
EXPOSE 9555
|
||||||
ENTRYPOINT ["/app/build/install/hipstershop/bin/AdService"]
|
ENTRYPOINT ["/app/build/install/hipstershop/bin/AdService"]
|
||||||
|
|
|
@ -2,23 +2,25 @@
|
||||||
|
|
||||||
The Ad service provides advertisement based on context keys. If no context keys are provided then it returns random ads.
|
The Ad service provides advertisement based on context keys. If no context keys are provided then it returns random ads.
|
||||||
|
|
||||||
## Local Build
|
## Building locally
|
||||||
|
|
||||||
|
The Ad service uses gradlew to compile/install/distribute. Gradle wrapper is already part of the source code. To build Ad Service, run:
|
||||||
|
|
||||||
The Ad service uses gradlew to compile/install/distribute. Gradle wrapper is already part of the source code. To build Ad Service, run
|
|
||||||
```
|
```
|
||||||
cd src/adservice; ./gradlew installDist
|
./gradlew installDist
|
||||||
```
|
```
|
||||||
It will create executable script src/adservice/build/install/hipstershop/bin/AdService
|
It will create executable script src/adservice/build/install/hipstershop/bin/AdService
|
||||||
|
|
||||||
### Upgrade gradle version
|
### Upgrading gradle version
|
||||||
If you need to upgrade the version of gradle then run
|
If you need to upgrade the version of gradle then run
|
||||||
|
|
||||||
```
|
```
|
||||||
cd src/adservice ; ./gradlew wrapper --gradle-version <new-version>
|
./gradlew wrapper --gradle-version <new-version>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker Build
|
## Building docker image
|
||||||
|
|
||||||
From repository root, run:
|
From the repository root, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build --file src/adservice/Dockerfile .
|
docker build --file src/adservice/Dockerfile .
|
||||||
|
|
|
@ -10,12 +10,14 @@ buildscript {
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3'
|
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.3'
|
||||||
|
classpath "gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.7.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'com.google.protobuf'
|
apply plugin: 'com.google.protobuf'
|
||||||
|
apply plugin: 'com.github.sherter.google-java-format'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -23,11 +25,11 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "adservice"
|
group = "adservice"
|
||||||
version = "0.1.0-SNAPSHOT" // CURRENT_OPENCENSUS_VERSION
|
version = "0.1.0-SNAPSHOT"
|
||||||
|
|
||||||
def opencensusVersion = "0.15.0" // LATEST_OPENCENSUS_RELEASE_VERSION
|
def opencensusVersion = "0.18.0"
|
||||||
def grpcVersion = "1.10.1" // CURRENT_GRPC_VERSION
|
def grpcVersion = "1.17.0"
|
||||||
def prometheusVersion = "0.3.0"
|
def jacksonVersion = "2.9.6"
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
sourceCompatibility = '1.8'
|
sourceCompatibility = '1.8'
|
||||||
|
@ -43,8 +45,10 @@ dependencies {
|
||||||
if (speed) {
|
if (speed) {
|
||||||
compile fileTree(dir: offlineCompile, include: '*.jar')
|
compile fileTree(dir: offlineCompile, include: '*.jar')
|
||||||
} else {
|
} else {
|
||||||
compile "com.google.api.grpc:proto-google-common-protos:1.11.0",
|
compile "com.google.api.grpc:proto-google-common-protos:1.12.0",
|
||||||
"io.opencensus:opencensus-exporter-stats-prometheus:${opencensusVersion}",
|
"io.opencensus:opencensus-api:${opencensusVersion}",
|
||||||
|
"io.opencensus:opencensus-contrib-grpc-util:${opencensusVersion}",
|
||||||
|
"io.opencensus:opencensus-exporter-trace-jaeger:${opencensusVersion}",
|
||||||
"io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}",
|
"io.opencensus:opencensus-exporter-stats-stackdriver:${opencensusVersion}",
|
||||||
"io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}",
|
"io.opencensus:opencensus-exporter-trace-stackdriver:${opencensusVersion}",
|
||||||
"io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}",
|
"io.opencensus:opencensus-exporter-trace-logging:${opencensusVersion}",
|
||||||
|
@ -52,9 +56,12 @@ dependencies {
|
||||||
"io.grpc:grpc-stub:${grpcVersion}",
|
"io.grpc:grpc-stub:${grpcVersion}",
|
||||||
"io.grpc:grpc-netty:${grpcVersion}",
|
"io.grpc:grpc-netty:${grpcVersion}",
|
||||||
"io.grpc:grpc-services:${grpcVersion}",
|
"io.grpc:grpc-services:${grpcVersion}",
|
||||||
"io.prometheus:simpleclient_httpserver:${prometheusVersion}"
|
"org.apache.logging.log4j:log4j-core:2.11.1"
|
||||||
|
|
||||||
runtime "io.opencensus:opencensus-impl:${opencensusVersion}",
|
runtime "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}",
|
||||||
|
"com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}",
|
||||||
|
"io.opencensus:opencensus-contrib-log-correlation-log4j2:${opencensusVersion}",
|
||||||
|
"io.opencensus:opencensus-impl:${opencensusVersion}",
|
||||||
"io.netty:netty-tcnative-boringssl-static:2.0.8.Final"
|
"io.netty:netty-tcnative-boringssl-static:2.0.8.Final"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +83,10 @@ protobuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
googleJavaFormat {
|
||||||
|
toolVersion '1.7'
|
||||||
|
}
|
||||||
|
|
||||||
// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code.
|
// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code.
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
|
@ -106,6 +117,8 @@ task adService(type: CreateStartScripts) {
|
||||||
applicationName = 'AdService'
|
applicationName = 'AdService'
|
||||||
outputDir = new File(project.buildDir, 'tmp')
|
outputDir = new File(project.buildDir, 'tmp')
|
||||||
classpath = jar.outputs.files + project.configurations.runtime
|
classpath = jar.outputs.files + project.configurations.runtime
|
||||||
|
defaultJvmOpts =
|
||||||
|
["-Dlog4j2.contextDataInjector=io.opencensus.contrib.logcorrelation.log4j2.OpenCensusTraceContextDataInjector"]
|
||||||
}
|
}
|
||||||
|
|
||||||
task adServiceClient(type: CreateStartScripts) {
|
task adServiceClient(type: CreateStartScripts) {
|
||||||
|
@ -113,6 +126,8 @@ task adServiceClient(type: CreateStartScripts) {
|
||||||
applicationName = 'AdServiceClient'
|
applicationName = 'AdServiceClient'
|
||||||
outputDir = new File(project.buildDir, 'tmp')
|
outputDir = new File(project.buildDir, 'tmp')
|
||||||
classpath = jar.outputs.files + project.configurations.runtime
|
classpath = jar.outputs.files + project.configurations.runtime
|
||||||
|
defaultJvmOpts =
|
||||||
|
["-Dlog4j2.contextDataInjector=io.opencensus.contrib.logcorrelation.log4j2.OpenCensusTraceContextDataInjector"]
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationDistribution.into('bin') {
|
applicationDistribution.into('bin') {
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
package hipstershop;
|
package hipstershop;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableListMultimap;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import hipstershop.Demo.Ad;
|
import hipstershop.Demo.Ad;
|
||||||
import hipstershop.Demo.AdRequest;
|
import hipstershop.Demo.AdRequest;
|
||||||
import hipstershop.Demo.AdResponse;
|
import hipstershop.Demo.AdResponse;
|
||||||
|
@ -24,48 +26,50 @@ import io.grpc.Server;
|
||||||
import io.grpc.ServerBuilder;
|
import io.grpc.ServerBuilder;
|
||||||
import io.grpc.StatusRuntimeException;
|
import io.grpc.StatusRuntimeException;
|
||||||
import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
|
import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
|
||||||
import io.grpc.stub.StreamObserver;
|
|
||||||
import io.grpc.services.*;
|
import io.grpc.services.*;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
import io.opencensus.common.Duration;
|
import io.opencensus.common.Duration;
|
||||||
import io.opencensus.common.Scope;
|
|
||||||
import io.opencensus.contrib.grpc.metrics.RpcViews;
|
import io.opencensus.contrib.grpc.metrics.RpcViews;
|
||||||
import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector;
|
|
||||||
import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
|
|
||||||
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
|
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
|
||||||
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
|
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
|
||||||
|
import io.opencensus.exporter.trace.jaeger.JaegerTraceExporter;
|
||||||
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
|
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
|
||||||
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
|
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
|
||||||
import io.opencensus.trace.AttributeValue;
|
import io.opencensus.trace.AttributeValue;
|
||||||
import io.opencensus.trace.Span;
|
import io.opencensus.trace.Span;
|
||||||
import io.opencensus.trace.SpanBuilder;
|
|
||||||
import io.opencensus.trace.Tracer;
|
import io.opencensus.trace.Tracer;
|
||||||
import io.opencensus.trace.Tracing;
|
import io.opencensus.trace.Tracing;
|
||||||
import io.opencensus.trace.samplers.Samplers;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import java.util.logging.Logger;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
public class AdService {
|
public final class AdService {
|
||||||
private static final Logger logger = Logger.getLogger(AdService.class.getName());
|
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(AdService.class);
|
||||||
private static final Tracer tracer = Tracing.getTracer();
|
private static final Tracer tracer = Tracing.getTracer();
|
||||||
|
|
||||||
private int MAX_ADS_TO_SERVE = 2;
|
private static int MAX_ADS_TO_SERVE = 2;
|
||||||
private Server server;
|
private Server server;
|
||||||
private HealthStatusManager healthMgr;
|
private HealthStatusManager healthMgr;
|
||||||
|
|
||||||
static final AdService service = new AdService();
|
private static final AdService service = new AdService();
|
||||||
|
|
||||||
private void start() throws IOException {
|
private void start() throws IOException {
|
||||||
int port = Integer.parseInt(System.getenv("PORT"));
|
int port = Integer.parseInt(System.getenv("PORT"));
|
||||||
healthMgr = new HealthStatusManager();
|
healthMgr = new HealthStatusManager();
|
||||||
|
|
||||||
server = ServerBuilder.forPort(port).addService(new AdServiceImpl())
|
server =
|
||||||
.addService(healthMgr.getHealthService()).build().start();
|
ServerBuilder.forPort(port)
|
||||||
|
.addService(new AdServiceImpl())
|
||||||
|
.addService(healthMgr.getHealthService())
|
||||||
|
.build()
|
||||||
|
.start();
|
||||||
logger.info("Ad Service started, listening on " + port);
|
logger.info("Ad Service started, listening on " + port);
|
||||||
Runtime.getRuntime()
|
Runtime.getRuntime()
|
||||||
.addShutdownHook(
|
.addShutdownHook(
|
||||||
|
@ -88,29 +92,23 @@ public class AdService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase {
|
private static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves ads based on context provided in the request {@code AdRequest}.
|
* Retrieves ads based on context provided in the request {@code AdRequest}.
|
||||||
*
|
*
|
||||||
* @param req the request containing context.
|
* @param req the request containing context.
|
||||||
* @param responseObserver the stream observer which gets notified with the value of
|
* @param responseObserver the stream observer which gets notified with the value of {@code
|
||||||
* {@code AdResponse}
|
* AdResponse}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
|
public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
|
||||||
AdService service = AdService.getInstance();
|
AdService service = AdService.getInstance();
|
||||||
Span parentSpan = tracer.getCurrentSpan();
|
|
||||||
SpanBuilder spanBuilder =
|
|
||||||
tracer
|
|
||||||
.spanBuilderWithExplicitParent("Retrieve Ads", parentSpan)
|
|
||||||
.setRecordEvents(true)
|
|
||||||
.setSampler(Samplers.alwaysSample());
|
|
||||||
try (Scope scope = spanBuilder.startScopedSpan()) {
|
|
||||||
Span span = tracer.getCurrentSpan();
|
Span span = tracer.getCurrentSpan();
|
||||||
|
try {
|
||||||
span.putAttribute("method", AttributeValue.stringAttributeValue("getAds"));
|
span.putAttribute("method", AttributeValue.stringAttributeValue("getAds"));
|
||||||
List<Ad> ads = new ArrayList<>();
|
List<Ad> allAds = new ArrayList<>();
|
||||||
logger.info("received ad request (context_words=" + req.getContextKeysCount() + ")");
|
logger.info("received ad request (context_words=" + req.getContextKeysList() + ")");
|
||||||
if (req.getContextKeysCount() > 0) {
|
if (req.getContextKeysCount() > 0) {
|
||||||
span.addAnnotation(
|
span.addAnnotation(
|
||||||
"Constructing Ads using context",
|
"Constructing Ads using context",
|
||||||
|
@ -120,47 +118,46 @@ public class AdService {
|
||||||
"Context Keys length",
|
"Context Keys length",
|
||||||
AttributeValue.longAttributeValue(req.getContextKeysCount())));
|
AttributeValue.longAttributeValue(req.getContextKeysCount())));
|
||||||
for (int i = 0; i < req.getContextKeysCount(); i++) {
|
for (int i = 0; i < req.getContextKeysCount(); i++) {
|
||||||
Ad ad = service.getAdsByKey(req.getContextKeys(i));
|
Collection<Ad> ads = service.getAdsByCategory(req.getContextKeys(i));
|
||||||
if (ad != null) {
|
allAds.addAll(ads);
|
||||||
ads.add(ad);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
span.addAnnotation("No Context provided. Constructing random Ads.");
|
span.addAnnotation("No Context provided. Constructing random Ads.");
|
||||||
ads = service.getDefaultAds();
|
allAds = service.getRandomAds();
|
||||||
}
|
}
|
||||||
if (ads.isEmpty()) {
|
if (allAds.isEmpty()) {
|
||||||
// Serve default ads.
|
// Serve random ads.
|
||||||
span.addAnnotation("No Ads found based on context. Constructing random Ads.");
|
span.addAnnotation("No Ads found based on context. Constructing random Ads.");
|
||||||
ads = service.getDefaultAds();
|
allAds = service.getRandomAds();
|
||||||
}
|
}
|
||||||
AdResponse reply = AdResponse.newBuilder().addAllAds(ads).build();
|
AdResponse reply = AdResponse.newBuilder().addAllAds(allAds).build();
|
||||||
responseObserver.onNext(reply);
|
responseObserver.onNext(reply);
|
||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
logger.log(Level.WARNING, "GetAds Failed", e.getStatus());
|
logger.log(Level.WARN, "GetAds Failed", e.getStatus());
|
||||||
return;
|
responseObserver.onError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final HashMap<String, Ad> cacheMap = new HashMap<String, Ad>();
|
private static final ImmutableListMultimap<String, Ad> adsMap = createAdsMap();
|
||||||
|
|
||||||
Ad getAdsByKey(String key) {
|
private Collection<Ad> getAdsByCategory(String category) {
|
||||||
return cacheMap.get(key);
|
return adsMap.get(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
public List<Ad> getDefaultAds() {
|
private List<Ad> getRandomAds() {
|
||||||
List<Ad> ads = new ArrayList<>(MAX_ADS_TO_SERVE);
|
List<Ad> ads = new ArrayList<>(MAX_ADS_TO_SERVE);
|
||||||
Object[] keys = cacheMap.keySet().toArray();
|
Collection<Ad> allAds = adsMap.values();
|
||||||
for (int i=0; i<MAX_ADS_TO_SERVE; i++) {
|
for (int i = 0; i < MAX_ADS_TO_SERVE; i++) {
|
||||||
ads.add(cacheMap.get(keys[new Random().nextInt(keys.length)]));
|
ads.add(Iterables.get(allAds, random.nextInt(allAds.size())));
|
||||||
}
|
}
|
||||||
return ads;
|
return ads;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AdService getInstance() {
|
private static AdService getInstance() {
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,46 +168,86 @@ public class AdService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initializeAds() {
|
private static ImmutableListMultimap<String, Ad> createAdsMap() {
|
||||||
cacheMap.put("camera", Ad.newBuilder().setRedirectUrl( "/product/2ZYFJ3GM2N")
|
Ad camera =
|
||||||
.setText("Film camera for sale. 50% off.").build());
|
Ad.newBuilder()
|
||||||
cacheMap.put("bike", Ad.newBuilder().setRedirectUrl("/product/9SIQT8TOJO")
|
.setRedirectUrl("/product/2ZYFJ3GM2N")
|
||||||
.setText("City Bike for sale. 10% off.").build());
|
.setText("Film camera for sale. 50% off.")
|
||||||
cacheMap.put("kitchen", Ad.newBuilder().setRedirectUrl("/product/1YMWWN1N4O")
|
.build();
|
||||||
.setText("Home Barista kitchen kit for sale. Buy one, get second kit for free").build());
|
Ad lens =
|
||||||
logger.info("Default Ads initialized");
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/66VCHSJNUP")
|
||||||
|
.setText("Vintage camera lens for sale. 20% off.")
|
||||||
|
.build();
|
||||||
|
Ad recordPlayer =
|
||||||
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/0PUK6V6EV0")
|
||||||
|
.setText("Vintage record player for sale. 30% off.")
|
||||||
|
.build();
|
||||||
|
Ad bike =
|
||||||
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/9SIQT8TOJO")
|
||||||
|
.setText("City Bike for sale. 10% off.")
|
||||||
|
.build();
|
||||||
|
Ad baristaKit =
|
||||||
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/1YMWWN1N4O")
|
||||||
|
.setText("Home Barista kitchen kit for sale. Buy one, get second kit for free")
|
||||||
|
.build();
|
||||||
|
Ad airPlant =
|
||||||
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/6E92ZMYYFZ")
|
||||||
|
.setText("Air plants for sale. Buy two, get third one for free")
|
||||||
|
.build();
|
||||||
|
Ad terrarium =
|
||||||
|
Ad.newBuilder()
|
||||||
|
.setRedirectUrl("/product/L9ECAV7KIM")
|
||||||
|
.setText("Terrarium for sale. Buy one, get second one for free")
|
||||||
|
.build();
|
||||||
|
return ImmutableListMultimap.<String, Ad>builder()
|
||||||
|
.putAll("photography", camera, lens)
|
||||||
|
.putAll("vintage", camera, lens, recordPlayer)
|
||||||
|
.put("cycling", bike)
|
||||||
|
.put("cookware", baristaKit)
|
||||||
|
.putAll("gardening", airPlant, terrarium)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initStackdriver() {
|
private static void initStackdriver() {
|
||||||
logger.info("Initialize StackDriver");
|
logger.info("Initialize StackDriver");
|
||||||
|
|
||||||
// Registers all RPC views.
|
|
||||||
RpcViews.registerAllViews();
|
|
||||||
|
|
||||||
// Registers logging trace exporter.
|
|
||||||
LoggingTraceExporter.register();
|
|
||||||
long sleepTime = 10; /* seconds */
|
long sleepTime = 10; /* seconds */
|
||||||
int maxAttempts = 3;
|
int maxAttempts = 5;
|
||||||
|
boolean statsExporterRegistered = false;
|
||||||
|
boolean traceExporterRegistered = false;
|
||||||
|
|
||||||
for (int i=0; i<maxAttempts; i++) {
|
for (int i = 0; i < maxAttempts; i++) {
|
||||||
try {
|
try {
|
||||||
|
if (!traceExporterRegistered) {
|
||||||
StackdriverTraceExporter.createAndRegister(
|
StackdriverTraceExporter.createAndRegister(
|
||||||
StackdriverTraceConfiguration.builder().build());
|
StackdriverTraceConfiguration.builder().build());
|
||||||
|
traceExporterRegistered = true;
|
||||||
|
}
|
||||||
|
if (!statsExporterRegistered) {
|
||||||
StackdriverStatsExporter.createAndRegister(
|
StackdriverStatsExporter.createAndRegister(
|
||||||
StackdriverStatsConfiguration.builder()
|
StackdriverStatsConfiguration.builder()
|
||||||
.setExportInterval(Duration.create(15, 0))
|
.setExportInterval(Duration.create(60, 0))
|
||||||
.build());
|
.build());
|
||||||
|
statsExporterRegistered = true;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (i==(maxAttempts-1)) {
|
if (i == (maxAttempts - 1)) {
|
||||||
logger.log(Level.WARNING, "Failed to register Stackdriver Exporter." +
|
logger.log(
|
||||||
" Tracing and Stats data will not reported to Stackdriver. Error message: " + e
|
Level.WARN,
|
||||||
.toString());
|
"Failed to register Stackdriver Exporter."
|
||||||
|
+ " Tracing and Stats data will not reported to Stackdriver. Error message: "
|
||||||
|
+ e.toString());
|
||||||
} else {
|
} else {
|
||||||
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds ");
|
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds ");
|
||||||
try {
|
try {
|
||||||
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
|
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
|
||||||
} catch (Exception se) {
|
} catch (Exception se) {
|
||||||
logger.log(Level.WARNING, "Exception while sleeping" + se.toString());
|
logger.log(Level.WARN, "Exception while sleeping" + se.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,20 +255,40 @@ public class AdService {
|
||||||
logger.info("StackDriver initialization complete.");
|
logger.info("StackDriver initialization complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void initJaeger() {
|
||||||
|
String jaegerAddr = System.getenv("JAEGER_SERVICE_ADDR");
|
||||||
|
if (jaegerAddr != null && !jaegerAddr.isEmpty()) {
|
||||||
|
String jaegerUrl = String.format("http://%s/api/traces", jaegerAddr);
|
||||||
|
// Register Jaeger Tracing.
|
||||||
|
JaegerTraceExporter.createAndRegister(jaegerUrl, "adservice");
|
||||||
|
logger.info("Jaeger initialization complete.");
|
||||||
|
} else {
|
||||||
|
logger.info("Jaeger initialization disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Main launches the server from the command line. */
|
/** Main launches the server from the command line. */
|
||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
// Add final keyword to pass checkStyle.
|
// Registers all RPC views.
|
||||||
|
/**
|
||||||
|
* [TODO:rghetia] replace registerAllViews with registerAllGrpcViews.
|
||||||
|
* registerAllGrpcViews registers new views using new measures however current grpc version records against
|
||||||
|
* old measures. When new version of grpc (0.19) is release revert back to new. After reverting
|
||||||
|
* back to new the new measure will not provide any tags (like method). This will create
|
||||||
|
* some discrepencies when compared grpc measurements in Go services.
|
||||||
|
*/
|
||||||
|
RpcViews.registerAllViews();
|
||||||
|
|
||||||
initializeAds();
|
new Thread(
|
||||||
|
new Runnable() {
|
||||||
new Thread( new Runnable() {
|
public void run() {
|
||||||
public void run(){
|
|
||||||
initStackdriver();
|
initStackdriver();
|
||||||
}
|
}
|
||||||
}).start();
|
})
|
||||||
|
.start();
|
||||||
|
|
||||||
// Register Prometheus exporters and export metrics to a Prometheus HTTPServer.
|
// Register Jaeger
|
||||||
PrometheusStatsCollector.createAndRegister();
|
initJaeger();
|
||||||
|
|
||||||
// Start the RPC server. You shouldn't see any output from gRPC before this.
|
// Start the RPC server. You shouldn't see any output from gRPC before this.
|
||||||
logger.info("AdService starting.");
|
logger.info("AdService starting.");
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package hipstershop;
|
package hipstershop;
|
||||||
|
|
||||||
|
|
||||||
import hipstershop.Demo.Ad;
|
import hipstershop.Demo.Ad;
|
||||||
import hipstershop.Demo.AdRequest;
|
import hipstershop.Demo.AdRequest;
|
||||||
import hipstershop.Demo.AdResponse;
|
import hipstershop.Demo.AdResponse;
|
||||||
|
@ -26,33 +25,32 @@ import io.grpc.StatusRuntimeException;
|
||||||
import io.opencensus.common.Duration;
|
import io.opencensus.common.Duration;
|
||||||
import io.opencensus.common.Scope;
|
import io.opencensus.common.Scope;
|
||||||
import io.opencensus.contrib.grpc.metrics.RpcViews;
|
import io.opencensus.contrib.grpc.metrics.RpcViews;
|
||||||
import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
|
import io.opencensus.contrib.grpc.util.StatusConverter;
|
||||||
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
|
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsConfiguration;
|
||||||
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
|
import io.opencensus.exporter.stats.stackdriver.StackdriverStatsExporter;
|
||||||
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
|
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceConfiguration;
|
||||||
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
|
import io.opencensus.exporter.trace.stackdriver.StackdriverTraceExporter;
|
||||||
import io.opencensus.trace.SpanBuilder;
|
import io.opencensus.trace.Span;
|
||||||
import io.opencensus.trace.Status.CanonicalCode;
|
|
||||||
import io.opencensus.trace.Tracer;
|
import io.opencensus.trace.Tracer;
|
||||||
import io.opencensus.trace.Tracing;
|
import io.opencensus.trace.Tracing;
|
||||||
import io.opencensus.trace.samplers.Samplers;
|
import io.opencensus.trace.samplers.Samplers;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
/** A simple client that requests ads from the Ads Service. */
|
/** A simple client that requests ads from the Ads Service. */
|
||||||
public class AdServiceClient {
|
public class AdServiceClient {
|
||||||
private static final Logger logger = Logger.getLogger(AdServiceClient.class.getName());
|
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(AdServiceClient.class);
|
||||||
private static final Tracer tracer = Tracing.getTracer();
|
private static final Tracer tracer = Tracing.getTracer();
|
||||||
|
|
||||||
private final ManagedChannel channel;
|
private final ManagedChannel channel;
|
||||||
private final hipstershop.AdServiceGrpc.AdServiceBlockingStub blockingStub;
|
private final hipstershop.AdServiceGrpc.AdServiceBlockingStub blockingStub;
|
||||||
|
|
||||||
/** Construct client connecting to Ad Service at {@code host:port}. */
|
/** Construct client connecting to Ad Service at {@code host:port}. */
|
||||||
public AdServiceClient(String host, int port) {
|
private AdServiceClient(String host, int port) {
|
||||||
this(
|
this(
|
||||||
ManagedChannelBuilder.forAddress(host, port)
|
ManagedChannelBuilder.forAddress(host, port)
|
||||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||||
|
@ -62,12 +60,12 @@ public class AdServiceClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct client for accessing RouteGuide server using the existing channel. */
|
/** Construct client for accessing RouteGuide server using the existing channel. */
|
||||||
AdServiceClient(ManagedChannel channel) {
|
private AdServiceClient(ManagedChannel channel) {
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
blockingStub = hipstershop.AdServiceGrpc.newBlockingStub(channel);
|
blockingStub = hipstershop.AdServiceGrpc.newBlockingStub(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() throws InterruptedException {
|
private void shutdown() throws InterruptedException {
|
||||||
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,42 +75,42 @@ public class AdServiceClient {
|
||||||
AdRequest request = AdRequest.newBuilder().addContextKeys(contextKey).build();
|
AdRequest request = AdRequest.newBuilder().addContextKeys(contextKey).build();
|
||||||
AdResponse response;
|
AdResponse response;
|
||||||
|
|
||||||
SpanBuilder spanBuilder =
|
Span span =
|
||||||
tracer.spanBuilder("AdsClient").setRecordEvents(true).setSampler(Samplers.alwaysSample());
|
tracer
|
||||||
try (Scope scope = spanBuilder.startScopedSpan()) {
|
.spanBuilder("AdsClient")
|
||||||
|
.setRecordEvents(true)
|
||||||
|
.setSampler(Samplers.alwaysSample())
|
||||||
|
.startSpan();
|
||||||
|
try (Scope scope = tracer.withSpan(span)) {
|
||||||
tracer.getCurrentSpan().addAnnotation("Getting Ads");
|
tracer.getCurrentSpan().addAnnotation("Getting Ads");
|
||||||
response = blockingStub.getAds(request);
|
response = blockingStub.getAds(request);
|
||||||
tracer.getCurrentSpan().addAnnotation("Received response from Ads Service.");
|
tracer.getCurrentSpan().addAnnotation("Received response from Ads Service.");
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
tracer
|
tracer.getCurrentSpan().setStatus(StatusConverter.fromGrpcStatus(e.getStatus()));
|
||||||
.getCurrentSpan()
|
logger.log(Level.WARN, "RPC failed: " + e.getStatus());
|
||||||
.setStatus(
|
|
||||||
CanonicalCode.valueOf(e.getStatus().getCode().name())
|
|
||||||
.toStatus()
|
|
||||||
.withDescription(e.getMessage()));
|
|
||||||
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
|
||||||
return;
|
return;
|
||||||
|
} finally {
|
||||||
|
span.end();
|
||||||
}
|
}
|
||||||
for(Ad ads: response.getAdsList()) {
|
for (Ad ads : response.getAdsList()) {
|
||||||
logger.info("Ads: " + ads.getText());
|
logger.info("Ads: " + ads.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) {
|
private static int getPortOrDefaultFromArgs(String[] args, int index, int defaultPort) {
|
||||||
int portNumber = defaultPort;
|
int portNumber = defaultPort;
|
||||||
if (index < args.length) {
|
if (index < args.length) {
|
||||||
try {
|
try {
|
||||||
portNumber = Integer.parseInt(args[index]);
|
portNumber = Integer.parseInt(args[index]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
logger.warning(
|
logger.warn(
|
||||||
String.format("Port %s is invalid, use default port %d.", args[index], defaultPort));
|
String.format("Port %s is invalid, use default port %d.", args[index], defaultPort));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return portNumber;
|
return portNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getStringOrDefaultFromArgs(
|
||||||
static String getStringOrDefaultFromArgs(
|
|
||||||
String[] args, int index, @Nullable String defaultString) {
|
String[] args, int index, @Nullable String defaultString) {
|
||||||
String s = defaultString;
|
String s = defaultString;
|
||||||
if (index < args.length) {
|
if (index < args.length) {
|
||||||
|
@ -125,54 +123,46 @@ public class AdServiceClient {
|
||||||
* Ads Service Client main. If provided, the first element of {@code args} is the context key to
|
* Ads Service Client main. If provided, the first element of {@code args} is the context key to
|
||||||
* get the ads from the Ads Service
|
* get the ads from the Ads Service
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
public static void main(String[] args) throws InterruptedException {
|
||||||
// Add final keyword to pass checkStyle.
|
// Add final keyword to pass checkStyle.
|
||||||
final String contextKeys = getStringOrDefaultFromArgs(args, 0, "camera");
|
final String contextKeys = getStringOrDefaultFromArgs(args, 0, "camera");
|
||||||
final String host = getStringOrDefaultFromArgs(args, 1, "localhost");
|
final String host = getStringOrDefaultFromArgs(args, 1, "localhost");
|
||||||
final int serverPort = getPortOrDefaultFromArgs(args, 2, 9555);
|
final int serverPort = getPortOrDefaultFromArgs(args, 2, 9555);
|
||||||
final String cloudProjectId = getStringOrDefaultFromArgs(args, 3, null);
|
|
||||||
//final int zPagePort = getPortOrDefaultFromArgs(args, 4, 3001);
|
|
||||||
|
|
||||||
// Registers all RPC views.
|
// Registers all RPC views.
|
||||||
RpcViews.registerAllViews();
|
RpcViews.registerAllGrpcViews();
|
||||||
|
|
||||||
|
|
||||||
// Registers logging trace exporter.
|
|
||||||
LoggingTraceExporter.register();
|
|
||||||
|
|
||||||
// Registers Stackdriver exporters.
|
// Registers Stackdriver exporters.
|
||||||
if (cloudProjectId != null) {
|
|
||||||
long sleepTime = 10; /* seconds */
|
long sleepTime = 10; /* seconds */
|
||||||
int maxAttempts = 3;
|
int maxAttempts = 3;
|
||||||
|
|
||||||
for (int i=0; i<maxAttempts; i++) {
|
for (int i = 0; i < maxAttempts; i++) {
|
||||||
try {
|
try {
|
||||||
StackdriverTraceExporter.createAndRegister(
|
StackdriverTraceExporter.createAndRegister(StackdriverTraceConfiguration.builder().build());
|
||||||
StackdriverTraceConfiguration.builder().setProjectId(cloudProjectId).build());
|
|
||||||
StackdriverStatsExporter.createAndRegister(
|
StackdriverStatsExporter.createAndRegister(
|
||||||
StackdriverStatsConfiguration.builder()
|
StackdriverStatsConfiguration.builder()
|
||||||
.setProjectId(cloudProjectId)
|
|
||||||
.setExportInterval(Duration.create(15, 0))
|
.setExportInterval(Duration.create(15, 0))
|
||||||
.build());
|
.build());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (i==(maxAttempts-1)) {
|
if (i == (maxAttempts - 1)) {
|
||||||
logger.log(Level.WARNING, "Failed to register Stackdriver Exporter." +
|
logger.log(
|
||||||
" Tracing and Stats data will not reported to Stackdriver. Error message: " + e
|
Level.WARN,
|
||||||
.toString());
|
"Failed to register Stackdriver Exporter."
|
||||||
|
+ " Tracing and Stats data will not reported to Stackdriver. Error message: "
|
||||||
|
+ e.toString());
|
||||||
} else {
|
} else {
|
||||||
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds");
|
logger.info("Attempt to register Stackdriver Exporter in " + sleepTime + " seconds");
|
||||||
try {
|
try {
|
||||||
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
|
Thread.sleep(TimeUnit.SECONDS.toMillis(sleepTime));
|
||||||
} catch (Exception se) {
|
} catch (Exception se) {
|
||||||
logger.log(Level.WARNING, "Exception while sleeping" + e.toString());
|
logger.log(Level.WARN, "Exception while sleeping" + e.toString());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register Prometheus exporters and export metrics to a Prometheus HTTPServer.
|
// Register Prometheus exporters and export metrics to a Prometheus HTTPServer.
|
||||||
//PrometheusStatsCollector.createAndRegister();
|
// PrometheusStatsCollector.createAndRegister();
|
||||||
|
|
||||||
AdServiceClient client = new AdServiceClient(host, serverPort);
|
AdServiceClient client = new AdServiceClient(host, serverPort);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -64,6 +64,10 @@ message Product {
|
||||||
string description = 3;
|
string description = 3;
|
||||||
string picture = 4;
|
string picture = 4;
|
||||||
Money price_usd = 5;
|
Money price_usd = 5;
|
||||||
|
|
||||||
|
// Categories such as "vintage" or "gardening" that can be used to look up
|
||||||
|
// other related products.
|
||||||
|
repeated string categories = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductsResponse {
|
message ListProductsResponse {
|
||||||
|
|
29
src/adservice/src/main/resources/log4j2.xml
Normal file
29
src/adservice/src/main/resources/log4j2.xml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration status="WARN">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="STDOUT" target="SYSTEM_OUT">
|
||||||
|
|
||||||
|
<!-- This is a JSON format that can be read by the Stackdriver Logging agent. The trace ID,
|
||||||
|
span ID, sampling decision, and timestamp are interpreted by Stackdriver. It uses the
|
||||||
|
special JSON keys that the Stackdriver Logging agent converts to "trace", "spanId",
|
||||||
|
"traceSampled", and "timestamp" in the Stackdriver LogEntry
|
||||||
|
(https://cloud.google.com/logging/docs/agent/configuration#special-fields). -->
|
||||||
|
|
||||||
|
<JsonLayout compact="true" eventEol="true">
|
||||||
|
<KeyValuePair key="logging.googleapis.com/trace" value="$${ctx:traceId}"/>
|
||||||
|
<KeyValuePair key="logging.googleapis.com/spanId" value="$${ctx:spanId}"/>
|
||||||
|
<KeyValuePair key="logging.googleapis.com/traceSampled" value="$${ctx:traceSampled}"/>
|
||||||
|
<KeyValuePair key="time" value="$${date:yyyy-MM-dd}T$${date:HH:mm:ss.SSS}Z"/>
|
||||||
|
</JsonLayout>
|
||||||
|
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="io.grpc.netty" level="INFO"/>
|
||||||
|
<Logger name="io.netty" level="INFO"/>
|
||||||
|
<Logger name="sun.net" level="INFO"/>
|
||||||
|
<Root level="TRACE">
|
||||||
|
<AppenderRef ref="STDOUT"/>
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,22 +1,28 @@
|
||||||
# cartservice_probe
|
FROM microsoft/dotnet:2.1-sdk-alpine as builder
|
||||||
FROM golang:1.10 as builder
|
|
||||||
RUN wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
|
||||||
chmod +x /go/bin/dep
|
|
||||||
ENV PROJECT github.com/GoogleCloudPlatform/microservices-demo/src/cartservice/probe
|
|
||||||
WORKDIR /go/src/$PROJECT
|
|
||||||
COPY probe/Gopkg.* ./
|
|
||||||
RUN dep ensure --vendor-only -v
|
|
||||||
COPY ./probe ./
|
|
||||||
RUN go build -o /cartservice_probe .
|
|
||||||
|
|
||||||
# cartservice
|
|
||||||
FROM gcr.io/google-appengine/aspnetcore:2.1.0
|
|
||||||
COPY --from=builder /cartservice_probe /cartservice_probe
|
|
||||||
RUN apt-get update && apt-get install net-tools telnet
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN dotnet restore && \
|
RUN dotnet restore && \
|
||||||
dotnet build && \
|
dotnet build && \
|
||||||
dotnet publish
|
dotnet publish -c release -r linux-musl-x64 -o /cartservice
|
||||||
WORKDIR /app/bin/Debug/netcoreapp2.0
|
|
||||||
ENTRYPOINT ["dotnet", "cartservice.dll", "start"]
|
# cartservice
|
||||||
|
FROM alpine:3.8
|
||||||
|
|
||||||
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
|
# Dependencies for runtime
|
||||||
|
# busybox-extras => telnet
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
busybox-extras \
|
||||||
|
libc6-compat \
|
||||||
|
libunwind \
|
||||||
|
libuuid \
|
||||||
|
libgcc \
|
||||||
|
libstdc++ \
|
||||||
|
libintl \
|
||||||
|
icu
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /cartservice .
|
||||||
|
ENTRYPOINT ["./cartservice", "start"]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using cartservice.interfaces;
|
using cartservice.interfaces;
|
||||||
|
using Grpc.Core;
|
||||||
using Grpc.Health.V1;
|
using Grpc.Health.V1;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
using static Grpc.Health.V1.Health;
|
using static Grpc.Health.V1.Health;
|
||||||
|
@ -11,12 +13,12 @@ namespace cartservice {
|
||||||
this.dependency = dependency;
|
this.dependency = dependency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HealthCheckResponse Check (HealthCheckRequest request) {
|
public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context){
|
||||||
Console.WriteLine ("Checking CartService Health");
|
Console.WriteLine ("Checking CartService Health");
|
||||||
|
|
||||||
return new HealthCheckResponse {
|
return Task.FromResult(new HealthCheckResponse {
|
||||||
Status = dependency.Ping() ? HealthCheckResponse.Types.ServingStatus.Serving : HealthCheckResponse.Types.ServingStatus.NotServing
|
Status = dependency.Ping() ? HealthCheckResponse.Types.ServingStatus.Serving : HealthCheckResponse.Types.ServingStatus.NotServing
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
|
<PackageReference Include="Google.Protobuf" Version="3.6.1" />
|
||||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.1" />
|
<PackageReference Include="Google.Protobuf.Tools" Version="3.5.1" />
|
||||||
<PackageReference Include="grpc" Version="1.12.0" />
|
<PackageReference Include="grpc" Version="1.12.0" />
|
||||||
<PackageReference Include="Grpc.HealthCheck" Version="1.15.0" />
|
<PackageReference Include="Grpc.HealthCheck" Version="1.12.0" />
|
||||||
<PackageReference Include="grpc.tools" Version="1.12.0" />
|
<PackageReference Include="grpc.tools" Version="1.12.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.1" />
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
vendor/
|
|
101
src/cartservice/probe/Gopkg.lock
generated
101
src/cartservice/probe/Gopkg.lock
generated
|
@ -1,101 +0,0 @@
|
||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "github.com/golang/protobuf"
|
|
||||||
packages = [
|
|
||||||
"proto",
|
|
||||||
"ptypes",
|
|
||||||
"ptypes/any",
|
|
||||||
"ptypes/duration",
|
|
||||||
"ptypes/timestamp"
|
|
||||||
]
|
|
||||||
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
|
||||||
version = "v1.1.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = [
|
|
||||||
"context",
|
|
||||||
"http/httpguts",
|
|
||||||
"http2",
|
|
||||||
"http2/hpack",
|
|
||||||
"idna",
|
|
||||||
"internal/timeseries",
|
|
||||||
"trace"
|
|
||||||
]
|
|
||||||
revision = "f4c29de78a2a91c00474a2e689954305c350adf9"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = ["unix"]
|
|
||||||
revision = "0ffbfd41fbef8ffcf9b62b0b0aa3a5873ed7a4fe"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "golang.org/x/text"
|
|
||||||
packages = [
|
|
||||||
"collate",
|
|
||||||
"collate/build",
|
|
||||||
"internal/colltab",
|
|
||||||
"internal/gen",
|
|
||||||
"internal/tag",
|
|
||||||
"internal/triegen",
|
|
||||||
"internal/ucd",
|
|
||||||
"language",
|
|
||||||
"secure/bidirule",
|
|
||||||
"transform",
|
|
||||||
"unicode/bidi",
|
|
||||||
"unicode/cldr",
|
|
||||||
"unicode/norm",
|
|
||||||
"unicode/rangetable"
|
|
||||||
]
|
|
||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
|
||||||
version = "v0.3.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
name = "google.golang.org/genproto"
|
|
||||||
packages = ["googleapis/rpc/status"]
|
|
||||||
revision = "daca94659cb50e9f37c1b834680f2e46358f10b0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
name = "google.golang.org/grpc"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"balancer",
|
|
||||||
"balancer/base",
|
|
||||||
"balancer/roundrobin",
|
|
||||||
"codes",
|
|
||||||
"connectivity",
|
|
||||||
"credentials",
|
|
||||||
"encoding",
|
|
||||||
"encoding/proto",
|
|
||||||
"grpclog",
|
|
||||||
"internal",
|
|
||||||
"internal/backoff",
|
|
||||||
"internal/channelz",
|
|
||||||
"internal/envconfig",
|
|
||||||
"internal/grpcrand",
|
|
||||||
"internal/transport",
|
|
||||||
"keepalive",
|
|
||||||
"metadata",
|
|
||||||
"naming",
|
|
||||||
"peer",
|
|
||||||
"resolver",
|
|
||||||
"resolver/dns",
|
|
||||||
"resolver/passthrough",
|
|
||||||
"stats",
|
|
||||||
"status",
|
|
||||||
"tap"
|
|
||||||
]
|
|
||||||
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
|
|
||||||
version = "v1.14.0"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
inputs-digest = "8f3c07df5ebc7dc4d50ca8a6c274eef95f3045d33bbe5f384271fa87166a457e"
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
|
@ -1,42 +0,0 @@
|
||||||
# Gopkg.toml example
|
|
||||||
#
|
|
||||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
|
||||||
# for detailed Gopkg.toml documentation.
|
|
||||||
#
|
|
||||||
# required = ["github.com/user/thing/cmd/thing"]
|
|
||||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project"
|
|
||||||
# version = "1.0.0"
|
|
||||||
#
|
|
||||||
# [[constraint]]
|
|
||||||
# name = "github.com/user/project2"
|
|
||||||
# branch = "dev"
|
|
||||||
# source = "github.com/myfork/project2"
|
|
||||||
#
|
|
||||||
# [[override]]
|
|
||||||
# name = "github.com/x/y"
|
|
||||||
# version = "2.4.0"
|
|
||||||
#
|
|
||||||
# [prune]
|
|
||||||
# non-go = false
|
|
||||||
# go-tests = true
|
|
||||||
# unused-packages = true
|
|
||||||
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/golang/protobuf"
|
|
||||||
version = "1.1.0"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "google.golang.org/grpc"
|
|
||||||
version = "1.14.0"
|
|
||||||
|
|
||||||
[prune]
|
|
||||||
go-tests = true
|
|
||||||
unused-packages = true
|
|
|
@ -1,4 +0,0 @@
|
||||||
# cartservice Probe
|
|
||||||
|
|
||||||
This probe makes a call to the cartservice over localhost and exits to verify
|
|
||||||
liveness of the cartservice.
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,51 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
pb "github.com/GoogleCloudPlatform/microservices-demo/src/cartservice/probe/genproto"
|
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
port := os.Getenv("PORT")
|
|
||||||
if port == "" {
|
|
||||||
log.Fatal("probe is executed without PORT env var")
|
|
||||||
}
|
|
||||||
log.Printf("probe executing on port %q", port)
|
|
||||||
|
|
||||||
conn, err := grpc.DialContext(context.TODO(),
|
|
||||||
"127.0.0.1:"+port,
|
|
||||||
grpc.WithBlock(),
|
|
||||||
grpc.WithTimeout(time.Second*3),
|
|
||||||
grpc.WithInsecure(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("probe failed: failed to connect: %+v", err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
if _, err := pb.NewCartServiceClient(conn).GetCart(context.TODO(),
|
|
||||||
&pb.GetCartRequest{UserId: "exec-probe-nonexistinguser"}); err != nil {
|
|
||||||
log.Fatalf("probe failed: failed to query: %+v", err)
|
|
||||||
}
|
|
||||||
log.Println("probe successful")
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.10-alpine as builder
|
FROM golang:1.12-alpine as builder
|
||||||
RUN apk add --no-cache ca-certificates git && \
|
RUN apk add --no-cache ca-certificates git && \
|
||||||
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
||||||
chmod +x /go/bin/dep
|
chmod +x /go/bin/dep
|
||||||
|
@ -15,7 +15,7 @@ RUN go build -gcflags='-N -l' -o /checkoutservice .
|
||||||
|
|
||||||
FROM alpine as release
|
FROM alpine as release
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
chmod +x /bin/grpc_health_probe
|
chmod +x /bin/grpc_health_probe
|
||||||
COPY --from=builder /checkoutservice /checkoutservice
|
COPY --from=builder /checkoutservice /checkoutservice
|
||||||
|
|
153
src/checkoutservice/Gopkg.lock
generated
153
src/checkoutservice/Gopkg.lock
generated
|
@ -2,27 +2,49 @@
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272"
|
||||||
name = "cloud.google.com/go"
|
name = "cloud.google.com/go"
|
||||||
packages = [
|
packages = [
|
||||||
"compute/metadata",
|
"compute/metadata",
|
||||||
"internal/version",
|
"internal/version",
|
||||||
"monitoring/apiv3",
|
"monitoring/apiv3",
|
||||||
"profiler",
|
"profiler",
|
||||||
"trace/apiv2"
|
"trace/apiv2",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
|
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
|
||||||
version = "v0.27.0"
|
version = "v0.27.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
|
||||||
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
packages = [
|
packages = ["."]
|
||||||
".",
|
pruneopts = "UT"
|
||||||
"propagation"
|
|
||||||
]
|
|
||||||
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
||||||
version = "v0.5.0"
|
version = "v0.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:1d8f3cb93c42c5652bb509fde29ecdd1feede9334e355e8bbdc0f9f95b40c254"
|
||||||
|
name = "git.apache.org/thrift.git"
|
||||||
|
packages = ["lib/go/thrift"]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "a5df39032ca206e2e6a9ec975147e81746d9a255"
|
||||||
|
source = "github.com/apache/thrift"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:f6bdf3d8d3cbb2f98d3ebaa66b3ac25166a06830027ece7d592d9ea09dedf504"
|
||||||
|
name = "github.com/GoogleCloudPlatform/microservices-demo"
|
||||||
|
packages = [
|
||||||
|
"src/checkoutservice/genproto",
|
||||||
|
"src/checkoutservice/money",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "33ca3b63d82698035ffc1230dcb650885a005197"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = [
|
packages = [
|
||||||
"proto",
|
"proto",
|
||||||
|
@ -33,41 +55,62 @@
|
||||||
"ptypes/empty",
|
"ptypes/empty",
|
||||||
"ptypes/struct",
|
"ptypes/struct",
|
||||||
"ptypes/timestamp",
|
"ptypes/timestamp",
|
||||||
"ptypes/wrappers"
|
"ptypes/wrappers",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:089d56c0adb79140365b5c86815ce97233986da6f3a525c6b706773e4b83876f"
|
||||||
name = "github.com/google/pprof"
|
name = "github.com/google/pprof"
|
||||||
packages = ["profile"]
|
packages = ["profile"]
|
||||||
revision = "e027b505a088ac3c68c339a1d7ce7724bf34538b"
|
pruneopts = "UT"
|
||||||
|
revision = "985cf9b4fdd2b479e4563ec57352005f69d5f9f6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8"
|
||||||
name = "github.com/google/uuid"
|
name = "github.com/google/uuid"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
|
pruneopts = "UT"
|
||||||
version = "v1.0.0"
|
revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
|
||||||
name = "github.com/googleapis/gax-go"
|
name = "github.com/googleapis/gax-go"
|
||||||
packages = ["."]
|
packages = [
|
||||||
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f"
|
".",
|
||||||
version = "v2.0.0"
|
"v2",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
|
||||||
|
version = "v2.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc"
|
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
|
||||||
|
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||||
|
version = "v1.0.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "3e01752db0189b9157070a0e1668a620f9a85da2"
|
revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
|
||||||
version = "v1.0.6"
|
version = "v1.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
|
||||||
name = "go.opencensus.io"
|
name = "go.opencensus.io"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
"exporter/jaeger",
|
||||||
|
"exporter/jaeger/internal/gen-go/jaeger",
|
||||||
"internal",
|
"internal",
|
||||||
"internal/tagencoding",
|
"internal/tagencoding",
|
||||||
"plugin/ocgrpc",
|
"plugin/ocgrpc",
|
||||||
|
@ -80,21 +123,23 @@
|
||||||
"trace",
|
"trace",
|
||||||
"trace/internal",
|
"trace/internal",
|
||||||
"trace/propagation",
|
"trace/propagation",
|
||||||
"trace/tracestate"
|
"trace/tracestate",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
|
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
|
||||||
version = "v0.16.0"
|
version = "v0.16.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
|
digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ssh/terminal"]
|
packages = ["ssh/terminal"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c"
|
revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:8ecb828bb550a8c6b7d75b8261a42c369461311616ebe5451966d067f5f993bf"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
"context",
|
"context",
|
||||||
|
@ -104,35 +149,46 @@
|
||||||
"http2/hpack",
|
"http2/hpack",
|
||||||
"idna",
|
"idna",
|
||||||
"internal/timeseries",
|
"internal/timeseries",
|
||||||
"trace"
|
"trace",
|
||||||
]
|
]
|
||||||
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2"
|
pruneopts = "UT"
|
||||||
|
revision = "1e06a53dbb7e2ed46e91183f219db23c6943c532"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:23443edff0740e348959763085df98400dcfd85528d7771bb0ce9f5f2754ff4a"
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"google",
|
"google",
|
||||||
"internal",
|
"internal",
|
||||||
"jws",
|
"jws",
|
||||||
"jwt"
|
"jwt",
|
||||||
]
|
]
|
||||||
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9"
|
pruneopts = "UT"
|
||||||
|
revision = "d668ce993890a79bda886613ee587a69dd5da7a6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
|
||||||
name = "golang.org/x/sync"
|
name = "golang.org/x/sync"
|
||||||
packages = ["semaphore"]
|
packages = ["semaphore"]
|
||||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
pruneopts = "UT"
|
||||||
|
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:12ef3ef293a3a3930a82e5f38a3c45a1b03a9ed72dedc192d90e89d59b1f13a5"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = ["unix"]
|
packages = [
|
||||||
revision = "1561086e645b2809fb9f8a1e2a38160bf8d53bf4"
|
"unix",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "7fbe1cd0fcc20051e1fcb87fbabec4a1bacaaeba"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = [
|
packages = [
|
||||||
"collate",
|
"collate",
|
||||||
|
@ -148,13 +204,15 @@
|
||||||
"unicode/bidi",
|
"unicode/bidi",
|
||||||
"unicode/cldr",
|
"unicode/cldr",
|
||||||
"unicode/norm",
|
"unicode/norm",
|
||||||
"unicode/rangetable"
|
"unicode/rangetable",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:b74a0ae8b7755bf9cdadead4dea674d76517cd2fea7bd482a6a46bb6b3ce085b"
|
||||||
name = "google.golang.org/api"
|
name = "google.golang.org/api"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapi/transport",
|
"googleapi/transport",
|
||||||
|
@ -164,11 +222,14 @@
|
||||||
"support/bundler",
|
"support/bundler",
|
||||||
"transport",
|
"transport",
|
||||||
"transport/grpc",
|
"transport/grpc",
|
||||||
"transport/http"
|
"transport/http",
|
||||||
|
"transport/http/internal/propagation",
|
||||||
]
|
]
|
||||||
revision = "19ff8768a5c0b8e46ea281065664787eefc24121"
|
pruneopts = "UT"
|
||||||
|
revision = "032faecc3e7e2c445ec37a1b1ec4e5a3016d96f2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -182,13 +243,15 @@
|
||||||
"internal/socket",
|
"internal/socket",
|
||||||
"internal/urlfetch",
|
"internal/urlfetch",
|
||||||
"socket",
|
"socket",
|
||||||
"urlfetch"
|
"urlfetch",
|
||||||
]
|
]
|
||||||
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06"
|
pruneopts = "UT"
|
||||||
version = "v1.2.0"
|
revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
|
||||||
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
|
||||||
name = "google.golang.org/genproto"
|
name = "google.golang.org/genproto"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapis/api/annotations",
|
"googleapis/api/annotations",
|
||||||
|
@ -201,11 +264,13 @@
|
||||||
"googleapis/monitoring/v3",
|
"googleapis/monitoring/v3",
|
||||||
"googleapis/rpc/errdetails",
|
"googleapis/rpc/errdetails",
|
||||||
"googleapis/rpc/status",
|
"googleapis/rpc/status",
|
||||||
"protobuf/field_mask"
|
"protobuf/field_mask",
|
||||||
]
|
]
|
||||||
revision = "c3f76f3b92d1ffa4c58a9ff842a58b8877655e0f"
|
pruneopts = "UT"
|
||||||
|
revision = "ae2f86662275e140f395167f1dab7081a5bd5fa8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:6497ab07ec89179db8d5a563d33635be04ceffaa29007a3ae74b9f15f4d3068e"
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -235,14 +300,32 @@
|
||||||
"resolver/passthrough",
|
"resolver/passthrough",
|
||||||
"stats",
|
"stats",
|
||||||
"status",
|
"status",
|
||||||
"tap"
|
"tap",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
|
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
|
||||||
version = "v1.14.0"
|
version = "v1.14.0"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "0c103e5e32d8ecdd70048b6d91e02b910e30bad54f06b230a9664f585433a669"
|
input-imports = [
|
||||||
|
"cloud.google.com/go/profiler",
|
||||||
|
"contrib.go.opencensus.io/exporter/stackdriver",
|
||||||
|
"github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/genproto",
|
||||||
|
"github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice/money",
|
||||||
|
"github.com/golang/protobuf/proto",
|
||||||
|
"github.com/google/uuid",
|
||||||
|
"github.com/sirupsen/logrus",
|
||||||
|
"go.opencensus.io/exporter/jaeger",
|
||||||
|
"go.opencensus.io/plugin/ocgrpc",
|
||||||
|
"go.opencensus.io/stats/view",
|
||||||
|
"go.opencensus.io/trace",
|
||||||
|
"golang.org/x/net/context",
|
||||||
|
"google.golang.org/grpc",
|
||||||
|
"google.golang.org/grpc/codes",
|
||||||
|
"google.golang.org/grpc/health/grpc_health_v1",
|
||||||
|
"google.golang.org/grpc/status",
|
||||||
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,7 @@ import (
|
||||||
"contrib.go.opencensus.io/exporter/stackdriver"
|
"contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"go.opencensus.io/exporter/jaeger"
|
||||||
"go.opencensus.io/plugin/ocgrpc"
|
"go.opencensus.io/plugin/ocgrpc"
|
||||||
"go.opencensus.io/stats/view"
|
"go.opencensus.io/stats/view"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
|
@ -98,7 +99,30 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initJaegerTracing() {
|
||||||
|
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
|
||||||
|
if svcAddr == "" {
|
||||||
|
log.Info("jaeger initialization disabled.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the Jaeger exporter to be able to retrieve
|
||||||
|
// the collected spans.
|
||||||
|
exporter, err := jaeger.NewExporter(jaeger.Options{
|
||||||
|
Endpoint: fmt.Sprintf("http://%s", svcAddr),
|
||||||
|
Process: jaeger.Process{
|
||||||
|
ServiceName: "checkoutservice",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
trace.RegisterExporter(exporter)
|
||||||
|
log.Info("jaeger initialization completed.")
|
||||||
|
}
|
||||||
|
|
||||||
func initStats(exporter *stackdriver.Exporter) {
|
func initStats(exporter *stackdriver.Exporter) {
|
||||||
|
view.SetReportingPeriod(60 * time.Second)
|
||||||
view.RegisterExporter(exporter)
|
view.RegisterExporter(exporter)
|
||||||
if err := view.Register(ocgrpc.DefaultServerViews...); err != nil {
|
if err := view.Register(ocgrpc.DefaultServerViews...); err != nil {
|
||||||
log.Warn("Error registering default server views")
|
log.Warn("Error registering default server views")
|
||||||
|
@ -107,7 +131,7 @@ func initStats(exporter *stackdriver.Exporter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTracing() {
|
func initStackDriverTracing() {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
for i := 1; i <= 3; i++ {
|
for i := 1; i <= 3; i++ {
|
||||||
|
@ -116,7 +140,6 @@ func initTracing() {
|
||||||
log.Infof("failed to initialize stackdriver exporter: %+v", err)
|
log.Infof("failed to initialize stackdriver exporter: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
trace.RegisterExporter(exporter)
|
trace.RegisterExporter(exporter)
|
||||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
|
||||||
log.Info("registered stackdriver tracing")
|
log.Info("registered stackdriver tracing")
|
||||||
|
|
||||||
// Register the views to collect server stats.
|
// Register the views to collect server stats.
|
||||||
|
@ -130,6 +153,11 @@ func initTracing() {
|
||||||
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initTracing() {
|
||||||
|
initJaegerTracing()
|
||||||
|
initStackDriverTracing()
|
||||||
|
}
|
||||||
|
|
||||||
func initProfiling(service, version string) {
|
func initProfiling(service, version string) {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
|
|
|
@ -1,10 +1,32 @@
|
||||||
FROM node:8
|
FROM node:8-alpine as base
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
|
||||||
|
FROM base as builder
|
||||||
|
|
||||||
|
# Some packages (e.g. @google-cloud/profiler) require additional
|
||||||
|
# deps for post-install scripts
|
||||||
|
RUN apk add --update --no-cache \
|
||||||
|
python \
|
||||||
|
make \
|
||||||
|
g++
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN npm install --only=production
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
|
||||||
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
chmod +x /bin/grpc_health_probe
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
COPY package*.json ./
|
|
||||||
RUN npm install --only=production
|
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 7000
|
EXPOSE 7000
|
||||||
CMD [ "node", "server.js" ]
|
|
||||||
|
ENTRYPOINT [ "node", "server.js" ]
|
||||||
|
|
|
@ -20,6 +20,7 @@ require('@google-cloud/trace-agent').start();
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
const leftPad = require('left-pad');
|
const leftPad = require('left-pad');
|
||||||
|
const pino = require('pino');
|
||||||
|
|
||||||
const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
|
const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
|
||||||
const PORT = 7000;
|
const PORT = 7000;
|
||||||
|
@ -28,6 +29,13 @@ const shopProto = grpc.load(PROTO_PATH).hipstershop;
|
||||||
const client = new shopProto.CurrencyService(`localhost:${PORT}`,
|
const client = new shopProto.CurrencyService(`localhost:${PORT}`,
|
||||||
grpc.credentials.createInsecure());
|
grpc.credentials.createInsecure());
|
||||||
|
|
||||||
|
const logger = pino({
|
||||||
|
name: 'currencyservice-client',
|
||||||
|
messageKey: 'message',
|
||||||
|
changeLevelName: 'severity',
|
||||||
|
useLevelLabels: true
|
||||||
|
});
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
from: {
|
from: {
|
||||||
currency_code: 'CHF',
|
currency_code: 'CHF',
|
||||||
|
@ -43,16 +51,16 @@ function _moneyToString (m) {
|
||||||
|
|
||||||
client.getSupportedCurrencies({}, (err, response) => {
|
client.getSupportedCurrencies({}, (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`Error in getSupportedCurrencies: ${err}`);
|
logger.error(`Error in getSupportedCurrencies: ${err}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Currency codes: ${response.currency_codes}`);
|
logger.info(`Currency codes: ${response.currency_codes}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
client.convert(request, (err, response) => {
|
client.convert(request, (err, response) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(`Error in convert: ${err}`);
|
logger.error(`Error in convert: ${err}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Convert: ${_moneyToString(request.from)} to ${_moneyToString(response)}`);
|
logger.log(`Convert: ${_moneyToString(request.from)} to ${_moneyToString(response)}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
35
src/currencyservice/data/currency_conversion.json
Normal file
35
src/currencyservice/data/currency_conversion.json
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"EUR": "1.0",
|
||||||
|
"USD": "1.1305",
|
||||||
|
"JPY": "126.40",
|
||||||
|
"BGN": "1.9558",
|
||||||
|
"CZK": "25.592",
|
||||||
|
"DKK": "7.4609",
|
||||||
|
"GBP": "0.85970",
|
||||||
|
"HUF": "315.51",
|
||||||
|
"PLN": "4.2996",
|
||||||
|
"RON": "4.7463",
|
||||||
|
"SEK": "10.5375",
|
||||||
|
"CHF": "1.1360",
|
||||||
|
"ISK": "136.80",
|
||||||
|
"NOK": "9.8040",
|
||||||
|
"HRK": "7.4210",
|
||||||
|
"RUB": "74.4208",
|
||||||
|
"TRY": "6.1247",
|
||||||
|
"AUD": "1.6072",
|
||||||
|
"BRL": "4.2682",
|
||||||
|
"CAD": "1.5128",
|
||||||
|
"CNY": "7.5857",
|
||||||
|
"HKD": "8.8743",
|
||||||
|
"IDR": "15999.40",
|
||||||
|
"ILS": "4.0875",
|
||||||
|
"INR": "79.4320",
|
||||||
|
"KRW": "1275.05",
|
||||||
|
"MXN": "21.7999",
|
||||||
|
"MYR": "4.6289",
|
||||||
|
"NZD": "1.6679",
|
||||||
|
"PHP": "59.083",
|
||||||
|
"SGD": "1.5349",
|
||||||
|
"THB": "36.012",
|
||||||
|
"ZAR": "16.0583"
|
||||||
|
}
|
62
src/currencyservice/package-lock.json
generated
62
src/currencyservice/package-lock.json
generated
|
@ -663,16 +663,36 @@
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||||
},
|
},
|
||||||
|
"fast-json-parse": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw=="
|
||||||
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||||
},
|
},
|
||||||
|
"fast-redact": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-k/uSk9PtFmvYx0m7bRk5B2gZChQk4euWhrn7Mf3vYSmwZBLh7cGNuMuc/vhH1MKMPyVJMMtl9oMwPnwlKqs7CQ=="
|
||||||
|
},
|
||||||
|
"fast-safe-stringify": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
|
||||||
|
},
|
||||||
"findit2": {
|
"findit2": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz",
|
||||||
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY="
|
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY="
|
||||||
},
|
},
|
||||||
|
"flatstr": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-YXblbv/vc1zuVVUtnKl1hPqqk7TalZCppnKE7Pr8FI/Rp48vzckS/4SJ4Y9O9RNiI82Vcw/FydmtqdQOg1Dpqw=="
|
||||||
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz",
|
||||||
|
@ -1570,6 +1590,26 @@
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||||
},
|
},
|
||||||
|
"pino": {
|
||||||
|
"version": "5.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino/-/pino-5.6.2.tgz",
|
||||||
|
"integrity": "sha512-JVMYqJkE58b2u5+t85zJLbUDOhoWDjEQqrRY1eQzuR4Ub9RIyUSQJms4deT8Joy+C/QIdrrie7NffgCm+ao9xw==",
|
||||||
|
"requires": {
|
||||||
|
"fast-json-parse": "^1.0.3",
|
||||||
|
"fast-redact": "^1.2.0",
|
||||||
|
"fast-safe-stringify": "^2.0.6",
|
||||||
|
"flatstr": "^1.0.5",
|
||||||
|
"pino-std-serializers": "^2.2.1",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"quick-format-unescaped": "^3.0.0",
|
||||||
|
"sonic-boom": "^0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pino-std-serializers": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-QqL7kkF7eMCpFG4hpZD8UPQga/kxkkh3E62HzMzTIL4OQyijyisAnBL8msBEAml8xcb/ioGhH7UUzGxuHqczhQ=="
|
||||||
|
},
|
||||||
"pretty-ms": {
|
"pretty-ms": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz",
|
||||||
|
@ -1599,6 +1639,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||||
},
|
},
|
||||||
|
"pump": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||||
|
"requires": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||||
|
@ -1609,6 +1658,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||||
},
|
},
|
||||||
|
"quick-format-unescaped": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-XmIOc07VM2kPm6m3j/U6jgxyUgDm2Rgh2c1PPy0JUHoQRdoh86hOym0bHyF6G1T6sn+N5lildhvl/T59H5KVyA=="
|
||||||
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
|
@ -1706,6 +1760,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz",
|
||||||
"integrity": "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag=="
|
"integrity": "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag=="
|
||||||
},
|
},
|
||||||
|
"sonic-boom": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-3qx6XXDeG+hPNa+jla1H6BMBLcjLl8L8NRERLVeIf/EuPqoqmq4K8owG29Xu7OypT/7/YT/0uKW6YitsKA+nLQ==",
|
||||||
|
"requires": {
|
||||||
|
"flatstr": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
"google-protobuf": "^3.0.0",
|
"google-protobuf": "^3.0.0",
|
||||||
"grpc": "^1.0.0",
|
"grpc": "^1.0.0",
|
||||||
"left-pad": "^1.3.0",
|
"left-pad": "^1.3.0",
|
||||||
|
"pino": "^5.6.2",
|
||||||
"request": "^2.87.0",
|
"request": "^2.87.0",
|
||||||
"xml2js": "^0.4.19"
|
"xml2js": "^0.4.19"
|
||||||
},
|
},
|
||||||
|
|
|
@ -64,6 +64,10 @@ message Product {
|
||||||
string description = 3;
|
string description = 3;
|
||||||
string picture = 4;
|
string picture = 4;
|
||||||
Money price_usd = 5;
|
Money price_usd = 5;
|
||||||
|
|
||||||
|
// Categories such as "vintage" or "gardening" that can be used to look up
|
||||||
|
// other related products.
|
||||||
|
repeated string categories = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductsResponse {
|
message ListProductsResponse {
|
||||||
|
@ -218,18 +222,18 @@ message PlaceOrderResponse {
|
||||||
OrderResult order = 1;
|
OrderResult order = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------Ads service------------------
|
// ------------Ad service------------------
|
||||||
|
|
||||||
service AdsService {
|
service AdService {
|
||||||
rpc GetAds(AdsRequest) returns (AdsResponse) {}
|
rpc GetAds(AdRequest) returns (AdResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdsRequest {
|
message AdRequest {
|
||||||
// List of important key words from the current page describing the context.
|
// List of important key words from the current page describing the context.
|
||||||
repeated string context_keys = 1;
|
repeated string context_keys = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdsResponse {
|
message AdResponse {
|
||||||
repeated Ad ads = 1;
|
repeated Ad ads = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,19 +30,24 @@ require('@google-cloud/debug-agent').start({
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
const request = require('request');
|
const pino = require('pino');
|
||||||
const xml2js = require('xml2js');
|
|
||||||
const protoLoader = require('@grpc/proto-loader');
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
|
||||||
const MAIN_PROTO_PATH = path.join(__dirname, './proto/demo.proto');
|
const MAIN_PROTO_PATH = path.join(__dirname, './proto/demo.proto');
|
||||||
const HEALTH_PROTO_PATH = path.join(__dirname, './proto/grpc/health/v1/health.proto');
|
const HEALTH_PROTO_PATH = path.join(__dirname, './proto/grpc/health/v1/health.proto');
|
||||||
|
|
||||||
const PORT = 7000;
|
const PORT = 7000;
|
||||||
const DATA_URL = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
|
|
||||||
|
|
||||||
const shopProto = _loadProto(MAIN_PROTO_PATH).hipstershop;
|
const shopProto = _loadProto(MAIN_PROTO_PATH).hipstershop;
|
||||||
const healthProto = _loadProto(HEALTH_PROTO_PATH).grpc.health.v1;
|
const healthProto = _loadProto(HEALTH_PROTO_PATH).grpc.health.v1;
|
||||||
|
|
||||||
|
const logger = pino({
|
||||||
|
name: 'currencyservice-server',
|
||||||
|
messageKey: 'message',
|
||||||
|
changeLevelName: 'severity',
|
||||||
|
useLevelLabels: true
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that loads a protobuf file.
|
* Helper function that loads a protobuf file.
|
||||||
*/
|
*/
|
||||||
|
@ -61,36 +66,12 @@ function _loadProto (path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that gets currency data from an XML webpage
|
* Helper function that gets currency data from a stored JSON file
|
||||||
* Uses public data from European Central Bank
|
* Uses public data from European Central Bank
|
||||||
*/
|
*/
|
||||||
let _data;
|
|
||||||
function _getCurrencyData (callback) {
|
function _getCurrencyData (callback) {
|
||||||
if (!_data) {
|
const data = require('./data/currency_conversion.json');
|
||||||
console.log('Fetching currency data...');
|
callback(data);
|
||||||
request(DATA_URL, (err, res) => {
|
|
||||||
if (err) {
|
|
||||||
throw new Error(`Error getting data: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = res.body.split('\n').slice(7, -2).join('\n');
|
|
||||||
xml2js.parseString(body, (err, resJs) => {
|
|
||||||
if (err) {
|
|
||||||
throw new Error(`Error parsing HTML: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const array = resJs['Cube']['Cube'].map(x => x['$']);
|
|
||||||
const results = array.reduce((acc, x) => {
|
|
||||||
acc[x['currency']] = x['rate'];
|
|
||||||
return acc;
|
|
||||||
}, { 'EUR': '1.0' });
|
|
||||||
_data = results;
|
|
||||||
callback(_data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback(_data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +89,7 @@ function _carry (amount) {
|
||||||
* Lists the supported currencies
|
* Lists the supported currencies
|
||||||
*/
|
*/
|
||||||
function getSupportedCurrencies (call, callback) {
|
function getSupportedCurrencies (call, callback) {
|
||||||
console.log('Getting supported currencies...');
|
logger.info('Getting supported currencies...');
|
||||||
_getCurrencyData((data) => {
|
_getCurrencyData((data) => {
|
||||||
callback(null, {currency_codes: Object.keys(data)});
|
callback(null, {currency_codes: Object.keys(data)});
|
||||||
});
|
});
|
||||||
|
@ -118,7 +99,7 @@ function getSupportedCurrencies (call, callback) {
|
||||||
* Converts between currencies
|
* Converts between currencies
|
||||||
*/
|
*/
|
||||||
function convert (call, callback) {
|
function convert (call, callback) {
|
||||||
console.log('received conversion request');
|
logger.info('received conversion request');
|
||||||
try {
|
try {
|
||||||
_getCurrencyData((data) => {
|
_getCurrencyData((data) => {
|
||||||
const request = call.request;
|
const request = call.request;
|
||||||
|
@ -142,12 +123,11 @@ function convert (call, callback) {
|
||||||
result.nanos = Math.floor(result.nanos);
|
result.nanos = Math.floor(result.nanos);
|
||||||
result.currency_code = request.to_code;
|
result.currency_code = request.to_code;
|
||||||
|
|
||||||
console.log(`conversion request successful`);
|
logger.info(`conversion request successful`);
|
||||||
callback(null, result);
|
callback(null, result);
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('conversion request failed.');
|
logger.error(`conversion request failed: ${err}`);
|
||||||
console.error(err);
|
|
||||||
callback(err.message);
|
callback(err.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +144,7 @@ function check (call, callback) {
|
||||||
* CurrencyConverter service at the sample server port
|
* CurrencyConverter service at the sample server port
|
||||||
*/
|
*/
|
||||||
function main () {
|
function main () {
|
||||||
console.log(`Starting gRPC server on port ${PORT}...`);
|
logger.info(`Starting gRPC server on port ${PORT}...`);
|
||||||
const server = new grpc.Server();
|
const server = new grpc.Server();
|
||||||
server.addService(shopProto.CurrencyService.service, {getSupportedCurrencies, convert});
|
server.addService(shopProto.CurrencyService.service, {getSupportedCurrencies, convert});
|
||||||
server.addService(healthProto.Health.service, {check});
|
server.addService(healthProto.Health.service, {check});
|
||||||
|
|
|
@ -1,27 +1,36 @@
|
||||||
|
FROM python:3-slim as base
|
||||||
|
|
||||||
|
FROM base as builder
|
||||||
|
|
||||||
# Use the grpc.io provided Python image as the base image
|
RUN apt-get -qq update \
|
||||||
FROM grpc/python:1.0
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
g++ \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# download the grpc health probe
|
# get packages
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
COPY requirements.txt .
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
FROM base as final
|
||||||
|
# Enable unbuffered logging
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
RUN apt-get -qq update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
wget
|
||||||
|
|
||||||
|
# Download the grpc health probe
|
||||||
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
chmod +x /bin/grpc_health_probe
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
# show python logs as they occur
|
|
||||||
ENV PYTHONUNBUFFERED=0
|
|
||||||
|
|
||||||
# install pip for python3
|
|
||||||
RUN apt-get -qqy update && \
|
|
||||||
apt-get -qqy install python3-pip
|
|
||||||
|
|
||||||
# get packages
|
|
||||||
WORKDIR /email_server
|
WORKDIR /email_server
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip3 install -r requirements.txt
|
# Grab packages from builder
|
||||||
|
COPY --from=builder /usr/local/lib/python3.7/ /usr/local/lib/python3.7/
|
||||||
|
|
||||||
# Add the application
|
# Add the application
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
ENTRYPOINT [ "python3", "email_server.py" ]
|
ENTRYPOINT [ "python", "email_server.py" ]
|
||||||
|
|
|
@ -19,30 +19,33 @@ import grpc
|
||||||
import demo_pb2
|
import demo_pb2
|
||||||
import demo_pb2_grpc
|
import demo_pb2_grpc
|
||||||
|
|
||||||
# from opencensus.trace.tracer import Tracer
|
from logger import getJSONLogger
|
||||||
# from opencensus.trace.exporters import stackdriver_exporter
|
logger = getJSONLogger('emailservice-client')
|
||||||
# from opencensus.trace.ext.grpc import client_interceptor
|
|
||||||
|
|
||||||
# try:
|
from opencensus.trace.tracer import Tracer
|
||||||
# exporter = stackdriver_exporter.StackdriverExporter()
|
from opencensus.trace.exporters import stackdriver_exporter
|
||||||
# tracer = Tracer(exporter=exporter)
|
from opencensus.trace.ext.grpc import client_interceptor
|
||||||
# tracer_interceptor = client_interceptor.OpenCensusClientInterceptor(tracer, host_port='0.0.0.0:8080')
|
|
||||||
# except:
|
try:
|
||||||
# tracer_interceptor = client_interceptor.OpenCensusClientInterceptor()
|
exporter = stackdriver_exporter.StackdriverExporter()
|
||||||
|
tracer = Tracer(exporter=exporter)
|
||||||
|
tracer_interceptor = client_interceptor.OpenCensusClientInterceptor(tracer, host_port='0.0.0.0:8080')
|
||||||
|
except:
|
||||||
|
tracer_interceptor = client_interceptor.OpenCensusClientInterceptor()
|
||||||
|
|
||||||
def send_confirmation_email(email, order):
|
def send_confirmation_email(email, order):
|
||||||
channel = grpc.insecure_channel('0.0.0.0:8080')
|
channel = grpc.insecure_channel('0.0.0.0:8080')
|
||||||
# channel = grpc.intercept_channel(channel, tracer_interceptor)
|
channel = grpc.intercept_channel(channel, tracer_interceptor)
|
||||||
stub = demo_pb2_grpc.EmailServiceStub(channel)
|
stub = demo_pb2_grpc.EmailServiceStub(channel)
|
||||||
try:
|
try:
|
||||||
response = stub.SendOrderConfirmation(demo_pb2.SendOrderConfirmationRequest(
|
response = stub.SendOrderConfirmation(demo_pb2.SendOrderConfirmationRequest(
|
||||||
email = email,
|
email = email,
|
||||||
order = order
|
order = order
|
||||||
))
|
))
|
||||||
print('Request sent.')
|
logger.info('Request sent.')
|
||||||
except grpc.RpcError as err:
|
except grpc.RpcError as err:
|
||||||
print(err.details())
|
logger.error(err.details())
|
||||||
print('{}, {}'.format(err.code().name, err.code().value))
|
logger.error('{}, {}'.format(err.code().name, err.code().value))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print('Client for email service.')
|
logger.info('Client for email service.')
|
||||||
|
|
|
@ -28,19 +28,19 @@ import demo_pb2_grpc
|
||||||
from grpc_health.v1 import health_pb2
|
from grpc_health.v1 import health_pb2
|
||||||
from grpc_health.v1 import health_pb2_grpc
|
from grpc_health.v1 import health_pb2_grpc
|
||||||
|
|
||||||
# from opencensus.trace.ext.grpc import server_interceptor
|
from opencensus.trace.exporters import stackdriver_exporter
|
||||||
# from opencensus.trace.samplers import always_on
|
from opencensus.trace.ext.grpc import server_interceptor
|
||||||
# from opencensus.trace.exporters import stackdriver_exporter
|
from opencensus.trace.samplers import always_on
|
||||||
# from opencensus.trace.exporters import print_exporter
|
|
||||||
|
|
||||||
# import googleclouddebugger
|
# import googleclouddebugger
|
||||||
|
import googlecloudprofiler
|
||||||
|
|
||||||
# try:
|
try:
|
||||||
# sampler = always_on.AlwaysOnSampler()
|
sampler = always_on.AlwaysOnSampler()
|
||||||
# exporter = stackdriver_exporter.StackdriverExporter()
|
exporter = stackdriver_exporter.StackdriverExporter()
|
||||||
# tracer_interceptor = server_interceptor.OpenCensusServerInterceptor(sampler, exporter)
|
tracer_interceptor = server_interceptor.OpenCensusServerInterceptor(sampler, exporter)
|
||||||
# except:
|
except:
|
||||||
# tracer_interceptor = server_interceptor.OpenCensusServerInterceptor()
|
tracer_interceptor = server_interceptor.OpenCensusServerInterceptor()
|
||||||
|
|
||||||
# try:
|
# try:
|
||||||
# googleclouddebugger.enable(
|
# googleclouddebugger.enable(
|
||||||
|
@ -50,6 +50,9 @@ from grpc_health.v1 import health_pb2_grpc
|
||||||
# except:
|
# except:
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
|
from logger import getJSONLogger
|
||||||
|
logger = getJSONLogger('emailservice-server')
|
||||||
|
|
||||||
# Loads confirmation email template from file
|
# Loads confirmation email template from file
|
||||||
env = Environment(
|
env = Environment(
|
||||||
loader=FileSystemLoader('templates'),
|
loader=FileSystemLoader('templates'),
|
||||||
|
@ -85,7 +88,7 @@ class EmailService(BaseEmailService):
|
||||||
"html_body": content
|
"html_body": content
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
print("Message sent: {}".format(response.rfc822_message_id))
|
logger.info("Message sent: {}".format(response.rfc822_message_id))
|
||||||
|
|
||||||
def SendOrderConfirmation(self, request, context):
|
def SendOrderConfirmation(self, request, context):
|
||||||
email = request.email
|
email = request.email
|
||||||
|
@ -95,7 +98,7 @@ class EmailService(BaseEmailService):
|
||||||
confirmation = template.render(order = order)
|
confirmation = template.render(order = order)
|
||||||
except TemplateError as err:
|
except TemplateError as err:
|
||||||
context.set_details("An error occurred when preparing the confirmation mail.")
|
context.set_details("An error occurred when preparing the confirmation mail.")
|
||||||
print(err.message)
|
logger.error(err.message)
|
||||||
context.set_code(grpc.StatusCode.INTERNAL)
|
context.set_code(grpc.StatusCode.INTERNAL)
|
||||||
return demo_pb2.Empty()
|
return demo_pb2.Empty()
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ class EmailService(BaseEmailService):
|
||||||
|
|
||||||
class DummyEmailService(BaseEmailService):
|
class DummyEmailService(BaseEmailService):
|
||||||
def SendOrderConfirmation(self, request, context):
|
def SendOrderConfirmation(self, request, context):
|
||||||
print('A request to send order confirmation email to {} has been received.'.format(request.email))
|
logger.info('A request to send order confirmation email to {} has been received.'.format(request.email))
|
||||||
return demo_pb2.Empty()
|
return demo_pb2.Empty()
|
||||||
|
|
||||||
class HealthCheck():
|
class HealthCheck():
|
||||||
|
@ -120,7 +123,8 @@ class HealthCheck():
|
||||||
status=health_pb2.HealthCheckResponse.SERVING)
|
status=health_pb2.HealthCheckResponse.SERVING)
|
||||||
|
|
||||||
def start(dummy_mode):
|
def start(dummy_mode):
|
||||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))#, interceptors=(tracer_interceptor,))
|
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10),
|
||||||
|
interceptors=(tracer_interceptor,))
|
||||||
service = None
|
service = None
|
||||||
if dummy_mode:
|
if dummy_mode:
|
||||||
service = DummyEmailService()
|
service = DummyEmailService()
|
||||||
|
@ -131,7 +135,7 @@ def start(dummy_mode):
|
||||||
health_pb2_grpc.add_HealthServicer_to_server(service, server)
|
health_pb2_grpc.add_HealthServicer_to_server(service, server)
|
||||||
|
|
||||||
port = os.environ.get('PORT', "8080")
|
port = os.environ.get('PORT', "8080")
|
||||||
print("listening on port: "+port)
|
logger.info("listening on port: "+port)
|
||||||
server.add_insecure_port('[::]:'+port)
|
server.add_insecure_port('[::]:'+port)
|
||||||
server.start()
|
server.start()
|
||||||
try:
|
try:
|
||||||
|
@ -140,7 +144,41 @@ def start(dummy_mode):
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
server.stop(0)
|
server.stop(0)
|
||||||
|
|
||||||
|
def initStackdriverProfiling():
|
||||||
|
project_id = None
|
||||||
|
try:
|
||||||
|
project_id = os.environ["GCP_PROJECT_ID"]
|
||||||
|
except KeyError:
|
||||||
|
# Environment variable not set
|
||||||
|
pass
|
||||||
|
|
||||||
|
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__':
|
if __name__ == '__main__':
|
||||||
print('starting the email service in dummy mode.')
|
logger.info('starting the email service in dummy mode.')
|
||||||
|
try:
|
||||||
|
enable_profiler = os.environ["ENABLE_PROFILER"]
|
||||||
|
if enable_profiler != "1":
|
||||||
|
raise KeyError()
|
||||||
|
else:
|
||||||
|
initStackdriverProfiling()
|
||||||
|
except KeyError:
|
||||||
|
logger.info("Skipping Stackdriver Profiler Python agent initialization. Set environment variable ENABLE_PROFILER=1 to enable.")
|
||||||
|
|
||||||
|
|
||||||
start(dummy_mode = True)
|
start(dummy_mode = True)
|
||||||
|
|
40
src/emailservice/logger.py
Normal file
40
src/emailservice/logger.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/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) (severity) (name) (message)')
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
return logger
|
7
src/emailservice/requirements.in
Normal file
7
src/emailservice/requirements.in
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
google-api-core==1.6.0
|
||||||
|
grpcio-health-checking==1.12.1
|
||||||
|
grpcio==1.16.1
|
||||||
|
jinja2==2.10
|
||||||
|
opencensus[stackdriver]==0.1.10
|
||||||
|
python-json-logger==0.1.9
|
||||||
|
google-cloud-profiler==1.0.8
|
|
@ -1,31 +1,34 @@
|
||||||
cachetools==2.1.0
|
#
|
||||||
certifi==2018.4.16
|
# This file is autogenerated by pip-compile
|
||||||
chardet==3.0.4
|
# To update, run:
|
||||||
cryptography==1.7.1
|
#
|
||||||
google-api-core==1.2.1
|
# pip-compile --output-file requirements.txt requirements.in
|
||||||
google-auth==1.5.0
|
#
|
||||||
google-cloud-core==0.28.1
|
cachetools==3.0.0 # via google-auth
|
||||||
google-cloud-trace==0.19.0
|
certifi==2018.11.29 # via requests
|
||||||
googleapis-common-protos==1.5.3
|
chardet==3.0.4 # via requests
|
||||||
grpc-google-iam-v1==0.11.4
|
google-api-core[grpc]==1.6.0
|
||||||
grpcio==1.12.1
|
google-api-python-client==1.7.8 # via google-cloud-profiler
|
||||||
grpcio-health-checking==1.14.1
|
google-auth-httplib2==0.0.3 # via google-api-python-client, google-cloud-profiler
|
||||||
grpcio-tools==1.12.1
|
google-auth==1.6.2 # via google-api-core, google-api-python-client, google-auth-httplib2, google-cloud-profiler
|
||||||
idna==2.7
|
google-cloud-core==0.29.1 # via google-cloud-trace
|
||||||
Jinja2==2.10
|
google-cloud-profiler==1.0.8
|
||||||
keyring==10.1
|
google-cloud-trace==0.20.2 # via opencensus
|
||||||
keyrings.alt==1.3
|
googleapis-common-protos==1.5.5 # via google-api-core
|
||||||
MarkupSafe==1.0
|
grpcio-health-checking==1.12.1
|
||||||
opencensus==0.1.5
|
grpcio==1.16.1
|
||||||
protobuf==3.6.0
|
httplib2==0.12.1 # via google-api-python-client, google-auth-httplib2
|
||||||
pyasn1==0.4.3
|
idna==2.8 # via requests
|
||||||
pyasn1-modules==0.2.2
|
jinja2==2.10
|
||||||
pycrypto==2.6.1
|
markupsafe==1.1.0 # via jinja2
|
||||||
pygobject==3.22.0
|
opencensus[stackdriver]==0.1.10
|
||||||
pytz==2018.5
|
protobuf==3.6.1 # via google-api-core, google-cloud-profiler, googleapis-common-protos, grpcio-health-checking
|
||||||
pyxdg==0.25
|
pyasn1-modules==0.2.3 # via google-auth
|
||||||
requests==2.19.1
|
pyasn1==0.4.5 # via pyasn1-modules, rsa
|
||||||
rsa==3.4.2
|
python-json-logger==0.1.9
|
||||||
SecretStorage==2.3.1
|
pytz==2018.9 # via google-api-core
|
||||||
six==1.11.0
|
requests==2.21.0 # via google-api-core, google-cloud-profiler
|
||||||
urllib3==1.23
|
rsa==4.0 # via google-auth
|
||||||
|
six==1.12.0 # via google-api-core, google-api-python-client, google-auth, grpcio, protobuf
|
||||||
|
uritemplate==3.0.0 # via google-api-python-client
|
||||||
|
urllib3==1.24.1 # via requests
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.10-alpine as builder
|
FROM golang:1.12-alpine as builder
|
||||||
RUN apk add --no-cache ca-certificates git && \
|
RUN apk add --no-cache ca-certificates git && \
|
||||||
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
||||||
chmod +x /go/bin/dep
|
chmod +x /go/bin/dep
|
||||||
|
|
104
src/frontend/Gopkg.lock
generated
104
src/frontend/Gopkg.lock
generated
|
@ -16,26 +16,32 @@
|
||||||
version = "v0.27.0"
|
version = "v0.27.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:9fe70def8f0ceb3d455a0acad9dadd6632287cdbf9c8c2ea50e8dabe2ade40c4"
|
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
|
||||||
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
packages = [
|
packages = ["."]
|
||||||
".",
|
|
||||||
"propagation",
|
|
||||||
]
|
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
||||||
version = "v0.5.0"
|
version = "v0.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:3ef905a7059a17712b7b27315692992f84f356e828d38f6ff0624e04103ec675"
|
digest = "1:1d8f3cb93c42c5652bb509fde29ecdd1feede9334e355e8bbdc0f9f95b40c254"
|
||||||
|
name = "git.apache.org/thrift.git"
|
||||||
|
packages = ["lib/go/thrift"]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "6503043bc42ab96da14c25f3aee2bb4add719774"
|
||||||
|
source = "github.com/apache/thrift"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:6cbe7676244a1429f4c22601f799d377a70449469ef636f91d992d719b559ff3"
|
||||||
name = "github.com/GoogleCloudPlatform/microservices-demo"
|
name = "github.com/GoogleCloudPlatform/microservices-demo"
|
||||||
packages = [
|
packages = [
|
||||||
"src/frontend/genproto",
|
"src/frontend/genproto",
|
||||||
"src/frontend/money",
|
"src/frontend/money",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "6d969441585ade8c91c235115c7cdb12ac61354f"
|
revision = "d944092100696aa4a5974ef5c2e710547a824622"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
|
digest = "1:72856926f8208767b837bf51e3373f49139f61889b67dc7fd3c2a0fd711e3f7a"
|
||||||
|
@ -61,23 +67,26 @@
|
||||||
name = "github.com/google/pprof"
|
name = "github.com/google/pprof"
|
||||||
packages = ["profile"]
|
packages = ["profile"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "84b7d314e22c8d12334e52726f68517973b6027b"
|
revision = "3ea8567a2e5752420fc544d2e2ad249721768934"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:3a26588bc48b96825977c1b3df964f8fd842cd6860cc26370588d3563433cf11"
|
digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8"
|
||||||
name = "github.com/google/uuid"
|
name = "github.com/google/uuid"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
|
revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
|
||||||
version = "v1.0.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:e145e9710a10bc114a6d3e2738aadf8de146adaa031854ffdf7bbfe15da85e63"
|
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
|
||||||
name = "github.com/googleapis/gax-go"
|
name = "github.com/googleapis/gax-go"
|
||||||
packages = ["."]
|
packages = [
|
||||||
|
".",
|
||||||
|
"v2",
|
||||||
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f"
|
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
|
||||||
version = "v2.0.0"
|
version = "v2.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
||||||
|
@ -95,6 +104,14 @@
|
||||||
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
|
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf"
|
||||||
version = "v1.6.2"
|
version = "v1.6.2"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
|
||||||
|
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||||
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
|
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
|
||||||
name = "github.com/pkg/errors"
|
name = "github.com/pkg/errors"
|
||||||
|
@ -104,18 +121,20 @@
|
||||||
version = "v0.8.0"
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc"
|
digest = "1:69b1cc331fca23d702bd72f860c6a647afd0aa9fcbc1d0659b1365e26546dd70"
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "3e01752db0189b9157070a0e1668a620f9a85da2"
|
revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95"
|
||||||
version = "v1.0.6"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:1bb914cfb78f68f488a91cd7872d3d06a5f83c5bbacf0296dbef44e120b00a91"
|
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
|
||||||
name = "go.opencensus.io"
|
name = "go.opencensus.io"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
"exporter/jaeger",
|
||||||
|
"exporter/jaeger/internal/gen-go/jaeger",
|
||||||
"internal",
|
"internal",
|
||||||
"internal/tagencoding",
|
"internal/tagencoding",
|
||||||
"plugin/ocgrpc",
|
"plugin/ocgrpc",
|
||||||
|
@ -136,15 +155,15 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
|
digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ssh/terminal"]
|
packages = ["ssh/terminal"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c"
|
revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:1c14517b2f106c61d75006199b46a46576058661d469658cb0f90739919641d2"
|
digest = "1:8ecb828bb550a8c6b7d75b8261a42c369461311616ebe5451966d067f5f993bf"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
"context",
|
"context",
|
||||||
|
@ -157,11 +176,11 @@
|
||||||
"trace",
|
"trace",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2"
|
revision = "927f97764cc334a6575f4b7a1584a147864d5723"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:f645667d687fc8bf228865a2c5455824ef05bad08841e673673ef2bb89ac5b90"
|
digest = "1:23443edff0740e348959763085df98400dcfd85528d7771bb0ce9f5f2754ff4a"
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -171,26 +190,26 @@
|
||||||
"jwt",
|
"jwt",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9"
|
revision = "d668ce993890a79bda886613ee587a69dd5da7a6"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a"
|
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
|
||||||
name = "golang.org/x/sync"
|
name = "golang.org/x/sync"
|
||||||
packages = ["semaphore"]
|
packages = ["semaphore"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:374fc90fcb026e9a367e3fad29e988e5dd944b68ca3f24a184d77abc5307dda4"
|
digest = "1:191cccd950a4aeadb60306062f2bdc2f924d750d0156ec6c691b17211bfd7349"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = [
|
packages = [
|
||||||
"unix",
|
"unix",
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "d0be0721c37eeb5299f245a996a483160fc36940"
|
revision = "82a175fd1598e8a172e58ebdf5ed262bb29129e5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||||
|
@ -217,7 +236,7 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:e9e388241f9f0f02000dddaeeb91153d53f0cd09dcec33879cc7e043a2e65d75"
|
digest = "1:2e81813e8e072aa700e101369890e55539729d817d32dbc3fab228d6b40c4d83"
|
||||||
name = "google.golang.org/api"
|
name = "google.golang.org/api"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapi/transport",
|
"googleapi/transport",
|
||||||
|
@ -228,12 +247,13 @@
|
||||||
"transport",
|
"transport",
|
||||||
"transport/grpc",
|
"transport/grpc",
|
||||||
"transport/http",
|
"transport/http",
|
||||||
|
"transport/http/internal/propagation",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "7ca32eb868bf53ea2fc406698eb98583a8073d19"
|
revision = "19e022d8cf43ce81f046bae8cc18c5397cc7732f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:26619fcd2452b4044174d26acd8b09c09dffee9a1c3a22d2383b873aa9a0131f"
|
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -250,12 +270,12 @@
|
||||||
"urlfetch",
|
"urlfetch",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
|
||||||
version = "v1.1.0"
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:7a3da01a8f840fbbef1f027dc091ae52a29c6ab9374e126b6bdc5bf3b0ff2687"
|
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
|
||||||
name = "google.golang.org/genproto"
|
name = "google.golang.org/genproto"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapis/api/annotations",
|
"googleapis/api/annotations",
|
||||||
|
@ -271,28 +291,33 @@
|
||||||
"protobuf/field_mask",
|
"protobuf/field_mask",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "36d5787dc5356b711fe8f3040271aaf51c35955b"
|
revision = "bd9b4fb69e2ffd37621a6caa54dcbead29b546f2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:4ad047d772a7d4841687df9534a767a9e243885ed6d7d2ced6af5995a5dc44b3"
|
digest = "1:3fc54ad826c0183f803bb97e0927dfc05fcb7b7a6ddabed646ee8184d861fa9b"
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"balancer",
|
"balancer",
|
||||||
"balancer/base",
|
"balancer/base",
|
||||||
"balancer/roundrobin",
|
"balancer/roundrobin",
|
||||||
|
"binarylog/grpc_binarylog_v1",
|
||||||
"codes",
|
"codes",
|
||||||
"connectivity",
|
"connectivity",
|
||||||
"credentials",
|
"credentials",
|
||||||
|
"credentials/internal",
|
||||||
"credentials/oauth",
|
"credentials/oauth",
|
||||||
"encoding",
|
"encoding",
|
||||||
"encoding/proto",
|
"encoding/proto",
|
||||||
"grpclog",
|
"grpclog",
|
||||||
"internal",
|
"internal",
|
||||||
"internal/backoff",
|
"internal/backoff",
|
||||||
|
"internal/binarylog",
|
||||||
"internal/channelz",
|
"internal/channelz",
|
||||||
"internal/envconfig",
|
"internal/envconfig",
|
||||||
"internal/grpcrand",
|
"internal/grpcrand",
|
||||||
|
"internal/grpcsync",
|
||||||
|
"internal/syscall",
|
||||||
"internal/transport",
|
"internal/transport",
|
||||||
"keepalive",
|
"keepalive",
|
||||||
"metadata",
|
"metadata",
|
||||||
|
@ -306,8 +331,8 @@
|
||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
|
revision = "df014850f6dee74ba2fc94874043a9f3f75fbfd8"
|
||||||
version = "v1.15.0"
|
version = "v1.17.0"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
|
@ -322,6 +347,7 @@
|
||||||
"github.com/gorilla/mux",
|
"github.com/gorilla/mux",
|
||||||
"github.com/pkg/errors",
|
"github.com/pkg/errors",
|
||||||
"github.com/sirupsen/logrus",
|
"github.com/sirupsen/logrus",
|
||||||
|
"go.opencensus.io/exporter/jaeger",
|
||||||
"go.opencensus.io/plugin/ocgrpc",
|
"go.opencensus.io/plugin/ocgrpc",
|
||||||
"go.opencensus.io/plugin/ochttp",
|
"go.opencensus.io/plugin/ochttp",
|
||||||
"go.opencensus.io/plugin/ochttp/propagation/b3",
|
"go.opencensus.io/plugin/ochttp/propagation/b3",
|
||||||
|
|
|
@ -33,10 +33,6 @@
|
||||||
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/GoogleCloudPlatform/microservices-demo"
|
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
|
|
||||||
package hipstershop
|
package hipstershop
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
import (
|
||||||
import fmt "fmt"
|
fmt "fmt"
|
||||||
import math "math"
|
proto "github.com/golang/protobuf/proto"
|
||||||
|
math "math"
|
||||||
|
)
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "golang.org/x/net/context"
|
context "golang.org/x/net/context"
|
||||||
|
@ -35,16 +37,17 @@ func (m *CartItem) Reset() { *m = CartItem{} }
|
||||||
func (m *CartItem) String() string { return proto.CompactTextString(m) }
|
func (m *CartItem) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CartItem) ProtoMessage() {}
|
func (*CartItem) ProtoMessage() {}
|
||||||
func (*CartItem) Descriptor() ([]byte, []int) {
|
func (*CartItem) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{0}
|
return fileDescriptor_ca53982754088a9d, []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CartItem) XXX_Unmarshal(b []byte) error {
|
func (m *CartItem) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_CartItem.Unmarshal(m, b)
|
return xxx_messageInfo_CartItem.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *CartItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *CartItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_CartItem.Marshal(b, m, deterministic)
|
return xxx_messageInfo_CartItem.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *CartItem) XXX_Merge(src proto.Message) {
|
func (m *CartItem) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_CartItem.Merge(dst, src)
|
xxx_messageInfo_CartItem.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *CartItem) XXX_Size() int {
|
func (m *CartItem) XXX_Size() int {
|
||||||
return xxx_messageInfo_CartItem.Size(m)
|
return xxx_messageInfo_CartItem.Size(m)
|
||||||
|
@ -81,16 +84,17 @@ func (m *AddItemRequest) Reset() { *m = AddItemRequest{} }
|
||||||
func (m *AddItemRequest) String() string { return proto.CompactTextString(m) }
|
func (m *AddItemRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*AddItemRequest) ProtoMessage() {}
|
func (*AddItemRequest) ProtoMessage() {}
|
||||||
func (*AddItemRequest) Descriptor() ([]byte, []int) {
|
func (*AddItemRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{1}
|
return fileDescriptor_ca53982754088a9d, []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AddItemRequest) XXX_Unmarshal(b []byte) error {
|
func (m *AddItemRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_AddItemRequest.Unmarshal(m, b)
|
return xxx_messageInfo_AddItemRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *AddItemRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *AddItemRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_AddItemRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_AddItemRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *AddItemRequest) XXX_Merge(src proto.Message) {
|
func (m *AddItemRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_AddItemRequest.Merge(dst, src)
|
xxx_messageInfo_AddItemRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *AddItemRequest) XXX_Size() int {
|
func (m *AddItemRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_AddItemRequest.Size(m)
|
return xxx_messageInfo_AddItemRequest.Size(m)
|
||||||
|
@ -126,16 +130,17 @@ func (m *EmptyCartRequest) Reset() { *m = EmptyCartRequest{} }
|
||||||
func (m *EmptyCartRequest) String() string { return proto.CompactTextString(m) }
|
func (m *EmptyCartRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*EmptyCartRequest) ProtoMessage() {}
|
func (*EmptyCartRequest) ProtoMessage() {}
|
||||||
func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
|
func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{2}
|
return fileDescriptor_ca53982754088a9d, []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *EmptyCartRequest) XXX_Unmarshal(b []byte) error {
|
func (m *EmptyCartRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_EmptyCartRequest.Unmarshal(m, b)
|
return xxx_messageInfo_EmptyCartRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *EmptyCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *EmptyCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_EmptyCartRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_EmptyCartRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *EmptyCartRequest) XXX_Merge(src proto.Message) {
|
func (m *EmptyCartRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_EmptyCartRequest.Merge(dst, src)
|
xxx_messageInfo_EmptyCartRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *EmptyCartRequest) XXX_Size() int {
|
func (m *EmptyCartRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_EmptyCartRequest.Size(m)
|
return xxx_messageInfo_EmptyCartRequest.Size(m)
|
||||||
|
@ -164,16 +169,17 @@ func (m *GetCartRequest) Reset() { *m = GetCartRequest{} }
|
||||||
func (m *GetCartRequest) String() string { return proto.CompactTextString(m) }
|
func (m *GetCartRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GetCartRequest) ProtoMessage() {}
|
func (*GetCartRequest) ProtoMessage() {}
|
||||||
func (*GetCartRequest) Descriptor() ([]byte, []int) {
|
func (*GetCartRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{3}
|
return fileDescriptor_ca53982754088a9d, []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GetCartRequest) XXX_Unmarshal(b []byte) error {
|
func (m *GetCartRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_GetCartRequest.Unmarshal(m, b)
|
return xxx_messageInfo_GetCartRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *GetCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *GetCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_GetCartRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_GetCartRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *GetCartRequest) XXX_Merge(src proto.Message) {
|
func (m *GetCartRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_GetCartRequest.Merge(dst, src)
|
xxx_messageInfo_GetCartRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *GetCartRequest) XXX_Size() int {
|
func (m *GetCartRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_GetCartRequest.Size(m)
|
return xxx_messageInfo_GetCartRequest.Size(m)
|
||||||
|
@ -203,16 +209,17 @@ func (m *Cart) Reset() { *m = Cart{} }
|
||||||
func (m *Cart) String() string { return proto.CompactTextString(m) }
|
func (m *Cart) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Cart) ProtoMessage() {}
|
func (*Cart) ProtoMessage() {}
|
||||||
func (*Cart) Descriptor() ([]byte, []int) {
|
func (*Cart) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{4}
|
return fileDescriptor_ca53982754088a9d, []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Cart) XXX_Unmarshal(b []byte) error {
|
func (m *Cart) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Cart.Unmarshal(m, b)
|
return xxx_messageInfo_Cart.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Cart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Cart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Cart.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Cart.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Cart) XXX_Merge(src proto.Message) {
|
func (m *Cart) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Cart.Merge(dst, src)
|
xxx_messageInfo_Cart.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Cart) XXX_Size() int {
|
func (m *Cart) XXX_Size() int {
|
||||||
return xxx_messageInfo_Cart.Size(m)
|
return xxx_messageInfo_Cart.Size(m)
|
||||||
|
@ -247,16 +254,17 @@ func (m *Empty) Reset() { *m = Empty{} }
|
||||||
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Empty) ProtoMessage() {}
|
func (*Empty) ProtoMessage() {}
|
||||||
func (*Empty) Descriptor() ([]byte, []int) {
|
func (*Empty) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{5}
|
return fileDescriptor_ca53982754088a9d, []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Empty) XXX_Unmarshal(b []byte) error {
|
func (m *Empty) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Empty.Unmarshal(m, b)
|
return xxx_messageInfo_Empty.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Empty) XXX_Merge(src proto.Message) {
|
func (m *Empty) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Empty.Merge(dst, src)
|
xxx_messageInfo_Empty.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Empty) XXX_Size() int {
|
func (m *Empty) XXX_Size() int {
|
||||||
return xxx_messageInfo_Empty.Size(m)
|
return xxx_messageInfo_Empty.Size(m)
|
||||||
|
@ -279,16 +287,17 @@ func (m *ListRecommendationsRequest) Reset() { *m = ListRecommendationsR
|
||||||
func (m *ListRecommendationsRequest) String() string { return proto.CompactTextString(m) }
|
func (m *ListRecommendationsRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListRecommendationsRequest) ProtoMessage() {}
|
func (*ListRecommendationsRequest) ProtoMessage() {}
|
||||||
func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
|
func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{6}
|
return fileDescriptor_ca53982754088a9d, []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ListRecommendationsRequest) XXX_Unmarshal(b []byte) error {
|
func (m *ListRecommendationsRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ListRecommendationsRequest.Unmarshal(m, b)
|
return xxx_messageInfo_ListRecommendationsRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ListRecommendationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ListRecommendationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ListRecommendationsRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ListRecommendationsRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ListRecommendationsRequest) XXX_Merge(src proto.Message) {
|
func (m *ListRecommendationsRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ListRecommendationsRequest.Merge(dst, src)
|
xxx_messageInfo_ListRecommendationsRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ListRecommendationsRequest) XXX_Size() int {
|
func (m *ListRecommendationsRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_ListRecommendationsRequest.Size(m)
|
return xxx_messageInfo_ListRecommendationsRequest.Size(m)
|
||||||
|
@ -324,16 +333,17 @@ func (m *ListRecommendationsResponse) Reset() { *m = ListRecommendations
|
||||||
func (m *ListRecommendationsResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ListRecommendationsResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListRecommendationsResponse) ProtoMessage() {}
|
func (*ListRecommendationsResponse) ProtoMessage() {}
|
||||||
func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
|
func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{7}
|
return fileDescriptor_ca53982754088a9d, []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ListRecommendationsResponse) XXX_Unmarshal(b []byte) error {
|
func (m *ListRecommendationsResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ListRecommendationsResponse.Unmarshal(m, b)
|
return xxx_messageInfo_ListRecommendationsResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ListRecommendationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ListRecommendationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ListRecommendationsResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ListRecommendationsResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ListRecommendationsResponse) XXX_Merge(src proto.Message) {
|
func (m *ListRecommendationsResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ListRecommendationsResponse.Merge(dst, src)
|
xxx_messageInfo_ListRecommendationsResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ListRecommendationsResponse) XXX_Size() int {
|
func (m *ListRecommendationsResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_ListRecommendationsResponse.Size(m)
|
return xxx_messageInfo_ListRecommendationsResponse.Size(m)
|
||||||
|
@ -357,6 +367,9 @@ type Product struct {
|
||||||
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
|
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
|
||||||
Picture string `protobuf:"bytes,4,opt,name=picture,proto3" json:"picture,omitempty"`
|
Picture string `protobuf:"bytes,4,opt,name=picture,proto3" json:"picture,omitempty"`
|
||||||
PriceUsd *Money `protobuf:"bytes,5,opt,name=price_usd,json=priceUsd,proto3" json:"price_usd,omitempty"`
|
PriceUsd *Money `protobuf:"bytes,5,opt,name=price_usd,json=priceUsd,proto3" json:"price_usd,omitempty"`
|
||||||
|
// Categories such as "vintage" or "gardening" that can be used to look up
|
||||||
|
// other related products.
|
||||||
|
Categories []string `protobuf:"bytes,6,rep,name=categories,proto3" json:"categories,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
XXX_unrecognized []byte `json:"-"`
|
XXX_unrecognized []byte `json:"-"`
|
||||||
XXX_sizecache int32 `json:"-"`
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
@ -366,16 +379,17 @@ func (m *Product) Reset() { *m = Product{} }
|
||||||
func (m *Product) String() string { return proto.CompactTextString(m) }
|
func (m *Product) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Product) ProtoMessage() {}
|
func (*Product) ProtoMessage() {}
|
||||||
func (*Product) Descriptor() ([]byte, []int) {
|
func (*Product) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{8}
|
return fileDescriptor_ca53982754088a9d, []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Product) XXX_Unmarshal(b []byte) error {
|
func (m *Product) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Product.Unmarshal(m, b)
|
return xxx_messageInfo_Product.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Product) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Product) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Product.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Product.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Product) XXX_Merge(src proto.Message) {
|
func (m *Product) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Product.Merge(dst, src)
|
xxx_messageInfo_Product.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Product) XXX_Size() int {
|
func (m *Product) XXX_Size() int {
|
||||||
return xxx_messageInfo_Product.Size(m)
|
return xxx_messageInfo_Product.Size(m)
|
||||||
|
@ -421,6 +435,13 @@ func (m *Product) GetPriceUsd() *Money {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Product) GetCategories() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Categories
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ListProductsResponse struct {
|
type ListProductsResponse struct {
|
||||||
Products []*Product `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"`
|
Products []*Product `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"`
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
@ -432,16 +453,17 @@ func (m *ListProductsResponse) Reset() { *m = ListProductsResponse{} }
|
||||||
func (m *ListProductsResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ListProductsResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListProductsResponse) ProtoMessage() {}
|
func (*ListProductsResponse) ProtoMessage() {}
|
||||||
func (*ListProductsResponse) Descriptor() ([]byte, []int) {
|
func (*ListProductsResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{9}
|
return fileDescriptor_ca53982754088a9d, []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ListProductsResponse) XXX_Unmarshal(b []byte) error {
|
func (m *ListProductsResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ListProductsResponse.Unmarshal(m, b)
|
return xxx_messageInfo_ListProductsResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ListProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ListProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ListProductsResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ListProductsResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ListProductsResponse) XXX_Merge(src proto.Message) {
|
func (m *ListProductsResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ListProductsResponse.Merge(dst, src)
|
xxx_messageInfo_ListProductsResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ListProductsResponse) XXX_Size() int {
|
func (m *ListProductsResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_ListProductsResponse.Size(m)
|
return xxx_messageInfo_ListProductsResponse.Size(m)
|
||||||
|
@ -470,16 +492,17 @@ func (m *GetProductRequest) Reset() { *m = GetProductRequest{} }
|
||||||
func (m *GetProductRequest) String() string { return proto.CompactTextString(m) }
|
func (m *GetProductRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GetProductRequest) ProtoMessage() {}
|
func (*GetProductRequest) ProtoMessage() {}
|
||||||
func (*GetProductRequest) Descriptor() ([]byte, []int) {
|
func (*GetProductRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{10}
|
return fileDescriptor_ca53982754088a9d, []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GetProductRequest) XXX_Unmarshal(b []byte) error {
|
func (m *GetProductRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_GetProductRequest.Unmarshal(m, b)
|
return xxx_messageInfo_GetProductRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *GetProductRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *GetProductRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_GetProductRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_GetProductRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *GetProductRequest) XXX_Merge(src proto.Message) {
|
func (m *GetProductRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_GetProductRequest.Merge(dst, src)
|
xxx_messageInfo_GetProductRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *GetProductRequest) XXX_Size() int {
|
func (m *GetProductRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_GetProductRequest.Size(m)
|
return xxx_messageInfo_GetProductRequest.Size(m)
|
||||||
|
@ -508,16 +531,17 @@ func (m *SearchProductsRequest) Reset() { *m = SearchProductsRequest{} }
|
||||||
func (m *SearchProductsRequest) String() string { return proto.CompactTextString(m) }
|
func (m *SearchProductsRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SearchProductsRequest) ProtoMessage() {}
|
func (*SearchProductsRequest) ProtoMessage() {}
|
||||||
func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
|
func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{11}
|
return fileDescriptor_ca53982754088a9d, []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SearchProductsRequest) XXX_Unmarshal(b []byte) error {
|
func (m *SearchProductsRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_SearchProductsRequest.Unmarshal(m, b)
|
return xxx_messageInfo_SearchProductsRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *SearchProductsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *SearchProductsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_SearchProductsRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_SearchProductsRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *SearchProductsRequest) XXX_Merge(src proto.Message) {
|
func (m *SearchProductsRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_SearchProductsRequest.Merge(dst, src)
|
xxx_messageInfo_SearchProductsRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *SearchProductsRequest) XXX_Size() int {
|
func (m *SearchProductsRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_SearchProductsRequest.Size(m)
|
return xxx_messageInfo_SearchProductsRequest.Size(m)
|
||||||
|
@ -546,16 +570,17 @@ func (m *SearchProductsResponse) Reset() { *m = SearchProductsResponse{}
|
||||||
func (m *SearchProductsResponse) String() string { return proto.CompactTextString(m) }
|
func (m *SearchProductsResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SearchProductsResponse) ProtoMessage() {}
|
func (*SearchProductsResponse) ProtoMessage() {}
|
||||||
func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
|
func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{12}
|
return fileDescriptor_ca53982754088a9d, []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SearchProductsResponse) XXX_Unmarshal(b []byte) error {
|
func (m *SearchProductsResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_SearchProductsResponse.Unmarshal(m, b)
|
return xxx_messageInfo_SearchProductsResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *SearchProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *SearchProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_SearchProductsResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_SearchProductsResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *SearchProductsResponse) XXX_Merge(src proto.Message) {
|
func (m *SearchProductsResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_SearchProductsResponse.Merge(dst, src)
|
xxx_messageInfo_SearchProductsResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *SearchProductsResponse) XXX_Size() int {
|
func (m *SearchProductsResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_SearchProductsResponse.Size(m)
|
return xxx_messageInfo_SearchProductsResponse.Size(m)
|
||||||
|
@ -585,16 +610,17 @@ func (m *GetQuoteRequest) Reset() { *m = GetQuoteRequest{} }
|
||||||
func (m *GetQuoteRequest) String() string { return proto.CompactTextString(m) }
|
func (m *GetQuoteRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GetQuoteRequest) ProtoMessage() {}
|
func (*GetQuoteRequest) ProtoMessage() {}
|
||||||
func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
|
func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{13}
|
return fileDescriptor_ca53982754088a9d, []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GetQuoteRequest) XXX_Unmarshal(b []byte) error {
|
func (m *GetQuoteRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_GetQuoteRequest.Unmarshal(m, b)
|
return xxx_messageInfo_GetQuoteRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *GetQuoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *GetQuoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_GetQuoteRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_GetQuoteRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *GetQuoteRequest) XXX_Merge(src proto.Message) {
|
func (m *GetQuoteRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_GetQuoteRequest.Merge(dst, src)
|
xxx_messageInfo_GetQuoteRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *GetQuoteRequest) XXX_Size() int {
|
func (m *GetQuoteRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_GetQuoteRequest.Size(m)
|
return xxx_messageInfo_GetQuoteRequest.Size(m)
|
||||||
|
@ -630,16 +656,17 @@ func (m *GetQuoteResponse) Reset() { *m = GetQuoteResponse{} }
|
||||||
func (m *GetQuoteResponse) String() string { return proto.CompactTextString(m) }
|
func (m *GetQuoteResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GetQuoteResponse) ProtoMessage() {}
|
func (*GetQuoteResponse) ProtoMessage() {}
|
||||||
func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
|
func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{14}
|
return fileDescriptor_ca53982754088a9d, []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GetQuoteResponse) XXX_Unmarshal(b []byte) error {
|
func (m *GetQuoteResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_GetQuoteResponse.Unmarshal(m, b)
|
return xxx_messageInfo_GetQuoteResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *GetQuoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *GetQuoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_GetQuoteResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_GetQuoteResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *GetQuoteResponse) XXX_Merge(src proto.Message) {
|
func (m *GetQuoteResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_GetQuoteResponse.Merge(dst, src)
|
xxx_messageInfo_GetQuoteResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *GetQuoteResponse) XXX_Size() int {
|
func (m *GetQuoteResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_GetQuoteResponse.Size(m)
|
return xxx_messageInfo_GetQuoteResponse.Size(m)
|
||||||
|
@ -669,16 +696,17 @@ func (m *ShipOrderRequest) Reset() { *m = ShipOrderRequest{} }
|
||||||
func (m *ShipOrderRequest) String() string { return proto.CompactTextString(m) }
|
func (m *ShipOrderRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ShipOrderRequest) ProtoMessage() {}
|
func (*ShipOrderRequest) ProtoMessage() {}
|
||||||
func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
|
func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{15}
|
return fileDescriptor_ca53982754088a9d, []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ShipOrderRequest) XXX_Unmarshal(b []byte) error {
|
func (m *ShipOrderRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ShipOrderRequest.Unmarshal(m, b)
|
return xxx_messageInfo_ShipOrderRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ShipOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ShipOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ShipOrderRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ShipOrderRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ShipOrderRequest) XXX_Merge(src proto.Message) {
|
func (m *ShipOrderRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ShipOrderRequest.Merge(dst, src)
|
xxx_messageInfo_ShipOrderRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ShipOrderRequest) XXX_Size() int {
|
func (m *ShipOrderRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_ShipOrderRequest.Size(m)
|
return xxx_messageInfo_ShipOrderRequest.Size(m)
|
||||||
|
@ -714,16 +742,17 @@ func (m *ShipOrderResponse) Reset() { *m = ShipOrderResponse{} }
|
||||||
func (m *ShipOrderResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ShipOrderResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ShipOrderResponse) ProtoMessage() {}
|
func (*ShipOrderResponse) ProtoMessage() {}
|
||||||
func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
|
func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{16}
|
return fileDescriptor_ca53982754088a9d, []int{16}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ShipOrderResponse) XXX_Unmarshal(b []byte) error {
|
func (m *ShipOrderResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ShipOrderResponse.Unmarshal(m, b)
|
return xxx_messageInfo_ShipOrderResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ShipOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ShipOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ShipOrderResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ShipOrderResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ShipOrderResponse) XXX_Merge(src proto.Message) {
|
func (m *ShipOrderResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ShipOrderResponse.Merge(dst, src)
|
xxx_messageInfo_ShipOrderResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ShipOrderResponse) XXX_Size() int {
|
func (m *ShipOrderResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_ShipOrderResponse.Size(m)
|
return xxx_messageInfo_ShipOrderResponse.Size(m)
|
||||||
|
@ -756,16 +785,17 @@ func (m *Address) Reset() { *m = Address{} }
|
||||||
func (m *Address) String() string { return proto.CompactTextString(m) }
|
func (m *Address) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Address) ProtoMessage() {}
|
func (*Address) ProtoMessage() {}
|
||||||
func (*Address) Descriptor() ([]byte, []int) {
|
func (*Address) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{17}
|
return fileDescriptor_ca53982754088a9d, []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Address) XXX_Unmarshal(b []byte) error {
|
func (m *Address) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Address.Unmarshal(m, b)
|
return xxx_messageInfo_Address.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Address.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Address.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Address) XXX_Merge(src proto.Message) {
|
func (m *Address) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Address.Merge(dst, src)
|
xxx_messageInfo_Address.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Address) XXX_Size() int {
|
func (m *Address) XXX_Size() int {
|
||||||
return xxx_messageInfo_Address.Size(m)
|
return xxx_messageInfo_Address.Size(m)
|
||||||
|
@ -834,16 +864,17 @@ func (m *Money) Reset() { *m = Money{} }
|
||||||
func (m *Money) String() string { return proto.CompactTextString(m) }
|
func (m *Money) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Money) ProtoMessage() {}
|
func (*Money) ProtoMessage() {}
|
||||||
func (*Money) Descriptor() ([]byte, []int) {
|
func (*Money) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{18}
|
return fileDescriptor_ca53982754088a9d, []int{18}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Money) XXX_Unmarshal(b []byte) error {
|
func (m *Money) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Money.Unmarshal(m, b)
|
return xxx_messageInfo_Money.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Money) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Money) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Money.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Money.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Money) XXX_Merge(src proto.Message) {
|
func (m *Money) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Money.Merge(dst, src)
|
xxx_messageInfo_Money.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Money) XXX_Size() int {
|
func (m *Money) XXX_Size() int {
|
||||||
return xxx_messageInfo_Money.Size(m)
|
return xxx_messageInfo_Money.Size(m)
|
||||||
|
@ -887,16 +918,17 @@ func (m *GetSupportedCurrenciesResponse) Reset() { *m = GetSupportedCurr
|
||||||
func (m *GetSupportedCurrenciesResponse) String() string { return proto.CompactTextString(m) }
|
func (m *GetSupportedCurrenciesResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
|
func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
|
||||||
func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
|
func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{19}
|
return fileDescriptor_ca53982754088a9d, []int{19}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *GetSupportedCurrenciesResponse) XXX_Unmarshal(b []byte) error {
|
func (m *GetSupportedCurrenciesResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_GetSupportedCurrenciesResponse.Unmarshal(m, b)
|
return xxx_messageInfo_GetSupportedCurrenciesResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *GetSupportedCurrenciesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *GetSupportedCurrenciesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_GetSupportedCurrenciesResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_GetSupportedCurrenciesResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *GetSupportedCurrenciesResponse) XXX_Merge(src proto.Message) {
|
func (m *GetSupportedCurrenciesResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_GetSupportedCurrenciesResponse.Merge(dst, src)
|
xxx_messageInfo_GetSupportedCurrenciesResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *GetSupportedCurrenciesResponse) XXX_Size() int {
|
func (m *GetSupportedCurrenciesResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_GetSupportedCurrenciesResponse.Size(m)
|
return xxx_messageInfo_GetSupportedCurrenciesResponse.Size(m)
|
||||||
|
@ -927,16 +959,17 @@ func (m *CurrencyConversionRequest) Reset() { *m = CurrencyConversionReq
|
||||||
func (m *CurrencyConversionRequest) String() string { return proto.CompactTextString(m) }
|
func (m *CurrencyConversionRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CurrencyConversionRequest) ProtoMessage() {}
|
func (*CurrencyConversionRequest) ProtoMessage() {}
|
||||||
func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
|
func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{20}
|
return fileDescriptor_ca53982754088a9d, []int{20}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CurrencyConversionRequest) XXX_Unmarshal(b []byte) error {
|
func (m *CurrencyConversionRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_CurrencyConversionRequest.Unmarshal(m, b)
|
return xxx_messageInfo_CurrencyConversionRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *CurrencyConversionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *CurrencyConversionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_CurrencyConversionRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_CurrencyConversionRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *CurrencyConversionRequest) XXX_Merge(src proto.Message) {
|
func (m *CurrencyConversionRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_CurrencyConversionRequest.Merge(dst, src)
|
xxx_messageInfo_CurrencyConversionRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *CurrencyConversionRequest) XXX_Size() int {
|
func (m *CurrencyConversionRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_CurrencyConversionRequest.Size(m)
|
return xxx_messageInfo_CurrencyConversionRequest.Size(m)
|
||||||
|
@ -975,16 +1008,17 @@ func (m *CreditCardInfo) Reset() { *m = CreditCardInfo{} }
|
||||||
func (m *CreditCardInfo) String() string { return proto.CompactTextString(m) }
|
func (m *CreditCardInfo) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CreditCardInfo) ProtoMessage() {}
|
func (*CreditCardInfo) ProtoMessage() {}
|
||||||
func (*CreditCardInfo) Descriptor() ([]byte, []int) {
|
func (*CreditCardInfo) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{21}
|
return fileDescriptor_ca53982754088a9d, []int{21}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CreditCardInfo) XXX_Unmarshal(b []byte) error {
|
func (m *CreditCardInfo) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_CreditCardInfo.Unmarshal(m, b)
|
return xxx_messageInfo_CreditCardInfo.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *CreditCardInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *CreditCardInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_CreditCardInfo.Marshal(b, m, deterministic)
|
return xxx_messageInfo_CreditCardInfo.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *CreditCardInfo) XXX_Merge(src proto.Message) {
|
func (m *CreditCardInfo) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_CreditCardInfo.Merge(dst, src)
|
xxx_messageInfo_CreditCardInfo.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *CreditCardInfo) XXX_Size() int {
|
func (m *CreditCardInfo) XXX_Size() int {
|
||||||
return xxx_messageInfo_CreditCardInfo.Size(m)
|
return xxx_messageInfo_CreditCardInfo.Size(m)
|
||||||
|
@ -1035,16 +1069,17 @@ func (m *ChargeRequest) Reset() { *m = ChargeRequest{} }
|
||||||
func (m *ChargeRequest) String() string { return proto.CompactTextString(m) }
|
func (m *ChargeRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ChargeRequest) ProtoMessage() {}
|
func (*ChargeRequest) ProtoMessage() {}
|
||||||
func (*ChargeRequest) Descriptor() ([]byte, []int) {
|
func (*ChargeRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{22}
|
return fileDescriptor_ca53982754088a9d, []int{22}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ChargeRequest) XXX_Unmarshal(b []byte) error {
|
func (m *ChargeRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ChargeRequest.Unmarshal(m, b)
|
return xxx_messageInfo_ChargeRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ChargeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ChargeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ChargeRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ChargeRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ChargeRequest) XXX_Merge(src proto.Message) {
|
func (m *ChargeRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ChargeRequest.Merge(dst, src)
|
xxx_messageInfo_ChargeRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ChargeRequest) XXX_Size() int {
|
func (m *ChargeRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_ChargeRequest.Size(m)
|
return xxx_messageInfo_ChargeRequest.Size(m)
|
||||||
|
@ -1080,16 +1115,17 @@ func (m *ChargeResponse) Reset() { *m = ChargeResponse{} }
|
||||||
func (m *ChargeResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ChargeResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ChargeResponse) ProtoMessage() {}
|
func (*ChargeResponse) ProtoMessage() {}
|
||||||
func (*ChargeResponse) Descriptor() ([]byte, []int) {
|
func (*ChargeResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{23}
|
return fileDescriptor_ca53982754088a9d, []int{23}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ChargeResponse) XXX_Unmarshal(b []byte) error {
|
func (m *ChargeResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_ChargeResponse.Unmarshal(m, b)
|
return xxx_messageInfo_ChargeResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *ChargeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *ChargeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_ChargeResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_ChargeResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *ChargeResponse) XXX_Merge(src proto.Message) {
|
func (m *ChargeResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_ChargeResponse.Merge(dst, src)
|
xxx_messageInfo_ChargeResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *ChargeResponse) XXX_Size() int {
|
func (m *ChargeResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_ChargeResponse.Size(m)
|
return xxx_messageInfo_ChargeResponse.Size(m)
|
||||||
|
@ -1119,16 +1155,17 @@ func (m *OrderItem) Reset() { *m = OrderItem{} }
|
||||||
func (m *OrderItem) String() string { return proto.CompactTextString(m) }
|
func (m *OrderItem) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OrderItem) ProtoMessage() {}
|
func (*OrderItem) ProtoMessage() {}
|
||||||
func (*OrderItem) Descriptor() ([]byte, []int) {
|
func (*OrderItem) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{24}
|
return fileDescriptor_ca53982754088a9d, []int{24}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *OrderItem) XXX_Unmarshal(b []byte) error {
|
func (m *OrderItem) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_OrderItem.Unmarshal(m, b)
|
return xxx_messageInfo_OrderItem.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *OrderItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *OrderItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_OrderItem.Marshal(b, m, deterministic)
|
return xxx_messageInfo_OrderItem.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *OrderItem) XXX_Merge(src proto.Message) {
|
func (m *OrderItem) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_OrderItem.Merge(dst, src)
|
xxx_messageInfo_OrderItem.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *OrderItem) XXX_Size() int {
|
func (m *OrderItem) XXX_Size() int {
|
||||||
return xxx_messageInfo_OrderItem.Size(m)
|
return xxx_messageInfo_OrderItem.Size(m)
|
||||||
|
@ -1168,16 +1205,17 @@ func (m *OrderResult) Reset() { *m = OrderResult{} }
|
||||||
func (m *OrderResult) String() string { return proto.CompactTextString(m) }
|
func (m *OrderResult) String() string { return proto.CompactTextString(m) }
|
||||||
func (*OrderResult) ProtoMessage() {}
|
func (*OrderResult) ProtoMessage() {}
|
||||||
func (*OrderResult) Descriptor() ([]byte, []int) {
|
func (*OrderResult) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{25}
|
return fileDescriptor_ca53982754088a9d, []int{25}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *OrderResult) XXX_Unmarshal(b []byte) error {
|
func (m *OrderResult) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_OrderResult.Unmarshal(m, b)
|
return xxx_messageInfo_OrderResult.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *OrderResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *OrderResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_OrderResult.Marshal(b, m, deterministic)
|
return xxx_messageInfo_OrderResult.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *OrderResult) XXX_Merge(src proto.Message) {
|
func (m *OrderResult) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_OrderResult.Merge(dst, src)
|
xxx_messageInfo_OrderResult.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *OrderResult) XXX_Size() int {
|
func (m *OrderResult) XXX_Size() int {
|
||||||
return xxx_messageInfo_OrderResult.Size(m)
|
return xxx_messageInfo_OrderResult.Size(m)
|
||||||
|
@ -1235,16 +1273,17 @@ func (m *SendOrderConfirmationRequest) Reset() { *m = SendOrderConfirmat
|
||||||
func (m *SendOrderConfirmationRequest) String() string { return proto.CompactTextString(m) }
|
func (m *SendOrderConfirmationRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SendOrderConfirmationRequest) ProtoMessage() {}
|
func (*SendOrderConfirmationRequest) ProtoMessage() {}
|
||||||
func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
|
func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{26}
|
return fileDescriptor_ca53982754088a9d, []int{26}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SendOrderConfirmationRequest) XXX_Unmarshal(b []byte) error {
|
func (m *SendOrderConfirmationRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_SendOrderConfirmationRequest.Unmarshal(m, b)
|
return xxx_messageInfo_SendOrderConfirmationRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *SendOrderConfirmationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *SendOrderConfirmationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_SendOrderConfirmationRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_SendOrderConfirmationRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *SendOrderConfirmationRequest) XXX_Merge(src proto.Message) {
|
func (m *SendOrderConfirmationRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_SendOrderConfirmationRequest.Merge(dst, src)
|
xxx_messageInfo_SendOrderConfirmationRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *SendOrderConfirmationRequest) XXX_Size() int {
|
func (m *SendOrderConfirmationRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_SendOrderConfirmationRequest.Size(m)
|
return xxx_messageInfo_SendOrderConfirmationRequest.Size(m)
|
||||||
|
@ -1284,16 +1323,17 @@ func (m *PlaceOrderRequest) Reset() { *m = PlaceOrderRequest{} }
|
||||||
func (m *PlaceOrderRequest) String() string { return proto.CompactTextString(m) }
|
func (m *PlaceOrderRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlaceOrderRequest) ProtoMessage() {}
|
func (*PlaceOrderRequest) ProtoMessage() {}
|
||||||
func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
|
func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{27}
|
return fileDescriptor_ca53982754088a9d, []int{27}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlaceOrderRequest) XXX_Unmarshal(b []byte) error {
|
func (m *PlaceOrderRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_PlaceOrderRequest.Unmarshal(m, b)
|
return xxx_messageInfo_PlaceOrderRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *PlaceOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlaceOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_PlaceOrderRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlaceOrderRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *PlaceOrderRequest) XXX_Merge(src proto.Message) {
|
func (m *PlaceOrderRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlaceOrderRequest.Merge(dst, src)
|
xxx_messageInfo_PlaceOrderRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlaceOrderRequest) XXX_Size() int {
|
func (m *PlaceOrderRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_PlaceOrderRequest.Size(m)
|
return xxx_messageInfo_PlaceOrderRequest.Size(m)
|
||||||
|
@ -1350,16 +1390,17 @@ func (m *PlaceOrderResponse) Reset() { *m = PlaceOrderResponse{} }
|
||||||
func (m *PlaceOrderResponse) String() string { return proto.CompactTextString(m) }
|
func (m *PlaceOrderResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlaceOrderResponse) ProtoMessage() {}
|
func (*PlaceOrderResponse) ProtoMessage() {}
|
||||||
func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
|
func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{28}
|
return fileDescriptor_ca53982754088a9d, []int{28}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlaceOrderResponse) XXX_Unmarshal(b []byte) error {
|
func (m *PlaceOrderResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_PlaceOrderResponse.Unmarshal(m, b)
|
return xxx_messageInfo_PlaceOrderResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *PlaceOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlaceOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_PlaceOrderResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlaceOrderResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *PlaceOrderResponse) XXX_Merge(src proto.Message) {
|
func (m *PlaceOrderResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlaceOrderResponse.Merge(dst, src)
|
xxx_messageInfo_PlaceOrderResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlaceOrderResponse) XXX_Size() int {
|
func (m *PlaceOrderResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_PlaceOrderResponse.Size(m)
|
return xxx_messageInfo_PlaceOrderResponse.Size(m)
|
||||||
|
@ -1389,16 +1430,17 @@ func (m *AdRequest) Reset() { *m = AdRequest{} }
|
||||||
func (m *AdRequest) String() string { return proto.CompactTextString(m) }
|
func (m *AdRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*AdRequest) ProtoMessage() {}
|
func (*AdRequest) ProtoMessage() {}
|
||||||
func (*AdRequest) Descriptor() ([]byte, []int) {
|
func (*AdRequest) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{29}
|
return fileDescriptor_ca53982754088a9d, []int{29}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AdRequest) XXX_Unmarshal(b []byte) error {
|
func (m *AdRequest) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_AdRequest.Unmarshal(m, b)
|
return xxx_messageInfo_AdRequest.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *AdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *AdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_AdRequest.Marshal(b, m, deterministic)
|
return xxx_messageInfo_AdRequest.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *AdRequest) XXX_Merge(src proto.Message) {
|
func (m *AdRequest) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_AdRequest.Merge(dst, src)
|
xxx_messageInfo_AdRequest.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *AdRequest) XXX_Size() int {
|
func (m *AdRequest) XXX_Size() int {
|
||||||
return xxx_messageInfo_AdRequest.Size(m)
|
return xxx_messageInfo_AdRequest.Size(m)
|
||||||
|
@ -1427,16 +1469,17 @@ func (m *AdResponse) Reset() { *m = AdResponse{} }
|
||||||
func (m *AdResponse) String() string { return proto.CompactTextString(m) }
|
func (m *AdResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*AdResponse) ProtoMessage() {}
|
func (*AdResponse) ProtoMessage() {}
|
||||||
func (*AdResponse) Descriptor() ([]byte, []int) {
|
func (*AdResponse) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{30}
|
return fileDescriptor_ca53982754088a9d, []int{30}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AdResponse) XXX_Unmarshal(b []byte) error {
|
func (m *AdResponse) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_AdResponse.Unmarshal(m, b)
|
return xxx_messageInfo_AdResponse.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *AdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *AdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_AdResponse.Marshal(b, m, deterministic)
|
return xxx_messageInfo_AdResponse.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *AdResponse) XXX_Merge(src proto.Message) {
|
func (m *AdResponse) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_AdResponse.Merge(dst, src)
|
xxx_messageInfo_AdResponse.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *AdResponse) XXX_Size() int {
|
func (m *AdResponse) XXX_Size() int {
|
||||||
return xxx_messageInfo_AdResponse.Size(m)
|
return xxx_messageInfo_AdResponse.Size(m)
|
||||||
|
@ -1468,16 +1511,17 @@ func (m *Ad) Reset() { *m = Ad{} }
|
||||||
func (m *Ad) String() string { return proto.CompactTextString(m) }
|
func (m *Ad) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Ad) ProtoMessage() {}
|
func (*Ad) ProtoMessage() {}
|
||||||
func (*Ad) Descriptor() ([]byte, []int) {
|
func (*Ad) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_demo_88bb8fdac9cd6be5, []int{31}
|
return fileDescriptor_ca53982754088a9d, []int{31}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Ad) XXX_Unmarshal(b []byte) error {
|
func (m *Ad) XXX_Unmarshal(b []byte) error {
|
||||||
return xxx_messageInfo_Ad.Unmarshal(m, b)
|
return xxx_messageInfo_Ad.Unmarshal(m, b)
|
||||||
}
|
}
|
||||||
func (m *Ad) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *Ad) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
return xxx_messageInfo_Ad.Marshal(b, m, deterministic)
|
return xxx_messageInfo_Ad.Marshal(b, m, deterministic)
|
||||||
}
|
}
|
||||||
func (dst *Ad) XXX_Merge(src proto.Message) {
|
func (m *Ad) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_Ad.Merge(dst, src)
|
xxx_messageInfo_Ad.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *Ad) XXX_Size() int {
|
func (m *Ad) XXX_Size() int {
|
||||||
return xxx_messageInfo_Ad.Size(m)
|
return xxx_messageInfo_Ad.Size(m)
|
||||||
|
@ -2319,101 +2363,102 @@ var _AdService_serviceDesc = grpc.ServiceDesc{
|
||||||
Metadata: "demo.proto",
|
Metadata: "demo.proto",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("demo.proto", fileDescriptor_demo_88bb8fdac9cd6be5) }
|
func init() { proto.RegisterFile("demo.proto", fileDescriptor_ca53982754088a9d) }
|
||||||
|
|
||||||
var fileDescriptor_demo_88bb8fdac9cd6be5 = []byte{
|
var fileDescriptor_ca53982754088a9d = []byte{
|
||||||
// 1483 bytes of a gzipped FileDescriptorProto
|
// 1500 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdd, 0x72, 0xd3, 0xc6,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xef, 0x72, 0x13, 0xb7,
|
||||||
0x17, 0x8f, 0x92, 0x38, 0x8e, 0x8f, 0x63, 0x27, 0xd9, 0x7f, 0x12, 0x8c, 0xc2, 0x47, 0xd8, 0x0c,
|
0x16, 0xcf, 0x26, 0xb1, 0x1d, 0x1f, 0xc7, 0x4e, 0xa2, 0x9b, 0x04, 0xb3, 0x81, 0x10, 0x94, 0x81,
|
||||||
0xfc, 0xa1, 0x80, 0x61, 0xd2, 0xce, 0x70, 0x01, 0x2d, 0xcd, 0x98, 0x8c, 0xf1, 0x14, 0x0a, 0x55,
|
0x0b, 0x17, 0x08, 0x4c, 0xee, 0x9d, 0xe1, 0x03, 0xdc, 0xd2, 0x8c, 0xc9, 0x18, 0x4f, 0xa1, 0xd0,
|
||||||
0xa0, 0x43, 0x87, 0x4e, 0x3d, 0x42, 0xbb, 0x60, 0x95, 0x48, 0x2b, 0x76, 0x57, 0x19, 0xcc, 0x65,
|
0x0d, 0xe9, 0xd0, 0xa1, 0x53, 0xcf, 0xb2, 0x12, 0xf1, 0x96, 0xec, 0x6a, 0x91, 0xb4, 0x19, 0xcc,
|
||||||
0xfb, 0x00, 0xbd, 0xef, 0x23, 0xf4, 0x05, 0xfa, 0x0e, 0xbd, 0xef, 0x2b, 0xf4, 0x39, 0x3a, 0xbb,
|
0xc7, 0xf6, 0x01, 0xfa, 0x1e, 0x7d, 0x81, 0xce, 0xf4, 0x11, 0xfa, 0xbd, 0xaf, 0xd0, 0xe7, 0xe8,
|
||||||
0xd2, 0xea, 0xcb, 0x76, 0x02, 0x37, 0xbd, 0xf3, 0x9e, 0xfd, 0xe9, 0x9c, 0xdf, 0x39, 0x7b, 0xbe,
|
0x48, 0xbb, 0xda, 0x7f, 0xb1, 0x13, 0xf8, 0xd2, 0x6f, 0xab, 0xa3, 0x9f, 0xce, 0xf9, 0xe9, 0xe8,
|
||||||
0x12, 0x00, 0x42, 0x03, 0xd6, 0x8d, 0x38, 0x93, 0x0c, 0x35, 0x47, 0x7e, 0x24, 0x24, 0xe5, 0x62,
|
0xfc, 0xb3, 0x01, 0x08, 0x0d, 0xd8, 0x4e, 0xc4, 0x99, 0x64, 0xa8, 0x35, 0xf2, 0x23, 0x21, 0x29,
|
||||||
0xc4, 0x22, 0x7c, 0x00, 0xcb, 0x3d, 0x97, 0xcb, 0x81, 0xa4, 0x01, 0x3a, 0x0f, 0x10, 0x71, 0x46,
|
0x17, 0x23, 0x16, 0xe1, 0x7d, 0x58, 0xe8, 0xb9, 0x5c, 0x0e, 0x24, 0x0d, 0xd0, 0x65, 0x80, 0x88,
|
||||||
0x62, 0x4f, 0x0e, 0x7d, 0xd2, 0xb1, 0x76, 0xac, 0xab, 0x0d, 0xa7, 0x91, 0x4a, 0x06, 0x04, 0xd9,
|
0x33, 0x12, 0x7b, 0x72, 0xe8, 0x93, 0xae, 0xb5, 0x65, 0xdd, 0x68, 0x3a, 0xcd, 0x54, 0x32, 0x20,
|
||||||
0xb0, 0xfc, 0x2e, 0x76, 0x43, 0xe9, 0xcb, 0x71, 0x67, 0x7e, 0xc7, 0xba, 0x5a, 0x73, 0xb2, 0x33,
|
0xc8, 0x86, 0x85, 0xf7, 0xb1, 0x1b, 0x4a, 0x5f, 0x8e, 0xbb, 0xb3, 0x5b, 0xd6, 0x8d, 0x9a, 0x93,
|
||||||
0x7e, 0x06, 0xed, 0x7d, 0x42, 0x94, 0x16, 0x87, 0xbe, 0x8b, 0xa9, 0x90, 0xe8, 0x0c, 0xd4, 0x63,
|
0xad, 0xf1, 0x4b, 0xe8, 0xec, 0x11, 0xa2, 0xb4, 0x38, 0xf4, 0x7d, 0x4c, 0x85, 0x44, 0x17, 0xa0,
|
||||||
0x41, 0x79, 0xae, 0x69, 0x49, 0x1d, 0x07, 0x04, 0x5d, 0x83, 0x45, 0x5f, 0xd2, 0x40, 0xab, 0x68,
|
0x11, 0x0b, 0xca, 0x73, 0x4d, 0x75, 0xb5, 0x1c, 0x10, 0x74, 0x13, 0xe6, 0x7d, 0x49, 0x03, 0xad,
|
||||||
0xee, 0x6d, 0x76, 0x0b, 0x6c, 0xba, 0x86, 0x8a, 0xa3, 0x21, 0xf8, 0x3a, 0xac, 0x1d, 0x04, 0x91,
|
0xa2, 0xb5, 0xbb, 0xb6, 0x53, 0x60, 0xb3, 0x63, 0xa8, 0x38, 0x1a, 0x82, 0x6f, 0xc1, 0xf2, 0x7e,
|
||||||
0x1c, 0x2b, 0xf1, 0x69, 0x7a, 0xf1, 0x35, 0x68, 0xf7, 0xa9, 0xfc, 0x28, 0xe8, 0x23, 0x58, 0x54,
|
0x10, 0xc9, 0xb1, 0x12, 0x9f, 0xa7, 0x17, 0xdf, 0x84, 0x4e, 0x9f, 0xca, 0x4f, 0x82, 0x3e, 0x85,
|
||||||
0xb8, 0xd9, 0x1c, 0xaf, 0x43, 0x4d, 0x11, 0x10, 0x9d, 0xf9, 0x9d, 0x85, 0xd9, 0x24, 0x13, 0x0c,
|
0x79, 0x85, 0x9b, 0xce, 0xf1, 0x16, 0xd4, 0x14, 0x01, 0xd1, 0x9d, 0xdd, 0x9a, 0x9b, 0x4e, 0x32,
|
||||||
0xae, 0x43, 0x4d, 0xb3, 0xc4, 0xdf, 0x83, 0xfd, 0xc8, 0x17, 0xd2, 0xa1, 0x1e, 0x0b, 0x02, 0x1a,
|
0xc1, 0xe0, 0x06, 0xd4, 0x34, 0x4b, 0xfc, 0x2d, 0xd8, 0x4f, 0x7d, 0x21, 0x1d, 0xea, 0xb1, 0x20,
|
||||||
0x12, 0x57, 0xfa, 0x2c, 0x14, 0xa7, 0x06, 0xe4, 0x22, 0x34, 0xf3, 0xb0, 0x27, 0x26, 0x1b, 0x0e,
|
0xa0, 0x21, 0x71, 0xa5, 0xcf, 0x42, 0x71, 0xae, 0x43, 0xae, 0x40, 0x2b, 0x77, 0x7b, 0x62, 0xb2,
|
||||||
0x64, 0x71, 0x17, 0xf8, 0x2b, 0xd8, 0x9e, 0xaa, 0x57, 0x44, 0x2c, 0x14, 0xb4, 0xfa, 0xbd, 0x35,
|
0xe9, 0x40, 0xe6, 0x77, 0x81, 0xbf, 0x80, 0x8d, 0x89, 0x7a, 0x45, 0xc4, 0x42, 0x41, 0xab, 0xe7,
|
||||||
0xf1, 0xfd, 0xef, 0x16, 0xd4, 0x9f, 0x26, 0x47, 0xd4, 0x86, 0xf9, 0x8c, 0xc0, 0xbc, 0x4f, 0x10,
|
0xad, 0x53, 0xe7, 0x7f, 0xb7, 0xa0, 0xf1, 0x22, 0x59, 0xa2, 0x0e, 0xcc, 0x66, 0x04, 0x66, 0x7d,
|
||||||
0x82, 0xc5, 0xd0, 0x0d, 0xa8, 0x7e, 0x8d, 0x86, 0xa3, 0x7f, 0xa3, 0x1d, 0x68, 0x12, 0x2a, 0x3c,
|
0x82, 0x10, 0xcc, 0x87, 0x6e, 0x40, 0xf5, 0x6b, 0x34, 0x1d, 0xfd, 0x8d, 0xb6, 0xa0, 0x45, 0xa8,
|
||||||
0xee, 0x47, 0xca, 0x50, 0x67, 0x41, 0x5f, 0x15, 0x45, 0xa8, 0x03, 0xf5, 0xc8, 0xf7, 0x64, 0xcc,
|
0xf0, 0xb8, 0x1f, 0x29, 0x43, 0xdd, 0x39, 0xbd, 0x55, 0x14, 0xa1, 0x2e, 0x34, 0x22, 0xdf, 0x93,
|
||||||
0x69, 0x67, 0x51, 0xdf, 0x9a, 0x23, 0xba, 0x05, 0x8d, 0x88, 0xfb, 0x1e, 0x1d, 0xc6, 0x82, 0x74,
|
0x31, 0xa7, 0xdd, 0x79, 0xbd, 0x6b, 0x96, 0xe8, 0x2e, 0x34, 0x23, 0xee, 0x7b, 0x74, 0x18, 0x0b,
|
||||||
0x6a, 0xfa, 0x89, 0x51, 0x29, 0x7a, 0x8f, 0x59, 0x48, 0xc7, 0xce, 0xb2, 0x06, 0x3d, 0x17, 0x04,
|
0xd2, 0xad, 0xe9, 0x27, 0x46, 0x25, 0xef, 0x3d, 0x63, 0x21, 0x1d, 0x3b, 0x0b, 0x1a, 0x74, 0x28,
|
||||||
0x3f, 0x84, 0x0d, 0xe5, 0x5c, 0xca, 0x2f, 0xf7, 0xea, 0x36, 0x2c, 0xa7, 0x2e, 0x24, 0x2e, 0x35,
|
0x08, 0xda, 0x04, 0xf0, 0x5c, 0x49, 0x8f, 0x18, 0xf7, 0xa9, 0xe8, 0xd6, 0x13, 0xf2, 0xb9, 0x04,
|
||||||
0xf7, 0x36, 0x4a, 0x7a, 0xd2, 0x0f, 0x9c, 0x0c, 0x85, 0x77, 0x61, 0xbd, 0x4f, 0x8d, 0x22, 0x13,
|
0x3f, 0x81, 0x55, 0x75, 0xf9, 0x94, 0x7f, 0x7e, 0xeb, 0x7b, 0xb0, 0x90, 0x5e, 0x31, 0xb9, 0x72,
|
||||||
0xf5, 0x8a, 0xbf, 0xf8, 0x26, 0x6c, 0x1e, 0x52, 0x97, 0x7b, 0xa3, 0xdc, 0x60, 0x02, 0xdc, 0x80,
|
0x6b, 0x77, 0xb5, 0x64, 0x27, 0x3d, 0xe0, 0x64, 0x28, 0xbc, 0x0d, 0x2b, 0x7d, 0x6a, 0x14, 0x99,
|
||||||
0xda, 0xbb, 0x98, 0xf2, 0x71, 0x8a, 0x4d, 0x0e, 0xf8, 0x21, 0x6c, 0x55, 0xe1, 0x29, 0xbf, 0x2e,
|
0x57, 0xa9, 0xf8, 0x03, 0xdf, 0x81, 0xb5, 0x03, 0xea, 0x72, 0x6f, 0x94, 0x1b, 0x4c, 0x80, 0xab,
|
||||||
0xd4, 0x39, 0x15, 0xf1, 0xd1, 0x29, 0xf4, 0x0c, 0x08, 0x87, 0xb0, 0xda, 0xa7, 0xf2, 0xbb, 0x98,
|
0x50, 0x7b, 0x1f, 0x53, 0x3e, 0x4e, 0xb1, 0xc9, 0x02, 0x3f, 0x81, 0xf5, 0x2a, 0x3c, 0xe5, 0xb7,
|
||||||
0x49, 0x6a, 0x4c, 0x76, 0xa1, 0xee, 0x12, 0xc2, 0xa9, 0x10, 0xda, 0x68, 0x55, 0xc5, 0x7e, 0x72,
|
0x03, 0x0d, 0x4e, 0x45, 0x7c, 0x7c, 0x0e, 0x3d, 0x03, 0xc2, 0x21, 0x2c, 0xf5, 0xa9, 0xfc, 0x26,
|
||||||
0xe7, 0x18, 0xd0, 0xa7, 0x65, 0xe5, 0x3e, 0xac, 0xe5, 0xf6, 0x52, 0xce, 0x37, 0x61, 0xd9, 0x63,
|
0x66, 0x92, 0x1a, 0x93, 0x3b, 0xd0, 0x70, 0x09, 0xe1, 0x54, 0x08, 0x6d, 0xb4, 0xaa, 0x62, 0x2f,
|
||||||
0x42, 0xea, 0xb7, 0xb1, 0x66, 0xbe, 0x4d, 0x5d, 0x61, 0xd4, 0xd3, 0x30, 0x58, 0x3b, 0x1c, 0xf9,
|
0xd9, 0x73, 0x0c, 0xe8, 0xf3, 0xa2, 0x76, 0x0f, 0x96, 0x73, 0x7b, 0x29, 0xe7, 0x3b, 0xb0, 0xe0,
|
||||||
0xd1, 0x13, 0x4e, 0x28, 0xff, 0x4f, 0x38, 0x7f, 0x01, 0xeb, 0x05, 0x83, 0x79, 0x7a, 0x4b, 0xee,
|
0x31, 0x21, 0xf5, 0xdb, 0x59, 0x53, 0xdf, 0xae, 0xa1, 0x30, 0x87, 0x82, 0x60, 0x06, 0xcb, 0x07,
|
||||||
0x7a, 0x6f, 0xfd, 0xf0, 0x4d, 0x5e, 0x3b, 0x60, 0x44, 0x03, 0x82, 0x7f, 0xb3, 0xa0, 0x9e, 0xda,
|
0x23, 0x3f, 0x7a, 0xce, 0x09, 0xe5, 0xff, 0x08, 0xe7, 0xff, 0xc1, 0x4a, 0xc1, 0x60, 0x1e, 0xfe,
|
||||||
0x45, 0x97, 0xa1, 0x2d, 0x24, 0xa7, 0x54, 0x0e, 0x8b, 0x2c, 0x1b, 0x4e, 0x2b, 0x91, 0x1a, 0x18,
|
0x92, 0xbb, 0xde, 0x3b, 0x3f, 0x3c, 0xca, 0x73, 0x0b, 0x8c, 0x68, 0x40, 0xf0, 0x2f, 0x16, 0x34,
|
||||||
0x82, 0x45, 0xcf, 0xb4, 0xb1, 0x86, 0xa3, 0x7f, 0xab, 0x04, 0x10, 0xd2, 0x95, 0x34, 0xcd, 0xf7,
|
0x52, 0xbb, 0xe8, 0x1a, 0x74, 0x84, 0xe4, 0x94, 0xca, 0x61, 0x91, 0x65, 0xd3, 0x69, 0x27, 0x52,
|
||||||
0xe4, 0xa0, 0x32, 0xdd, 0x63, 0x71, 0x28, 0xf9, 0xd8, 0x64, 0x7a, 0x7a, 0x44, 0x67, 0x61, 0xf9,
|
0x03, 0x43, 0x30, 0xef, 0x99, 0x32, 0xd7, 0x74, 0xf4, 0xb7, 0x0a, 0x00, 0x21, 0x5d, 0x49, 0xd3,
|
||||||
0x83, 0x1f, 0x0d, 0x3d, 0x46, 0xa8, 0x4e, 0xf4, 0x9a, 0x53, 0xff, 0xe0, 0x47, 0x3d, 0x46, 0x28,
|
0x7c, 0x48, 0x16, 0x2a, 0x13, 0x3c, 0x16, 0x87, 0x92, 0x8f, 0x4d, 0x26, 0xa4, 0x4b, 0x74, 0x11,
|
||||||
0x7e, 0x01, 0x35, 0x1d, 0x4a, 0xb4, 0x0b, 0x2d, 0x2f, 0xe6, 0x9c, 0x86, 0xde, 0x38, 0x01, 0x26,
|
0x16, 0x3e, 0xfa, 0xd1, 0xd0, 0x63, 0x84, 0xea, 0x44, 0xa8, 0x39, 0x8d, 0x8f, 0x7e, 0xd4, 0x63,
|
||||||
0x6c, 0x56, 0x8c, 0x50, 0xa1, 0x95, 0xe1, 0x38, 0xf4, 0xa5, 0xd0, 0x6c, 0x16, 0x9c, 0xe4, 0xa0,
|
0x84, 0xe2, 0x57, 0x50, 0xd3, 0xae, 0x44, 0xdb, 0xd0, 0xf6, 0x62, 0xce, 0x69, 0xe8, 0x8d, 0x13,
|
||||||
0xa4, 0xa1, 0x1b, 0x32, 0xa1, 0xe9, 0xd4, 0x9c, 0xe4, 0x80, 0xfb, 0x70, 0xa1, 0x4f, 0xe5, 0x61,
|
0x60, 0xc2, 0x66, 0xd1, 0x08, 0x15, 0x5a, 0x19, 0x8e, 0x43, 0x5f, 0x0a, 0xcd, 0x66, 0xce, 0x49,
|
||||||
0x1c, 0x45, 0x8c, 0x4b, 0x4a, 0x7a, 0x89, 0x1e, 0x9f, 0xe6, 0x79, 0x79, 0x19, 0xda, 0x25, 0x93,
|
0x16, 0x4a, 0x1a, 0xba, 0x21, 0x13, 0x9a, 0x4e, 0xcd, 0x49, 0x16, 0xb8, 0x0f, 0x9b, 0x7d, 0x2a,
|
||||||
0xa6, 0x21, 0xb4, 0x8a, 0x36, 0x05, 0xfe, 0x11, 0xce, 0xf6, 0x32, 0x41, 0x78, 0x4c, 0xb9, 0xf0,
|
0x0f, 0xe2, 0x28, 0x62, 0x5c, 0x52, 0xd2, 0x4b, 0xf4, 0xf8, 0x34, 0x8f, 0xcb, 0x6b, 0xd0, 0x29,
|
||||||
0x59, 0x68, 0x1e, 0xf9, 0x0a, 0x2c, 0xbe, 0xe6, 0x2c, 0x38, 0x21, 0x47, 0xf4, 0xbd, 0x6a, 0x69,
|
0x99, 0x34, 0x05, 0xa3, 0x5d, 0xb4, 0x29, 0xf0, 0xf7, 0x70, 0xb1, 0x97, 0x09, 0xc2, 0x13, 0xca,
|
||||||
0x92, 0x25, 0x8e, 0x25, 0x91, 0x5c, 0x92, 0x4c, 0x07, 0xe0, 0x1f, 0x0b, 0xda, 0x3d, 0x4e, 0x89,
|
0x85, 0xcf, 0x42, 0xf3, 0xc8, 0xd7, 0x61, 0xfe, 0x2d, 0x67, 0xc1, 0x19, 0x31, 0xa2, 0xf7, 0x55,
|
||||||
0xaf, 0xfa, 0x31, 0x19, 0x84, 0xaf, 0x19, 0xba, 0x01, 0xc8, 0xd3, 0x92, 0xa1, 0xe7, 0x72, 0x32,
|
0xc9, 0x93, 0x2c, 0xb9, 0x58, 0xe2, 0xc9, 0xba, 0x64, 0xda, 0x01, 0x7f, 0x59, 0xd0, 0xe9, 0x71,
|
||||||
0x0c, 0xe3, 0xe0, 0x15, 0xe5, 0x69, 0x3c, 0xd6, 0xbc, 0x0c, 0xfb, 0xad, 0x96, 0xa3, 0x2b, 0xb0,
|
0x4a, 0x7c, 0x55, 0xaf, 0xc9, 0x20, 0x7c, 0xcb, 0xd0, 0x6d, 0x40, 0x9e, 0x96, 0x0c, 0x3d, 0x97,
|
||||||
0x5a, 0x44, 0x7b, 0xc7, 0xc7, 0xe9, 0xc8, 0x69, 0xe5, 0xd0, 0xde, 0xf1, 0x31, 0xfa, 0x12, 0xb6,
|
0x93, 0x61, 0x18, 0x07, 0x6f, 0x28, 0x4f, 0xfd, 0xb1, 0xec, 0x65, 0xd8, 0xaf, 0xb5, 0x1c, 0x5d,
|
||||||
0x8b, 0x38, 0xfa, 0x3e, 0xf2, 0xb9, 0x6e, 0x8f, 0xc3, 0x31, 0x75, 0x79, 0x1a, 0xbb, 0x4e, 0xfe,
|
0x87, 0xa5, 0x22, 0xda, 0x3b, 0x39, 0x49, 0x5b, 0x52, 0x3b, 0x87, 0xf6, 0x4e, 0x4e, 0xd0, 0xff,
|
||||||
0xcd, 0x41, 0x06, 0xf8, 0x81, 0xba, 0x1c, 0xdd, 0x87, 0x73, 0x33, 0x3e, 0x0f, 0x58, 0x28, 0x47,
|
0x61, 0xa3, 0x88, 0xa3, 0x1f, 0x22, 0x9f, 0xeb, 0xf2, 0x39, 0x1c, 0x53, 0x97, 0xa7, 0xbe, 0xeb,
|
||||||
0xfa, 0xc9, 0x6b, 0xce, 0xd9, 0x69, 0xdf, 0x3f, 0x56, 0x00, 0x3c, 0x86, 0x56, 0x6f, 0xe4, 0xf2,
|
0xe6, 0x67, 0xf6, 0x33, 0xc0, 0x77, 0xd4, 0xe5, 0xe8, 0x11, 0x5c, 0x9a, 0x72, 0x3c, 0x60, 0xa1,
|
||||||
0x37, 0x59, 0x4d, 0x7f, 0x06, 0x4b, 0x6e, 0xa0, 0x32, 0xe4, 0x84, 0xe0, 0xa5, 0x08, 0x74, 0x0f,
|
0x1c, 0xe9, 0x27, 0xaf, 0x39, 0x17, 0x27, 0x9d, 0x7f, 0xa6, 0x00, 0x78, 0x0c, 0xed, 0xde, 0xc8,
|
||||||
0x9a, 0x05, 0xeb, 0xe9, 0x40, 0xdc, 0x2e, 0x57, 0x48, 0x29, 0x88, 0x0e, 0xe4, 0x4c, 0xf0, 0x1d,
|
0xe5, 0x47, 0x59, 0x4e, 0xff, 0x07, 0xea, 0x6e, 0xa0, 0x22, 0xe4, 0x0c, 0xe7, 0xa5, 0x08, 0xf4,
|
||||||
0x68, 0x1b, 0xd3, 0xf9, 0xd3, 0x4b, 0xee, 0x86, 0xc2, 0xf5, 0xb4, 0x0b, 0x59, 0xb1, 0xb4, 0x0a,
|
0x10, 0x5a, 0x05, 0xeb, 0x69, 0xc3, 0xdc, 0x28, 0x67, 0x48, 0xc9, 0x89, 0x0e, 0xe4, 0x4c, 0xf0,
|
||||||
0xd2, 0x01, 0xc1, 0x3f, 0x41, 0x43, 0x57, 0x98, 0x9e, 0xf9, 0x66, 0x1a, 0x5b, 0xa7, 0x4e, 0x63,
|
0x7d, 0xe8, 0x18, 0xd3, 0xf9, 0xd3, 0x4b, 0xee, 0x86, 0xc2, 0xf5, 0xf4, 0x15, 0xb2, 0x64, 0x69,
|
||||||
0x95, 0x15, 0xaa, 0x33, 0xa4, 0x3c, 0xa7, 0x66, 0x85, 0xba, 0xc7, 0xbf, 0xcc, 0x43, 0xd3, 0x94,
|
0x17, 0xa4, 0x03, 0x82, 0x7f, 0x80, 0xa6, 0xce, 0x30, 0x3d, 0x13, 0x98, 0x6e, 0x6d, 0x9d, 0xdb,
|
||||||
0x70, 0x7c, 0x24, 0x55, 0xa1, 0x30, 0x75, 0xcc, 0x09, 0xd5, 0xf5, 0x79, 0x40, 0xd0, 0x6d, 0xd8,
|
0xad, 0x55, 0x54, 0xa8, 0xca, 0x90, 0xf2, 0x9c, 0x18, 0x15, 0x6a, 0x1f, 0xff, 0x34, 0x0b, 0x2d,
|
||||||
0x10, 0x23, 0x3f, 0x8a, 0x54, 0x6d, 0x17, 0x8b, 0x3c, 0xc9, 0x26, 0x64, 0xee, 0x9e, 0x65, 0xc5,
|
0x93, 0xc2, 0xf1, 0xb1, 0x54, 0x89, 0xc2, 0xd4, 0x32, 0x27, 0xd4, 0xd0, 0xeb, 0x01, 0x41, 0xf7,
|
||||||
0x8e, 0xee, 0x40, 0x2b, 0xfb, 0x42, 0xb3, 0x59, 0x98, 0xc9, 0x66, 0xc5, 0x00, 0x7b, 0x4c, 0x48,
|
0x60, 0x55, 0x8c, 0xfc, 0x28, 0x52, 0xb9, 0x5d, 0x4c, 0xf2, 0x24, 0x9a, 0x90, 0xd9, 0x7b, 0x99,
|
||||||
0x74, 0x1f, 0xd6, 0xb2, 0x0f, 0x4d, 0x6f, 0x58, 0x3c, 0xa1, 0x83, 0xad, 0x1a, 0xb4, 0xe9, 0x19,
|
0x25, 0x3b, 0xba, 0x0f, 0xed, 0xec, 0x84, 0x66, 0x33, 0x37, 0x95, 0xcd, 0xa2, 0x01, 0xf6, 0x98,
|
||||||
0x37, 0x4c, 0x27, 0xab, 0xe9, 0x4e, 0xb6, 0x55, 0xfa, 0x2a, 0x0b, 0xa8, 0x69, 0x65, 0x04, 0xce,
|
0x90, 0xe8, 0x11, 0x2c, 0x67, 0x07, 0x4d, 0x6d, 0x98, 0x3f, 0xa3, 0x82, 0x2d, 0x19, 0xb4, 0xa9,
|
||||||
0x1d, 0xd2, 0x90, 0x68, 0x79, 0x8f, 0x85, 0xaf, 0x7d, 0x1e, 0xe8, 0xb4, 0x29, 0x8c, 0x1b, 0x1a,
|
0x19, 0xb7, 0x4d, 0x25, 0xab, 0xe9, 0x4a, 0xb6, 0x5e, 0x3a, 0x95, 0x39, 0xd4, 0x94, 0x32, 0x02,
|
||||||
0xb8, 0xfe, 0x91, 0x19, 0x37, 0xfa, 0x80, 0xba, 0x50, 0xd3, 0xa1, 0x49, 0x63, 0xdc, 0x99, 0xb4,
|
0x97, 0x0e, 0x68, 0x48, 0xb4, 0xbc, 0xc7, 0xc2, 0xb7, 0x3e, 0x0f, 0x74, 0xd8, 0x14, 0xda, 0x0d,
|
||||||
0x91, 0xc4, 0xd4, 0x49, 0x60, 0xf8, 0x6f, 0x0b, 0xd6, 0x9f, 0x1e, 0xb9, 0x1e, 0x2d, 0xf5, 0xe8,
|
0x0d, 0x5c, 0xff, 0xd8, 0xb4, 0x1b, 0xbd, 0x40, 0x3b, 0x50, 0xd3, 0xae, 0x49, 0x7d, 0xdc, 0x3d,
|
||||||
0x99, 0x9b, 0xc6, 0x2e, 0xb4, 0xf4, 0x85, 0x69, 0x05, 0x69, 0x9c, 0x57, 0x94, 0xd0, 0x74, 0x83,
|
0x6d, 0x23, 0xf1, 0xa9, 0x93, 0xc0, 0xf0, 0x9f, 0x16, 0xac, 0xbc, 0x38, 0x76, 0x3d, 0x5a, 0xaa,
|
||||||
0x62, 0x87, 0x5f, 0xf8, 0x98, 0x0e, 0x9f, 0x79, 0x52, 0x2b, 0x7a, 0x52, 0xc9, 0xed, 0xa5, 0x4f,
|
0xd1, 0x53, 0x27, 0x91, 0x6d, 0x68, 0xeb, 0x0d, 0x53, 0x0a, 0x52, 0x3f, 0x2f, 0x2a, 0xa1, 0xa9,
|
||||||
0xcb, 0xed, 0x07, 0x80, 0x8a, 0x6e, 0x65, 0x23, 0x37, 0x8d, 0x8e, 0xf5, 0x71, 0xd1, 0xe9, 0x42,
|
0x06, 0xc5, 0x0a, 0x3f, 0xf7, 0x29, 0x15, 0x3e, 0xbb, 0x49, 0xad, 0x78, 0x93, 0x4a, 0x6c, 0xd7,
|
||||||
0x63, 0x9f, 0x98, 0xa0, 0x5c, 0x82, 0x15, 0x8f, 0x85, 0x92, 0xbe, 0x97, 0xc3, 0xb7, 0x74, 0x6c,
|
0x3f, 0x2f, 0xb6, 0x1f, 0x03, 0x2a, 0x5e, 0x2b, 0x6b, 0xb9, 0xa9, 0x77, 0xac, 0x4f, 0xf3, 0xce,
|
||||||
0xba, 0x62, 0x33, 0x95, 0x7d, 0x43, 0xc7, 0x02, 0xdf, 0x02, 0x50, 0xf8, 0xd4, 0xda, 0x25, 0x58,
|
0x0e, 0x34, 0xf7, 0x88, 0x71, 0xca, 0x55, 0x58, 0xf4, 0x58, 0x28, 0xe9, 0x07, 0x39, 0x7c, 0x47,
|
||||||
0x70, 0x89, 0x19, 0xee, 0xab, 0x95, 0x18, 0x38, 0xea, 0x0e, 0xdf, 0x85, 0xf9, 0x7d, 0xa2, 0x34,
|
0xc7, 0xa6, 0x2a, 0xb6, 0x52, 0xd9, 0x57, 0x74, 0x2c, 0xf0, 0x5d, 0x00, 0x85, 0x4f, 0xad, 0x5d,
|
||||||
0x2b, 0xe6, 0x9c, 0x7a, 0x72, 0x18, 0x73, 0xf3, 0xa2, 0x4d, 0x23, 0x7b, 0xce, 0x8f, 0xd4, 0xbc,
|
0x85, 0x39, 0x97, 0x98, 0xe6, 0xbe, 0x54, 0xf1, 0x81, 0xa3, 0xf6, 0xf0, 0x03, 0x98, 0xdd, 0x23,
|
||||||
0x51, 0x56, 0xcc, 0xbc, 0x51, 0xbf, 0xf7, 0xfe, 0xb2, 0xa0, 0xa9, 0x2a, 0xec, 0x90, 0xf2, 0x63,
|
0x4a, 0xb3, 0x62, 0xce, 0xa9, 0x27, 0x87, 0x31, 0x37, 0x2f, 0xda, 0x32, 0xb2, 0x43, 0x7e, 0xac,
|
||||||
0xdf, 0xa3, 0xe8, 0x9e, 0x9e, 0x62, 0xba, 0x28, 0xb7, 0xab, 0x11, 0x2f, 0x2c, 0xd6, 0x76, 0x39,
|
0xfa, 0x8d, 0xb2, 0x62, 0xfa, 0x8d, 0xfa, 0xde, 0xfd, 0xc3, 0x82, 0x96, 0xca, 0xb0, 0x03, 0xca,
|
||||||
0xd5, 0x93, 0xcd, 0x73, 0x0e, 0xdd, 0x85, 0x7a, 0xba, 0xfd, 0x56, 0xbe, 0x2e, 0xef, 0xc4, 0xf6,
|
0x4f, 0x7c, 0x8f, 0xa2, 0x87, 0xba, 0x8b, 0xe9, 0xa4, 0xdc, 0xa8, 0x7a, 0xbc, 0x30, 0x78, 0xdb,
|
||||||
0xfa, 0x44, 0x85, 0xe3, 0x39, 0xf4, 0x35, 0x34, 0xb2, 0x3d, 0x1b, 0x9d, 0x9f, 0xd4, 0x5f, 0x54,
|
0xe5, 0x50, 0x4f, 0x26, 0xd3, 0x19, 0xf4, 0x00, 0x1a, 0xe9, 0x74, 0x5c, 0x39, 0x5d, 0x9e, 0x99,
|
||||||
0x30, 0xd5, 0xfc, 0xde, 0xaf, 0x16, 0x6c, 0x96, 0xf7, 0x53, 0xe3, 0xd6, 0xcf, 0xf0, 0xbf, 0x29,
|
0xed, 0x95, 0x53, 0x19, 0x8e, 0x67, 0xd0, 0x97, 0xd0, 0xcc, 0xe6, 0x70, 0x74, 0xf9, 0xb4, 0xfe,
|
||||||
0xcb, 0x2b, 0xfa, 0x7f, 0x49, 0xcd, 0xec, 0xb5, 0xd9, 0xbe, 0x7a, 0x3a, 0x30, 0x79, 0x30, 0xc5,
|
0xa2, 0x82, 0x89, 0xe6, 0x77, 0x7f, 0xb6, 0x60, 0xad, 0x3c, 0xbf, 0x9a, 0x6b, 0xfd, 0x08, 0xff,
|
||||||
0x62, 0x1e, 0x36, 0xd3, 0xc5, 0xab, 0xe7, 0x4a, 0xf7, 0x88, 0xbd, 0x31, 0x2c, 0xfa, 0xb0, 0x52,
|
0x9a, 0x30, 0xdc, 0xa2, 0x7f, 0x97, 0xd4, 0x4c, 0x1f, 0xab, 0xed, 0x1b, 0xe7, 0x03, 0x93, 0x07,
|
||||||
0xdc, 0x32, 0xd1, 0x14, 0x2f, 0xec, 0x4b, 0x13, 0x96, 0xaa, 0x4b, 0x1f, 0x9e, 0x43, 0x0f, 0x00,
|
0x53, 0x2c, 0x66, 0x61, 0x2d, 0x1d, 0xbc, 0x7a, 0xae, 0x74, 0x8f, 0xd9, 0x91, 0x61, 0xd1, 0x87,
|
||||||
0xf2, 0x25, 0x13, 0x5d, 0xa8, 0x86, 0xba, 0xbc, 0x7d, 0xda, 0x53, 0x77, 0x42, 0x3c, 0x87, 0x5e,
|
0xc5, 0xe2, 0x94, 0x89, 0x26, 0xdc, 0xc2, 0xbe, 0x7a, 0xca, 0x52, 0x75, 0xe8, 0xc3, 0x33, 0xe8,
|
||||||
0x42, 0xbb, 0xbc, 0x56, 0x22, 0x5c, 0x42, 0x4e, 0x5d, 0x51, 0xed, 0xdd, 0x13, 0x31, 0x59, 0x14,
|
0x31, 0x40, 0x3e, 0x64, 0xa2, 0xcd, 0xaa, 0xab, 0xcb, 0xd3, 0xa7, 0x3d, 0x71, 0x26, 0xc4, 0x33,
|
||||||
0xfe, 0xb0, 0x60, 0xf5, 0x30, 0x6d, 0x5e, 0xc6, 0xff, 0x01, 0x2c, 0x9b, 0x6d, 0x10, 0x9d, 0xab,
|
0xe8, 0x35, 0x74, 0xca, 0x63, 0x25, 0xc2, 0x25, 0xe4, 0xc4, 0x11, 0xd5, 0xde, 0x3e, 0x13, 0x93,
|
||||||
0x92, 0x2e, 0x2e, 0xa5, 0xf6, 0xf9, 0x19, 0xb7, 0x59, 0x04, 0x1e, 0x41, 0x23, 0x5b, 0xd2, 0x2a,
|
0x79, 0xe1, 0x57, 0x0b, 0x96, 0x0e, 0xd2, 0xe2, 0x65, 0xee, 0x3f, 0x80, 0x05, 0x33, 0x0d, 0xa2,
|
||||||
0xc9, 0x52, 0xdd, 0x16, 0xed, 0x0b, 0xb3, 0xae, 0x33, 0xb2, 0x7f, 0x5a, 0xb0, 0x6a, 0x5a, 0x8f,
|
0x4b, 0x55, 0xd2, 0xc5, 0xa1, 0xd4, 0xbe, 0x3c, 0x65, 0x37, 0xf3, 0xc0, 0x53, 0x68, 0x66, 0x43,
|
||||||
0x21, 0xfb, 0x12, 0xb6, 0xa6, 0x2f, 0x39, 0x53, 0x9f, 0xed, 0x7a, 0x95, 0xf0, 0x09, 0xdb, 0x11,
|
0x5a, 0x25, 0x58, 0xaa, 0xd3, 0xa2, 0xbd, 0x39, 0x6d, 0x3b, 0x23, 0xfb, 0x9b, 0x05, 0x4b, 0xa6,
|
||||||
0x9e, 0x43, 0x7d, 0xa8, 0x27, 0x0b, 0x8f, 0x44, 0x57, 0xca, 0xb5, 0x30, 0x6b, 0x1d, 0xb2, 0xa7,
|
0xf4, 0x18, 0xb2, 0xaf, 0x61, 0x7d, 0xf2, 0x90, 0x33, 0xf1, 0xd9, 0x6e, 0x55, 0x09, 0x9f, 0x31,
|
||||||
0x0c, 0x17, 0x3c, 0xb7, 0xf7, 0x1c, 0xda, 0x4f, 0xdd, 0x71, 0x40, 0xc3, 0xac, 0x82, 0x7b, 0xb0,
|
0x1d, 0xe1, 0x19, 0xd4, 0x87, 0x46, 0x32, 0xf0, 0x48, 0x74, 0xbd, 0x9c, 0x0b, 0xd3, 0xc6, 0x21,
|
||||||
0x94, 0x4c, 0x64, 0x64, 0x97, 0x35, 0x17, 0x37, 0x04, 0x7b, 0x7b, 0xea, 0x5d, 0x16, 0x90, 0x11,
|
0x7b, 0x42, 0x73, 0xc1, 0x33, 0xbb, 0x87, 0xd0, 0x79, 0xe1, 0x8e, 0x03, 0x1a, 0x66, 0x19, 0xdc,
|
||||||
0xac, 0x1c, 0xa8, 0x0e, 0x6a, 0x94, 0xbe, 0x50, 0x7f, 0xb0, 0x4c, 0x19, 0x24, 0xe8, 0x5a, 0x25,
|
0x83, 0x7a, 0xd2, 0x91, 0x91, 0x5d, 0xd6, 0x5c, 0x9c, 0x10, 0xec, 0x8d, 0x89, 0x7b, 0x99, 0x43,
|
||||||
0x1b, 0x66, 0x0f, 0x9b, 0x19, 0x35, 0xfb, 0x0a, 0x56, 0x7b, 0x23, 0xea, 0xbd, 0x65, 0x71, 0xe6,
|
0x46, 0xb0, 0xb8, 0xaf, 0x2a, 0xa8, 0x51, 0xfa, 0x4a, 0xfd, 0x60, 0x99, 0xd0, 0x48, 0xd0, 0xcd,
|
||||||
0xc1, 0x13, 0x80, 0xbc, 0xef, 0x56, 0xb2, 0x7b, 0x62, 0xce, 0xd8, 0x17, 0x67, 0xde, 0x67, 0xde,
|
0x4a, 0x34, 0x4c, 0x6f, 0x36, 0x53, 0x72, 0xf6, 0x0d, 0x2c, 0xf5, 0x46, 0xd4, 0x7b, 0xc7, 0xe2,
|
||||||
0x3c, 0x54, 0x2d, 0xd8, 0x68, 0xbf, 0x0b, 0x4b, 0x7d, 0xb5, 0x83, 0x0b, 0xb4, 0x55, 0x6d, 0xa7,
|
0xec, 0x06, 0xcf, 0x01, 0xf2, 0xba, 0x5b, 0x89, 0xee, 0x53, 0x7d, 0xc6, 0xbe, 0x32, 0x75, 0x3f,
|
||||||
0xa9, 0xc6, 0x33, 0x13, 0x72, 0xa3, 0xe9, 0xd5, 0x92, 0xfe, 0xe7, 0xc5, 0xe7, 0xff, 0x06, 0x00,
|
0xbb, 0xcd, 0x13, 0x55, 0x82, 0x8d, 0xf6, 0x07, 0x50, 0xef, 0xab, 0x19, 0x5c, 0xa0, 0xf5, 0x6a,
|
||||||
0x00, 0xff, 0xff, 0x22, 0xc9, 0xfe, 0x20, 0xca, 0x10, 0x00, 0x00,
|
0x39, 0x4d, 0x35, 0x5e, 0x38, 0x25, 0x37, 0x9a, 0xde, 0xd4, 0xf5, 0x9f, 0x1b, 0xff, 0xfd, 0x3b,
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0xb2, 0xa0, 0x6e, 0x6c, 0xea, 0x10, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
"products": ps,
|
"products": ps,
|
||||||
"cart_size": len(cart),
|
"cart_size": len(cart),
|
||||||
"banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments
|
"banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments
|
||||||
"ad": fe.chooseAd(r.Context(), log),
|
"ad": fe.chooseAd(r.Context(), []string{}, log),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request)
|
||||||
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
|
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
|
||||||
"session_id": sessionID(r),
|
"session_id": sessionID(r),
|
||||||
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
"request_id": r.Context().Value(ctxKeyRequestID{}),
|
||||||
"ad": fe.chooseAd(r.Context(), log),
|
"ad": fe.chooseAd(r.Context(), p.Categories, log),
|
||||||
"user_currency": currentCurrency(r),
|
"user_currency": currentCurrency(r),
|
||||||
"currencies": currencies,
|
"currencies": currencies,
|
||||||
"product": product,
|
"product": product,
|
||||||
|
@ -346,8 +346,8 @@ func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Requ
|
||||||
|
|
||||||
// chooseAd queries for advertisements available and randomly chooses one, if
|
// chooseAd queries for advertisements available and randomly chooses one, if
|
||||||
// available. It ignores the error retrieving the ad since it is not critical.
|
// available. It ignores the error retrieving the ad since it is not critical.
|
||||||
func (fe *frontendServer) chooseAd(ctx context.Context, log logrus.FieldLogger) *pb.Ad {
|
func (fe *frontendServer) chooseAd(ctx context.Context, ctxKeys []string, log logrus.FieldLogger) *pb.Ad {
|
||||||
ads, err := fe.getAd(ctx)
|
ads, err := fe.getAd(ctx, ctxKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithField("error", err).Warn("failed to retrieve ads")
|
log.WithField("error", err).Warn("failed to retrieve ads")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"go.opencensus.io/exporter/jaeger"
|
||||||
"go.opencensus.io/plugin/ocgrpc"
|
"go.opencensus.io/plugin/ocgrpc"
|
||||||
"go.opencensus.io/plugin/ochttp"
|
"go.opencensus.io/plugin/ochttp"
|
||||||
"go.opencensus.io/plugin/ochttp/propagation/b3"
|
"go.opencensus.io/plugin/ochttp/propagation/b3"
|
||||||
|
@ -142,7 +143,31 @@ func main() {
|
||||||
log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
|
log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initJaegerTracing(log logrus.FieldLogger) {
|
||||||
|
|
||||||
|
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
|
||||||
|
if svcAddr == "" {
|
||||||
|
log.Info("jaeger initialization disabled.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the Jaeger exporter to be able to retrieve
|
||||||
|
// the collected spans.
|
||||||
|
exporter, err := jaeger.NewExporter(jaeger.Options{
|
||||||
|
Endpoint: fmt.Sprintf("http://%s", svcAddr),
|
||||||
|
Process: jaeger.Process{
|
||||||
|
ServiceName: "frontend",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
trace.RegisterExporter(exporter)
|
||||||
|
log.Info("jaeger initialization completed.")
|
||||||
|
}
|
||||||
|
|
||||||
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
|
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
|
||||||
|
view.SetReportingPeriod(60 * time.Second)
|
||||||
view.RegisterExporter(exporter)
|
view.RegisterExporter(exporter)
|
||||||
if err := view.Register(ochttp.DefaultServerViews...); err != nil {
|
if err := view.Register(ochttp.DefaultServerViews...); err != nil {
|
||||||
log.Warn("Error registering http default server views")
|
log.Warn("Error registering http default server views")
|
||||||
|
@ -156,17 +181,19 @@ func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTracing(log logrus.FieldLogger) {
|
func initStackdriverTracing(log logrus.FieldLogger) {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
for i := 1; i <= 3; i++ {
|
for i := 1; i <= 3; i++ {
|
||||||
log = log.WithField("retry", i)
|
log = log.WithField("retry", i)
|
||||||
exporter, err := stackdriver.NewExporter(stackdriver.Options{})
|
exporter, err := stackdriver.NewExporter(stackdriver.Options{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// log.Warnf is used since there are multiple backends (stackdriver & jaeger)
|
||||||
|
// to store the traces. In production setup most likely you would use only one backend.
|
||||||
|
// In that case you should use log.Fatalf.
|
||||||
log.Warnf("failed to initialize stackdriver exporter: %+v", err)
|
log.Warnf("failed to initialize stackdriver exporter: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
trace.RegisterExporter(exporter)
|
trace.RegisterExporter(exporter)
|
||||||
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
|
||||||
log.Info("registered stackdriver tracing")
|
log.Info("registered stackdriver tracing")
|
||||||
|
|
||||||
// Register the views to collect server stats.
|
// Register the views to collect server stats.
|
||||||
|
@ -180,6 +207,18 @@ func initTracing(log logrus.FieldLogger) {
|
||||||
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initTracing(log logrus.FieldLogger) {
|
||||||
|
// This is a demo app with low QPS. trace.AlwaysSample() is used here
|
||||||
|
// to make sure traces are available for observation and analysis.
|
||||||
|
// In a production environment or high QPS setup please use
|
||||||
|
// trace.ProbabilitySampler set at the desired probability.
|
||||||
|
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
|
||||||
|
|
||||||
|
initJaegerTracing(log)
|
||||||
|
initStackdriverTracing(log)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func initProfiling(log logrus.FieldLogger, service, version string) {
|
func initProfiling(log logrus.FieldLogger, service, version string) {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
|
|
|
@ -116,12 +116,12 @@ func (fe *frontendServer) getRecommendations(ctx context.Context, userID string,
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fe *frontendServer) getAd(ctx context.Context) ([]*pb.Ad, error) {
|
func (fe *frontendServer) getAd(ctx context.Context, ctxKeys []string) ([]*pb.Ad, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
|
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
resp, err := pb.NewAdServiceClient(fe.adSvcConn).GetAds(ctx, &pb.AdRequest{
|
resp, err := pb.NewAdServiceClient(fe.adSvcConn).GetAds(ctx, &pb.AdRequest{
|
||||||
ContextKeys: nil,
|
ContextKeys: ctxKeys,
|
||||||
})
|
})
|
||||||
return resp.GetAds(), errors.Wrap(err, "failed to get ads")
|
return resp.GetAds(), errors.Wrap(err, "failed to get ads")
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-2 mb-3">
|
<div class="col-md-2 mb-3">
|
||||||
<label for="credit_card_cvv">CVV</label>
|
<label for="credit_card_cvv">CVV</label>
|
||||||
<input type="text" class="form-control" id="credit_card_cvv"
|
<input type="password" class="form-control" id="credit_card_cvv"
|
||||||
|
autocomplete="off"
|
||||||
name="credit_card_cvv" value="672" required pattern="\d{3}">
|
name="credit_card_cvv" value="672" required pattern="\d{3}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
FROM python:3.6
|
FROM python:3-slim as base
|
||||||
|
|
||||||
|
FROM base as builder
|
||||||
|
|
||||||
|
RUN apt-get -qq update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
g++
|
||||||
|
|
||||||
COPY requirements.txt .
|
COPY requirements.txt .
|
||||||
RUN pip install -r requirements.txt
|
|
||||||
|
RUN pip install --install-option="--prefix=/install" -r requirements.txt
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
COPY --from=builder /install /usr/local
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
ENTRYPOINT ./loadgen.sh
|
ENTRYPOINT ./loadgen.sh
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash -eu
|
#!/bin/sh -eu
|
||||||
#
|
#
|
||||||
# Copyright 2018 Google LLC
|
# Copyright 2018 Google LLC
|
||||||
#
|
#
|
||||||
|
|
|
@ -60,7 +60,7 @@ def checkout(l):
|
||||||
'country': 'United States',
|
'country': 'United States',
|
||||||
'credit_card_number': '4432-8015-6152-0454',
|
'credit_card_number': '4432-8015-6152-0454',
|
||||||
'credit_card_expiration_month': '1',
|
'credit_card_expiration_month': '1',
|
||||||
'credit_card_expiration_year': '2019',
|
'credit_card_expiration_year': '2039',
|
||||||
'credit_card_cvv': '672',
|
'credit_card_cvv': '672',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
1
src/loadgenerator/requirements.in
Normal file
1
src/loadgenerator/requirements.in
Normal file
|
@ -0,0 +1 @@
|
||||||
|
locustio==0.8.1
|
|
@ -1,2 +1,23 @@
|
||||||
|
#
|
||||||
|
# This file is autogenerated by pip-compile
|
||||||
|
# To update, run:
|
||||||
|
#
|
||||||
|
# pip-compile --output-file requirements.txt requirements.in
|
||||||
|
#
|
||||||
|
certifi==2018.11.29 # via requests
|
||||||
|
chardet==3.0.4 # via requests
|
||||||
|
click==7.0 # via flask
|
||||||
|
flask==1.0.2 # via locustio
|
||||||
|
gevent==1.4.0 # via locustio
|
||||||
|
greenlet==0.4.15 # via gevent
|
||||||
|
idna==2.8 # via requests
|
||||||
|
itsdangerous==1.1.0 # via flask
|
||||||
|
jinja2==2.10 # via flask
|
||||||
locustio==0.8.1
|
locustio==0.8.1
|
||||||
pyzmq==17.0.0
|
markupsafe==1.1.0 # via jinja2
|
||||||
|
msgpack-python==0.5.6 # via locustio
|
||||||
|
pyzmq==17.0.0 # via locustio
|
||||||
|
requests==2.21.0 # via locustio
|
||||||
|
six==1.12.0 # via locustio
|
||||||
|
urllib3==1.24.1 # via requests
|
||||||
|
werkzeug==0.14.1 # via flask
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
FROM node:8
|
FROM node:8-alpine as base
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
FROM base as builder
|
||||||
chmod +x /bin/grpc_health_probe
|
|
||||||
|
# Some packages (e.g. @google-cloud/profiler) require additional
|
||||||
|
# deps for post-install scripts
|
||||||
|
RUN apk add --update --no-cache \
|
||||||
|
python \
|
||||||
|
make \
|
||||||
|
g++
|
||||||
|
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
@ -9,8 +15,18 @@ COPY package*.json ./
|
||||||
|
|
||||||
RUN npm install --only=production
|
RUN npm install --only=production
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
|
||||||
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY --from=builder /usr/src/app/node_modules ./node_modules
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
EXPOSE 50051
|
EXPOSE 50051
|
||||||
|
|
||||||
CMD [ "node", "index.js" ]
|
ENTRYPOINT [ "node", "index.js" ]
|
||||||
|
|
|
@ -14,6 +14,15 @@
|
||||||
|
|
||||||
const cardValidator = require('simple-card-validator');
|
const cardValidator = require('simple-card-validator');
|
||||||
const uuid = require('uuid/v4');
|
const uuid = require('uuid/v4');
|
||||||
|
const pino = require('pino');
|
||||||
|
|
||||||
|
const logger = pino({
|
||||||
|
name: 'paymentservice-charge',
|
||||||
|
messageKey: 'message',
|
||||||
|
changeLevelName: 'severity',
|
||||||
|
useLevelLabels: true
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
class CreditCardError extends Error {
|
class CreditCardError extends Error {
|
||||||
constructor (message) {
|
constructor (message) {
|
||||||
|
@ -67,7 +76,7 @@ module.exports = function charge (request) {
|
||||||
const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;
|
const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;
|
||||||
if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }
|
if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }
|
||||||
|
|
||||||
console.log(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
|
logger.info(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
|
||||||
Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);
|
Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);
|
||||||
|
|
||||||
return { transaction_id: uuid() };
|
return { transaction_id: uuid() };
|
||||||
|
|
62
src/paymentservice/package-lock.json
generated
62
src/paymentservice/package-lock.json
generated
|
@ -700,16 +700,36 @@
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||||
},
|
},
|
||||||
|
"fast-json-parse": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw=="
|
||||||
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||||
},
|
},
|
||||||
|
"fast-redact": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-k/uSk9PtFmvYx0m7bRk5B2gZChQk4euWhrn7Mf3vYSmwZBLh7cGNuMuc/vhH1MKMPyVJMMtl9oMwPnwlKqs7CQ=="
|
||||||
|
},
|
||||||
|
"fast-safe-stringify": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
|
||||||
|
},
|
||||||
"findit2": {
|
"findit2": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz",
|
||||||
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY="
|
"integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY="
|
||||||
},
|
},
|
||||||
|
"flatstr": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-YXblbv/vc1zuVVUtnKl1hPqqk7TalZCppnKE7Pr8FI/Rp48vzckS/4SJ4Y9O9RNiI82Vcw/FydmtqdQOg1Dpqw=="
|
||||||
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.1.tgz",
|
||||||
|
@ -1592,6 +1612,26 @@
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
|
||||||
},
|
},
|
||||||
|
"pino": {
|
||||||
|
"version": "5.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino/-/pino-5.6.2.tgz",
|
||||||
|
"integrity": "sha512-JVMYqJkE58b2u5+t85zJLbUDOhoWDjEQqrRY1eQzuR4Ub9RIyUSQJms4deT8Joy+C/QIdrrie7NffgCm+ao9xw==",
|
||||||
|
"requires": {
|
||||||
|
"fast-json-parse": "^1.0.3",
|
||||||
|
"fast-redact": "^1.2.0",
|
||||||
|
"fast-safe-stringify": "^2.0.6",
|
||||||
|
"flatstr": "^1.0.5",
|
||||||
|
"pino-std-serializers": "^2.2.1",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"quick-format-unescaped": "^3.0.0",
|
||||||
|
"sonic-boom": "^0.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pino-std-serializers": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-QqL7kkF7eMCpFG4hpZD8UPQga/kxkkh3E62HzMzTIL4OQyijyisAnBL8msBEAml8xcb/ioGhH7UUzGxuHqczhQ=="
|
||||||
|
},
|
||||||
"pretty-ms": {
|
"pretty-ms": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz",
|
||||||
|
@ -1621,6 +1661,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||||
},
|
},
|
||||||
|
"pump": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||||
|
"requires": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||||
|
@ -1631,6 +1680,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||||
},
|
},
|
||||||
|
"quick-format-unescaped": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-XmIOc07VM2kPm6m3j/U6jgxyUgDm2Rgh2c1PPy0JUHoQRdoh86hOym0bHyF6G1T6sn+N5lildhvl/T59H5KVyA=="
|
||||||
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
|
@ -1728,6 +1782,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/simple-card-validator/-/simple-card-validator-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/simple-card-validator/-/simple-card-validator-1.1.0.tgz",
|
||||||
"integrity": "sha1-675uRp/q7Cy7SBX4Qyu+BMccNvk="
|
"integrity": "sha1-675uRp/q7Cy7SBX4Qyu+BMccNvk="
|
||||||
},
|
},
|
||||||
|
"sonic-boom": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-3qx6XXDeG+hPNa+jla1H6BMBLcjLl8L8NRERLVeIf/EuPqoqmq4K8owG29Xu7OypT/7/YT/0uKW6YitsKA+nLQ==",
|
||||||
|
"requires": {
|
||||||
|
"flatstr": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"@google-cloud/trace-agent": "^2.11.0",
|
"@google-cloud/trace-agent": "^2.11.0",
|
||||||
"@grpc/proto-loader": "^0.1.0",
|
"@grpc/proto-loader": "^0.1.0",
|
||||||
"grpc": "^1.12.3",
|
"grpc": "^1.12.3",
|
||||||
|
"pino": "^5.6.2",
|
||||||
"simple-card-validator": "^1.1.0",
|
"simple-card-validator": "^1.1.0",
|
||||||
"uuid": "^3.2.1"
|
"uuid": "^3.2.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -64,6 +64,10 @@ message Product {
|
||||||
string description = 3;
|
string description = 3;
|
||||||
string picture = 4;
|
string picture = 4;
|
||||||
Money price_usd = 5;
|
Money price_usd = 5;
|
||||||
|
|
||||||
|
// Categories such as "vintage" or "gardening" that can be used to look up
|
||||||
|
// other related products.
|
||||||
|
repeated string categories = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ListProductsResponse {
|
message ListProductsResponse {
|
||||||
|
@ -218,18 +222,18 @@ message PlaceOrderResponse {
|
||||||
OrderResult order = 1;
|
OrderResult order = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------Ads service------------------
|
// ------------Ad service------------------
|
||||||
|
|
||||||
service AdsService {
|
service AdService {
|
||||||
rpc GetAds(AdsRequest) returns (AdsResponse) {}
|
rpc GetAds(AdRequest) returns (AdResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdsRequest {
|
message AdRequest {
|
||||||
// List of important key words from the current page describing the context.
|
// List of important key words from the current page describing the context.
|
||||||
repeated string context_keys = 1;
|
repeated string context_keys = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdsResponse {
|
message AdResponse {
|
||||||
repeated Ad ads = 1;
|
repeated Ad ads = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,18 @@
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
|
const pino = require('pino');
|
||||||
const protoLoader = require('@grpc/proto-loader');
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
|
||||||
const charge = require('./charge');
|
const charge = require('./charge');
|
||||||
|
|
||||||
|
const logger = pino({
|
||||||
|
name: 'paymentservice-server',
|
||||||
|
messageKey: 'message',
|
||||||
|
changeLevelName: 'severity',
|
||||||
|
useLevelLabels: true
|
||||||
|
});
|
||||||
|
|
||||||
class HipsterShopServer {
|
class HipsterShopServer {
|
||||||
constructor (protoRoot, port = HipsterShopServer.DEFAULT_PORT) {
|
constructor (protoRoot, port = HipsterShopServer.DEFAULT_PORT) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
@ -38,7 +46,7 @@ class HipsterShopServer {
|
||||||
*/
|
*/
|
||||||
static ChargeServiceHandler (call, callback) {
|
static ChargeServiceHandler (call, callback) {
|
||||||
try {
|
try {
|
||||||
console.log(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`);
|
logger.info(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`);
|
||||||
const response = charge(call.request);
|
const response = charge(call.request);
|
||||||
callback(null, response);
|
callback(null, response);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -53,7 +61,7 @@ class HipsterShopServer {
|
||||||
|
|
||||||
listen () {
|
listen () {
|
||||||
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
|
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
|
||||||
console.log(`PaymentService grpc server listening on ${this.port}`);
|
logger.info(`PaymentService grpc server listening on ${this.port}`);
|
||||||
this.server.start();
|
this.server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.10-alpine AS builder
|
FROM golang:1.12-alpine AS builder
|
||||||
RUN apk add --no-cache ca-certificates git && \
|
RUN apk add --no-cache ca-certificates git && \
|
||||||
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
|
||||||
chmod +x /go/bin/dep
|
chmod +x /go/bin/dep
|
||||||
|
@ -15,7 +15,7 @@ RUN go build -o /productcatalogservice .
|
||||||
|
|
||||||
FROM alpine AS release
|
FROM alpine AS release
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
chmod +x /bin/grpc_health_probe
|
chmod +x /bin/grpc_health_probe
|
||||||
WORKDIR /productcatalogservice
|
WORKDIR /productcatalogservice
|
||||||
|
|
148
src/productcatalogservice/Gopkg.lock
generated
148
src/productcatalogservice/Gopkg.lock
generated
|
@ -2,27 +2,46 @@
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:467af0aad47996b25b838d6f14c8371123a8a76ec239020a6c5894e1f8f60272"
|
||||||
name = "cloud.google.com/go"
|
name = "cloud.google.com/go"
|
||||||
packages = [
|
packages = [
|
||||||
"compute/metadata",
|
"compute/metadata",
|
||||||
"internal/version",
|
"internal/version",
|
||||||
"monitoring/apiv3",
|
"monitoring/apiv3",
|
||||||
"profiler",
|
"profiler",
|
||||||
"trace/apiv2"
|
"trace/apiv2",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
|
revision = "c728a003b238b26cef9ab6753a5dc424b331c3ad"
|
||||||
version = "v0.27.0"
|
version = "v0.27.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
|
||||||
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
name = "contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
packages = [
|
packages = ["."]
|
||||||
".",
|
pruneopts = "UT"
|
||||||
"propagation"
|
|
||||||
]
|
|
||||||
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
revision = "37aa2801fbf0205003e15636096ebf0373510288"
|
||||||
version = "v0.5.0"
|
version = "v0.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:d3a57cdbaefaceca4ebe6258ed86a992bdcfc93a8442dbda5343e2d43a8f8a6a"
|
||||||
|
name = "git.apache.org/thrift.git"
|
||||||
|
packages = ["lib/go/thrift"]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "67df34afa782be67154034b31e4ad7cb3834fed1"
|
||||||
|
source = "github.com/apache/thrift"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
digest = "1:14e66208d324c0ecb49934b5ac311c50a94e3a458e92b0026ef9e26919ac8d9d"
|
||||||
|
name = "github.com/GoogleCloudPlatform/microservices-demo"
|
||||||
|
packages = ["src/productcatalogservice/genproto"]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "10dfd04ab174cc680ed6ffef26cc4fb09ec40404"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:4fbf68bee2a60f6af6414572936edb295f6f26b73c6fb25ab0e7b03b013854f5"
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
packages = [
|
packages = [
|
||||||
"jsonpb",
|
"jsonpb",
|
||||||
|
@ -34,46 +53,67 @@
|
||||||
"ptypes/empty",
|
"ptypes/empty",
|
||||||
"ptypes/struct",
|
"ptypes/struct",
|
||||||
"ptypes/timestamp",
|
"ptypes/timestamp",
|
||||||
"ptypes/wrappers"
|
"ptypes/wrappers",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
|
||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:2e3c336fc7fde5c984d2841455a658a6d626450b1754a854b3b32e7a8f49a07a"
|
||||||
name = "github.com/google/go-cmp"
|
name = "github.com/google/go-cmp"
|
||||||
packages = [
|
packages = [
|
||||||
"cmp",
|
"cmp",
|
||||||
"cmp/internal/diff",
|
"cmp/internal/diff",
|
||||||
"cmp/internal/function",
|
"cmp/internal/function",
|
||||||
"cmp/internal/value"
|
"cmp/internal/value",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "3af367b6b30c263d47e8895973edcca9a49cf029"
|
revision = "3af367b6b30c263d47e8895973edcca9a49cf029"
|
||||||
version = "v0.2.0"
|
version = "v0.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:fc55304e290027108ae0cac675a171bcd854f9c657678c20ceea837718ea6819"
|
||||||
name = "github.com/google/pprof"
|
name = "github.com/google/pprof"
|
||||||
packages = ["profile"]
|
packages = ["profile"]
|
||||||
revision = "e027b505a088ac3c68c339a1d7ce7724bf34538b"
|
pruneopts = "UT"
|
||||||
|
revision = "e84dfd68c163c45ea47aa24b3dc7eaa93f6675b1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:cd9864c6366515827a759931746738ede6079faa08df9c584596370d6add135c"
|
||||||
name = "github.com/googleapis/gax-go"
|
name = "github.com/googleapis/gax-go"
|
||||||
packages = ["."]
|
packages = [
|
||||||
revision = "317e0006254c44a0ac427cc52a0e083ff0b9622f"
|
".",
|
||||||
version = "v2.0.0"
|
"v2",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
|
||||||
|
version = "v2.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:d867dfa6751c8d7a435821ad3b736310c2ed68945d05b50fb9d23aee0540c8cc"
|
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
|
||||||
|
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||||
|
version = "v1.0.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:87c2e02fb01c27060ccc5ba7c5a407cc91147726f8f40b70cceeedbc52b1f3a8"
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "3e01752db0189b9157070a0e1668a620f9a85da2"
|
revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
|
||||||
version = "v1.0.6"
|
version = "v1.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a5154dfd6b37bef5a3eab759e13296348e639dc8c7604f538368167782b08ccd"
|
||||||
name = "go.opencensus.io"
|
name = "go.opencensus.io"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
"exporter/jaeger",
|
||||||
|
"exporter/jaeger/internal/gen-go/jaeger",
|
||||||
"internal",
|
"internal",
|
||||||
"internal/tagencoding",
|
"internal/tagencoding",
|
||||||
"plugin/ocgrpc",
|
"plugin/ocgrpc",
|
||||||
|
@ -86,21 +126,23 @@
|
||||||
"trace",
|
"trace",
|
||||||
"trace/internal",
|
"trace/internal",
|
||||||
"trace/propagation",
|
"trace/propagation",
|
||||||
"trace/tracestate"
|
"trace/tracestate",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
|
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
|
||||||
version = "v0.16.0"
|
version = "v0.16.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
|
digest = "1:38f553aff0273ad6f367cb0a0f8b6eecbaef8dc6cb8b50e57b6a81c1d5b1e332"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["ssh/terminal"]
|
packages = ["ssh/terminal"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "0e37d006457bf46f9e6692014ba72ef82c33022c"
|
revision = "ff983b9c42bc9fbf91556e191cc8efb585c16908"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:9d2f08c64693fbe7177b5980f80c35672c80f12be79bb3bc86948b934d70e4ee"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
"context",
|
"context",
|
||||||
|
@ -110,35 +152,46 @@
|
||||||
"http2/hpack",
|
"http2/hpack",
|
||||||
"idna",
|
"idna",
|
||||||
"internal/timeseries",
|
"internal/timeseries",
|
||||||
"trace"
|
"trace",
|
||||||
]
|
]
|
||||||
revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2"
|
pruneopts = "UT"
|
||||||
|
revision = "ed066c81e75eba56dd9bd2139ade88125b855585"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:511a6232760c10dcb1ebf1ab83ef0291e2baf801f203ca6314759c5458b73a6a"
|
||||||
name = "golang.org/x/oauth2"
|
name = "golang.org/x/oauth2"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"google",
|
"google",
|
||||||
"internal",
|
"internal",
|
||||||
"jws",
|
"jws",
|
||||||
"jwt"
|
"jwt",
|
||||||
]
|
]
|
||||||
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9"
|
pruneopts = "UT"
|
||||||
|
revision = "5dab4167f31cbd76b407f1486c86b40748bc5073"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:75515eedc0dc2cb0b40372008b616fa2841d831c63eedd403285ff286c593295"
|
||||||
name = "golang.org/x/sync"
|
name = "golang.org/x/sync"
|
||||||
packages = ["semaphore"]
|
packages = ["semaphore"]
|
||||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
pruneopts = "UT"
|
||||||
|
revision = "37e7f081c4d4c64e13b10787722085407fe5d15f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:43cde116ff48f299eddb7e6515677e6d0a2c915854bb05a333877f07c3bb3033"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = ["unix"]
|
packages = [
|
||||||
revision = "1561086e645b2809fb9f8a1e2a38160bf8d53bf4"
|
"unix",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
|
revision = "11f53e03133963fb11ae0588e08b5e0b85be8be5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||||
name = "golang.org/x/text"
|
name = "golang.org/x/text"
|
||||||
packages = [
|
packages = [
|
||||||
"collate",
|
"collate",
|
||||||
|
@ -154,13 +207,15 @@
|
||||||
"unicode/bidi",
|
"unicode/bidi",
|
||||||
"unicode/cldr",
|
"unicode/cldr",
|
||||||
"unicode/norm",
|
"unicode/norm",
|
||||||
"unicode/rangetable"
|
"unicode/rangetable",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:26a71f62c83707b9952821c2a895bd041588501fa370cc267221817fcc721253"
|
||||||
name = "google.golang.org/api"
|
name = "google.golang.org/api"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapi/transport",
|
"googleapi/transport",
|
||||||
|
@ -170,11 +225,14 @@
|
||||||
"support/bundler",
|
"support/bundler",
|
||||||
"transport",
|
"transport",
|
||||||
"transport/grpc",
|
"transport/grpc",
|
||||||
"transport/http"
|
"transport/http",
|
||||||
|
"transport/http/internal/propagation",
|
||||||
]
|
]
|
||||||
revision = "19ff8768a5c0b8e46ea281065664787eefc24121"
|
pruneopts = "UT"
|
||||||
|
revision = "43037ff31f6958582e5d3c19d9ac1a4d2819669c"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:c4eaa5f79d36f76ef4bd0c4f96e36bc1b7b5a359528d1267f0cb7a5d58b7b5bb"
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -188,13 +246,15 @@
|
||||||
"internal/socket",
|
"internal/socket",
|
||||||
"internal/urlfetch",
|
"internal/urlfetch",
|
||||||
"socket",
|
"socket",
|
||||||
"urlfetch"
|
"urlfetch",
|
||||||
]
|
]
|
||||||
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06"
|
pruneopts = "UT"
|
||||||
version = "v1.2.0"
|
revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
|
||||||
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:3552e7267a98c605e6cbfe6b03c34589265ab72e6078b95fb2e10e0cb44f5cc8"
|
||||||
name = "google.golang.org/genproto"
|
name = "google.golang.org/genproto"
|
||||||
packages = [
|
packages = [
|
||||||
"googleapis/api/annotations",
|
"googleapis/api/annotations",
|
||||||
|
@ -207,11 +267,13 @@
|
||||||
"googleapis/monitoring/v3",
|
"googleapis/monitoring/v3",
|
||||||
"googleapis/rpc/errdetails",
|
"googleapis/rpc/errdetails",
|
||||||
"googleapis/rpc/status",
|
"googleapis/rpc/status",
|
||||||
"protobuf/field_mask"
|
"protobuf/field_mask",
|
||||||
]
|
]
|
||||||
revision = "c3f76f3b92d1ffa4c58a9ff842a58b8877655e0f"
|
pruneopts = "UT"
|
||||||
|
revision = "db91494dd46c1fdcbbde05e5ff5eb56df8f7d79a"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
|
digest = "1:6497ab07ec89179db8d5a563d33635be04ceffaa29007a3ae74b9f15f4d3068e"
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -241,14 +303,32 @@
|
||||||
"resolver/passthrough",
|
"resolver/passthrough",
|
||||||
"stats",
|
"stats",
|
||||||
"status",
|
"status",
|
||||||
"tap"
|
"tap",
|
||||||
]
|
]
|
||||||
|
pruneopts = "UT"
|
||||||
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
|
revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
|
||||||
version = "v1.14.0"
|
version = "v1.14.0"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "b68fd9438c2eb711d9fc51c1f23c5ca0d5169bf4022351dfc400cd35ba39dfaa"
|
input-imports = [
|
||||||
|
"cloud.google.com/go/profiler",
|
||||||
|
"contrib.go.opencensus.io/exporter/stackdriver",
|
||||||
|
"github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto",
|
||||||
|
"github.com/golang/protobuf/jsonpb",
|
||||||
|
"github.com/golang/protobuf/proto",
|
||||||
|
"github.com/google/go-cmp/cmp",
|
||||||
|
"github.com/sirupsen/logrus",
|
||||||
|
"go.opencensus.io/exporter/jaeger",
|
||||||
|
"go.opencensus.io/plugin/ocgrpc",
|
||||||
|
"go.opencensus.io/stats/view",
|
||||||
|
"go.opencensus.io/trace",
|
||||||
|
"golang.org/x/net/context",
|
||||||
|
"google.golang.org/grpc",
|
||||||
|
"google.golang.org/grpc/codes",
|
||||||
|
"google.golang.org/grpc/health/grpc_health_v1",
|
||||||
|
"google.golang.org/grpc/status",
|
||||||
|
]
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -3,3 +3,36 @@
|
||||||
Run the following command to restore dependencies to `vendor/` directory:
|
Run the following command to restore dependencies to `vendor/` directory:
|
||||||
|
|
||||||
dep ensure --vendor-only
|
dep ensure --vendor-only
|
||||||
|
|
||||||
|
## Dynamic catalog reloading / artificial delay
|
||||||
|
|
||||||
|
This service has a "dynamic catalog reloading" feature that is purposefully
|
||||||
|
not well implemented. The goal of this feature is to allow you to modify the
|
||||||
|
`products.json` file and have the changes be picked up without having to
|
||||||
|
restart the service.
|
||||||
|
|
||||||
|
However, this feature is bugged: the catalog is actually reloaded on each
|
||||||
|
request, introducing a noticeable delay in the frontend. This delay will also
|
||||||
|
show up in profiling tools: the `parseCatalog` function will take more than 80%
|
||||||
|
of the CPU time.
|
||||||
|
|
||||||
|
You can trigger this feature (and the delay) by sending a `USR1` signal and
|
||||||
|
remove it (if needed) by sending a `USR2` signal:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Trigger bug
|
||||||
|
kubectl exec \
|
||||||
|
$(kubectl get pods -l app=productcatalogservice -o jsonpath='{.items[0].metadata.name}') \
|
||||||
|
-c server -- kill -USR1 1
|
||||||
|
# Remove bug
|
||||||
|
kubectl exec \
|
||||||
|
$(kubectl get pods -l app=productcatalogservice -o jsonpath='{.items[0].metadata.name}') \
|
||||||
|
-c server -- kill -USR2 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Latency injection
|
||||||
|
|
||||||
|
This service has an `EXTRA_LATENCY` environment variable. This will inject a sleep for the specified [time.Duration](https://golang.org/pkg/time/#ParseDuration) on every call to
|
||||||
|
to the server.
|
||||||
|
|
||||||
|
For example, use `EXTRA_LATENCY="5.5s"` to sleep for 5.5 seconds on every request.
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 67,
|
"units": 67,
|
||||||
"nanos": 990000000
|
"nanos": 990000000
|
||||||
}
|
},
|
||||||
|
"categories": ["vintage"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "66VCHSJNUP",
|
"id": "66VCHSJNUP",
|
||||||
|
@ -20,7 +21,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 12,
|
"units": 12,
|
||||||
"nanos": 490000000
|
"nanos": 490000000
|
||||||
}
|
},
|
||||||
|
"categories": ["photography", "vintage"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "1YMWWN1N4O",
|
"id": "1YMWWN1N4O",
|
||||||
|
@ -30,7 +32,8 @@
|
||||||
"priceUsd": {
|
"priceUsd": {
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 124
|
"units": 124
|
||||||
}
|
},
|
||||||
|
"categories": ["cookware"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "L9ECAV7KIM",
|
"id": "L9ECAV7KIM",
|
||||||
|
@ -41,7 +44,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 36,
|
"units": 36,
|
||||||
"nanos": 450000000
|
"nanos": 450000000
|
||||||
}
|
},
|
||||||
|
"categories": ["gardening"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2ZYFJ3GM2N",
|
"id": "2ZYFJ3GM2N",
|
||||||
|
@ -51,7 +55,8 @@
|
||||||
"priceUsd": {
|
"priceUsd": {
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 2245
|
"units": 2245
|
||||||
}
|
},
|
||||||
|
"categories": ["photography", "vintage"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "0PUK6V6EV0",
|
"id": "0PUK6V6EV0",
|
||||||
|
@ -62,7 +67,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 65,
|
"units": 65,
|
||||||
"nanos": 500000000
|
"nanos": 500000000
|
||||||
}
|
},
|
||||||
|
"categories": ["music", "vintage"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "LS4PSXUNUM",
|
"id": "LS4PSXUNUM",
|
||||||
|
@ -73,7 +79,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 24,
|
"units": 24,
|
||||||
"nanos": 330000000
|
"nanos": 330000000
|
||||||
}
|
},
|
||||||
|
"categories": ["cookware"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "9SIQT8TOJO",
|
"id": "9SIQT8TOJO",
|
||||||
|
@ -84,7 +91,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 789,
|
"units": 789,
|
||||||
"nanos": 500000000
|
"nanos": 500000000
|
||||||
}
|
},
|
||||||
|
"categories": ["cycling"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "6E92ZMYYFZ",
|
"id": "6E92ZMYYFZ",
|
||||||
|
@ -95,7 +103,8 @@
|
||||||
"currencyCode": "USD",
|
"currencyCode": "USD",
|
||||||
"units": 12,
|
"units": 12,
|
||||||
"nanos": 300000000
|
"nanos": 300000000
|
||||||
}
|
},
|
||||||
|
"categories": ["gardening"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,10 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
pb "github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto"
|
pb "github.com/GoogleCloudPlatform/microservices-demo/src/productcatalogservice/genproto"
|
||||||
|
@ -32,6 +35,7 @@ import (
|
||||||
"contrib.go.opencensus.io/exporter/stackdriver"
|
"contrib.go.opencensus.io/exporter/stackdriver"
|
||||||
"github.com/golang/protobuf/jsonpb"
|
"github.com/golang/protobuf/jsonpb"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"go.opencensus.io/exporter/jaeger"
|
||||||
"go.opencensus.io/plugin/ocgrpc"
|
"go.opencensus.io/plugin/ocgrpc"
|
||||||
"go.opencensus.io/stats/view"
|
"go.opencensus.io/stats/view"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
|
@ -41,18 +45,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
catalogJSON []byte
|
cat pb.ListProductsResponse
|
||||||
|
catalogMutex *sync.Mutex
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
|
extraLatency time.Duration
|
||||||
|
|
||||||
port = flag.Int("port", 3550, "port to listen at")
|
port = flag.Int("port", 3550, "port to listen at")
|
||||||
|
|
||||||
|
reloadCatalog bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
c, err := ioutil.ReadFile("products.json")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to open product catalog json file: %v", err)
|
|
||||||
}
|
|
||||||
catalogJSON = c
|
|
||||||
log = logrus.New()
|
log = logrus.New()
|
||||||
log.Formatter = &logrus.JSONFormatter{
|
log.Formatter = &logrus.JSONFormatter{
|
||||||
FieldMap: logrus.FieldMap{
|
FieldMap: logrus.FieldMap{
|
||||||
|
@ -63,7 +66,11 @@ func init() {
|
||||||
TimestampFormat: time.RFC3339Nano,
|
TimestampFormat: time.RFC3339Nano,
|
||||||
}
|
}
|
||||||
log.Out = os.Stdout
|
log.Out = os.Stdout
|
||||||
log.Info("successfully parsed product catalog json")
|
catalogMutex = &sync.Mutex{}
|
||||||
|
err := readCatalogFile(&cat)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("could not parse product catalog")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -71,6 +78,34 @@ func main() {
|
||||||
go initProfiling("productcatalogservice", "1.0.0")
|
go initProfiling("productcatalogservice", "1.0.0")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
// set injected latency
|
||||||
|
if s := os.Getenv("EXTRA_LATENCY"); s != "" {
|
||||||
|
v, err := time.ParseDuration(s)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to parse EXTRA_LATENCY (%s) as time.Duration: %+v", v, err)
|
||||||
|
}
|
||||||
|
extraLatency = v
|
||||||
|
log.Infof("extra latency enabled (duration: %v)", extraLatency)
|
||||||
|
} else {
|
||||||
|
extraLatency = time.Duration(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
sigs := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
sig := <-sigs
|
||||||
|
log.Printf("Received signal: %s", sig)
|
||||||
|
if sig == syscall.SIGUSR1 {
|
||||||
|
reloadCatalog = true
|
||||||
|
log.Infof("Enable catalog reloading")
|
||||||
|
} else {
|
||||||
|
reloadCatalog = false
|
||||||
|
log.Infof("Disable catalog reloading")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
log.Infof("starting grpc server at :%d", *port)
|
log.Infof("starting grpc server at :%d", *port)
|
||||||
run(*port)
|
run(*port)
|
||||||
select {}
|
select {}
|
||||||
|
@ -89,7 +124,29 @@ func run(port int) string {
|
||||||
return l.Addr().String()
|
return l.Addr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initJaegerTracing() {
|
||||||
|
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
|
||||||
|
if svcAddr == "" {
|
||||||
|
log.Info("jaeger initialization disabled.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Register the Jaeger exporter to be able to retrieve
|
||||||
|
// the collected spans.
|
||||||
|
exporter, err := jaeger.NewExporter(jaeger.Options{
|
||||||
|
Endpoint: fmt.Sprintf("http://%s", svcAddr),
|
||||||
|
Process: jaeger.Process{
|
||||||
|
ServiceName: "productcatalogservice",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
trace.RegisterExporter(exporter)
|
||||||
|
log.Info("jaeger initialization completed.")
|
||||||
|
}
|
||||||
|
|
||||||
func initStats(exporter *stackdriver.Exporter) {
|
func initStats(exporter *stackdriver.Exporter) {
|
||||||
|
view.SetReportingPeriod(60 * time.Second)
|
||||||
view.RegisterExporter(exporter)
|
view.RegisterExporter(exporter)
|
||||||
if err := view.Register(ocgrpc.DefaultServerViews...); err != nil {
|
if err := view.Register(ocgrpc.DefaultServerViews...); err != nil {
|
||||||
log.Info("Error registering default server views")
|
log.Info("Error registering default server views")
|
||||||
|
@ -98,7 +155,7 @@ func initStats(exporter *stackdriver.Exporter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTracing() {
|
func initStackDriverTracing() {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
for i := 1; i <= 3; i++ {
|
for i := 1; i <= 3; i++ {
|
||||||
|
@ -121,6 +178,11 @@ func initTracing() {
|
||||||
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
log.Warn("could not initialize stackdriver exporter after retrying, giving up")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initTracing() {
|
||||||
|
initJaegerTracing()
|
||||||
|
initStackDriverTracing()
|
||||||
|
}
|
||||||
|
|
||||||
func initProfiling(service, version string) {
|
func initProfiling(service, version string) {
|
||||||
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
// TODO(ahmetb) this method is duplicated in other microservices using Go
|
||||||
// since they are not sharing packages.
|
// since they are not sharing packages.
|
||||||
|
@ -145,12 +207,28 @@ func initProfiling(service, version string) {
|
||||||
|
|
||||||
type productCatalog struct{}
|
type productCatalog struct{}
|
||||||
|
|
||||||
func parseCatalog() []*pb.Product {
|
func readCatalogFile(catalog *pb.ListProductsResponse) error {
|
||||||
var cat pb.ListProductsResponse
|
catalogMutex.Lock()
|
||||||
|
defer catalogMutex.Unlock()
|
||||||
if err := jsonpb.Unmarshal(bytes.NewReader(catalogJSON), &cat); err != nil {
|
catalogJSON, err := ioutil.ReadFile("products.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to open product catalog json file: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := jsonpb.Unmarshal(bytes.NewReader(catalogJSON), catalog); err != nil {
|
||||||
log.Warnf("failed to parse the catalog JSON: %v", err)
|
log.Warnf("failed to parse the catalog JSON: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("successfully parsed product catalog json")
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCatalog() []*pb.Product {
|
||||||
|
if reloadCatalog || len(cat.Products) == 0 {
|
||||||
|
err := readCatalogFile(&cat)
|
||||||
|
if err != nil {
|
||||||
|
return []*pb.Product{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cat.Products
|
return cat.Products
|
||||||
}
|
}
|
||||||
|
@ -160,10 +238,12 @@ func (p *productCatalog) Check(ctx context.Context, req *healthpb.HealthCheckReq
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
|
func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb.ListProductsResponse, error) {
|
||||||
|
time.Sleep(extraLatency)
|
||||||
return &pb.ListProductsResponse{Products: parseCatalog()}, nil
|
return &pb.ListProductsResponse{Products: parseCatalog()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
|
func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductRequest) (*pb.Product, error) {
|
||||||
|
time.Sleep(extraLatency)
|
||||||
var found *pb.Product
|
var found *pb.Product
|
||||||
for i := 0; i < len(parseCatalog()); i++ {
|
for i := 0; i < len(parseCatalog()); i++ {
|
||||||
if req.Id == parseCatalog()[i].Id {
|
if req.Id == parseCatalog()[i].Id {
|
||||||
|
@ -177,6 +257,7 @@ func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetProductReque
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
|
func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.SearchProductsRequest) (*pb.SearchProductsResponse, error) {
|
||||||
|
time.Sleep(extraLatency)
|
||||||
// Intepret query as a substring match in name or description.
|
// Intepret query as a substring match in name or description.
|
||||||
var ps []*pb.Product
|
var ps []*pb.Product
|
||||||
for _, p := range parseCatalog() {
|
for _, p := range parseCatalog() {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
FROM python:2.7-slim
|
FROM python:2.7-slim
|
||||||
RUN apt-get update -qqy && \
|
RUN apt-get update -qqy && \
|
||||||
apt-get -qqy install wget && \
|
apt-get -qqy install wget g++ && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
# show python logs as they occur
|
# show python logs as they occur
|
||||||
ENV PYTHONUNBUFFERED=0
|
ENV PYTHONUNBUFFERED=0
|
||||||
|
|
||||||
# download the grpc health probe
|
# download the grpc health probe
|
||||||
RUN GRPC_HEALTH_PROBE_VERSION=v0.1.0-alpha.1 && \
|
RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \
|
||||||
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
|
||||||
chmod +x /bin/grpc_health_probe
|
chmod +x /bin/grpc_health_probe
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,18 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import sys
|
||||||
import grpc
|
import grpc
|
||||||
import demo_pb2
|
import demo_pb2
|
||||||
import demo_pb2_grpc
|
import demo_pb2_grpc
|
||||||
import sys
|
|
||||||
|
|
||||||
from opencensus.trace.tracer import Tracer
|
from opencensus.trace.tracer import Tracer
|
||||||
from opencensus.trace.exporters import stackdriver_exporter
|
from opencensus.trace.exporters import stackdriver_exporter
|
||||||
from opencensus.trace.ext.grpc import client_interceptor
|
from opencensus.trace.ext.grpc import client_interceptor
|
||||||
|
|
||||||
|
from logger import getJSONLogger
|
||||||
|
logger = getJSONLogger('recommendationservice-server')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# get port
|
# get port
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
|
@ -45,4 +48,4 @@ if __name__ == "__main__":
|
||||||
request = demo_pb2.ListRecommendationsRequest(user_id="test", product_ids=["test"])
|
request = demo_pb2.ListRecommendationsRequest(user_id="test", product_ids=["test"])
|
||||||
# make call to server
|
# make call to server
|
||||||
response = stub.ListRecommendations(request)
|
response = stub.ListRecommendations(request)
|
||||||
print(response)
|
logger.info(response)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue