Merge branch 'master' into pull/28

# Conflicts:
#	.gitignore
#	kubernetes-manifests/frontend.yaml
#	kubernetes-manifests/loadgenerator.yaml
#	release/kubernetes-manifests.yaml
#	src/loadgenerator/Dockerfile
#	src/loadgenerator/loadgen.sh
This commit is contained in:
asamanta 2020-03-12 16:39:04 -04:00
commit a4148a51c8
29 changed files with 462 additions and 44 deletions

4
.gitignore vendored
View file

@ -9,5 +9,7 @@ pkg/
.idea .idea
.skaffold-*.yaml .skaffold-*.yaml
.kubernetes-manifests-*/ .kubernetes-manifests-*/
env/
.project .project
.eclipse.buildship.core.prefs .eclipse.buildship.core.prefs

1
build.out Normal file
View file

@ -0,0 +1 @@
{"builds":[{"imageName":"gcr.io/lesser-weevil/emailservice","tag":"gcr.io/lesser-weevil/emailservice:v0.1.0-74-g468e8dc@sha256:7256c7e27888c37e06c19036032b594c5240d9a80bbe54963fda437346239742"},{"imageName":"gcr.io/lesser-weevil/productcatalogservice","tag":"gcr.io/lesser-weevil/productcatalogservice:v0.1.0-74-g468e8dc@sha256:19b199f0a976a3cebd5cf00d99d040a82c9824506de988d9485fffa828428898"},{"imageName":"gcr.io/lesser-weevil/recommendationservice","tag":"gcr.io/lesser-weevil/recommendationservice:v0.1.0-74-g468e8dc@sha256:3300a437de46c8d2e2144540ce0fe51ec2ea7b728c724021182337fd051bacad"},{"imageName":"gcr.io/lesser-weevil/shippingservice","tag":"gcr.io/lesser-weevil/shippingservice:v0.1.0-74-g468e8dc@sha256:dd8c49052601f9e3873d0c8034e6010645d83768df3526ee99cb43a71ce8344d"},{"imageName":"gcr.io/lesser-weevil/checkoutservice","tag":"gcr.io/lesser-weevil/checkoutservice:v0.1.0-74-g468e8dc@sha256:0955d209db61815892477b6f06b0f7a4c3c3d96e714c8c472faa5a442a2af875"},{"imageName":"gcr.io/lesser-weevil/paymentservice","tag":"gcr.io/lesser-weevil/paymentservice:v0.1.0-74-g468e8dc@sha256:07903a2bddf38920a940a2ab9aaddfbc7c06b0aa27dc07aaf8b9694722b44d92"},{"imageName":"gcr.io/lesser-weevil/currencyservice","tag":"gcr.io/lesser-weevil/currencyservice:v0.1.0-74-g468e8dc@sha256:df6b933e6b42a27035419119f93b471e4f9973b2934c0124da399c64dfc779a9"},{"imageName":"gcr.io/lesser-weevil/cartservice","tag":"gcr.io/lesser-weevil/cartservice:v0.1.0-74-g468e8dc@sha256:538f48876ad2f13603b4992bb3b75cde587333920f0a9f7e4d6d54924d349d3b"},{"imageName":"gcr.io/lesser-weevil/frontend","tag":"gcr.io/lesser-weevil/frontend:v0.1.0-74-g468e8dc@sha256:8b552b7de8dd9c45439d4a334f9d8dfeec0b989075a85e11cb17a81f2e47bab5"},{"imageName":"gcr.io/lesser-weevil/loadgenerator","tag":"gcr.io/lesser-weevil/loadgenerator:v0.1.0-74-g468e8dc@sha256:e874a37782981f587238a8b5ce807f7ce65d4c2f97c6bb847462de5a1aeb74c0"},{"imageName":"gcr.io/lesser-weevil/adservice","tag":"gcr.io/lesser-weevil/adservice:v0.1.0-74-g468e8dc@sha256:446a5743ebf2b7f27758c9d7588742223a42328838e7de222363f170d30e6231"},{"imageName":"gcr.io/lesser-weevil/pingjob","tag":"gcr.io/lesser-weevil/pingjob:v0.1.0-74-g468e8dc@sha256:0ade87236d2d837ca1d9b468497b7d05d729b6420120da35b8a9e64b20ce10a8"}]}

View file

@ -17,6 +17,8 @@ kind: Deployment
metadata: metadata:
name: adservice name: adservice
spec: spec:
revisionHistoryLimit: 1
replicas: 5
selector: selector:
matchLabels: matchLabels:
app: adservice app: adservice

View file

@ -17,6 +17,8 @@ kind: Deployment
metadata: metadata:
name: cartservice name: cartservice
spec: spec:
revisionHistoryLimit: 1
replicas: 10
selector: selector:
matchLabels: matchLabels:
app: cartservice app: cartservice
@ -41,10 +43,10 @@ spec:
resources: resources:
requests: requests:
cpu: 200m cpu: 200m
memory: 64Mi memory: 128Mi
limits: limits:
cpu: 300m cpu: 300m
memory: 128Mi memory: 256Mi
readinessProbe: readinessProbe:
initialDelaySeconds: 15 initialDelaySeconds: 15
exec: exec:

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: checkoutservice name: checkoutservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: checkoutservice app: checkoutservice

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: currencyservice name: currencyservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: currencyservice app: currencyservice
@ -67,3 +68,22 @@ spec:
- name: grpc - name: grpc
port: 7000 port: 7000
targetPort: 7000 targetPort: 7000
---
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: currencyservice
labels:
app: currencyservice
spec:
maxReplicas: 7
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: currencyservice
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 19

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: emailservice name: emailservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: emailservice app: emailservice

View file

@ -15,15 +15,82 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: frontend name: frontend-a
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: frontend app: frontend
env: a
template: template:
metadata: metadata:
labels: labels:
app: frontend app: frontend
env: a
spec:
containers:
- name: server
image: frontend
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: PORT
value: "8080"
- 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: apps/v1
kind: Deployment
metadata:
name: frontend-b
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
app: frontend
env: b
template:
metadata:
labels:
app: frontend
env: b
annotations: annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true" sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec: spec:
@ -100,6 +167,7 @@ spec:
type: LoadBalancer type: LoadBalancer
selector: selector:
app: frontend app: frontend
env: b
ports: ports:
- name: http - name: http
port: 80 port: 80

View file

@ -16,6 +16,7 @@ kind: Deployment
metadata: metadata:
name: loadgenerator name: loadgenerator
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: loadgenerator app: loadgenerator
@ -29,6 +30,17 @@ spec:
spec: spec:
terminationGracePeriodSeconds: 5 terminationGracePeriodSeconds: 5
restartPolicy: Always 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: containers:
- name: main - name: main
image: loadgenerator image: loadgenerator
@ -43,4 +55,4 @@ spec:
memory: 256Mi memory: 256Mi
limits: limits:
cpu: 500m cpu: 500m
memory: 512Mi memory: 512Mi

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: paymentservice name: paymentservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: paymentservice app: paymentservice

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: productcatalogservice name: productcatalogservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: productcatalogservice app: productcatalogservice

View file

@ -15,15 +15,18 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: recommendationservice name: recommendationservice-v1
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: recommendationservice app: recommendationservice
version: v1
template: template:
metadata: metadata:
labels: labels:
app: recommendationservice app: recommendationservice
version: v1
spec: spec:
terminationGracePeriodSeconds: 5 terminationGracePeriodSeconds: 5
containers: containers:
@ -58,6 +61,53 @@ spec:
cpu: 200m cpu: 200m
memory: 450Mi memory: 450Mi
--- ---
apiVersion: apps/v1
kind: Deployment
metadata:
name: recommendationservice-v2
spec:
selector:
matchLabels:
app: recommendationservice
version: v2
template:
metadata:
labels:
app: recommendationservice
version: v2
spec:
terminationGracePeriodSeconds: 5
containers:
- name: server
image: recommendationservice
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: PORT
value: "8080"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "productcatalogservice:3550"
- name: ENABLE_PROFILER
value: "0"
resources:
requests:
cpu: 100m
memory: 220Mi
limits:
cpu: 200m
memory: 450Mi
revisionHistoryLimit: 1
---
#In order for istio to route traffic correctly, it needs a kubernetes service to route traffic to
#the workloads in question.
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
@ -67,6 +117,38 @@ spec:
selector: selector:
app: recommendationservice app: recommendationservice
ports: ports:
- name: grpc - name: grpc
port: 8080 port: 8080
targetPort: 8080 targetPort: 8080
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: recommendationservice
spec:
hosts:
- recommendationservice
http:
- route:
- destination:
host: recommendationservice
subset: v1
weight: 90
- destination:
host: recommendationservice
subset: v2
weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: recommendationservice
spec:
host: recommendationservice
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: redis-cart name: redis-cart
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: redis-cart app: redis-cart

View file

@ -17,6 +17,7 @@ kind: Deployment
metadata: metadata:
name: shippingservice name: shippingservice
spec: spec:
revisionHistoryLimit: 1
selector: selector:
matchLabels: matchLabels:
app: shippingservice app: shippingservice
@ -24,6 +25,7 @@ spec:
metadata: metadata:
labels: labels:
app: shippingservice app: shippingservice
version: deployment
spec: spec:
containers: containers:
- name: server - name: server
@ -56,6 +58,47 @@ spec:
cpu: 200m cpu: 200m
memory: 128Mi memory: 128Mi
--- ---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: shippingservice-rs
spec:
replicas: 2
selector:
matchLabels:
app: shippingservice
owner: rs
template:
metadata:
labels:
app: shippingservice
owner: rs
spec:
containers:
- name: server
image: shippingservice
ports:
- containerPort: 50051
env:
- name: PORT
value: "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
---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:

View file

@ -46,7 +46,7 @@ const request = {
}; };
function _moneyToString (m) { function _moneyToString (m) {
return `${m.units}.${m.nanos.toString().padStart(9,'0')} ${m.currency_code}`; return `${m.units}.${m.nanos.toString().padStart(9, '0')} ${m.currency_code}`;
} }
client.getSupportedCurrencies({}, (err, response) => { client.getSupportedCurrencies({}, (err, response) => {

View file

@ -92,7 +92,13 @@ function _loadProto (path) {
*/ */
function _getCurrencyData (callback) { function _getCurrencyData (callback) {
const data = require('./data/currency_conversion.json'); const data = require('./data/currency_conversion.json');
callback(data); // Currency conversion API slows down during peak hours.
let delay = 0;
const hour = new Date().getHours();
if (hour > 8 && hour < 17) {
delay = 100; // add 100ms slowdown
}
setTimeout(() => callback(data), delay);
} }
/** /**

View file

@ -10,7 +10,9 @@
<p> <p>
<small class="text-muted"> <small class="text-muted">
This website is hosted for demo purposes only. It is not an This website is hosted for demo purposes only. It is not an
actual shop. This is not an official Google project. actual shop. This is not an official Google project. Demo
deployment for Google Cloud &amp; Signals Monitoring
Topology.
</small> </small>
</p> </p>
<small class="text-muted"> <small class="text-muted">

View file

@ -17,6 +17,9 @@
you catch up with the hipster trend and express your you catch up with the hipster trend and express your
personal style. Start shopping hip and vintage items now! personal style. Start shopping hip and vintage items now!
</p> </p>
<p class="lead text-muted">
Cloud Topology
</p>
</div> </div>
</section> </section>

View file

@ -14,8 +14,5 @@ FROM base
COPY --from=builder /install /usr/local COPY --from=builder /install /usr/local
COPY . . COPY . .
RUN chmod +x ./loadgen.sh ENTRYPOINT ["./loadgen.sh"]
RUN apt-get -qq update \
&& apt-get install -y --no-install-recommends \
curl
ENTRYPOINT ./loadgen.sh

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh -eu
# #
# Copyright 2018 Google LLC # Copyright 2018 Google LLC
# #
@ -14,22 +14,19 @@
# 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
set -e set -e
trap "exit" TERM trap "exit" TERM
if [[ -z "${FRONTEND_ADDR}" ]]; then if [ -z "${FRONTEND_ADDR}" ]; then
echo >&2 "FRONTEND_ADDR not specified" echo >&2 "FRONTEND_ADDR not specified"
exit 1 exit 1
fi fi
set -x set -x
locust \
# if one request to the frontend fails, then exit -f locustfile.py \
STATUSCODE=$(curl --silent --output /dev/stderr --write-out "%{http_code}" http://${FRONTEND_ADDR}) --host="http://${FRONTEND_ADDR}" \
if test $STATUSCODE -ne 200; then --no-web \
echo "Error: Could not reach frontend - Status code: ${STATUSCODE}" -c "${USERS:-10}" \
exit 1 -r 1
fi
# else, run loadgen
locust --host="http://${FRONTEND_ADDR}" --no-web -c "${USERS:-10}" 2>&1

View file

@ -14,7 +14,9 @@
# 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 math
import random import random
import time
from locust import HttpLocust, TaskSet from locust import HttpLocust, TaskSet
products = [ products = [
@ -28,29 +30,39 @@ products = [
'LS4PSXUNUM', 'LS4PSXUNUM',
'OLJCESPC7Z'] 'OLJCESPC7Z']
def index(l): def index(l):
l.client.get("/") l.client.get("/")
def setCurrency(l): def setCurrency(l):
currencies = ['EUR', 'USD', 'JPY', 'CAD'] currencies = ['EUR', 'USD', 'JPY', 'CAD']
l.client.post("/setCurrency", l.client.post("/setCurrency",
{'currency_code': random.choice(currencies)}) {'currency_code': random.choice(currencies)})
def browseProduct(l): def browseProduct(l):
l.client.get("/product/" + random.choice(products)) l.client.get("/product/" + random.choice(products))
def viewCart(l): def viewCart(l):
l.client.get("/cart") l.client.get("/cart")
def addToCart(l): def addToCart(l):
product = random.choice(products) product = random.choice(products)
l.client.get("/product/" + product) l.client.get("/product/" + product)
l.client.post("/cart", { l.client.post("/cart", {
'product_id': product, 'product_id': product,
'quantity': random.choice([1,2,3,4,5,10])}) 'quantity': random.choice([1, 2, 3, 4, 5, 10])})
def checkout(l): def checkout(l):
addToCart(l) addToCart(l)
# For five minutes every other hour, credit cards passed by the user will be
# invalid and the paymentservice will fail.
now = time.localtime()
expiration_year = '2015' if (now.tm_hour % 2) & (now.tm_min < 5) else '2060'
l.client.post("/cart/checkout", { l.client.post("/cart/checkout", {
'email': 'someone@example.com', 'email': 'someone@example.com',
'street_address': '1600 Amphitheatre Parkway', 'street_address': '1600 Amphitheatre Parkway',
@ -60,23 +72,41 @@ 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': '2039', 'credit_card_expiration_year': expiration_year,
'credit_card_cvv': '672', 'credit_card_cvv': '672',
}) })
class UserBehavior(TaskSet): class UserBehavior(TaskSet):
min_wait = 500
max_wait = 15000
tasks = {index: 1,
setCurrency: 2,
browseProduct: 10,
addToCart: 2,
viewCart: 3,
checkout: 1}
def on_start(self): def on_start(self):
index(self) index(self)
tasks = {index: 1, def wait_function(self):
setCurrency: 2, """Wait time between user activity is diurnal.
browseProduct: 10,
addToCart: 2, Compute user's activity rate (wait time between actions) so traffic is
viewCart: 3, minimum at hrs=0.0|24.0 and maximum at hrs=12.0.
checkout: 1} """
now = time.localtime()
hrs = now.tm_hour + now.tm_min/60.0
# Compute scale factor is between 0 and 1.
traffic_scaler = -1.0 * math.cos(2.0 * math.pi * hrs / 24)
traffic_scaler = (traffic_scaler + 1) / 2.0
# Scale traffic between minimum and maximum wait times.
wait = self.max_wait + (self.min_wait - self.max_wait) * traffic_scaler
return round(wait)
class WebsiteUser(HttpLocust): class WebsiteUser(HttpLocust):
task_set = UserBehavior task_set = UserBehavior
min_wait = 1000
max_wait = 10000

View file

@ -1 +1 @@
locustio==0.8.1 locustio==0.9.0

View file

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile # This file is autogenerated by pip-compile
# To update, run: # To update, run:
# #
# pip-compile --output-file requirements.txt requirements.in # pip-compile --output-file=requirements.txt requirements.in
# #
certifi==2018.11.29 # via requests certifi==2018.11.29 # via requests
chardet==3.0.4 # via requests chardet==3.0.4 # via requests
@ -13,9 +13,9 @@ greenlet==0.4.15 # via gevent
idna==2.8 # via requests idna==2.8 # via requests
itsdangerous==1.1.0 # via flask itsdangerous==1.1.0 # via flask
jinja2==2.10 # via flask jinja2==2.10 # via flask
locustio==0.8.1 locustio==0.9.0
markupsafe==1.1.0 # via jinja2 markupsafe==1.1.0 # via jinja2
msgpack-python==0.5.6 # via locustio msgpack==0.6.1 # via locustio
pyzmq==17.0.0 # via locustio pyzmq==17.0.0 # via locustio
requests==2.21.0 # via locustio requests==2.21.0 # via locustio
six==1.12.0 # via locustio six==1.12.0 # via locustio

View file

@ -15,6 +15,7 @@
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 pino = require('pino');
const grpc = require('grpc');
const logger = pino({ const logger = pino({
name: 'paymentservice-charge', name: 'paymentservice-charge',
@ -28,6 +29,7 @@ class CreditCardError extends Error {
constructor (message) { constructor (message) {
super(message); super(message);
this.code = 400; // Invalid argument error this.code = 400; // Invalid argument error
this.status = grpc.status.INVALID_ARGUMENT;
} }
} }

18
src/pingjob/Dockerfile Normal file
View file

@ -0,0 +1,18 @@
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 .
RUN pip install --install-option="--prefix=/install" -r requirements.txt
FROM base
COPY --from=builder /install /usr/local
COPY . .
ENTRYPOINT ["./pinger.sh"]

87
src/pingjob/pinger.py Normal file
View file

@ -0,0 +1,87 @@
#!/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 random
import requests
import sys
BASE = sys.argv[1]
products = [
'0PUK6V6EV0',
'1YMWWN1N4O',
'2ZYFJ3GM2N',
'66VCHSJNUP',
'6E92ZMYYFZ',
'9SIQT8TOJO',
'L9ECAV7KIM',
'LS4PSXUNUM',
'OLJCESPC7Z']
def index():
requests.get(BASE + "/")
def setCurrency():
currencies = ['EUR', 'USD', 'JPY', 'CAD']
requests.post(BASE + "/setCurrency",
{'currency_code': random.choice(currencies)})
def browseProduct():
requests.get(BASE + "/product/" + random.choice(products))
def viewCart():
requests.get(BASE + "/cart")
def addToCart():
product = random.choice(products)
requests.get(BASE + "/product/" + product)
requests.post(BASE + "/cart", {
'product_id': product,
'quantity': random.choice([1, 2, 3, 4, 5, 10])})
def checkout():
addToCart()
requests.post(BASE + "/cart/checkout", {
'email': 'someone@example.com',
'street_address': '1600 Amphitheatre Parkway',
'zip_code': '94043',
'city': 'Mountain View',
'state': 'CA',
'country': 'United States',
'credit_card_number': '4432-8015-6152-0454',
'credit_card_expiration_month': '1',
'credit_card_expiration_year': '2039',
'credit_card_cvv': '672',
})
if not BASE:
print("ERROR: no frontend address")
else:
print("pinging" + BASE)
index()
browseProduct()
addToCart()
viewCart()
checkout()
print("pinging complete")

27
src/pingjob/pinger.sh Executable file
View file

@ -0,0 +1,27 @@
#!/bin/sh -eu
#
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#!/bin/bash
set -e
trap "exit" TERM
if [ -z "${FRONTEND_ADDR}" ]; then
echo >&2 "FRONTEND_ADDR not specified"
exit 1
fi
set -x
python pinger.py "${FRONTEND_ADDR}"

View file

@ -0,0 +1 @@
requests

View file

@ -0,0 +1,11 @@
#
# 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
idna==2.8 # via requests
requests==2.21.0
urllib3==1.24.1 # via requests