Merge branch 'master' of sso://user/ahmetb/microservices-demo into createCartService

This commit is contained in:
Simon Zeltser 2018-06-21 14:54:12 -07:00
commit bd7da5fe89
25 changed files with 3694 additions and 9 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
bin/
pkg/
.DS_Store .DS_Store
*.pyc *.pyc
*.swp *.swp

View file

@ -0,0 +1,37 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: checkoutservice
spec:
replicas: 1
template:
metadata:
labels:
app: checkoutservice
spec:
containers:
- name: server
image: checkoutservice
ports:
- containerPort: 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"
---
apiVersion: v1
kind: Service
metadata:
name: checkoutservice
spec:
type: ClusterIP
selector:
app: checkoutservice
ports:
- port: 5050
targetPort: 5050

View file

@ -0,0 +1,27 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: emailservice
spec:
template:
metadata:
labels:
app: emailservice
spec:
containers:
- name: server
image: emailservice
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: emailservice
spec:
type: ClusterIP
selector:
app: emailservice
ports:
- port: 5000
targetPort: 5000

View file

@ -0,0 +1,27 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: paymentservice
spec:
template:
metadata:
labels:
app: paymentservice
spec:
containers:
- name: server
image: paymentservice
ports:
- containerPort: 50051
---
apiVersion: v1
kind: Service
metadata:
name: paymentservice
spec:
type: ClusterIP
selector:
app: paymentservice
ports:
- port: 50051
targetPort: 50051

View file

@ -0,0 +1,27 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: productcatalogservice
spec:
template:
metadata:
labels:
app: productcatalogservice
spec:
containers:
- name: server
image: productcatalogservice
ports:
- containerPort: 3550
---
apiVersion: v1
kind: Service
metadata:
name: productcatalogservice
spec:
type: ClusterIP
selector:
app: productcatalogservice
ports:
- port: 3550
targetPort: 3550

View file

@ -0,0 +1,30 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: recommendationservice
spec:
template:
metadata:
labels:
app: recommendationservice
spec:
containers:
- name: server
image: recommendationservice
ports:
- containerPort: 8080
env:
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
---
apiVersion: v1
kind: Service
metadata:
name: recommendationservice
spec:
type: ClusterIP
selector:
app: recommendationservice
ports:
- port: 8080
targetPort: 8080

View file

@ -0,0 +1,27 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: shippingservice
spec:
template:
metadata:
labels:
app: shippingservice
spec:
containers:
- name: server
image: shippingservice
ports:
- containerPort: 50051
---
apiVersion: v1
kind: Service
metadata:
name: shippingservice
spec:
type: ClusterIP
selector:
app: shippingservice
ports:
- port: 50051
targetPort: 50051

20
skaffold.yaml Normal file
View file

@ -0,0 +1,20 @@
apiVersion: skaffold/v1alpha2
kind: Config
build:
artifacts:
- imageName: emailservice
workspace: src/emailservice
- imageName: productcatalogservice
workspace: src/productcatalogservice
- imageName: recommendationservice
workspace: src/recommendationservice
- imageName: shippingservice
workspace: src/shippingservice
- imageName: checkoutservice
workspace: src/checkoutservice
- imageName: paymentservice
workspace: src/paymentservice
deploy:
kubectl:
manifests:
- ./kubernetes-manifests/**.yaml

View file

@ -0,0 +1,13 @@
FROM golang:1.10-alpine as builder
RUN apk add --no-cache ca-certificates git
WORKDIR /src/microservices-demo/catalogservice
COPY . .
RUN go get -d ./...
RUN go build -o /catalogservice .
FROM alpine as release
RUN apk add --no-cache \
ca-certificates
COPY --from=builder /catalogservice /catalogservice
EXPOSE 5050
ENTRYPOINT ["/catalogservice"]

View file

@ -0,0 +1,6 @@
#!/bin/bash -e
PATH=$PATH:$GOPATH/bin
protodir=../../pb
protoc --go_out=plugins=grpc:genproto -I $protodir $protodir/demo.proto

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
package main
import (
"context"
"fmt"
"log"
"net"
"os"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "./genproto"
"google.golang.org/grpc"
)
const (
listenPort = "5050"
)
type checkoutService struct {
productCatalogSvcAddr string
cartSvcAddr string
currencySvcAddr string
shippingSvcAddr string
emailSvcAddr string
paymentSvcAddr string
}
func main() {
port := listenPort
if os.Getenv("PORT") != "" {
port = os.Getenv("PORT")
}
svc := new(checkoutService)
mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
// mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
// mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
// mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
// mustMapEnv(&svc.emailSvcAddr, "EMAIL_SERVICE_ADDR")
// mustMapEnv(&svc.paymentSvcAddr, "PAYMENT_SERVICE_ADDR")
log.Printf("service config: %+v", svc)
lis, err := net.Listen("tcp", fmt.Sprintf(":%s", port))
if err != nil {
log.Fatal(err)
}
srv := grpc.NewServer()
pb.RegisterCheckoutServiceServer(srv, svc)
log.Printf("starting to listen on tcp: %q", lis.Addr().String())
log.Fatal(srv.Serve(lis))
}
func mustMapEnv(target *string, envKey string) {
v := os.Getenv(envKey)
if v == "" {
panic(fmt.Sprintf("environment variable %q not set", envKey))
}
*target = v
}
func (cs *checkoutService) CreateOrder(ctx context.Context, req *pb.CreateOrderRequest) (*pb.CreateOrderResponse, error) {
log.Printf("[CreateOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)
resp := new(pb.CreateOrderResponse)
conn, err := grpc.Dial(cs.shippingSvcAddr, grpc.WithInsecure())
if err != nil {
return nil, status.Errorf(codes.Unavailable, "could not connect shippping service: %+v", err)
}
defer conn.Close()
shippingQuote, err := pb.NewShippingServiceClient(conn).
GetQuote(ctx, &pb.GetQuoteRequest{
Address: req.Address,
Items: nil}) // TODO(ahmetb): query CartService for items
if err != nil {
return nil, status.Errorf(codes.Unavailable, "failed to get shipping quote: %+v", err)
}
resp.ShippingCost = &pb.Money{
Amount: shippingQuote.GetCostUsd(),
CurrencyCode: "USD", // TOD(ahmetb) convert to req.UserCurrency
}
// TODO(ahmetb) calculate resp.OrderItem with req.UserCurrency
return resp, nil
}
func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.PlaceOrderRequest) (*pb.PlaceOrderResponse, error) {
log.Printf("[PlaceOrder] user_id=%q user_currency=%q", req.UserId, req.UserCurrency)
resp := new(pb.PlaceOrderResponse)
return resp, nil
}

View file

@ -0,0 +1 @@
node_modules

3
src/paymentservice/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules
proto
.DS_Store

View file

@ -0,0 +1,13 @@
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . .
EXPOSE 50051
CMD [ "node", "index.js" ]

View file

@ -0,0 +1,64 @@
const cardValidator = require('simple-card-validator');
class CreditCardError extends Error {
constructor(message) {
super(message);
this.code = 400; // Invalid argument error
}
}
class InvalidCreditCard extends CreditCardError {
constructor(cardType) {
super(`Credit card info is invalid`);
}
}
class UnacceptedCreditCard extends CreditCardError {
constructor(cardType) {
super(`Sorry, we cannot process ${cardType} credit cards. Only VISA or MasterCard is accepted.`);
}
}
class ExpiredCreditCard extends CreditCardError {
constructor(number, month, year) {
super(`Your credit card (ending ${number.substr(-4)}) expired on ${month}/${year}`);
}
}
/**
* Verifies the credit card number and (pretend) charges the card.
*
* @param {*} request
* @return transaction_id - a random number.
*/
module.exports = function charge(request) {
const { amount, credit_card: creditCard } = request;
const cardNumber = creditCard.credit_card_number;
const cardInfo = cardValidator(cardNumber);
const {
card_type: cardType,
valid,
cvv_length: cvvLength,
} = cardInfo.getCardDetails();
if (!valid)
throw new InvalidCreditCard();
// Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will
// throw UnacceptedCreditCard error.
if (!(cardType === 'visa' || cardType == 'mastercard'))
throw new UnacceptedCreditCard(cardType);
// Also validate expiration is > today.
const currentMonth = new Date().getMonth() + 1;
const currentYear = new Date().getFullYear();
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);
console.log(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
Amount: ${amount.currency_code}${amount.amount.decimal}.${amount.amount.fractional}`)
return { transaction_id: -1 }
}

6
src/paymentservice/genproto.sh Executable file
View file

@ -0,0 +1,6 @@
#!/bin/bash -e
# protos are loaded dynamically for node, simply copies over the proto.
mkdir -p proto && \
cp ../../pb/demo.proto proto

View file

@ -0,0 +1,27 @@
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
const HipsterShopServer = require('./server');
const PORT = process.env['PORT'];
const PROTO_PATH = __dirname + '/proto/demo.proto';
const server = new HipsterShopServer(PROTO_PATH, PORT);
server.listen();

788
src/paymentservice/package-lock.json generated Normal file
View file

@ -0,0 +1,788 @@
{
"name": "paymentservice",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@grpc/proto-loader": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.1.0.tgz",
"integrity": "sha512-GHoZBR5N+65AWazsCiJDxeMSbUpp2qNYbjeD3mP27L2PT25+GvIupIIJiCgULH87NAiAd9SmWMRBVz+uSiHpgA==",
"requires": {
"@types/lodash": "4.14.110",
"@types/node": "9.6.22",
"lodash": "4.17.10",
"protobufjs": "6.8.6"
},
"dependencies": {
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"protobufjs": {
"version": "6.8.6",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.6.tgz",
"integrity": "sha512-eH2OTP9s55vojr3b7NBaF9i4WhWPkv/nq55nznWNp/FomKrLViprUcqnBjHph2tFQ+7KciGPTPsVWGz0SOhL0Q==",
"requires": {
"@protobufjs/aspromise": "1.1.2",
"@protobufjs/base64": "1.1.2",
"@protobufjs/codegen": "2.0.4",
"@protobufjs/eventemitter": "1.1.0",
"@protobufjs/fetch": "1.1.0",
"@protobufjs/float": "1.0.2",
"@protobufjs/inquire": "1.1.0",
"@protobufjs/path": "1.1.2",
"@protobufjs/pool": "1.1.0",
"@protobufjs/utf8": "1.1.0",
"@types/long": "3.0.32",
"@types/node": "8.10.20",
"long": "4.0.0"
},
"dependencies": {
"@types/node": {
"version": "8.10.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.20.tgz",
"integrity": "sha512-M7x8+5D1k/CuA6jhiwuSCmE8sbUWJF0wYsjcig9WrXvwUI5ArEoUBdOXpV4JcEMrLp02/QbDjw+kI+vQeKyQgg=="
}
}
}
}
},
"@protobufjs/aspromise": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
},
"@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
},
"@protobufjs/codegen": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
},
"@protobufjs/eventemitter": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
"integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
},
"@protobufjs/fetch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
"integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
"requires": {
"@protobufjs/aspromise": "1.1.2",
"@protobufjs/inquire": "1.1.0"
}
},
"@protobufjs/float": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
},
"@protobufjs/inquire": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
"integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
},
"@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
},
"@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
},
"@protobufjs/utf8": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
},
"@types/lodash": {
"version": "4.14.110",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.110.tgz",
"integrity": "sha512-iXYLa6olt4tnsCA+ZXeP6eEW3tk1SulWeYyP/yooWfAtXjozqXgtX4+XUtMuOCfYjKGz3F34++qUc3Q+TJuIIw=="
},
"@types/long": {
"version": "3.0.32",
"resolved": "https://registry.npmjs.org/@types/long/-/long-3.0.32.tgz",
"integrity": "sha512-ZXyOOm83p7X8p3s0IYM3VeueNmHpkk/yMlP8CLeOnEcu6hIwPH7YjZBvhQkR0ZFS2DqZAxKtJ/M5fcuv3OU5BA=="
},
"@types/node": {
"version": "9.6.22",
"resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.22.tgz",
"integrity": "sha512-RIg9EkxzVMkNH0M4sLRngK23f5QiigJC0iODQmu4nopzstt8AjegYund3r82iMrd2BNCjcZVnklaItvKHaGfBA=="
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"ascli": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz",
"integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=",
"requires": {
"colour": "0.7.1",
"optjs": "3.2.2"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"bytebuffer": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz",
"integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=",
"requires": {
"long": "3.2.0"
}
},
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"requires": {
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wrap-ansi": "2.1.0"
}
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"colour": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz",
"integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"grpc": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/grpc/-/grpc-1.12.3.tgz",
"integrity": "sha512-QPwbAXRXd8IyXAhTdUVgjEqSdvXoTq5uFWSo+eGMTcra12PBJUkAceD+1AUVOx1GqBY74/7T7eB7BB+UOcOY8w==",
"requires": {
"lodash": "4.17.10",
"nan": "2.10.0",
"node-pre-gyp": "0.10.0",
"protobufjs": "5.0.3"
},
"dependencies": {
"abbrev": {
"version": "1.1.1",
"bundled": true
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
},
"aproba": {
"version": "1.2.0",
"bundled": true
},
"are-we-there-yet": {
"version": "1.1.4",
"bundled": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.3.6"
}
},
"balanced-match": {
"version": "1.0.0",
"bundled": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"chownr": {
"version": "1.0.1",
"bundled": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true
},
"debug": {
"version": "2.6.9",
"bundled": true,
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.5.1",
"bundled": true
},
"delegates": {
"version": "1.0.0",
"bundled": true
},
"detect-libc": {
"version": "1.0.3",
"bundled": true
},
"fs-minipass": {
"version": "1.2.5",
"bundled": true,
"requires": {
"minipass": "2.3.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"requires": {
"aproba": "1.2.0",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"glob": {
"version": "7.1.2",
"bundled": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"has-unicode": {
"version": "2.0.1",
"bundled": true
},
"iconv-lite": {
"version": "0.4.23",
"bundled": true,
"requires": {
"safer-buffer": "2.1.2"
}
},
"ignore-walk": {
"version": "3.0.1",
"bundled": true,
"requires": {
"minimatch": "3.0.4"
}
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"bundled": true
},
"ini": {
"version": "1.3.5",
"bundled": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"requires": {
"number-is-nan": "1.0.1"
}
},
"isarray": {
"version": "1.0.0",
"bundled": true
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"requires": {
"brace-expansion": "1.1.11"
}
},
"minimist": {
"version": "1.2.0",
"bundled": true
},
"minipass": {
"version": "2.3.0",
"bundled": true,
"requires": {
"safe-buffer": "5.1.2",
"yallist": "3.0.2"
}
},
"minizlib": {
"version": "1.1.0",
"bundled": true,
"requires": {
"minipass": "2.3.0"
}
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"requires": {
"minimist": "0.0.8"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"bundled": true
}
}
},
"ms": {
"version": "2.0.0",
"bundled": true
},
"needle": {
"version": "2.2.1",
"bundled": true,
"requires": {
"debug": "2.6.9",
"iconv-lite": "0.4.23",
"sax": "1.2.4"
}
},
"node-pre-gyp": {
"version": "0.10.0",
"bundled": true,
"requires": {
"detect-libc": "1.0.3",
"mkdirp": "0.5.1",
"needle": "2.2.1",
"nopt": "4.0.1",
"npm-packlist": "1.1.10",
"npmlog": "4.1.2",
"rc": "1.2.7",
"rimraf": "2.6.2",
"semver": "5.5.0",
"tar": "4.4.2"
}
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"requires": {
"abbrev": "1.1.1",
"osenv": "0.1.5"
}
},
"npm-bundled": {
"version": "1.0.3",
"bundled": true
},
"npm-packlist": {
"version": "1.1.10",
"bundled": true,
"requires": {
"ignore-walk": "3.0.1",
"npm-bundled": "1.0.3"
}
},
"npmlog": {
"version": "4.1.2",
"bundled": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"bundled": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true
},
"osenv": {
"version": "0.1.5",
"bundled": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true
},
"process-nextick-args": {
"version": "2.0.0",
"bundled": true
},
"rc": {
"version": "1.2.7",
"bundled": true,
"requires": {
"deep-extend": "0.5.1",
"ini": "1.3.5",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
}
},
"readable-stream": {
"version": "2.3.6",
"bundled": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "2.0.0",
"safe-buffer": "5.1.2",
"string_decoder": "1.1.1",
"util-deprecate": "1.0.2"
}
},
"rimraf": {
"version": "2.6.2",
"bundled": true,
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true
},
"safer-buffer": {
"version": "2.1.2",
"bundled": true
},
"sax": {
"version": "1.2.4",
"bundled": true
},
"semver": {
"version": "5.5.0",
"bundled": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"bundled": true,
"requires": {
"safe-buffer": "5.1.2"
}
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true
},
"tar": {
"version": "4.4.2",
"bundled": true,
"requires": {
"chownr": "1.0.1",
"fs-minipass": "1.2.5",
"minipass": "2.3.0",
"minizlib": "1.1.0",
"mkdirp": "0.5.1",
"safe-buffer": "5.1.2",
"yallist": "3.0.2"
}
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true
},
"wide-align": {
"version": "1.1.2",
"bundled": true,
"requires": {
"string-width": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true
},
"yallist": {
"version": "3.0.2",
"bundled": true
}
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"requires": {
"number-is-nan": "1.0.1"
}
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"requires": {
"invert-kv": "1.0.0"
}
},
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
},
"long": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
"integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "1.1.11"
}
},
"nan": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA=="
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"optjs": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz",
"integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4="
},
"os-locale": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"requires": {
"lcid": "1.0.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"protobufjs": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz",
"integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==",
"requires": {
"ascli": "1.0.1",
"bytebuffer": "5.0.1",
"glob": "7.1.2",
"yargs": "3.32.0"
}
},
"simple-card-validator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-card-validator/-/simple-card-validator-1.1.0.tgz",
"integrity": "sha1-675uRp/q7Cy7SBX4Qyu+BMccNvk="
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"window-size": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
"integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"requires": {
"string-width": "1.0.2",
"strip-ansi": "3.0.1"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
},
"yargs": {
"version": "3.32.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
"integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
"requires": {
"camelcase": "2.1.1",
"cliui": "3.2.0",
"decamelize": "1.2.0",
"os-locale": "1.4.0",
"string-width": "1.0.2",
"window-size": "0.1.4",
"y18n": "3.2.1"
}
}
}
}

View file

@ -0,0 +1,16 @@
{
"name": "paymentservice",
"version": "0.0.1",
"description": "Payment Microservice demo",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jonathan Lui",
"license": "ISC",
"dependencies": {
"@grpc/proto-loader": "^0.1.0",
"grpc": "^1.12.3",
"simple-card-validator": "^1.1.0"
}
}

View file

@ -0,0 +1,65 @@
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
const charge = require('./charge');
class HipsterShopServer {
constructor(protoFile, port = HipsterShopServer.DEFAULT_PORT) {
this.port = port;
this.server = new grpc.Server();
this.loadProto(protoFile);
}
/**
* Handler for PaymentService.Charge.
* @param {*} call { ChargeRequest }
* @param {*} callback fn(err, ChargeResponse)
*/
static ChargeServiceHandler(call, callback) {
try {
console.log(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`)
const response = charge(call.request)
callback(null, response);
} catch (err) {
console.warn(err);
callback(err);
}
}
listen() {
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
console.log(`PaymentService grpc server listening on ${this.port}`);
this.server.start();
}
loadProto(path) {
const packageDefinition = protoLoader.loadSync(
path,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
},
);
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const hipsterShopPackage = protoDescriptor.hipstershop;
this.addProtoService(hipsterShopPackage.PaymentService.service);
}
addProtoService(service) {
this.server.addService(
service,
{
charge: HipsterShopServer.ChargeServiceHandler.bind(this),
},
);
}
}
HipsterShopServer.DEFAULT_PORT = 50051;
module.exports = HipsterShopServer;

View file

@ -5,12 +5,12 @@ RUN apk add --no-cache \
WORKDIR /src/microservices-demo/productcatalogservice WORKDIR /src/microservices-demo/productcatalogservice
COPY . . COPY . .
RUN go get -d ./... RUN go get -d ./...
RUN go build -v -o /productcatalogservice . RUN go build -o /productcatalogservice .
FROM alpine as release FROM alpine as release
RUN apk add --no-cache \ RUN apk add --no-cache \
ca-certificates ca-certificates
COPY --from=builder /productcatalogservice /productcatalogservice COPY --from=builder /productcatalogservice /productcatalogservice
EXPOSE 3550 EXPOSE 3550
ENTRYPOINT /productcatalogservice ENTRYPOINT ["/productcatalogservice"]

View file

@ -4,11 +4,11 @@ FROM grpc/python:1.0
ENV PYTHONUNBUFFERED=0 ENV PYTHONUNBUFFERED=0
# add files into working directory # add files into working directory
ADD ./*.py /home/ COPY . /home/
WORKDIR /home WORKDIR /home
# set listen port # set listen port
ENV PORT "8080" ENV PORT "8080"
EXPOSE 8080 EXPOSE 8080
ENTRYPOINT python /home/recommendation_server.py ENTRYPOINT ["python", "/home/recommendation_server.py"]

View file

@ -5,10 +5,10 @@ RUN apk add --no-cache \
WORKDIR /src/microservices-demo/shippingservice WORKDIR /src/microservices-demo/shippingservice
COPY . . COPY . .
RUN go get -d ./... RUN go get -d ./...
RUN go build -v -o /shippingservice . RUN go build -o /shippingservice .
FROM alpine as release FROM alpine as release
COPY --from=builder /shippingservice /shippingservice COPY --from=builder /shippingservice /shippingservice
ENV APP_PORT=50051 ENV APP_PORT=50051
EXPOSE 50051 EXPOSE 50051
ENTRYPOINT /shippingservice ENTRYPOINT ["/shippingservice"]

View file

@ -167,7 +167,7 @@ func testRecommendationService() error {
} }
func testPaymentService() error { func testPaymentService() error {
addr := os.Getenv("RECOMMENDATION_SERVICE_ADDR") addr := os.Getenv("PAYMENT_SERVICE_ADDR")
conn, err := grpc.Dial(addr, grpc.WithInsecure()) conn, err := grpc.Dial(addr, grpc.WithInsecure())
if err != nil { if err != nil {
return err return err
@ -184,13 +184,13 @@ func testPaymentService() error {
Fractional: 55}, Fractional: 55},
}, },
CreditCard: &pb.CreditCardInfo{ CreditCard: &pb.CreditCardInfo{
CreditCardNumber: "9999-9999-9999-9999", CreditCardNumber: "4444-4530-1092-6639",
CreditCardCvv: 612, CreditCardCvv: 612,
CreditCardExpirationYear: 2022, CreditCardExpirationYear: 2022,
CreditCardExpirationMonth: 10}, CreditCardExpirationMonth: 10},
}) })
if err != nil { if err != nil {
return nil return err
} }
log.Printf("--> resp: %+v", resp) log.Printf("--> resp: %+v", resp)
return nil return nil