Showing preview only (1,575K chars total). Download the full file or copy to clipboard to get everything.
Repository: GoogleCloudPlatform/microservices-demo
Branch: main
Commit: 1725a8044b95
Files: 316
Total size: 1.4 MB
Directory structure:
gitextract_n0fmcr6r/
├── .deploystack/
│ ├── deploystack.yaml
│ ├── messages/
│ │ ├── description.txt
│ │ └── success.txt
│ ├── scripts/
│ │ └── preinit.sh
│ ├── test
│ └── test.yaml
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── CODEOWNERS
│ ├── CODE_OF_CONDUCT.md
│ ├── CONTRIBUTING.md
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.md
│ │ ├── feature-request.md
│ │ └── other.md
│ ├── SECURITY.md
│ ├── auto-approve.yml
│ ├── header-checker-lint.yml
│ ├── pull_request_template.md
│ ├── release-cluster/
│ │ ├── README.md
│ │ ├── backend-config.yaml
│ │ ├── frontend-config.yaml
│ │ ├── frontend-ingress.yaml
│ │ ├── frontend-service.yaml
│ │ └── managed-cert.yaml
│ ├── renovate.json5
│ ├── snippet-bot.yml
│ ├── terraform/
│ │ ├── README.md
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ └── workflows/
│ ├── README.md
│ ├── ci-main.yaml
│ ├── ci-pr.yaml
│ ├── cleanup.yaml
│ ├── helm-chart-ci.yaml
│ ├── install-dependencies.sh
│ ├── kubevious-manifests-ci.yaml
│ ├── kustomize-build-ci.yaml
│ └── terraform-validate-ci.yaml
├── .gitignore
├── LICENSE
├── README.md
├── cloudbuild.yaml
├── docs/
│ ├── adding-new-microservice.md
│ ├── cloudshell-tutorial.md
│ ├── deploystack.md
│ ├── development-guide.md
│ ├── product-requirements.md
│ ├── purpose.md
│ └── releasing/
│ ├── README.md
│ ├── license_header.txt
│ ├── make-docker-images.sh
│ ├── make-helm-chart.sh
│ ├── make-release-artifacts.sh
│ └── make-release.sh
├── helm-chart/
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates/
│ │ ├── NOTES.txt
│ │ ├── adservice.yaml
│ │ ├── cartservice.yaml
│ │ ├── checkoutservice.yaml
│ │ ├── common.yaml
│ │ ├── currencyservice.yaml
│ │ ├── emailservice.yaml
│ │ ├── frontend.yaml
│ │ ├── loadgenerator.yaml
│ │ ├── opentelemetry-collector.yaml
│ │ ├── paymentservice.yaml
│ │ ├── productcatalogservice.yaml
│ │ ├── recommendationservice.yaml
│ │ └── shippingservice.yaml
│ └── values.yaml
├── istio-manifests/
│ ├── allow-egress-googleapis.yaml
│ ├── frontend-gateway.yaml
│ └── frontend.yaml
├── kubernetes-manifests/
│ ├── README.md
│ ├── adservice.yaml
│ ├── cartservice.yaml
│ ├── checkoutservice.yaml
│ ├── currencyservice.yaml
│ ├── emailservice.yaml
│ ├── frontend.yaml
│ ├── kustomization.yaml
│ ├── loadgenerator.yaml
│ ├── paymentservice.yaml
│ ├── productcatalogservice.yaml
│ ├── recommendationservice.yaml
│ └── shippingservice.yaml
├── kustomize/
│ ├── README.md
│ ├── base/
│ │ ├── adservice.yaml
│ │ ├── cartservice.yaml
│ │ ├── checkoutservice.yaml
│ │ ├── currencyservice.yaml
│ │ ├── emailservice.yaml
│ │ ├── frontend.yaml
│ │ ├── kustomization.yaml
│ │ ├── loadgenerator.yaml
│ │ ├── paymentservice.yaml
│ │ ├── productcatalogservice.yaml
│ │ ├── recommendationservice.yaml
│ │ └── shippingservice.yaml
│ ├── components/
│ │ ├── alloydb/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-registry/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-tag/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-tag-suffix/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── custom-base-url/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── cymbal-branding/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── google-cloud-operations/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ └── otel-collector.yaml
│ │ ├── memorystore/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── network-policies/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ ├── network-policy-adservice.yaml
│ │ │ ├── network-policy-cartservice.yaml
│ │ │ ├── network-policy-checkoutservice.yaml
│ │ │ ├── network-policy-currencyservice.yaml
│ │ │ ├── network-policy-deny-all.yaml
│ │ │ ├── network-policy-emailservice.yaml
│ │ │ ├── network-policy-frontend.yaml
│ │ │ ├── network-policy-loadgenerator.yaml
│ │ │ ├── network-policy-paymentservice.yaml
│ │ │ ├── network-policy-productcatalogservice.yaml
│ │ │ ├── network-policy-recommendationservice.yaml
│ │ │ ├── network-policy-redis.yaml
│ │ │ └── network-policy-shippingservice.yaml
│ │ ├── non-public-frontend/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── service-mesh-istio/
│ │ │ ├── README.md
│ │ │ ├── allow-egress-googleapis.yaml
│ │ │ ├── frontend-gateway.yaml
│ │ │ ├── frontend.yaml
│ │ │ └── kustomization.yaml
│ │ ├── shopping-assistant/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ ├── scripts/
│ │ │ │ ├── 1_deploy_alloydb_infra.sh
│ │ │ │ ├── 2_create_populate_alloydb_tables.sh
│ │ │ │ └── generate_sql_from_products.py
│ │ │ └── shoppingassistantservice.yaml
│ │ ├── single-shared-session/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── spanner/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ └── without-loadgenerator/
│ │ ├── README.md
│ │ ├── delete-loadgenerator.patch.yaml
│ │ └── kustomization.yaml
│ ├── kustomization.yaml
│ └── tests/
│ ├── README.md
│ ├── memorystore-with-all-components/
│ │ └── kustomization.yaml
│ ├── service-mesh-istio-with-all-components/
│ │ └── kustomization.yaml
│ └── spanner-with-all-components/
│ └── kustomization.yaml
├── protos/
│ ├── demo.proto
│ └── grpc/
│ └── health/
│ └── v1/
│ └── health.proto
├── release/
│ ├── istio-manifests.yaml
│ └── kubernetes-manifests.yaml
├── skaffold.yaml
├── src/
│ ├── adservice/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── build.gradle
│ │ ├── genproto.sh
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── hipstershop/
│ │ │ ├── AdService.java
│ │ │ └── AdServiceClient.java
│ │ ├── proto/
│ │ │ └── demo.proto
│ │ └── resources/
│ │ └── log4j2.xml
│ ├── cartservice/
│ │ ├── cartservice.sln
│ │ ├── src/
│ │ │ ├── .dockerignore
│ │ │ ├── Dockerfile
│ │ │ ├── Dockerfile.debug
│ │ │ ├── Program.cs
│ │ │ ├── Startup.cs
│ │ │ ├── appsettings.json
│ │ │ ├── cartservice.csproj
│ │ │ ├── cartstore/
│ │ │ │ ├── AlloyDBCartStore.cs
│ │ │ │ ├── ICartStore.cs
│ │ │ │ ├── RedisCartStore.cs
│ │ │ │ └── SpannerCartStore.cs
│ │ │ ├── protos/
│ │ │ │ └── Cart.proto
│ │ │ └── services/
│ │ │ ├── CartService.cs
│ │ │ └── HealthCheckService.cs
│ │ └── tests/
│ │ ├── CartServiceTests.cs
│ │ └── cartservice.tests.csproj
│ ├── checkoutservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ └── money/
│ │ ├── money.go
│ │ └── money_test.go
│ ├── currencyservice/
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── client.js
│ │ ├── data/
│ │ │ └── currency_conversion.json
│ │ ├── genproto.sh
│ │ ├── package.json
│ │ ├── proto/
│ │ │ ├── demo.proto
│ │ │ └── grpc/
│ │ │ └── health/
│ │ │ └── v1/
│ │ │ └── health.proto
│ │ └── server.js
│ ├── emailservice/
│ │ ├── Dockerfile
│ │ ├── demo_pb2.py
│ │ ├── demo_pb2_grpc.py
│ │ ├── email_client.py
│ │ ├── email_server.py
│ │ ├── genproto.sh
│ │ ├── logger.py
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ └── templates/
│ │ └── confirmation.html
│ ├── frontend/
│ │ ├── .dockerignore
│ │ ├── .gitkeep
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── deployment_details.go
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── handlers.go
│ │ ├── main.go
│ │ ├── middleware.go
│ │ ├── money/
│ │ │ ├── money.go
│ │ │ └── money_test.go
│ │ ├── packaging_info.go
│ │ ├── rpc.go
│ │ ├── static/
│ │ │ ├── images/
│ │ │ │ └── credits.txt
│ │ │ └── styles/
│ │ │ ├── bot.css
│ │ │ ├── cart.css
│ │ │ ├── order.css
│ │ │ └── styles.css
│ │ ├── templates/
│ │ │ ├── ad.html
│ │ │ ├── assistant.html
│ │ │ ├── cart.html
│ │ │ ├── error.html
│ │ │ ├── footer.html
│ │ │ ├── header.html
│ │ │ ├── home.html
│ │ │ ├── order.html
│ │ │ ├── product.html
│ │ │ └── recommendations.html
│ │ └── validator/
│ │ ├── validator.go
│ │ └── validator_test.go
│ ├── loadgenerator/
│ │ ├── Dockerfile
│ │ ├── locustfile.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── paymentservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── charge.js
│ │ ├── genproto.sh
│ │ ├── index.js
│ │ ├── logger.js
│ │ ├── package.json
│ │ ├── proto/
│ │ │ ├── demo.proto
│ │ │ └── grpc/
│ │ │ └── health/
│ │ │ └── v1/
│ │ │ └── health.proto
│ │ └── server.js
│ ├── productcatalogservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── catalog_loader.go
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── product_catalog.go
│ │ ├── product_catalog_test.go
│ │ ├── products.json
│ │ └── server.go
│ ├── recommendationservice/
│ │ ├── Dockerfile
│ │ ├── client.py
│ │ ├── demo_pb2.py
│ │ ├── demo_pb2_grpc.py
│ │ ├── genproto.sh
│ │ ├── logger.py
│ │ ├── recommendation_server.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── shippingservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── quote.go
│ │ ├── shippingservice_test.go
│ │ └── tracker.go
│ └── shoppingassistantservice/
│ ├── Dockerfile
│ ├── requirements.in
│ ├── requirements.txt
│ └── shoppingassistantservice.py
└── terraform/
├── README.md
├── main.tf
├── memorystore.tf
├── output.tf
├── providers.tf
└── variables.tf
================================================
FILE CONTENTS
================================================
================================================
FILE: .deploystack/deploystack.yaml
================================================
# The fields inside this deploystack.yaml file are documented in https://github.com/GoogleCloudPlatform/deploystack.
title: Microservices Demo (Online Boutique)
name: microservices-demo
duration: 5
collect_project: true
collect_region: true
region_type: compute
region_default: us-central1
hard_settings:
filepath_manifest: ../kustomize/
memorystore: "false"
name: online-boutique
namespace: default
documentation_link: https://cloud.google.com/shell/docs/cloud-shell-tutorials/deploystack/microservices-demo
================================================
FILE: .deploystack/messages/description.txt
================================================
Online Boutique is a cloud-first microservices demo application. Online Boutique
consists of an 11-tier microservices application. The application is a web-based
e-commerce app where users can browse items, add them to the cart, and purchase
them.
================================================
FILE: .deploystack/messages/success.txt
================================================
Congrats!
You have successfully provisioned a GKE (Google Kubernetes Engine) cluster and
deployed Online Boutique's 11 microservices, which includes a load generator.
================================================
FILE: .deploystack/scripts/preinit.sh
================================================
# Copyright 2022 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.
ROOT=$(pwd)
sed -i.tmp "s/project_id/gcp_project_id/" $ROOT/terraform/terraform.tfvars
================================================
FILE: .deploystack/test
================================================
#! /bin/bash
# Copyright 2021 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.
# DEPLOYSTACK - this file is a test script that is used by DeployStack's
# testing rig to make sure that the Terraform script installs and uninstalls
# cleanly
# DON'T REMOVE FROM test script.
CYAN='\033[0;36m'
BCYAN='\033[1;36m'
NC='\033[0m' # No Color
DIVIDER=$(printf %"$(tput cols)"s | tr " " "*")
DIVIDER+="\n"
function get_project_id() {
local __resultvar=$1
VALUE=$(gcloud config get-value project | xargs)
eval $__resultvar="'$VALUE'"
}
function get_project_number() {
local __resultvar=$1
local PRO=$2
VALUE=$(gcloud projects list --filter="project_id=$PRO" --format="value(PROJECT_NUMBER)" | xargs)
eval $__resultvar="'$VALUE'"
}
# DISPLAY HELPERS
function section_open() {
section_description=$1
printf "$DIVIDER"
printf "${CYAN}$section_description${NC} \n"
printf "$DIVIDER"
}
function section_close() {
printf "$DIVIDER"
printf "${CYAN}$section_description ${BCYAN}- done${NC}\n"
printf "\n\n"
}
function evalTest() {
local command=$1
local expected=$2
local ERR=""
got=$(eval $command 2>errFile)
ERR=$(<errFile)
if [ ${#ERR} -gt 0 ]; then
if [ "$expected" = "EXPECTERROR" ]; then
printf "ok \n"
return
fi
printf "expecting no error, got error='$ERR' \n"
exit 1
fi
if [ "$got" != "$expected" ]; then
printf "expecting: '$expected' got: '$got' \n"
exit 1
fi
printf "$expected is ok\n"
}
function generateProject(){
local __resultvar
local __STACKSUFFIX
local __BA
local __RANDOMSUFFIX
local __DATELABEL
local PROJECTID
local current
__resultvar=$1
__STACKSUFFIX=$2
__BA=$3
__RANDOMSUFFIX=$(
LC_ALL=C tr -dc 'a-z0-9' </dev/urandom | head -c 8
echo
)
__DATELABEL=$(date +%F)
PROJECTID=ds-test-$__STACKSUFFIX-$__RANDOMSUFFIX
current=$(gcloud config list account --format "value(core.account)")
# shellcheck disable=SC2034
GOOGLE_APPLICATION_CREDENTIALS=.deploystack/creds.json
gcloud projects create "$PROJECTID" --labels="deploystack-disposable-test-project=$__DATELABEL" --folder="155265971980"
gcloud auth activate-service-account --project="$PROJECTID" --key-file=.deploystack/creds.json -q
gcloud config set account test-runner@ds-tester-helper.iam.gserviceaccount.com -q
gcloud beta billing projects link "$PROJECTID" --billing-account="$__BA" -q
gcloud config set account "$current" -q
eval "$__resultvar"="'$PROJECTID'"
}
# END DON'T REMOVE FROM test script.
suffix=ms
# This is only needed if you tests fail alot because of overlapping runs of the
# same set of tests.
section_open "Generate random test project"
generateProject PROJECT "$suffix" "$BA"
section_close
# We need to force the use of gke-gcloud-auth-plugin (for GKE authentication)
# if we're using kubectl 1.25 or lower.
export USE_GKE_GCLOUD_AUTH_PLUGIN=True
DIR="terraform"
gcloud services enable cloudresourcemanager.googleapis.com --project=$PROJECT
REGION="us-central1"
NAME="online-boutique"
NAMESPACE="default"
FILEPATH_MANIFEST="../kustomize/"
MEMORYSTORE="false"
gcloud config set project ${PROJECT}
terraform -chdir="$DIR" init
terraform -chdir="$DIR" apply -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
section_open "Testing Google Kubernetes Engine cluster exists"
evalTest 'gcloud container clusters describe online-boutique --format="value(name)" --region $REGION' "online-boutique"
section_close
section_open "Testing Online Boutique's services are running"
evalTest "kubectl get deployment adservice --no-headers -o=name 2> /dev/null" "deployment.apps/adservice"
evalTest "kubectl get deployment cartservice --no-headers -o=name 2> /dev/null" "deployment.apps/cartservice"
evalTest "kubectl get deployment checkoutservice --no-headers -o=name 2> /dev/null" "deployment.apps/checkoutservice"
evalTest "kubectl get deployment currencyservice --no-headers -o=name 2> /dev/null" "deployment.apps/currencyservice"
evalTest "kubectl get deployment emailservice --no-headers -o=name 2> /dev/null" "deployment.apps/emailservice"
evalTest "kubectl get deployment loadgenerator --no-headers -o=name 2> /dev/null" "deployment.apps/loadgenerator"
evalTest "kubectl get deployment paymentservice --no-headers -o=name 2> /dev/null" "deployment.apps/paymentservice"
evalTest "kubectl get deployment productcatalogservice --no-headers -o=name 2> /dev/null" "deployment.apps/productcatalogservice"
evalTest "kubectl get deployment recommendationservice --no-headers -o=name 2> /dev/null" "deployment.apps/recommendationservice"
evalTest "kubectl get deployment redis-cart --no-headers -o=name 2> /dev/null" "deployment.apps/redis-cart"
evalTest "kubectl get deployment shippingservice --no-headers -o=name 2> /dev/null" "deployment.apps/shippingservice"
section_close
sleep 120
ENDPOINT=$( kubectl get service frontend-external --no-headers 2> /dev/null | awk '{print $4}')
section_open "Testing Online Boutique's front-end is working"
evalTest 'curl -s -o /dev/null -w "%{http_code}" $ENDPOINT' "200"
section_close
# Uncomment the line: "deletion_protection = false"
sed -i "s/# deletion_protection/deletion_protection/g" ${DIR}/main.tf
terraform -chdir="$DIR" apply -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
terraform -chdir="$DIR" destroy -auto-approve \
-var gcp_project_id="${PROJECT}" \
-var name="${NAME}" \
-var region="${REGION}" \
-var namespace="${NAMESPACE}" \
-var filepath_manifest="${FILEPATH_MANIFEST}" \
-var memorystore="${MEMORYSTORE}"
section_open "Testing Google Kubernetes Engine cluster does NOT exist"
evalTest 'gcloud container clusters describe online-boutique --format="value(name)" --region $REGION' "EXPECTERROR"
section_close
# This is only needed if you tests fail alot because of overlapping runs of the
# same set of tests. Really don't do this if you don't want to severely irritate
# @tpryan
section_open "Delete Test Project"
gcloud projects delete $PROJECT -q
section_close
printf "$DIVIDER"
printf "CONGRATS!!!!!!! \n"
printf "You got the end the of your test with everything working. \n"
printf "$DIVIDER"
================================================
FILE: .deploystack/test.yaml
================================================
# Copyright 2021 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.
# DEPLOYSTACK - this file is the cloudbuild for running testing automatically
# in the testing rig
steps:
- name: 'bash'
id: "creds"
args: ['-c','echo $$CREDS > .deploystack/creds.json']
secretEnv: ['CREDS']
- name: 'gcr.io/cloudshell-images/cloudshell:latest'
entrypoint: bash
args: [ '.deploystack/test' ]
secretEnv: ['BA']
timeout: 4200s
options:
machineType: 'E2_HIGHCPU_8'
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/creds/versions/latest
env: 'CREDS'
- versionName: projects/$PROJECT_ID/secrets/billing_account/versions/latest
env: 'BA'
================================================
FILE: .editorconfig
================================================
# The .editorconfig is used to maintain consistent code style.
# The .editorconfig file is supported by most text editors.
# See https://editorconfig.org
root = true
[*]
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[*.cs]
indent_size = 4
[Dockerfile*]
indent_size = 4
[*.go]
indent_style = tab
[*.java]
indent_size = 4
[*.py]
indent_size = 4
================================================
FILE: .gitattributes
================================================
# This file configures the git settings for this repository.
# Converts "CR + LF" to "LF", for all "text" files — for local files on all OSes and files pushed to the remote repo.
* text=auto eol=lf
================================================
FILE: .github/CODEOWNERS
================================================
# See https://help.github.com/en/articles/about-code-owners
# for more info about CODEOWNERS file.
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence.
* @GoogleCloudPlatform/devrel-flagship-app-maintainers @yoshi-approver
================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Code of Conduct
As contributors and maintainers of this project,
and in the interest of fostering an open and welcoming community,
we pledge to respect all people who contribute through reporting issues,
posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in this project
a harassment-free experience for everyone,
regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information,
such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct.
By adopting this Code of Conduct,
project maintainers commit themselves to fairly and consistently
applying these principles to every aspect of managing this project.
Project maintainers who do not follow or enforce the Code of Conduct
may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported by opening an issue
or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
================================================
FILE: .github/CONTRIBUTING.md
================================================
# How to Contribute
Thank you so much for your interest in contributing to Online Boutique.
Before contributing, you must:
* Sign the [Contributor License Agreement (CLA)](#contributor-license-agreement).
* Follow the [Google Open Source Community Guidelines](https://opensource.google.com/conduct/).
* Follow the [Contribution Process](#contribution-process).
## Contributor License Agreement
Contributions to Online Boutique must be accompanied by a Contributor License
Agreement (CLA). You (or your employer) retain the copyright to your contribution.
The CLA gives us permission to use and redistribute your contributions as
part of the project. Head over to <https://cla.developers.google.com/> to see
your current agreements on file or to sign a new one.
You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.
## Contribution Process
Here's the process for making a change to this repository:
1. Review Online Boutique's [purpose](/docs/purpose.md) and [product requirements](/docs/product-requirements.md).
1. If your proposed changes **do not align** with the purpose and product requirements of Online Boutique, you may be asked to instead maintain your own fork of this repository.
1. For **small changes** (such as a bug fixes or spelling corrections):
1. Fork this repository and submit a [pull request](https://help.github.com/articles/about-pull-requests/).
1. Wait for a maintainer of this repository to review your change.
1. For **bigger changes**:
1. Create a [GitHub issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose) describing the change **before** working on the implementation. This is important to avoid potentially having to discard your development efforts.
1. Wait for a maintainer of this repository to review your GitHub issue. For significantly complex proposals, you may be asked to start a Google Doc to discuss design decisions.
If you have any questions, please [create a GitHub issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose).
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
### Describe the bug
<!-- A clear and concise description of what the bug is. -->
### To Reproduce
<!-- Steps to reproduce the behavior: -->
<!-- 1. Built image '...' -->
<!-- 2. Ran command '....' -->
<!-- 3. See error -->
### Logs
<!-- Add logs to help explain your problem -->
### Screenshots
<!-- If applicable, add screenshots to help explain your problem -->
### Environment
<!-- - OS: [e.g. MacOS Big Sur v11.6] -->
<!-- - Kubernetes distribution, version: [e.g. minikube, GKE (Standard or Autopilot), EKS, AWS ... ] -->
<!-- - Any relevant tool version: [e.g. Docker v20.10.8] -->
### Additional context
<!-- Add any other context about the problem here -->
### Exposure
<!-- Is the bug intermittent, persistent? Is it widespread, local? -->
================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
### Describe request or inquiry
<!-- Add any other context about the problem or helpful links here! -->
### What purpose/environment will this feature serve?
<!-- Add reasoning -->
================================================
FILE: .github/ISSUE_TEMPLATE/other.md
================================================
---
name: Other
about: Have a question or need clarification?
title: ''
labels: ''
assignees: ''
---
### Write down your inquiry
<!-- Write your question/inquiry here and any addition context -->
================================================
FILE: .github/SECURITY.md
================================================
# Security Policy
To report a security issue, please use [g.co/vulnz](https://g.co/vulnz).
The Google Security Team will respond within 5 working days of your report on g.co/vulnz.
We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue.
================================================
FILE: .github/auto-approve.yml
================================================
# Copyright 2023 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.
# https://github.com/googleapis/repo-automation-bots/tree/main/packages/auto-approve
processes:
- "PythonDependency"
- "PythonSampleAppDependency"
- "JavaDependency"
- "JavaSampleAppDependency"
- "GoDependency"
- "NodeDependency"
- "DockerDependency"
================================================
FILE: .github/header-checker-lint.yml
================================================
# Copyright 2023 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 file configures a GitHub Bot called "License Header Lint GCF": https://github.com/apps/license-header-lint-gcf
# The bot runs a GitHub check called "header-check" (inside pull-requests) that warns us about invalid/missing license headers.
# The schema for this configutation file is documented at https://github.com/googleapis/repo-automation-bots/tree/main/packages/header-checker-lint#header-checker-lint.
allowedCopyrightHolders:
- 'Google LLC'
allowedLicenses:
- 'Apache-2.0'
# If you want to ignore certain files/folders, use ignoreFiles.
# ignoreFiles:
# - '**/requirements.txt'
# If you want to ignore checking the license year, use ignoreLicenseYear.
# ignoreLicenseYear: true # Useful when migrating in code licensed at previous years.
sourceFileExtensions:
- 'cs'
- 'css'
- 'Dockerfile'
- 'dockerignore'
- 'gitignore'
- 'go'
- 'html'
- 'java'
- 'js'
- 'proto'
- 'py'
- 'sh'
- 'tf'
- 'yaml'
- 'yml'
================================================
FILE: .github/pull_request_template.md
================================================
### Background
<!-- What was happening before this PR, and the problem(s) it solves -->
### Fixes
<!-- Link the issue(s) this PR fixes-->
### Change Summary
<!-- Short summary of the changes submitted -->
### Additional Notes
<!-- Any remaining concerns -->
### Testing Procedure
<!-- If applicable, write how to test for reviewers-->
### Related PRs or Issues
<!-- Dependent PRs, or any relevant linked issues -->
================================================
FILE: .github/release-cluster/README.md
================================================
# cymbal-shops.retail.cymbal.dev manifests
This directory contains extra deploy manifests for configuring Online Boutique solution on GKE for cymbal-shops.retail.cymbal.dev.
_Note: before moving forward, the Online Boutique apps should already be deployed [on the online-boutique-release GKE cluster](/docs/releasing#10-deploy-releasekubernetes-manifestsyaml-to-our-online-boutique-release-gke-cluster)._
## Public static IP address
Create the static public IP address:
```
STATIC_IP_NAME=online-boutique-ip # name hard-coded in: frontend-ingress.yaml
gcloud compute addresses create $STATIC_IP_NAME --global
```
When ready to do so, you could grab this public IP address and update your DNS:
```
gcloud compute addresses describe $STATIC_IP_NAME \
--global \
--format "value(address)"
```
## Cloud Armor
Set up Cloud Armor:
```
SECURITY_POLICY_NAME=online-boutique-security-policy # Name hard-coded in: backendconfig.yaml
gcloud compute security-policies create $SECURITY_POLICY_NAME \
--description "Block various attacks"
gcloud compute security-policies rules create 1000 \
--security-policy $SECURITY_POLICY_NAME \
--expression "evaluatePreconfiguredExpr('xss-stable')" \
--action "deny-403" \
--description "XSS attack filtering"
gcloud compute security-policies rules create 12345 \
--security-policy $SECURITY_POLICY_NAME \
--expression "evaluatePreconfiguredExpr('cve-canary')" \
--action "deny-403" \
--description "CVE-2021-44228 and CVE-2021-45046"
gcloud compute security-policies update $SECURITY_POLICY_NAME \
--enable-layer7-ddos-defense
gcloud compute security-policies update $SECURITY_POLICY_NAME \
--log-level=VERBOSE
```
## SSL Policy
Set up an SSL policy in order to later set up a redirect from HTTP to HTTPs:
```
SSL_POLICY_NAME=online-boutique-ssl-policy # Name hard-coded in: frontendconfig.yaml
gcloud compute ssl-policies create $SSL_POLICY_NAME \
--profile COMPATIBLE \
--min-tls-version 1.0
```
## Deploy Kubernetes manifests
Deploy the Kubernetes manifests in this current folder:
```
kubectl apply -f .
```
Wait for the `ManagedCertificate` to be provisioned. This usually takes about 30 minutes.
```
kubectl get managedcertificates
```
Remove the default `LoadBalancer` `Service` not used at this point:
```
kubectl delete service frontend-external
```
Remove the `loadgenerator` `Deployment` not used at this point:
```
kubectl delete deployment loadgenerator
```
================================================
FILE: .github/release-cluster/backend-config.yaml
================================================
# Copyright 2024 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.
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: frontend-backend-config
spec:
securityPolicy:
name: online-boutique-security-policy
================================================
FILE: .github/release-cluster/frontend-config.yaml
================================================
# Copyright 2024 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.
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
name: frontend-frontend-config
spec:
sslPolicy: online-boutique-ssl-policy
redirectToHttps:
enabled: true
responseCodeName: MOVED_PERMANENTLY_DEFAULT
================================================
FILE: .github/release-cluster/frontend-ingress.yaml
================================================
# Copyright 2024 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.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: frontend-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: online-boutique-ip
networking.gke.io/managed-certificates: online-boutique-certificate
networking.gke.io/v1beta1.FrontendConfig: frontend-frontend-config
spec:
defaultBackend:
service:
name: frontend
port:
number: 80
rules:
- http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: frontend
port:
number: 80
================================================
FILE: .github/release-cluster/frontend-service.yaml
================================================
# Copyright 2024 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.
apiVersion: v1
kind: Service
metadata:
name: frontend
annotations:
cloud.google.com/neg: '{"ingress": true}'
cloud.google.com/backend-config: '{"default": "frontend-backend-config"}'
spec:
type: ClusterIP
selector:
app: frontend
ports:
- name: http
port: 80
targetPort: 8080
================================================
FILE: .github/release-cluster/managed-cert.yaml
================================================
# Copyright 2024 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.
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: online-boutique-certificate
spec:
domains:
- cymbal-shops.retail.cymbal.dev
================================================
FILE: .github/renovate.json5
================================================
{
extends: [
'github>GoogleCloudPlatform/kubernetes-engine-samples//.github/renovate-configs/dee-platform-ops.json5',
'schedule:earlyMondays',
],
'pip-compile': {
enabled: true,
managerFilePatterns: [
'/(^|/)requirements\\.txt$/',
],
},
pip_requirements: {
enabled: false,
},
constraints: {
python: '~=3.11.0',
},
kubernetes: {
managerFilePatterns: [
'/\\.yaml$/',
],
ignorePaths: [
'release/**',
'kustomize/base/**',
],
},
}
================================================
FILE: .github/snippet-bot.yml
================================================
# Copyright 2021 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.
================================================
FILE: .github/terraform/README.md
================================================
This folder contains the Terraform for some of the infrastructure used by the CICD (continuous integration and continuous delivery/continuous deployment) of this repository.
## Update this Terraform
To make changes to this Terraform, follow these steps:
1. Make sure you have access to the `online-boutique-ci` Google Cloud project.
1. Move into this folder: `cd .github/terraform`
1. Set the PROJECT_ID environment variable: `export PROJECT_ID=online-boutique-ci`
1. Prepare Terraform and download the necessary Terraform dependencies (such as the "hashicorp/google" Terraform provider): `terraform init`
1. Apply the Terraform: `terraform apply -var project_id=${PROJECT_ID}`
* Ideally, you would see `Apply complete! Resources: 0 added, 0 changed, 0 destroyed.` in the output.
1. Make your desired changes to the Terraform code.
1. Apply the Terraform: `terraform apply -var project_id=${PROJECT_ID}`
* This time, Terraform will prompt you confirm your changes before applying them.
================================================
FILE: .github/terraform/main.tf
================================================
/**
* Copyright 2024 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.
*/
# Set defaults for the google Terraform provider.
provider "google" {
project = var.project_id
region = "us-central1"
zone = "us-central1-a"
}
terraform {
# Store the state inside a Google Cloud Storage bucket.
backend "gcs" {
bucket = "cicd-terraform-state"
prefix = "terraform-state"
}
}
# Enable Google Cloud APIs.
module "enable_google_apis" {
source = "terraform-google-modules/project-factory/google//modules/project_services"
version = "~> 18.0"
disable_services_on_destroy = false
activate_apis = [
"cloudresourcemanager.googleapis.com",
"container.googleapis.com",
"iam.googleapis.com",
"storage.googleapis.com",
]
project_id = var.project_id
}
# Google Cloud Storage for storing Terraform state (.tfstate).
resource "google_storage_bucket" "terraform_state_storage_bucket" {
name = "cicd-terraform-state"
location = "us"
storage_class = "STANDARD"
force_destroy = false
public_access_prevention = "enforced"
uniform_bucket_level_access = true
versioning {
enabled = true
}
}
# Google Cloud IAM service account for GKE clusters.
# We avoid using the Compute Engine default service account because it's too permissive.
resource "google_service_account" "gke_clusters_service_account" {
account_id = "gke-clusters-service-account"
display_name = "My Service Account"
depends_on = [
module.enable_google_apis
]
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_metric_writer" {
project = var.project_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_logging_writer" {
project = var.project_id
role = "roles/logging.logWriter"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_monitoring_viewer" {
project = var.project_id
role = "roles/monitoring.viewer"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# See https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa
resource "google_project_iam_member" "gke_clusters_service_account_role_stackdriver_writer" {
project = var.project_id
role = "roles/stackdriver.resourceMetadata.writer"
member = "serviceAccount:${google_service_account.gke_clusters_service_account.email}"
}
# The GKE cluster used for pull-request (PR) staging deployments.
resource "google_container_cluster" "prs_gke_cluster" {
name = "prs-gke-cluster"
location = "us-central1"
enable_autopilot = true
project = var.project_id
deletion_protection = true
depends_on = [
module.enable_google_apis
]
cluster_autoscaling {
auto_provisioning_defaults {
service_account = google_service_account.gke_clusters_service_account.email
}
}
# Need an empty ip_allocation_policy to overcome an error related to autopilot node pool constraints.
# Workaround from https://github.com/hashicorp/terraform-provider-google/issues/10782#issuecomment-1024488630
ip_allocation_policy {
}
}
================================================
FILE: .github/terraform/variables.tf
================================================
/**
* Copyright 2024 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 file lists variables that you can set using the -var flag during "terraform apply".
# Example: terraform apply -var project_id="${PROJECT_ID}"
variable "project_id" {
type = string
description = "The Google Cloud project ID."
}
================================================
FILE: .github/terraform/versions.tf
================================================
/**
* Copyright 2024 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.
*/
terraform {
required_version = ">= 0.13"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 7.0"
}
}
}
================================================
FILE: .github/workflows/README.md
================================================
# GitHub Actions Workflows
This page describes the CI/CD workflows for the Online Boutique app, which run in [Github Actions](https://github.com/GoogleCloudPlatform/microservices-demo/actions).
## Infrastructure
The CI/CD pipelines for Online Boutique run in Github Actions, using a pool of two [self-hosted runners]((https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners)). These runners are GCE instances (virtual machines) that, for every open Pull Request in the repo, run the code test pipeline, deploy test pipeline, and (on main) deploy the latest version of the app to [cymbal-shops.retail.cymbal.dev](https://cymbal-shops.retail.cymbal.dev)
We also host a test GKE cluster, which is where the deploy tests run. Every PR has its own namespace in the cluster.
## Workflows
**Note**: In order for the current CI/CD setup to work on your pull request, you must branch directly off the repo (no forks). This is because the Github secrets necessary for these tests aren't copied over when you fork.
### Code Tests - [ci-pr.yaml](ci-pr.yaml)
These tests run on every commit for every open PR, as well as any commit to main / any release branch. Currently, this workflow runs only Go unit tests.
### Deploy Tests- [ci-pr.yaml](ci-pr.yaml)
These tests run on every commit for every open PR, as well as any commit to main / any release branch. This workflow:
1. Creates a dedicated GKE namespace for that PR, if it doesn't already exist, in the PR GKE cluster.
2. Uses `skaffold run` to build and push the images specific to that PR commit. Then skaffold deploys those images, via `kubernetes-manifests`, to the PR namespace in the test cluster.
3. Tests to make sure all the pods start up and become ready.
4. Gets the LoadBalancer IP for the frontend service.
5. Comments that IP in the pull request, for staging.
### Push and Deploy Latest - [push-deploy](push-deploy.yml)
This is the Continuous Deployment workflow, and it runs on every commit to the main branch. This workflow:
1. Builds the container images for every service, tagging as `latest`.
2. Pushes those images to Google Container Registry.
Note that this workflow does not update the image tags used in `release/kubernetes-manifests.yaml` - these release manifests are tied to a stable `v0.x.x` release.
### Cleanup - [cleanup.yaml](cleanup.yaml)
This workflow runs when a PR closes, regardless of whether it was merged into main. This workflow deletes the PR-specific GKE namespace in the test cluster.
## Appendix - Creating a new Actions runner
Should one of the two self-hosted Github Actions runners (GCE instances) fail, or you want to add more runner capacity, this is how to provision a new runner. Note that you need IAM access to the admin Online Boutique GCP project in order to do this.
1. Create a GCE instance.
- VM should be at least n1-standard-4 with 50GB persistent disk
- VM should use custom service account with permissions to: access a GKE cluster, create GCS storage buckets, and push to GCR.
2. SSH into new VM through the Google Cloud Console.
3. Install project-specific dependencies, including go, docker, skaffold, and kubectl:
```
wget -O - https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/.github/workflows/install-dependencies.sh | bash
```
The instance will restart when the script completes in order to finish the Docker install.
4. SSH back into the VM.
5. Follow the instructions to add a new runner on the [Actions Settings page](https://github.com/GoogleCloudPlatform/microservices-demo/settings/actions) to authenticate the new runner
6. Start GitHub Actions as a background service:
```
sudo ~/actions-runner/svc.sh install ; sudo ~/actions-runner/svc.sh start
```
================================================
FILE: .github/workflows/ci-main.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Continuous Integration - Main/Release"
on:
push:
# run on pushes to main or release/*
branches:
- main
- release/*
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
jobs:
code-tests:
runs-on: [self-hosted, is-enabled]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
env:
DOTNET_INSTALL_DIR: "./.dotnet"
with:
dotnet-version: '10.0'
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Go Unit Tests
timeout-minutes: 10
run: |
for SERVICE in "shippingservice" "productcatalogservice"; do
echo "testing $SERVICE..."
pushd src/$SERVICE
go test
popd
done
- name: C# Unit Tests
timeout-minutes: 10
run: |
dotnet test src/cartservice/
deployment-tests:
runs-on: [self-hosted, is-enabled]
needs: code-tests
strategy:
matrix:
profile: ["local-code"]
fail-fast: true
steps:
- uses: actions/checkout@v6
- name: Build + Deploy PR images to GKE
timeout-minutes: 20
run: |
PR_NUMBER=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')
NAMESPACE="pr${PR_NUMBER}"
echo "::set-env name=NAMESPACE::$NAMESPACE"
echo "::set-env name=PR_NUMBER::$PR_NUMBER"
yes | gcloud auth configure-docker us-docker.pkg.dev
gcloud container clusters get-credentials $PR_CLUSTER --region $REGION --project $PROJECT_ID
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $NAMESPACE
EOF
echo Deploying application
skaffold config set --global local-cluster false
skaffold run --default-repo=us-docker.pkg.dev/$PROJECT_ID/$GITHUB_REF --tag=$GITHUB_SHA --namespace=$NAMESPACE -p network-policies
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
- name: Wait For Pods
timeout-minutes: 20
run: |
set -x
kubectl config set-context --current --namespace=$NAMESPACE
kubectl wait --for=condition=available --timeout=1000s deployment/redis-cart
kubectl wait --for=condition=available --timeout=1000s deployment/adservice
kubectl wait --for=condition=available --timeout=1000s deployment/cartservice
kubectl wait --for=condition=available --timeout=1000s deployment/checkoutservice
kubectl wait --for=condition=available --timeout=1000s deployment/currencyservice
kubectl wait --for=condition=available --timeout=1000s deployment/emailservice
kubectl wait --for=condition=available --timeout=1000s deployment/frontend
kubectl wait --for=condition=available --timeout=1000s deployment/loadgenerator
kubectl wait --for=condition=available --timeout=1000s deployment/paymentservice
kubectl wait --for=condition=available --timeout=1000s deployment/productcatalogservice
kubectl wait --for=condition=available --timeout=1000s deployment/recommendationservice
kubectl wait --for=condition=available --timeout=1000s deployment/shippingservice
- name: Smoke Test
timeout-minutes: 5
run: |
set -x
# start fresh loadgenerator pod
kubectl delete pod -l app=loadgenerator
# wait for requests to come in
REQUEST_COUNT="0"
while [[ "$REQUEST_COUNT" -lt "50" ]]; do
sleep 5
REQUEST_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $2}')
done
# ensure there are no errors hitting endpoints
ERROR_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $3}' | sed "s/[(][^)]*[)]//g")
if [[ "$ERROR_COUNT" -gt "0" ]]; then
exit 1
fi
================================================
FILE: .github/workflows/ci-pr.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Continuous Integration - Pull Request"
on:
pull_request:
branches:
- main
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
# Ensure this workflow only runs for the most recent commit of a pull-request
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
code-tests:
runs-on: [self-hosted, is-enabled]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-dotnet@v5
env:
DOTNET_INSTALL_DIR: "./.dotnet"
with:
dotnet-version: '10.0'
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Go Unit Tests
timeout-minutes: 10
run: |
for GO_PACKAGE in "shippingservice" "productcatalogservice" "frontend/validator"; do
echo "Testing $GO_PACKAGE..."
pushd src/$GO_PACKAGE
go test
popd
done
- name: C# Unit Tests
timeout-minutes: 10
run: |
dotnet test src/cartservice/
deployment-tests:
runs-on: [self-hosted, is-enabled]
needs: code-tests
strategy:
matrix:
profile: ["local-code"]
fail-fast: true
steps:
- uses: actions/checkout@v6
with:
ref: ${{github.event.pull_request.head.sha}}
- name: Build + Deploy PR images to GKE
timeout-minutes: 20
run: |
NAMESPACE="pr${PR_NUMBER}"
echo "::set-env name=NAMESPACE::$NAMESPACE"
yes | gcloud auth configure-docker us-docker.pkg.dev
gcloud container clusters get-credentials $PR_CLUSTER --region $REGION --project $PROJECT_ID
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $NAMESPACE
EOF
echo Deploying application
skaffold config set --global local-cluster false
skaffold run --default-repo=us-docker.pkg.dev/$PROJECT_ID/refs/pull/$PR_NUMBER --tag=$PR_NUMBER --namespace=$NAMESPACE -p network-policies
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PR_NUMBER: ${{ github.event.pull_request.number }}
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
- name: Wait For Pods
timeout-minutes: 20
run: |
set -x
kubectl config set-context --current --namespace=$NAMESPACE
kubectl wait --for=condition=available --timeout=1000s deployment/redis-cart
kubectl wait --for=condition=available --timeout=1000s deployment/adservice
kubectl wait --for=condition=available --timeout=1000s deployment/cartservice
kubectl wait --for=condition=available --timeout=1000s deployment/checkoutservice
kubectl wait --for=condition=available --timeout=1000s deployment/currencyservice
kubectl wait --for=condition=available --timeout=1000s deployment/emailservice
kubectl wait --for=condition=available --timeout=1000s deployment/frontend
kubectl wait --for=condition=available --timeout=1000s deployment/loadgenerator
kubectl wait --for=condition=available --timeout=1000s deployment/paymentservice
kubectl wait --for=condition=available --timeout=1000s deployment/productcatalogservice
kubectl wait --for=condition=available --timeout=1000s deployment/recommendationservice
kubectl wait --for=condition=available --timeout=1000s deployment/shippingservice
- name: Query EXTERNAL_IP for staging
timeout-minutes: 5
run: |
set -x
NAMESPACE="pr${PR_NUMBER}"
get_externalIP() {
kubectl get service frontend-external --namespace $NAMESPACE -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
}
until [[ -n "$(get_externalIP)" ]]; do
echo "Querying for external IP for frontend-external on namespace: $NAMESPACE{}"
sleep 3
done
EXTERNAL_IP=$(get_externalIP)
echo "::set-env name=EXTERNAL_IP::$EXTERNAL_IP"
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
PR_NUMBER: ${{ github.event.pull_request.number }}
- name: Smoke Test
timeout-minutes: 5
run: |
set -x
# start fresh loadgenerator pod
kubectl delete pod -l app=loadgenerator
# wait for requests to come in
REQUEST_COUNT="0"
while [[ "$REQUEST_COUNT" -lt "50" ]]; do
sleep 5
REQUEST_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $2}')
done
# ensure there are no errors hitting endpoints
ERROR_COUNT=$(kubectl logs -l app=loadgenerator | grep Aggregated | awk '{print $3}' | sed "s/[(][^)]*[)]//g")
if [[ "$ERROR_COUNT" -gt "0" ]]; then
exit 1
fi
- name: Comment EXTERNAL_IP
timeout-minutes: 5
env:
COMMENTS_URL: ${{ github.event.pull_request.comments_url }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
$COMMENTS_URL \
-H "Content-Type: application/json" \
-H "Authorization: token $GITHUB_TOKEN" \
--data '{ "body": "🚲 PR staged at '"http://${EXTERNAL_IP}"'"}'
sleep 60
================================================
FILE: .github/workflows/cleanup.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: "Clean up deployment"
on:
pull_request:
# run on pull requests targeting main
branches:
- main
types: closed
paths-ignore:
- '**/README.md'
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
jobs:
cleanup-namespace:
runs-on: [self-hosted, is-enabled]
steps:
- name: Delete PR namespace in staging cluster
if: ${{ always() }}
timeout-minutes: 20
run: |
gcloud container clusters get-credentials $PR_CLUSTER \
--region $REGION --project $PROJECT_ID
NAMESPACE="pr${PR_NUMBER}"
kubectl delete namespace $NAMESPACE
env:
PROJECT_ID: "online-boutique-ci"
PR_CLUSTER: "prs-gke-cluster"
REGION: "us-central1"
PR_NUMBER: ${{ github.event.number }}
================================================
FILE: .github/workflows/helm-chart-ci.yaml
================================================
# Copyright 2022 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.
name: helm-chart-ci
on:
push:
branches:
- main
paths:
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
pull_request:
paths:
- 'helm-chart/**'
- '.github/workflows/helm-chart-ci.yaml'
jobs:
helm-chart-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: helm lint
run: |
cd helm-chart/
helm lint --strict
- name: helm template default
run: |
cd helm-chart/
helm template . > helm-template.yaml
cat helm-template.yaml
kustomize create --resources helm-template.yaml
kustomize build .
- name: helm template grpc health probes
run: |
# Test related to https://medium.com/google-cloud/b5bd26253a4c
cd helm-chart/
SPANNER_CONNECTION_STRING=projects/PROJECT_ID/instances/SPANNER_INSTANCE_NAME/databases/SPANNER_DATABASE_NAME
helm template . \
--set nativeGrpcHealthCheck=true \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template spanner
run: |
# Test related to https://medium.com/google-cloud/f7248e077339
cd helm-chart/
SPANNER_CONNECTION_STRING=projects/PROJECT_ID/instances/SPANNER_INSTANCE_NAME/databases/SPANNER_DATABASE_NAME
SPANNER_DB_USER_GSA_ID=spanner-db-user@my-project.iam.gserviceaccount.com
helm template . \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.type=spanner \
--set cartDatabase.connectionString=${SPANNER_CONNECTION_STRING} \
--set serviceAccounts.create=true \
--set serviceAccounts.annotationsOnlyForCartservice=true \
--set "serviceAccounts.annotations.iam\.gke\.io/gcp-service-account=${SPANNER_DB_USER_GSA_ID}" \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template asm
run: |
# Test related to https://medium.com/google-cloud/246119e46d53
cd helm-chart/
helm template . \
--set networkPolicies.create=true \
--set sidecars.create=true \
--set serviceAccounts.create=true \
--set authorizationPolicies.create=true \
--set frontend.externalService=false \
--set frontend.virtualService.create=true \
--set frontend.virtualService.gateway.name=asm-ingressgateway \
--set frontend.virtualService.gateway.namespace=asm-ingress \
--set frontend.virtualService.gateway.labelKey=asm \
--set frontend.virtualService.gateway.labelValue=ingressgateway \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
- name: helm template memorystore istio tls origination
run: |
# Test related to https://medium.com/google-cloud/64b71969318d
cd helm-chart/
REDIS_IP=0.0.0.0
REDIS_PORT=7378
REDIS_CERT=dsjfgkldsjflkdsjflksdajfkldsjkfljsdaklfjaskjfakdsjfaklsdjflskadjfklasjfkls
helm template . \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.connectionString=${REDIS_IP}:${REDIS_PORT} \
--set cartDatabase.externalRedisTlsOrigination.enable=true \
--set cartDatabase.externalRedisTlsOrigination.certificate="${REDIS_CERT}" \
--set cartDatabase.externalRedisTlsOrigination.endpointAddress=${REDIS_IP} \
--set cartDatabase.externalRedisTlsOrigination.endpointPort=${REDIS_PORT} \
-n onlineboutique \
> helm-template.yaml
cat helm-template.yaml
kustomize build .
================================================
FILE: .github/workflows/install-dependencies.sh
================================================
#!/bin/bash
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -euo pipefail
# install wget
sudo apt install -y wget
# install dotnet CLI
sudo apt-get update
sudo apt-get install wget
wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg
sudo mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/
wget https://packages.microsoft.com/config/debian/9/prod.list
sudo mv prod.list /etc/apt/sources.list.d/microsoft-prod.list
sudo chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg
sudo chown root:root /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get install -y apt-transport-https && \
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-10.0
echo "✅ dotnet installed"
# install kubectl
sudo apt-get install -yqq kubectl git
echo "✅ kubectl installed"
# install go
wget https://golang.org/dl/go1.25.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.25.linux-amd64.tar.gz
echo 'export GOPATH=$HOME/go' >> ~/.profile
echo 'export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin' >> ~/.profile
source ~/.profile
echo "✅ golang installed"
# install build-essential (gcc, used for go test)
sudo apt install -y build-essential
# install addlicense
go install github.com/google/addlicense@latest
sudo ln -s $HOME/go/bin/addlicense /bin
# install build-essential (gcc, used for go test)
sudo apt install -y build-essential
# install skaffold
curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \
chmod +x skaffold && \
sudo mv skaffold /usr/local/bin
echo "✅ skaffold installed"
# install docker
sudo apt install -yqq apt-transport-https ca-certificates curl gnupg2 software-properties-common && \
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - && \
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \
sudo apt-get update && \
sudo apt-get install -yqq docker-ce && \
sudo usermod -aG docker ${USER}
echo "✅ docker installed, rebooting..."
# reboot for docker setup
sudo reboot
================================================
FILE: .github/workflows/kubevious-manifests-ci.yaml
================================================
# Copyright 2023 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.
name: kubevious-manifests-ci
on:
push:
branches:
- main
paths:
- 'helm-chart/**'
- 'kustomize/**'
- '.github/workflows/kubevious-manifests-ci.yaml'
pull_request:
paths:
- 'helm-chart/**'
- 'kustomize/**'
- '.github/workflows/kubevious-manifests-ci.yaml'
permissions:
contents: read
jobs:
kubevious-manifests-ci:
runs-on: ubuntu-24.04
timeout-minutes: 1
steps:
- uses: actions/checkout@v6
- name: Validate kubernetes-manifests
id: kubernetes-manifests-validation
uses: kubevious/cli@v1.0.64
with:
manifests: kubernetes-manifests
skip_rules: container-latest-image
- name: Validate helm-chart
id: helm-chart-validation
uses: kubevious/cli@v1.0.64
with:
manifests: helm-chart
- name: Validate kustomize
id: kustomize-validation
uses: kubevious/cli@v1.0.64
with:
manifests: kustomize
skip_rules: container-latest-image
================================================
FILE: .github/workflows/kustomize-build-ci.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: kustomize-build-ci
on:
push:
branches:
- main
paths:
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
pull_request:
paths:
- 'kustomize/**'
- '.github/workflows/kustomize-build-ci.yaml'
jobs:
kustomize-build-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: kustomize build base
run: |
cd kustomize/
kubectl kustomize .
# Build the different combinations of Kustomize components found in kustomize/tests.
- name: kustomize build tests
run: |
cd kustomize/tests
KUSTOMIZE_TESTS_SUBFOLDERS=$(ls -d */)
for test in $KUSTOMIZE_TESTS_SUBFOLDERS;
do
echo "## kustomize build for " + $test
kustomize build $test
done
================================================
FILE: .github/workflows/terraform-validate-ci.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: terraform-validate-ci
on:
push:
branches:
- main
paths:
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
pull_request:
paths:
- 'terraform/**'
- '.github/workflows/terraform-validate-ci.yaml'
jobs:
terraform-validate-ci:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: hashicorp/setup-terraform@v4
- name: terraform init & validate
run: |
cd terraform/
terraform init -backend=false
terraform validate
================================================
FILE: .gitignore
================================================
.DS_Store
.eclipse.buildship.core.prefs
.gradle/
.idea/
.kubernetes-manifests-*/
.project
.skaffold-*.yaml
.terraform.lock.hcl
.terraform/*
.venv/
.vs/
.vscode/
*.iml
*.ipr
*.iws
*.pyc
*.swp
*.tfstate*
*.tfvars
*~
bin/
build/
Dockerfile.pip
node_modules/
obj/
pkg/
release/wi-kubernetes-manifests.yaml
vendor/
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
================================================
FILE: README.md
================================================
<!-- <p align="center">
<img src="/src/frontend/static/icons/Hipster_HeroLogoMaroon.svg" width="300" alt="Online Boutique" />
</p> -->

**Online Boutique** is a cloud-first microservices demo application. The application is a
web-based e-commerce app where users can browse items, add them to the cart, and purchase them.
Google uses this application to demonstrate how developers can modernize enterprise applications using Google Cloud products, including: [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine), [Cloud Service Mesh (CSM)](https://cloud.google.com/service-mesh), [gRPC](https://grpc.io/), [Cloud Operations](https://cloud.google.com/products/operations), [Spanner](https://cloud.google.com/spanner), [Memorystore](https://cloud.google.com/memorystore), [AlloyDB](https://cloud.google.com/alloydb), and [Gemini](https://ai.google.dev/). This application works on any Kubernetes cluster.
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).
## Architecture
**Online Boutique** is composed of 11 microservices written in different
languages that talk to each other over gRPC.
[](/docs/img/architecture-diagram.png)
Find **Protocol Buffers Descriptions** at the [`./protos` directory](/protos).
| 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. |
| [cartservice](/src/cartservice) | C# | Stores the items in the user's shopping 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. |
| [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 (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 (mock) |
| [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. |
| [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. |
| [loadgenerator](/src/loadgenerator) | Python/Locust | Continuously sends requests imitating realistic user shopping flows to the frontend. |
## Screenshots
| Home Page | Checkout Screen |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| [](/docs/img/online-boutique-frontend-1.png) | [](/docs/img/online-boutique-frontend-2.png) |
## Quickstart (GKE)
1. Ensure you have the following requirements:
- [Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).
- Shell environment with `gcloud`, `git`, and `kubectl`.
2. Clone the latest major version.
```sh
git clone --depth 1 --branch v0 https://github.com/GoogleCloudPlatform/microservices-demo.git
cd microservices-demo/
```
The `--depth 1` argument skips downloading git history.
3. Set the Google Cloud project and region and ensure the Google Kubernetes Engine API is enabled.
```sh
export PROJECT_ID=<PROJECT_ID>
export REGION=us-central1
gcloud services enable container.googleapis.com \
--project=${PROJECT_ID}
```
Substitute `<PROJECT_ID>` with the ID of your Google Cloud project.
4. Create a GKE cluster and get the credentials for it.
```sh
gcloud container clusters create-auto online-boutique \
--project=${PROJECT_ID} --region=${REGION}
```
Creating the cluster may take a few minutes.
5. Deploy Online Boutique to the cluster.
```sh
kubectl apply -f ./release/kubernetes-manifests.yaml
```
6. Wait for the pods to be ready.
```sh
kubectl get pods
```
After a few minutes, you should see the Pods in a `Running` state:
```
NAME READY STATUS RESTARTS AGE
adservice-76bdd69666-ckc5j 1/1 Running 0 2m58s
cartservice-66d497c6b7-dp5jr 1/1 Running 0 2m59s
checkoutservice-666c784bd6-4jd22 1/1 Running 0 3m1s
currencyservice-5d5d496984-4jmd7 1/1 Running 0 2m59s
emailservice-667457d9d6-75jcq 1/1 Running 0 3m2s
frontend-6b8d69b9fb-wjqdg 1/1 Running 0 3m1s
loadgenerator-665b5cd444-gwqdq 1/1 Running 0 3m
paymentservice-68596d6dd6-bf6bv 1/1 Running 0 3m
productcatalogservice-557d474574-888kr 1/1 Running 0 3m
recommendationservice-69c56b74d4-7z8r5 1/1 Running 0 3m1s
redis-cart-5f59546cdd-5jnqf 1/1 Running 0 2m58s
shippingservice-6ccc89f8fd-v686r 1/1 Running 0 2m58s
```
7. Access the web frontend in a browser using the frontend's external IP.
```sh
kubectl get service frontend-external | awk '{print $4}'
```
Visit `http://EXTERNAL_IP` in a web browser to access your instance of Online Boutique.
8. Congrats! You've deployed the default Online Boutique. To deploy a different variation of Online Boutique (e.g., with Google Cloud Operations tracing, Istio, etc.), see [Deploy Online Boutique variations with Kustomize](#deploy-online-boutique-variations-with-kustomize).
9. Once you are done with it, delete the GKE cluster.
```sh
gcloud container clusters delete online-boutique \
--project=${PROJECT_ID} --region=${REGION}
```
Deleting the cluster may take a few minutes.
## Additional deployment options
- **Terraform**: [See these instructions](/terraform) to learn how to deploy Online Boutique using [Terraform](https://www.terraform.io/intro).
- **Istio / Cloud Service Mesh**: [See these instructions](/kustomize/components/service-mesh-istio/README.md) to deploy Online Boutique alongside an Istio-backed service mesh.
- **Non-GKE clusters (Minikube, Kind, etc)**: See the [Development guide](/docs/development-guide.md) to learn how you can deploy Online Boutique on non-GKE clusters.
- **AI assistant using Gemini**: [See these instructions](/kustomize/components/shopping-assistant/README.md) to deploy a Gemini-powered AI assistant that suggests products to purchase based on an image.
- **And more**: The [`/kustomize` directory](/kustomize) contains instructions for customizing the deployment of Online Boutique with other variations.
## Documentation
- [Development](/docs/development-guide.md) to learn how to run and develop this app locally.
## Demos featuring Online Boutique
- [Security hardening of the OnlineBoutique sample apps with the Docker Hardened Images (DHI)](https://medium.com/google-cloud/security-hardening-of-the-onlineboutique-sample-apps-with-docker-hardened-images-dhi-ca1fad348343)
- [alpine, distroless or scratch?](https://medium.com/google-cloud/alpine-distroless-or-scratch-caac35250e0b)
- [Platform Engineering in action: Deploy the Online Boutique sample apps with Score and Humanitec](https://medium.com/p/d99101001e69)
- [The new Kubernetes Gateway API with Istio and Anthos Service Mesh (ASM)](https://medium.com/p/9d64c7009cd)
- [Use Azure Redis Cache with the Online Boutique sample on AKS](https://medium.com/p/981bd98b53f8)
- [Sail Sharp, 8 tips to optimize and secure your .NET containers for Kubernetes](https://medium.com/p/c68ba253844a)
- [Deploy multi-region application with Anthos and Google cloud Spanner](https://medium.com/google-cloud/a2ea3493ed0)
- [Use Google Cloud Memorystore (Redis) with the Online Boutique sample on GKE](https://medium.com/p/82f7879a900d)
- [Use Helm to simplify the deployment of Online Boutique, with a Service Mesh, GitOps, and more!](https://medium.com/p/246119e46d53)
- [How to reduce microservices complexity with Apigee and Anthos Service Mesh](https://cloud.google.com/blog/products/application-modernization/api-management-and-service-mesh-go-together)
- [gRPC health probes with Kubernetes 1.24+](https://medium.com/p/b5bd26253a4c)
- [Use Google Cloud Spanner with the Online Boutique sample](https://medium.com/p/f7248e077339)
- [Seamlessly encrypt traffic from any apps in your Mesh to Memorystore (redis)](https://medium.com/google-cloud/64b71969318d)
- [Strengthen your app's security with Cloud Service Mesh and Anthos Config Management](https://cloud.google.com/service-mesh/docs/strengthen-app-security)
- [From edge to mesh: Exposing service mesh applications through GKE Ingress](https://cloud.google.com/architecture/exposing-service-mesh-apps-through-gke-ingress)
- [Take the first step toward SRE with Cloud Operations Sandbox](https://cloud.google.com/blog/products/operations/on-the-road-to-sre-with-cloud-operations-sandbox)
- [Deploying the Online Boutique sample application on Cloud Service Mesh](https://cloud.google.com/service-mesh/docs/onlineboutique-install-kpt)
- [Anthos Service Mesh Workshop: Lab Guide](https://codelabs.developers.google.com/codelabs/anthos-service-mesh-workshop)
- [KubeCon EU 2019 - Reinventing Networking: A Deep Dive into Istio's Multicluster Gateways - Steve Dake, Independent](https://youtu.be/-t2BfT59zJA?t=982)
- 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)
- [Google Cloud Next'18 London – Keynote](https://youtu.be/nIq2pkNcfEI?t=3071)
showing Stackdriver Incident Response Management
- [Microservices demo showcasing Go Micro](https://github.com/go-micro/demo)
================================================
FILE: cloudbuild.yaml
================================================
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# [START cloudbuild_microservice_demo_cloudbuild]
# 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:v2.16.1'
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'
# [END cloudbuild_microservice_demo_cloudbuild]
================================================
FILE: docs/adding-new-microservice.md
================================================
# Adding a new microservice
This document outlines the steps required to add a new microservice to the Online Boutique application.
## 1. Create a new directory
Create a new directory for your microservice within the `src/` directory. The directory name should be the name of your microservice.
## 2. Add source code
Place your microservice's source code inside the newly created directory. The structure of this directory should follow the conventions of the existing microservices. For example, a Python-based service would include at minimum the following files:
- `README.md`: The service's description and documentation.
- `main.py`: The application's entry point.
- `requirements.in`: A list of Python dependencies.
- `Dockerfile`: To containerize the application.
Take a look at existing microservices for inspiration.
## 3. Create a Dockerfile
Create a `Dockerfile` in your microservice's directory. This file will define the steps to build a container image for your service.
Refer to this example and tweak based on your new service's needs: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/src/frontend/Dockerfile
## 4. Create Kubernetes manifests
Create a new directory under `kustomize/components/` in the root of the repository for your microservice. Inside this directory, add the necessary Kubernetes YAML files for your new microservice. This typically includes:
- A **Deployment** to manage your service's pods.
- A **Service** to expose your microservice to other services within the cluster.
Ensure you follow the existing naming conventions and that the container image specified in the Deployment matches the one built by your `cloudbuild.yaml` and `skaffold.yaml` files.
Refer to this example and tweak based on your new service's needs: https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize/components/shopping-assistant
## 5. Update the root `kustomization.yaml` file
Add your newly created component to the root kustomization file so it gets picked up by the deployment cycle.
The file is available here: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/kustomize/kustomization.yaml
## 6. Update the root `skaffold.yaml`
Add your newly created service to the root skaffold file so the images build correctly.
The file is available here: https://github.com/GoogleCloudPlatform/microservices-demo/blob/main/skaffold.yaml
## 7. Update the Helm chart
Add your newly created service to the Helm chart templates and default values.
The chart is available here: https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/helm-chart
## 8. Update the documentation
Finally, update the project's documentation to reflect the addition of your new microservice. This may include:
- Adding a section to the main `README.md` if the service introduces significant new functionality.
- Updating the architecture diagrams in the `docs/img` directory.
- Adding a new document in the `docs` directory if the service requires detailed explanation.
================================================
FILE: docs/cloudshell-tutorial.md
================================================
# Online Boutique quickstart
This tutorial shows you how to deploy **[Online Boutique](https://github.com/GoogleCloudPlatform/microservices-demo)** to a Kubernetes cluster.
You'll be able to run Online Boutique on:
- a local **[minikube](https://minikube.sigs.k8s.io/docs/)** cluster, which comes built in to the Cloud Shell instance
- a **[Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine)** cluster using a new or existing [Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project)
Let's get started!
## Kubernetes cluster setup
Set up a Kubernetes cluster using the instructions below for either **minikube** or **GKE**.
### Minikube instructions
Minikube creates a local Kubernetes cluster on Cloud Shell.
1. Click <walkthrough-editor-spotlight spotlightId="minikube-status-bar">minikube</walkthrough-editor-spotlight> on the status bar located at the bottom of the editor window.
2. The command palette will prompt you to choose which minikube cluster to control. Select **minikube** and, in the next prompt, click **Start** if the cluster has not already been started.
3. If prompted, authorize Cloud Shell to make a GCP API call with your credentials.
*It may take a few minutes for minikube to finish starting.*
Once minikube has started, you're ready to move on to the next step.
### GKE instructions
In order to create a GKE cluster, you'll need to **[create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project)** or use an existing project.
1. Access the command palette by going to **View > Find Command**.
2. Run the command **"Cloud Code: Create GKE cluster"**.
3. Select your GCP project.
4. Apply the following configurations in the GKE wizard:
> - Zone: us-central1-b
> - Cluster name: onlineboutique
> - Node count: 4
> - Machine type: e2-standard-2
5. Click **Create Cluster**. Once your cluster has been created successfully, you can move on to the next step.
## Run on Kubernetes
Now you can run Online Boutique on your Kubernetes cluster!
1. Launch the <walkthrough-editor-spotlight spotlightId="cloud-code-status-bar">Cloud Code menu</walkthrough-editor-spotlight> from the status bar and select <walkthrough-editor-spotlight spotlightId="cloud-code-run-on-k8s">Run on Kubernetes</walkthrough-editor-spotlight>.
2. If prompted to select a Skaffold Profile, select **[default]**.
3. Select **Yes** to confirm your current context.
4. If you're using a GKE cluster, you'll need to confirm your container image registry.
5. If prompted, authorize Cloud Shell to make a GCP API call with your credentials.
Cloud Code uses configurations defined in <walkthrough-editor-open-file filePath="skaffold.yaml">skaffold.yaml</walkthrough-editor-open-file> to build and deploy the app. *It may take a few minutes for the deploy to complete.*
6. Once the app is running, the local URLs will be displayed in the <walkthrough-editor-spotlight spotlightId="output">Output</walkthrough-editor-spotlight> terminal.
7. To access your Online Boutique frontend service, click on the <walkthrough-spotlight-pointer spotlightId="devshell-web-preview-button" target="cloudshell">Web Preview button</walkthrough-spotlight-pointer> in the upper right of the editor window.
8. Select **Change Port** and enter '4503' as the port, then click **Change and Preview**. Your app will open in a new window.
## Stop the app
To stop running the app:
1. Go to the <walkthrough-editor-spotlight spotlightId="activity-bar-debug">Debug view</walkthrough-editor-spotlight>
2. Click the **Stop** icon.
3. Select **Yes** to clean up deployed resources.
You can start, stop, and debug apps from the Debug view.
### Clean up
If you've deployed your app to a GKE cluster in your Google Cloud project, you'll want to delete the cluster to avoid incurring charges.
1. Navigate to the <walkthrough-editor-spotlight spotlightId="activity-bar-cloud-k8s">Cloud Code - Kubernetes view</walkthrough-editor-spotlight> in the Activity bar.
2. Under the <walkthrough-editor-spotlight spotlightId="cloud-code-gke-explorer">Google Kubernetes Engine Explorer tab</walkthrough-editor-spotlight>, right-click on your cluster and select **Delete Cluster**.
## Conclusion
<walkthrough-conclusion-trophy></walkthrough-conclusion-trophy>
Congratulations! You've successfully deployed Online Boutique using Cloud Shell.
<walkthrough-inline-feedback></walkthrough-inline-feedback>
##### What's next?
Try other deployment options for Online Boutique:
- **Istio/Cloud Service Mesh**: <walkthrough-editor-open-file filePath="./kustomize/components/service-mesh-istio/README.md">See these instructions</walkthrough-editor-open-file>.
Learn more about the [Cloud Shell](https://cloud.google.com/shell) IDE environment and the [Cloud Code](https://cloud.google.com/code) extension.
================================================
FILE: docs/deploystack.md
================================================
## Deploy Online Boutique with DeployStack
The "Open in Google Cloud Shell" button below will use [DeployStack](https://cloud.google.com/shell/docs/cloud-shell-tutorials/deploystack/overview) to deploy Online Boutique to a new Google Kubernetes Engine (GKE) cluster.
<!-- TODO: remove reference to the deploystack-enable branch when it pushes to main -->
<a href="https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fmicroservices-demo&shellonly=true&cloudshell_image=gcr.io/ds-artifacts-cloudshell/deploystack_custom_image" target="_new">
<img alt="Open in Cloud Shell" src="https://gstatic.com/cloudssh/images/open-btn.svg">
</a>
The button will open up a [Cloud Shell](https://cloud.google.com/shell) session where you will select your Google Cloud project. After project selection, the following will happen automatically:
1. a GKE cluster will be created inside the select project
2. Online Boutique (and its load generator) will be deployed to that cluster
================================================
FILE: docs/development-guide.md
================================================
# Development Guide
This doc explains how to build and run the Online Boutique source code locally using the `skaffold` command-line tool.
## Prerequisites
- [Docker for Desktop](https://www.docker.com/products/docker-desktop)
- [kubectl](https://kubernetes.io/docs/tasks/tools/) (can be installed via `gcloud components install kubectl` for Option 1 - GKE)
- [skaffold **2.0.2+**](https://skaffold.dev/docs/install/) (latest version recommended), a tool that builds and deploys Docker images in bulk.
- Clone the repository.
```sh
git clone https://github.com/GoogleCloudPlatform/microservices-demo
cd microservices-demo/
```
- A Google Cloud project with Google Container Registry enabled. (for Option 1 - GKE)
- [Minikube](https://minikube.sigs.k8s.io/docs/start/) (optional for Option 2 - Local Cluster)
- [Kind](https://kind.sigs.k8s.io/) (optional for Option 2 - Local Cluster)
## Option 1: Google Kubernetes Engine (GKE)
> 💡 Recommended if you're using Google Cloud and want to try it on
> a realistic cluster. **Note**: If your cluster has Workload Identity enabled,
> [see these instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable)
1. Create a Google Kubernetes Engine cluster and make sure `kubectl` is pointing
to the cluster.
```sh
gcloud services enable container.googleapis.com
```
```sh
gcloud container clusters create-auto demo --region=us-central1
```
```
kubectl get nodes
```
2. Enable Artifact Registry (AR) on your GCP project and configure the
`docker` CLI to authenticate to AR:
```sh
gcloud services enable artifactregistry.googleapis.com
```
```sh
gcloud artifacts repositories create microservices-demo \
--repository-format=docker \
--location=us \
```
```sh
gcloud auth configure-docker -q
```
3. In the root of this repository, run:
```
skaffold run --default-repo=us-docker.pkg.dev/PROJECT_ID/microservices-demo
```
Where `PROJECT_ID` is replaced by your Google Cloud project ID.
This command:
- Builds the container images.
- Pushes them to AR.
- Applies the `./kubernetes-manifests` deploying the application to
Kubernetes.
**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=us-docker.pkg.dev/[PROJECT_ID]/microservices-demo` instead.
4. Find the IP address of your application, then visit the application on your
browser to confirm installation.
kubectl get service frontend-external
5. Navigate to `http://EXTERNAL-IP` to access the web frontend.
## Option 2 - Local Cluster
1. Launch a local Kubernetes cluster with one of the following tools:
- To launch **Minikube** (tested with Ubuntu Linux). Please, ensure that the
local Kubernetes cluster has at least:
- 4 CPUs
- 4.0 GiB memory
- 32 GB disk space
```shell
minikube start --cpus=4 --memory 4096 --disk-size 32g
```
- To launch **Docker for Desktop** (tested with Mac/Windows). 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
- To launch a **Kind** cluster:
```shell
kind create cluster
```
2. Run `kubectl get nodes` to verify you're connected to the respective control plane.
3. 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
automatically as you refactor the code, run `skaffold dev` command.
4. Run `kubectl get pods` to verify the Pods are ready and running.
5. Run `kubectl port-forward deployment/frontend 8080:8080` to forward a port to the frontend service.
6. Navigate to `localhost:8080` to access the web frontend.
## Adding a new microservice
In general, the set of core microservices for Online Boutique is fairly complete and unlikely to change in the future, but it can be useful to add an additional optional microservice that can be deployed to complement the core services.
See the [Adding a new microservice](adding-new-microservice.md) guide for instructions on how to add a new microservice.
## Cleanup
If you've deployed the application with `skaffold run` command, you can run
`skaffold delete` to clean up the deployed resources.
================================================
FILE: docs/product-requirements.md
================================================
## Product Requirements
This document contains a list of requirements that every change made to this repository should meet.
Every change must:
1. Preserve the golden user journey taken by Kubernetes beginners.
1. Preserve the simplicity of demos.
1. Preserve the simplicity of the GKE quickstart.
These requirements are about the default deployment (default configuration) of Online Boutique.
Changes that will violate any of these rules should not be built into the default configuration of Online Boutique.
Such changes should be opt-in only — ideally, as a [Kustomize Component](https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize) if they align with the [purpose of Online Boutique](/docs/purpose.md).
### 1. Preserve the golden user journey taken by Kubernetes beginners
The following statement about Online Boutique should always be true:
> A user outside of Google can deploy Online Boutique's default configuration on a [_kind_ Kubernetes cluster](https://kind.sigs.k8s.io/).
This statement describes the golden user journey that we expect new Kubernetes users to take while onboarding to Online Boutique.
Being able to run Online Boutique on a _kind_ cluster ensures that Online Boutique is free and cloud-agnostic. This is aligned with [Google's mission](https://about.google/) of making information universally accessible and useful. To be specific, Online Boutique should be useful and accessible to developers that are new to Kubernetes.
### 2. Preserve the simplicity of demos
New changes should not complicate the primary user journey showcased in live demos and tutorials.
Today, the primary user journey is as follows:
1. Visit Online Boutique on a web browser.
2. Select an item from the homepage and add the item to the cart.
3. The checkout form is pre-populated with placeholder data (e.g. the shipping address).
4. The user checks out and completes the order.
### 3. Preserve the simplicity of the GKE quickstart
New changes should not add additional complexity in the [main Online Boutique quickstart](https://github.com/GoogleCloudPlatform/microservices-demo#quickstart-gke).
In particular, new changes should not add extra required steps or additional required tools in that quickstart.
Ideally, extensions to Online Boutique's default functionality (such as a new microservice or a new cloud service integration) should be added as a [Kustomize Component](https://github.com/GoogleCloudPlatform/microservices-demo/tree/main/kustomize/components) which users can optionally opt into.
================================================
FILE: docs/purpose.md
================================================
## Purpose
Today, the primary purpose of Online Boutique is to demonstrate:
* [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine)
* [Anthos](https://cloud.google.com/anthos)
* [Google Cloud Operations](https://cloud.google.com/products/operations)
* tools and technologies commonly used alongside the above products
while being accessible and useful to all new Kubernetes users.
### Why does the purpose matter?
We filter and prioritize the work to be done in this repository based on the purpose defined above.
If you wish to make changes to this repository that do not align with the above purpose, we encourage you to maintain your own fork of Online Boutique.
================================================
FILE: docs/releasing/README.md
================================================
# Releasing Online Boutique
This document walks through the process of creating a new release of Online Boutique.
## Prerequisites for tagging a release
1. Choose the logical [next release tag](https://github.com/GoogleCloudPlatform/bank-of-anthos/releases), using [semantic versioning](https://semver.org/): `vX.Y.Z`.
If this release includes significant feature changes, update the minor version (`Y`). Otherwise, for bug-fix releases or standard quarterly release, update the patch version `Z`).
2. Ensure that the following commands are in your `PATH`:
- `gsed` (found in the `gnu-sed` Brew package for macOS, or by symlinking `sed` for Linux)
- `gcloud`
- `helm`
3. Make sure that your `gcloud` is authenticated:
```sh
gcloud auth login
gcloud auth configure-docker us-central1-docker.pkg.dev
```
## Create and tag the new release
Run the `make-release.sh` script found inside the `docs/releasing/` directory:
```sh
# assuming you are inside the root path of the bank-of-anthos repository
export TAG=vX.Y.Z # This is the new version (e.g. `v0.3.5`)
export REPO_PREFIX=us-central1-docker.pkg.dev/google-samples/microservices-demo # This is the Docker repository for tagged images
export PROJECT_ID=google-samples # This is the Google Cloud project for the release CI
./docs/releasing/make-release.sh
```
This script does the following:
1. Uses `make-docker-images.sh` to build and push a Docker image for each microservice to the previously specified repository.
2. Uses `make-release-artifacts.sh` to regenerates (and update the image $TAGS) YAML file at `./release/kubernetes-manifests.yaml` and `./kustomize/base/`.
3. Runs `git tag` and pushes a new branch (e.g., `release/v0.3.5`) with the changes to `./release/kubernetes-manifests.yaml`.
You can then browse the [Container Registry repository](https://pantheon.corp.google.com/gcr/images/google-samples/global/microservices-demo?project=google-samples) to make sure a Docker image was created for each microservice (with the new version tag).
## Create the PR
Now that the release branch has been created, you can find it in the [list of branches](https://github.com/GoogleCloudPlatform/microservices-demo/branches) and create a pull request targeting `main` (the default branch).
This process is going to trigger multiple CI checks as well as stage the release onto a temporary cluster. Once the PR has been approved and all checks are successfully passing, you can then merge the branch. Make sure to include the release draft (see next section) in the pull-request description for reviewers to see.
Once reviewed and you're ready to merge, make sure to not delete the release branch or the tags during that process.
## Add notes to the release
Once the PR has been fully merged, you are ready to create a new release for the newly created [tag](https://github.com/GoogleCloudPlatform/microservices-demo/tags).
- Click the breadcrumbs on the row of the latest tag that was created in the [tags](https://github.com/GoogleCloudPlatform/microservices-demo/tags) page
- Select the `Create release` option
The release notes should contain a brief description of the changes since the previous release (like bug fixed and new features). For inspiration, you can look at the list of [releases](https://github.com/GoogleCloudPlatform/microservices-demo/releases).
> ***Note:*** No assets need to be uploaded. They are picked up automatically from the tagged revision
## Deploy on the production environment
Once the release notes are published, you should then replace the version of the production environment to the newly published version.
1. Connect to the [online-boutique-release GKE cluster](https://pantheon.corp.google.com/kubernetes/clusters/details/us-central1-c/online-boutique-release/details?project=online-boutique-ci):
```sh
gcloud container clusters get-credentials online-boutique-release \
--zone us-central1-c --project online-boutique-ci
```
2. Deploy `release/kubernetes-manifests.yaml` to it:
```sh
kubectl apply -f ./release/kubernetes-manifests.yaml
```
3. Remove unnecessary objects:
```sh
kubectl delete service frontend-external
kubectl delete deployment loadgenerator
```
3. Make sure [cymbal-shops.retail.cymbal.dev](https://cymbal-shops.retail.cymbal.dev) works.
## Update major tags
1. Update the relevant major tag (for example, `v1`):
```sh
export MAJOR_TAG=v0 # Edit this as needed (to v1/v2/v3/etc)
git checkout release/${TAG}
git pull
git push --delete origin ${MAJOR_TAG} # Delete the remote tag (if it exists)
git tag --delete ${MAJOR_TAG} # Delete the local tag (if it exists)
git tag -a ${MAJOR_TAG} -m "Updating ${MAJOR_TAG} to its most recent release: ${TAG}"
git push origin ${MAJOR_TAG} # Push the new tag to origin
```
## Announce the new release internally
Once the new release is out, you can now announce it via [g/online-boutique-announce](https://groups.google.com/a/google.com/g/online-boutique-announce).
================================================
FILE: docs/releasing/license_header.txt
================================================
# Copyright 2025 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.
================================================
FILE: docs/releasing/make-docker-images.sh
================================================
#!/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
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
log() { echo "$1" >&2; }
TAG="${TAG:?TAG env variable must be specified}"
REPO_PREFIX="${REPO_PREFIX:?REPO_PREFIX env variable must be specified}"
PROJECT_ID="${PROJECT_ID:?PROJECT_ID env variable must be specified e.g. google-samples}"
while IFS= read -d $'\0' -r dir; do
# build image
svcname="$(basename "${dir}")"
builddir="${dir}"
#PR 516 moved cartservice build artifacts one level down to src
if [ $svcname == "cartservice" ]
then
builddir="${dir}/src"
fi
image="${REPO_PREFIX}/$svcname:$TAG"
image_with_sample_public_image_tag="${REPO_PREFIX}/$svcname:sample-public-image-$TAG"
(
cd "${builddir}"
log "Building (and pushing) image on Google Cloud Build: ${image}"
gcloud builds submit --project=${PROJECT_ID} --tag=${image}
gcloud artifacts docker tags add ${image} ${image_with_sample_public_image_tag}
)
done < <(find "${REPO_ROOT}/src" -mindepth 1 -maxdepth 1 -type d -print0)
log "Successfully built and pushed all images."
================================================
FILE: docs/releasing/make-helm-chart.sh
================================================
#!/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.
# Packages and pushes Online Boutique's Helm chart in public Artifact Registry.
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
log() { echo "$1" >&2; }
TAG="${TAG:?TAG env variable must be specified}"
HELM_CHART_REPO="us-docker.pkg.dev/online-boutique-ci/charts"
cd ${REPO_ROOT}/helm-chart
gsed -i "s/^appVersion:.*/appVersion: \"${TAG}\"/" Chart.yaml
gsed -i "s/^version:.*/version: ${TAG:1}/" Chart.yaml
helm package .
helm push onlineboutique-${TAG:1}.tgz oci://$HELM_CHART_REPO
rm ./onlineboutique-${TAG:1}.tgz
log "Successfully built and pushed the Helm chart."
================================================
FILE: docs/releasing/make-release-artifacts.sh
================================================
#!/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
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
[[ -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:-${REPO_ROOT}/release}"
print_license_header() {
cat "${SCRIPT_DIR}/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_except_kustomization() {
local dir
dir="$1"
while IFS= read -d $'\0' -r file; do
echo "---"
# strip license headers (pattern "^# ")
awk '
/^[^# ]/ { found = 1 }
found { print }' "${file}"
done < <(find "${dir}" -name '*.yaml' ! -name 'kustomization.yaml' -type f -print0)
}
mk_kubernetes_manifests() {
out_manifest="$(read_manifests_except_kustomization "${REPO_ROOT}/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 '# [START gke_release_kubernetes_manifests_microservices_demo]'
echo "${out_manifest}"
echo "# [END gke_release_kubernetes_manifests_microservices_demo]"
}
mk_istio_manifests() {
print_license_header
print_autogenerated_warning
echo '# [START servicemesh_release_istio_manifests_microservices_demo]'
# This just copies the yaml from the component (excluding kustomization.yaml)
# since there is no easy way to render individual kustomize component resources
read_manifests_except_kustomization "${REPO_ROOT}/kustomize/components/service-mesh-istio/"
echo '# [END servicemesh_release_istio_manifests_microservices_demo]'
}
mk_kustomize_base() {
for file_to_copy in ./kubernetes-manifests/*.yaml
do
# Don't copy kustomization.yaml.
if [[ $file_to_copy == "./kubernetes-manifests/kustomization.yaml" ]]; then
continue
fi
cp ${file_to_copy} ./kustomize/base/
service_name="$(basename "${file_to_copy}" .yaml)"
image="$REPO_PREFIX/$service_name:$TAG"
# Inside redis.yaml, we use the official `redis:alpine` Docker image.
# We don't use an image from `us-central1-docker.pkg.dev/google-samples/microservices-demo`.
if [[ $service_name == "redis" ]]; then
continue
fi
pattern="^(\s*)image:\s.*${service_name}(.*)(\s*)"
replace="\1image: ${image}\3"
gsed --in-place --regexp-extended "s|${pattern}|${replace}|g" ./kustomize/base/${service_name}.yaml
done
}
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}"
mk_kustomize_base
log "Written Kustomize base"
}
main
================================================
FILE: docs/releasing/make-release.sh
================================================
#!/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 main.
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REPO_ROOT=$SCRIPT_DIR/../..
[[ -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. us-central1-docker.pkg.dev\/google-samples\/microservices-demo}"
PROJECT_ID="${PROJECT_ID:?PROJECT_ID env variable must be specified e.g. google-samples}"
if [[ "$TAG" != v* ]]; then
fail "\$TAG must start with 'v', e.g. v0.1.0 (got: $TAG)"
fi
# ensure there are no uncommitted changes
if [[ $(git status -s | wc -l) -gt 0 ]]; then
echo "error: can't have uncommitted changes"
exit 1
fi
# make sure local source is up to date
git checkout main
git pull
# build and push images
"${SCRIPT_DIR}"/make-docker-images.sh
# update yaml
"${SCRIPT_DIR}"/make-release-artifacts.sh
# build and push images
"${SCRIPT_DIR}"/make-helm-chart.sh
# create git release / push to new branch
git checkout -b "release/${TAG}"
git add "${REPO_ROOT}/release/"
git add "${REPO_ROOT}/kustomize/base/"
git add "${REPO_ROOT}/helm-chart/"
git commit --allow-empty -m "Release $TAG"
log "Pushing k8s manifests to release/${TAG}..."
git tag "$TAG"
git push --set-upstream origin "release/${TAG}"
git push --tags
log "Successfully tagged release $TAG."
================================================
FILE: helm-chart/Chart.yaml
================================================
# Copyright 2023 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: v2
name: onlineboutique
description: A Helm chart for Kubernetes for Online Boutique
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.10.5
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v0.10.5"
================================================
FILE: helm-chart/README.md
================================================
# Helm chart for Online Boutique
If you'd like to deploy Online Boutique via its Helm chart, you could leverage the following instructions.
**Warning:** Online Boutique's Helm chart is currently experimental. If you have feedback or run into issues, let us know inside [GitHub Issue #1319](https://github.com/GoogleCloudPlatform/microservices-demo/issues/1319) or by creating a [new GitHub Issue](https://github.com/GoogleCloudPlatform/microservices-demo/issues/new/choose).
Deploy the default setup of Online Boutique:
```sh
helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install
```
Deploy advanced scenario of Online Boutique:
```sh
helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
--set images.repository=us-docker.pkg.dev/my-project/microservices-demo \
--set frontend.externalService=false \
--set redis.create=false \
--set cartservice.database.type=spanner \
--set cartservice.database.connectionString=projects/my-project/instances/onlineboutique/databases/carts \
--set serviceAccounts.create=true \
--set authorizationPolicies.create=true \
--set networkPolicies.create=true \
--set sidecars.create=true \
--set frontend.virtualService.create=true \
--set 'serviceAccounts.annotations.iam\.gke\.io/gcp-service-account=spanner-db-user@my-project.iam.gserviceaccount.com' \
--set serviceAccounts.annotationsOnlyForCartservice=true \
-n onlineboutique
```
For the full list of configurations, see [values.yaml](./values.yaml).
You could also find advanced scenarios with these blogs below:
- [Online Boutique sample’s Helm chart, to simplify the setup of advanced and secured scenarios with Service Mesh and GitOps](https://medium.com/google-cloud/246119e46d53)
- [gRPC health probes with Kubernetes 1.24+](https://medium.com/google-cloud/b5bd26253a4c)
- [Use Google Cloud Spanner with the Online Boutique sample](https://medium.com/google-cloud/f7248e077339)
================================================
FILE: helm-chart/templates/NOTES.txt
================================================
{{- if and .Values.frontend.create .Values.frontend.externalService }}
Note: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status of the frontend IP address with:
kubectl get --namespace {{ .Release.Namespace }} svc -w {{ .Values.frontend.name }}-external
Get the external IP address of the frontend:
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ .Values.frontend.name }}-external --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP
{{- end }}
{{- if .Values.frontend.virtualService.create }}
Get the external IP address of the ingress gateway:
export SERVICE_IP=$(kubectl get svc --namespace {{ .Values.frontend.virtualService.gateway.namespace }} {{ .Values.frontend.virtualService.gateway.name }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP
{{- end }}
================================================
FILE: helm-chart/templates/adservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.adService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.adService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.adService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.adService.name }}
template:
metadata:
labels:
app: {{ .Values.adService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.adService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.adService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 9555
env:
- name: PORT
value: "9555"
resources:
{{- toYaml .Values.adService.resources | nindent 10 }}
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
livenessProbe:
initialDelaySeconds: 20
periodSeconds: 15
grpc:
port: 9555
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.adService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.adService.name }}
ports:
- name: grpc
port: 9555
targetPort: 9555
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.adService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
ports:
- port: 9555
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.adService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.adService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.adService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.AdService/GetAds
methods:
- POST
ports:
- "9555"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/cartservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.cartService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.cartService.name }}
namespace: {{.Release.Namespace}}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.cartService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.cartService.name }}
template:
metadata:
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
annotations:
sidecar.istio.io/userVolumeMount: '[{"name": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}", "mountPath": "/etc/certs", "readonly": true}]'
sidecar.istio.io/userVolume: '[{"name": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}", "secret": {"secretName": "{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}"}}]'
proxy.istio.io/config: '{"holdApplicationUntilProxyStarts": true}'
{{- end }}
labels:
app: {{ .Values.cartService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.cartService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- end }}
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.cartService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 7070
env:
{{- if eq .Values.cartDatabase.type "spanner" }}
- name: SPANNER_CONNECTION_STRING
{{- else }}
- name: REDIS_ADDR
{{- end }}
value: {{ .Values.cartDatabase.connectionString | quote }}
resources:
{{- toYaml .Values.cartService.resources | nindent 10 }}
readinessProbe:
initialDelaySeconds: 15
grpc:
port: 7070
livenessProbe:
initialDelaySeconds: 15
periodSeconds: 10
grpc:
port: 7070
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.cartService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.cartService.name }}
ports:
- name: grpc
port: 7070
targetPort: 7070
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 7070
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.cartService.name }}
egress:
- hosts:
- istio-system/*
{{- if eq .Values.cartDatabase.type "redis" }}
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
- ./{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
{{- else }}
- ./{{ .Values.cartDatabase.inClusterRedis.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.cartService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CartService/AddItem
- /hipstershop.CartService/GetCart
- /hipstershop.CartService/EmptyCart
methods:
- POST
ports:
- "7070"
{{- end }}
{{- if .Values.cartDatabase.inClusterRedis.create }}
---
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
template:
metadata:
labels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.cartDatabase.inClusterRedis.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: redis
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
{{- if .Values.cartDatabase.inClusterRedis.publicRepository }}
image: redis:alpine@sha256:2afba59292f25f5d1af200496db41bea2c6c816b059f57ae74703a50a03a27d0
{{- else }}
image: {{ .Values.images.repository }}/redis:alpine
{{- end }}
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: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
type: ClusterIP
selector:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
ports:
- name: tcp-redis
port: 6379
targetPort: 6379
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
ports:
- port: 6379
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
egress:
- hosts:
- istio-system/*
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.cartDatabase.inClusterRedis.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.cartDatabase.inClusterRedis.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.cartService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
ports:
- "6379"
{{- end }}
{{- end }}
{{- if .Values.cartDatabase.externalRedisTlsOrigination.enable }}
---
apiVersion: v1
data:
{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.pem: {{ .Values.cartDatabase.externalRedisTlsOrigination.certificate | b64enc | quote }}
kind: Secret
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
spec:
exportTo:
- '.'
host: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
trafficPolicy:
tls:
mode: SIMPLE
caCertificates: /etc/certs/{{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.pem
---
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}
namespace: {{ .Release.Namespace }}
spec:
hosts:
- {{ .Values.cartDatabase.externalRedisTlsOrigination.name }}.{{ .Release.Namespace }}
addresses:
- {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointAddress }}/32
endpoints:
- address: {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointAddress }}
location: MESH_EXTERNAL
resolution: STATIC
ports:
- number: {{ .Values.cartDatabase.externalRedisTlsOrigination.endpointPort }}
name: tcp-redis
protocol: TCP
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/checkoutservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.checkoutService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.checkoutService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.checkoutService.name }}
template:
metadata:
labels:
app: {{ .Values.checkoutService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.checkoutService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.checkoutService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 5050
readinessProbe:
grpc:
port: 5050
livenessProbe:
grpc:
port: 5050
env:
- name: PORT
value: "5050"
- name: PRODUCT_CATALOG_SERVICE_ADDR
value: "{{ .Values.productCatalogService.name }}:3550"
- name: SHIPPING_SERVICE_ADDR
value: "{{ .Values.shippingService.name }}:50051"
- name: PAYMENT_SERVICE_ADDR
value: "{{ .Values.paymentService.name }}:50051"
- name: EMAIL_SERVICE_ADDR
value: "{{ .Values.emailService.name }}:5000"
- name: CURRENCY_SERVICE_ADDR
value: "{{ .Values.currencyService.name }}:7000"
- name: CART_SERVICE_ADDR
value: "{{ .Values.cartService.name }}:7070"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.checkoutService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if .Values.googleCloudOperations.profiler }}
- name: ENABLE_PROFILER
value: "1"
{{- end }}
resources:
{{- toYaml .Values.checkoutService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.checkoutService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.checkoutService.name }}
ports:
- name: grpc
port: 5050
targetPort: 5050
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
ports:
- port: 5050
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.checkoutService.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.cartService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.currencyService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.emailService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.paymentService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.productCatalogService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.shippingService.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.checkoutService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.checkoutService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CheckoutService/PlaceOrder
methods:
- POST
ports:
- "5050"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/common.yaml
================================================
# Copyright 2024 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.
{{- if .Values.networkPolicies.create }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: {{ .Release.Namespace }}
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: {{ .Release.Namespace }}
spec: {}
{{- end }}
================================================
FILE: helm-chart/templates/currencyservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.currencyService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.currencyService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.currencyService.name }}
template:
metadata:
labels:
app: {{ .Values.currencyService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.currencyService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.currencyService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- name: grpc
containerPort: 7000
env:
- name: PORT
value: "7000"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.currencyService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
grpc:
port: 7000
livenessProbe:
grpc:
port: 7000
resources:
{{- toYaml .Values.currencyService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.currencyService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.currencyService.name }}
ports:
- name: grpc
port: 7000
targetPort: 7000
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.currencyService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 7000
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.currencyService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.currencyService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.currencyService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.CurrencyService/Convert
- /hipstershop.CurrencyService/GetSupportedCurrencies
methods:
- POST
ports:
- "7000"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/emailservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.emailService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.emailService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.emailService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.emailService.name }}
template:
metadata:
labels:
app: {{ .Values.emailService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.emailService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.emailService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.emailService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
periodSeconds: 5
grpc:
port: 8080
livenessProbe:
periodSeconds: 5
grpc:
port: 8080
resources:
{{- toYaml .Values.emailService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.emailService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.emailService.name }}
ports:
- name: grpc
port: 5000
targetPort: 8080
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.emailService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 8080
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.emailService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.emailService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.emailService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.EmailService/SendOrderConfirmation
methods:
- POST
ports:
- "8080"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/frontend.yaml
================================================
# Copyright 2024 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.
{{- if .Values.frontend.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.frontend.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.frontend.name }}
spec:
selector:
matchLabels:
app: {{ .Values.frontend.name }}
template:
metadata:
labels:
app: {{ .Values.frontend.name }}
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.frontend.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.frontend.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
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: "{{ .Values.productCatalogService.name }}:3550"
- name: CURRENCY_SERVICE_ADDR
value: "{{ .Values.currencyService.name }}:7000"
- name: CART_SERVICE_ADDR
value: "{{ .Values.cartService.name }}:7070"
- name: RECOMMENDATION_SERVICE_ADDR
value: "{{ .Values.recommendationService.name }}:8080"
- name: SHIPPING_SERVICE_ADDR
value: "{{ .Values.shippingService.name }}:50051"
- name: CHECKOUT_SERVICE_ADDR
value: "{{ .Values.checkoutService.name }}:5050"
- name: AD_SERVICE_ADDR
value: "{{ .Values.adService.name }}:9555"
- name: SHOPPING_ASSISTANT_SERVICE_ADDR
value: "{{ .Values.shoppingAssistantService.name }}:80"
- name: ENV_PLATFORM
value: {{ .Values.frontend.platform | quote }}
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.frontend.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if .Values.googleCloudOperations.profiler }}
- name: ENABLE_PROFILER
value: "1"
{{- end }}
- name: CYMBAL_BRANDING
value: {{ .Values.frontend.cymbalBranding | quote }}
- name: ENABLE_ASSISTANT
value: {{ .Values.shoppingAssistantService.create | quote }}
- name: ENABLE_SINGLE_SHARED_SESSION
value: {{ .Values.frontend.singleSharedSession | quote }}
resources:
{{- toYaml .Values.frontend.resources | nindent 12 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.frontend.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.frontend.name }}
ports:
- name: http
port: 80
targetPort: 8080
{{- if .Values.frontend.externalService }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.frontend.name }}-external
namespace: {{ .Release.Namespace }}
spec:
type: LoadBalancer
selector:
app: {{ .Values.frontend.name }}
ports:
- name: http
port: 80
targetPort: 8080
{{- end }}
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
policyTypes:
- Ingress
- Egress
ingress:
{{- if .Values.frontend.externalService }}
- {}
{{- else }}
- from:
- podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
{{- if .Values.frontend.virtualService.create }}
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: {{ .Values.frontend.virtualService.gateway.namespace }}
podSelector:
matchLabels:
{{ .Values.frontend.virtualService.gateway.labelKey }}: {{ .Values.frontend.virtualService.gateway.labelValue }}
{{- end }}
ports:
- port: 8080
protocol: TCP
{{- end }}
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.frontend.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.adService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.cartService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.checkoutService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.currencyService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.productCatalogService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.recommendationService.name }}.{{ .Release.Namespace }}.svc.cluster.local
- ./{{ .Values.shippingService.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.frontend.name }}
rules:
{{- if .Values.frontend.externalService }}
- to:
{{- else }}
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.loadGenerator.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
{{- if .Values.frontend.virtualService.create }}
- cluster.local/ns/{{ .Values.frontend.virtualService.gateway.namespace }}/sa/{{ .Values.frontend.virtualService.gateway.name }}
{{- end }}
to:
{{- end }}
- operation:
methods:
- GET
- POST
ports:
- "8080"
{{- end }}
{{- if .Values.frontend.virtualService.create }}
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: {{ .Values.frontend.name }}
namespace: {{ .Release.Namespace }}
spec:
{{- with .Values.frontend.virtualService.hosts }}
hosts:
{{- toYaml . | nindent 2 }}
{{- end }}
gateways:
- {{ .Values.frontend.virtualService.gateway.namespace }}/{{ .Values.frontend.virtualService.gateway.name }}
http:
- route:
- destination:
host: {{ .Values.frontend.name }}
port:
number: 80
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/loadgenerator.yaml
================================================
# Copyright 2022 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.
{{- if .Values.loadGenerator.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.loadGenerator.name }}
spec:
selector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
replicas: 1
template:
metadata:
labels:
app: {{ .Values.loadGenerator.name }}
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "true"
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.loadGenerator.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
restartPolicy: Always
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
{{- if .Values.loadGenerator.checkFrontendInitContainer }}
initContainers:
- command:
- /bin/sh
- -exc
- |
MAX_RETRIES=12
RETRY_INTERVAL=10
for i in $(seq 1 $MAX_RETRIES); do
echo "Attempt $i: Pinging frontend: ${FRONTEND_ADDR}..."
STATUSCODE=$(wget --server-response http://${FRONTEND_ADDR} 2>&1 | awk '/^ HTTP/{print $2}')
if [ $STATUSCODE -eq 200 ]; then
echo "Frontend is reachable."
exit 0
fi
echo "Error: Could not reach frontend - Status code: ${STATUSCODE}"
sleep $RETRY_INTERVAL
done
echo "Failed to reach frontend after $MAX_RETRIES attempts."
exit 1
name: frontend-check
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: busybox:latest@sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f
env:
- name: FRONTEND_ADDR
value: "{{ .Values.frontend.name }}:80"
{{- end }}
containers:
- name: main
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.loadGenerator.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
env:
- name: FRONTEND_ADDR
value: "{{ .Values.frontend.name }}:80"
- name: USERS
value: "10"
- name: RATE
value: "1"
resources:
{{- toYaml .Values.loadGenerator.resources | nindent 10 }}
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.loadGenerator.name }}
spec:
podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
policyTypes:
- Egress
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.loadGenerator.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.loadGenerator.name }}
egress:
- hosts:
- istio-system/*
- ./{{ .Values.frontend.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/opentelemetry-collector.yaml
================================================
# Copyright 2022 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.
{{- if .Values.opentelemetryCollector.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
template:
metadata:
labels:
app: {{ .Values.opentelemetryCollector.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.opentelemetryCollector.name }}
{{- else }}
serviceAccountName: default
{{- end }}
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
{{- if eq .Values.opentelemetryCollector.projectId "PROJECT_ID" }}
initContainers:
# Init container retrieves the current cloud project id from the metadata server
# and inserts it into the collector config template
# https://cloud.google.com/compute/docs/storing-retrieving-metadata
- name: otel-gateway-init
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: busybox:latest@sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f
command:
- '/bin/sh'
- '-c'
- |
sed "s/PROJECT_ID/$(curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/project/project-id)/" /template/collector-gateway-config-template.yaml >> /conf/collector-gateway-config.yaml
volumeMounts:
- name: collector-gateway-config-template
mountPath: /template
- name: collector-gateway-config
mountPath: /conf
{{- end }}
containers:
# This gateway container will receive traces and metrics from each microservice
# and forward it to GCP
- name: otel-gateway
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
args:
- --config=/conf/collector-gateway-config.yaml
image: otel/opentelemetry-collector-contrib:0.147.0@sha256:e7c92c715f28ff142f3bcaccd4fc5603cf4c71276ef09954a38eb4038500a5a5
volumeMounts:
- name: collector-gateway-config
mountPath: /conf
volumes:
# Simple ConfigMap volume with template file
- name: collector-gateway-config-template
configMap:
items:
- key: collector-gateway-config-template.yaml
path: collector-gateway-config-template.yaml
name: collector-gateway-config-template
# Create a volume to store the expanded template (with correct cloud project ID)
- name: collector-gateway-config
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
ports:
- name: grpc-otlp
port: 4317
protocol: TCP
targetPort: 4317
selector:
app: {{ .Values.opentelemetryCollector.name }}
type: ClusterIP
---
apiVersion: v1
kind: ConfigMap
metadata:
name: collector-gateway-config-template
namespace: {{ .Release.Namespace }}
# Open Telemetry Collector config
# https://opentelemetry.io/docs/collector/configuration/
data:
collector-gateway-config-template.yaml: |
receivers:
otlp:
protocols:
grpc:
processors:
exporters:
googlecloud:
project: {{ .Values.opentelemetryCollector.projectId | quote }}
service:
pipelines:
traces:
receivers: [otlp] # Receive otlp-formatted data from other collector instances
processors: []
exporters: [googlecloud] # Export traces directly to Google Cloud
metrics:
receivers: [otlp]
processors: []
exporters: [googlecloud] # Export metrics to Google Cloud
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.adService.name }}
- podSelector:
matchLabels:
app: {{ .Values.cartService.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
- podSelector:
matchLabels:
app: {{ .Values.currencyService.name }}
- podSelector:
matchLabels:
app: {{ .Values.emailService.name }}
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.loadGenerator.name }}
- podSelector:
matchLabels:
app: {{ .Values.paymentService.name }}
- podSelector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
- podSelector:
matchLabels:
app: {{ .Values.recommendationService.name }}
- podSelector:
matchLabels:
app: {{ .Values.shippingService.name }}
ports:
- port: 4317
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.opentelemetryCollector.name }}
egress:
- hosts:
- istio-system/*
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.opentelemetryCollector.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.opentelemetryCollector.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.adService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.cartService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.currencyService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.emailService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.loadGenerator.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.paymentService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.productCatalogService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.recommendationService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.shippingService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
ports:
- "4317"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/paymentservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.paymentService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.paymentService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.paymentService.name }}
template:
metadata:
labels:
app: {{ .Values.paymentService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.paymentService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.paymentService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 50051
env:
- name: PORT
value: "50051"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.paymentService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
readinessProbe:
grpc:
port: 50051
livenessProbe:
grpc:
port: 50051
resources:
{{- toYaml .Values.paymentService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.paymentService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.paymentService.name }}
ports:
- name: grpc
port: 50051
targetPort: 50051
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.paymentService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
ports:
- port: 50051
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.paymentService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.paymentService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.paymentService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
{{- else }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/default
{{- end }}
to:
- operation:
paths:
- /hipstershop.PaymentService/Charge
methods:
- POST
ports:
- "50051"
{{- end }}
{{- end }}
================================================
FILE: helm-chart/templates/productcatalogservice.yaml
================================================
# Copyright 2024 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.
{{- if .Values.productCatalogService.create }}
{{- if .Values.serviceAccounts.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{.Release.Namespace}}
{{- if not .Values.serviceAccounts.annotationsOnlyForCartservice }}
{{- with .Values.serviceAccounts.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
---
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.productCatalogService.name }}
spec:
selector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
template:
metadata:
labels:
app: {{ .Values.productCatalogService.name }}
spec:
{{- if .Values.serviceAccounts.create }}
serviceAccountName: {{ .Values.productCatalogService.name }}
{{- else }}
serviceAccountName: default
{{- end }}
terminationGracePeriodSeconds: 5
{{- if .Values.securityContext.enable }}
securityContext:
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
{{- if .Values.seccompProfile.enable }}
seccompProfile:
type: {{ .Values.seccompProfile.type }}
{{- end }}
{{- end }}
containers:
- name: server
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
image: {{ .Values.images.repository }}/{{ .Values.productCatalogService.name }}:{{ .Values.images.tag | default .Chart.AppVersion }}
ports:
- containerPort: 3550
env:
- name: PORT
value: "3550"
{{- if .Values.opentelemetryCollector.create }}
- name: COLLECTOR_SERVICE_ADDR
value: "{{ .Values.opentelemetryCollector.name }}:4317"
- name: OTEL_SERVICE_NAME
value: "{{ .Values.productCatalogService.name }}"
{{- end }}
{{- if .Values.googleCloudOperations.tracing }}
- name: ENABLE_TRACING
value: "1"
{{- end }}
{{- if not .Values.googleCloudOperations.profiler }}
- name: DISABLE_PROFILER
value: "1"
{{- end }}
- name: EXTRA_LATENCY
value: {{ .Values.productCatalogService.extraLatency }}
readinessProbe:
grpc:
port: 3550
livenessProbe:
grpc:
port: 3550
resources:
{{- toYaml .Values.productCatalogService.resources | nindent 10 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ .Values.productCatalogService.name }}
spec:
type: ClusterIP
selector:
app: {{ .Values.productCatalogService.name }}
ports:
- name: grpc
port: 3550
targetPort: 3550
{{- if .Values.networkPolicies.create }}
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: {{ .Values.frontend.name }}
- podSelector:
matchLabels:
app: {{ .Values.checkoutService.name }}
- podSelector:
matchLabels:
app: {{ .Values.recommendationService.name }}
ports:
- port: 3550
protocol: TCP
egress:
- {}
{{- end }}
{{- if .Values.sidecars.create }}
---
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
workloadSelector:
labels:
app: {{ .Values.productCatalogService.name }}
egress:
- hosts:
- istio-system/*
{{- if .Values.opentelemetryCollector.create }}
- ./{{ .Values.opentelemetryCollector.name }}.{{ .Release.Namespace }}.svc.cluster.local
{{- end }}
{{- end }}
{{- if .Values.authorizationPolicies.create }}
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: {{ .Values.productCatalogService.name }}
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: {{ .Values.productCatalogService.name }}
rules:
- from:
- source:
principals:
{{- if .Values.serviceAccounts.create }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.frontend.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.checkoutService.name }}
- cluster.local/ns/{{ .Release.Namespace }}/sa/{{ .Values.recommenda
gitextract_n0fmcr6r/
├── .deploystack/
│ ├── deploystack.yaml
│ ├── messages/
│ │ ├── description.txt
│ │ └── success.txt
│ ├── scripts/
│ │ └── preinit.sh
│ ├── test
│ └── test.yaml
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── CODEOWNERS
│ ├── CODE_OF_CONDUCT.md
│ ├── CONTRIBUTING.md
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug-report.md
│ │ ├── feature-request.md
│ │ └── other.md
│ ├── SECURITY.md
│ ├── auto-approve.yml
│ ├── header-checker-lint.yml
│ ├── pull_request_template.md
│ ├── release-cluster/
│ │ ├── README.md
│ │ ├── backend-config.yaml
│ │ ├── frontend-config.yaml
│ │ ├── frontend-ingress.yaml
│ │ ├── frontend-service.yaml
│ │ └── managed-cert.yaml
│ ├── renovate.json5
│ ├── snippet-bot.yml
│ ├── terraform/
│ │ ├── README.md
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── versions.tf
│ └── workflows/
│ ├── README.md
│ ├── ci-main.yaml
│ ├── ci-pr.yaml
│ ├── cleanup.yaml
│ ├── helm-chart-ci.yaml
│ ├── install-dependencies.sh
│ ├── kubevious-manifests-ci.yaml
│ ├── kustomize-build-ci.yaml
│ └── terraform-validate-ci.yaml
├── .gitignore
├── LICENSE
├── README.md
├── cloudbuild.yaml
├── docs/
│ ├── adding-new-microservice.md
│ ├── cloudshell-tutorial.md
│ ├── deploystack.md
│ ├── development-guide.md
│ ├── product-requirements.md
│ ├── purpose.md
│ └── releasing/
│ ├── README.md
│ ├── license_header.txt
│ ├── make-docker-images.sh
│ ├── make-helm-chart.sh
│ ├── make-release-artifacts.sh
│ └── make-release.sh
├── helm-chart/
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates/
│ │ ├── NOTES.txt
│ │ ├── adservice.yaml
│ │ ├── cartservice.yaml
│ │ ├── checkoutservice.yaml
│ │ ├── common.yaml
│ │ ├── currencyservice.yaml
│ │ ├── emailservice.yaml
│ │ ├── frontend.yaml
│ │ ├── loadgenerator.yaml
│ │ ├── opentelemetry-collector.yaml
│ │ ├── paymentservice.yaml
│ │ ├── productcatalogservice.yaml
│ │ ├── recommendationservice.yaml
│ │ └── shippingservice.yaml
│ └── values.yaml
├── istio-manifests/
│ ├── allow-egress-googleapis.yaml
│ ├── frontend-gateway.yaml
│ └── frontend.yaml
├── kubernetes-manifests/
│ ├── README.md
│ ├── adservice.yaml
│ ├── cartservice.yaml
│ ├── checkoutservice.yaml
│ ├── currencyservice.yaml
│ ├── emailservice.yaml
│ ├── frontend.yaml
│ ├── kustomization.yaml
│ ├── loadgenerator.yaml
│ ├── paymentservice.yaml
│ ├── productcatalogservice.yaml
│ ├── recommendationservice.yaml
│ └── shippingservice.yaml
├── kustomize/
│ ├── README.md
│ ├── base/
│ │ ├── adservice.yaml
│ │ ├── cartservice.yaml
│ │ ├── checkoutservice.yaml
│ │ ├── currencyservice.yaml
│ │ ├── emailservice.yaml
│ │ ├── frontend.yaml
│ │ ├── kustomization.yaml
│ │ ├── loadgenerator.yaml
│ │ ├── paymentservice.yaml
│ │ ├── productcatalogservice.yaml
│ │ ├── recommendationservice.yaml
│ │ └── shippingservice.yaml
│ ├── components/
│ │ ├── alloydb/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-registry/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-tag/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── container-images-tag-suffix/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── custom-base-url/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── cymbal-branding/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── google-cloud-operations/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ └── otel-collector.yaml
│ │ ├── memorystore/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── network-policies/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ ├── network-policy-adservice.yaml
│ │ │ ├── network-policy-cartservice.yaml
│ │ │ ├── network-policy-checkoutservice.yaml
│ │ │ ├── network-policy-currencyservice.yaml
│ │ │ ├── network-policy-deny-all.yaml
│ │ │ ├── network-policy-emailservice.yaml
│ │ │ ├── network-policy-frontend.yaml
│ │ │ ├── network-policy-loadgenerator.yaml
│ │ │ ├── network-policy-paymentservice.yaml
│ │ │ ├── network-policy-productcatalogservice.yaml
│ │ │ ├── network-policy-recommendationservice.yaml
│ │ │ ├── network-policy-redis.yaml
│ │ │ └── network-policy-shippingservice.yaml
│ │ ├── non-public-frontend/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── service-mesh-istio/
│ │ │ ├── README.md
│ │ │ ├── allow-egress-googleapis.yaml
│ │ │ ├── frontend-gateway.yaml
│ │ │ ├── frontend.yaml
│ │ │ └── kustomization.yaml
│ │ ├── shopping-assistant/
│ │ │ ├── README.md
│ │ │ ├── kustomization.yaml
│ │ │ ├── scripts/
│ │ │ │ ├── 1_deploy_alloydb_infra.sh
│ │ │ │ ├── 2_create_populate_alloydb_tables.sh
│ │ │ │ └── generate_sql_from_products.py
│ │ │ └── shoppingassistantservice.yaml
│ │ ├── single-shared-session/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ ├── spanner/
│ │ │ ├── README.md
│ │ │ └── kustomization.yaml
│ │ └── without-loadgenerator/
│ │ ├── README.md
│ │ ├── delete-loadgenerator.patch.yaml
│ │ └── kustomization.yaml
│ ├── kustomization.yaml
│ └── tests/
│ ├── README.md
│ ├── memorystore-with-all-components/
│ │ └── kustomization.yaml
│ ├── service-mesh-istio-with-all-components/
│ │ └── kustomization.yaml
│ └── spanner-with-all-components/
│ └── kustomization.yaml
├── protos/
│ ├── demo.proto
│ └── grpc/
│ └── health/
│ └── v1/
│ └── health.proto
├── release/
│ ├── istio-manifests.yaml
│ └── kubernetes-manifests.yaml
├── skaffold.yaml
├── src/
│ ├── adservice/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── build.gradle
│ │ ├── genproto.sh
│ │ ├── gradle/
│ │ │ └── wrapper/
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── settings.gradle
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── hipstershop/
│ │ │ ├── AdService.java
│ │ │ └── AdServiceClient.java
│ │ ├── proto/
│ │ │ └── demo.proto
│ │ └── resources/
│ │ └── log4j2.xml
│ ├── cartservice/
│ │ ├── cartservice.sln
│ │ ├── src/
│ │ │ ├── .dockerignore
│ │ │ ├── Dockerfile
│ │ │ ├── Dockerfile.debug
│ │ │ ├── Program.cs
│ │ │ ├── Startup.cs
│ │ │ ├── appsettings.json
│ │ │ ├── cartservice.csproj
│ │ │ ├── cartstore/
│ │ │ │ ├── AlloyDBCartStore.cs
│ │ │ │ ├── ICartStore.cs
│ │ │ │ ├── RedisCartStore.cs
│ │ │ │ └── SpannerCartStore.cs
│ │ │ ├── protos/
│ │ │ │ └── Cart.proto
│ │ │ └── services/
│ │ │ ├── CartService.cs
│ │ │ └── HealthCheckService.cs
│ │ └── tests/
│ │ ├── CartServiceTests.cs
│ │ └── cartservice.tests.csproj
│ ├── checkoutservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ └── money/
│ │ ├── money.go
│ │ └── money_test.go
│ ├── currencyservice/
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── client.js
│ │ ├── data/
│ │ │ └── currency_conversion.json
│ │ ├── genproto.sh
│ │ ├── package.json
│ │ ├── proto/
│ │ │ ├── demo.proto
│ │ │ └── grpc/
│ │ │ └── health/
│ │ │ └── v1/
│ │ │ └── health.proto
│ │ └── server.js
│ ├── emailservice/
│ │ ├── Dockerfile
│ │ ├── demo_pb2.py
│ │ ├── demo_pb2_grpc.py
│ │ ├── email_client.py
│ │ ├── email_server.py
│ │ ├── genproto.sh
│ │ ├── logger.py
│ │ ├── requirements.in
│ │ ├── requirements.txt
│ │ └── templates/
│ │ └── confirmation.html
│ ├── frontend/
│ │ ├── .dockerignore
│ │ ├── .gitkeep
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── deployment_details.go
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── handlers.go
│ │ ├── main.go
│ │ ├── middleware.go
│ │ ├── money/
│ │ │ ├── money.go
│ │ │ └── money_test.go
│ │ ├── packaging_info.go
│ │ ├── rpc.go
│ │ ├── static/
│ │ │ ├── images/
│ │ │ │ └── credits.txt
│ │ │ └── styles/
│ │ │ ├── bot.css
│ │ │ ├── cart.css
│ │ │ ├── order.css
│ │ │ └── styles.css
│ │ ├── templates/
│ │ │ ├── ad.html
│ │ │ ├── assistant.html
│ │ │ ├── cart.html
│ │ │ ├── error.html
│ │ │ ├── footer.html
│ │ │ ├── header.html
│ │ │ ├── home.html
│ │ │ ├── order.html
│ │ │ ├── product.html
│ │ │ └── recommendations.html
│ │ └── validator/
│ │ ├── validator.go
│ │ └── validator_test.go
│ ├── loadgenerator/
│ │ ├── Dockerfile
│ │ ├── locustfile.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── paymentservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── charge.js
│ │ ├── genproto.sh
│ │ ├── index.js
│ │ ├── logger.js
│ │ ├── package.json
│ │ ├── proto/
│ │ │ ├── demo.proto
│ │ │ └── grpc/
│ │ │ └── health/
│ │ │ └── v1/
│ │ │ └── health.proto
│ │ └── server.js
│ ├── productcatalogservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── catalog_loader.go
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── product_catalog.go
│ │ ├── product_catalog_test.go
│ │ ├── products.json
│ │ └── server.go
│ ├── recommendationservice/
│ │ ├── Dockerfile
│ │ ├── client.py
│ │ ├── demo_pb2.py
│ │ ├── demo_pb2_grpc.py
│ │ ├── genproto.sh
│ │ ├── logger.py
│ │ ├── recommendation_server.py
│ │ ├── requirements.in
│ │ └── requirements.txt
│ ├── shippingservice/
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── genproto/
│ │ │ ├── demo.pb.go
│ │ │ └── demo_grpc.pb.go
│ │ ├── genproto.sh
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── quote.go
│ │ ├── shippingservice_test.go
│ │ └── tracker.go
│ └── shoppingassistantservice/
│ ├── Dockerfile
│ ├── requirements.in
│ ├── requirements.txt
│ └── shoppingassistantservice.py
└── terraform/
├── README.md
├── main.tf
├── memorystore.tf
├── output.tf
├── providers.tf
└── variables.tf
SYMBOL INDEX (2102 symbols across 54 files)
FILE: src/adservice/src/main/java/hipstershop/AdService.java
class AdService (line 41) | public final class AdService {
method start (line 53) | private void start() throws IOException {
method stop (line 77) | private void stop() {
class AdServiceImpl (line 84) | private static class AdServiceImpl extends hipstershop.AdServiceGrpc.A...
method getAds (line 93) | @Override
method getAdsByCategory (line 123) | private Collection<Ad> getAdsByCategory(String category) {
method getRandomAds (line 129) | private List<Ad> getRandomAds() {
method getInstance (line 138) | private static AdService getInstance() {
method blockUntilShutdown (line 143) | private void blockUntilShutdown() throws InterruptedException {
method createAdsMap (line 149) | private static ImmutableListMultimap<String, Ad> createAdsMap() {
method initStats (line 195) | private static void initStats() {
method initTracing (line 209) | private static void initTracing() {
method main (line 223) | public static void main(String[] args) throws IOException, Interrupted...
FILE: src/adservice/src/main/java/hipstershop/AdServiceClient.java
class AdServiceClient (line 32) | public class AdServiceClient {
method AdServiceClient (line 40) | private AdServiceClient(String host, int port) {
method AdServiceClient (line 50) | private AdServiceClient(ManagedChannel channel) {
method shutdown (line 55) | private void shutdown() throws InterruptedException {
method getAds (line 60) | public void getAds(String contextKey) {
method getPortOrDefaultFromArgs (line 76) | private static int getPortOrDefaultFromArgs(String[] args) {
method getStringOrDefaultFromArgs (line 88) | private static String getStringOrDefaultFromArgs(
method main (line 101) | public static void main(String[] args) throws InterruptedException {
FILE: src/cartservice/src/Startup.cs
class Startup (line 16) | public class Startup
method Startup (line 18) | public Startup(IConfiguration configuration)
method ConfigureServices (line 27) | public void ConfigureServices(IServiceCollection services)
method Configure (line 63) | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
FILE: src/cartservice/src/cartstore/AlloyDBCartStore.cs
class AlloyDBCartStore (line 25) | public class AlloyDBCartStore : ICartStore
method AlloyDBCartStore (line 30) | public AlloyDBCartStore(IConfiguration configuration)
method AddItemAsync (line 62) | public async Task AddItemAsync(string userId, string productId, int qu...
method GetCartAsync (line 104) | public async Task<Hipstershop.Cart> GetCartAsync(string userId)
method EmptyCartAsync (line 141) | public async Task EmptyCartAsync(string userId)
method Ping (line 164) | public bool Ping()
FILE: src/cartservice/src/cartstore/ICartStore.cs
type ICartStore (line 19) | public interface ICartStore
method AddItemAsync (line 21) | Task AddItemAsync(string userId, string productId, int quantity);
method EmptyCartAsync (line 22) | Task EmptyCartAsync(string userId);
method GetCartAsync (line 23) | Task<Hipstershop.Cart> GetCartAsync(string userId);
method Ping (line 24) | bool Ping();
FILE: src/cartservice/src/cartstore/RedisCartStore.cs
class RedisCartStore (line 24) | public class RedisCartStore : ICartStore
method RedisCartStore (line 28) | public RedisCartStore(IDistributedCache cache)
method AddItemAsync (line 33) | public async Task AddItemAsync(string userId, string productId, int qu...
method EmptyCartAsync (line 68) | public async Task EmptyCartAsync(string userId)
method GetCartAsync (line 83) | public async Task<Hipstershop.Cart> GetCartAsync(string userId)
method Ping (line 106) | public bool Ping()
FILE: src/cartservice/src/cartstore/SpannerCartStore.cs
class SpannerCartStore (line 23) | public class SpannerCartStore : ICartStore
method SpannerCartStore (line 30) | public SpannerCartStore(IConfiguration configuration)
method AddItemAsync (line 54) | public async Task AddItemAsync(string userId, string productId, int qu...
method GetCartAsync (line 105) | public async Task<Hipstershop.Cart> GetCartAsync(string userId)
method EmptyCartAsync (line 145) | public async Task EmptyCartAsync(string userId)
method Ping (line 172) | public bool Ping()
FILE: src/cartservice/src/services/CartService.cs
class CartService (line 24) | public class CartService : Hipstershop.CartService.CartServiceBase
method CartService (line 29) | public CartService(ICartStore cartStore)
method AddItem (line 34) | public async override Task<Empty> AddItem(AddItemRequest request, Serv...
method GetCart (line 40) | public override Task<Cart> GetCart(GetCartRequest request, ServerCallC...
method EmptyCart (line 45) | public async override Task<Empty> EmptyCart(EmptyCartRequest request, ...
FILE: src/cartservice/src/services/HealthCheckService.cs
class HealthCheckService (line 24) | internal class HealthCheckService : HealthBase
method HealthCheckService (line 28) | public HealthCheckService (ICartStore cartStore)
method Check (line 33) | public override Task<HealthCheckResponse> Check(HealthCheckRequest req...
FILE: src/cartservice/tests/CartServiceTests.cs
class CartServiceTests (line 27) | public class CartServiceTests
method CartServiceTests (line 31) | public CartServiceTests()
method GetItem_NoAddItemBefore_EmptyCartReturned (line 41) | [Fact]
method AddItem_ItemExists_Updated (line 70) | [Fact]
method AddItem_New_Inserted (line 116) | [Fact]
FILE: src/checkoutservice/genproto/demo.pb.go
constant _ (line 32) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 34) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type CartItem (line 37) | type CartItem struct
method Reset (line 46) | func (x *CartItem) Reset() {
method String (line 55) | func (x *CartItem) String() string {
method ProtoMessage (line 59) | func (*CartItem) ProtoMessage() {}
method ProtoReflect (line 61) | func (x *CartItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 74) | func (*CartItem) Descriptor() ([]byte, []int) {
method GetProductId (line 78) | func (x *CartItem) GetProductId() string {
method GetQuantity (line 85) | func (x *CartItem) GetQuantity() int32 {
type AddItemRequest (line 92) | type AddItemRequest struct
method Reset (line 101) | func (x *AddItemRequest) Reset() {
method String (line 110) | func (x *AddItemRequest) String() string {
method ProtoMessage (line 114) | func (*AddItemRequest) ProtoMessage() {}
method ProtoReflect (line 116) | func (x *AddItemRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 129) | func (*AddItemRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 133) | func (x *AddItemRequest) GetUserId() string {
method GetItem (line 140) | func (x *AddItemRequest) GetItem() *CartItem {
type EmptyCartRequest (line 147) | type EmptyCartRequest struct
method Reset (line 155) | func (x *EmptyCartRequest) Reset() {
method String (line 164) | func (x *EmptyCartRequest) String() string {
method ProtoMessage (line 168) | func (*EmptyCartRequest) ProtoMessage() {}
method ProtoReflect (line 170) | func (x *EmptyCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 183) | func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 187) | func (x *EmptyCartRequest) GetUserId() string {
type GetCartRequest (line 194) | type GetCartRequest struct
method Reset (line 202) | func (x *GetCartRequest) Reset() {
method String (line 211) | func (x *GetCartRequest) String() string {
method ProtoMessage (line 215) | func (*GetCartRequest) ProtoMessage() {}
method ProtoReflect (line 217) | func (x *GetCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 230) | func (*GetCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 234) | func (x *GetCartRequest) GetUserId() string {
type Cart (line 241) | type Cart struct
method Reset (line 250) | func (x *Cart) Reset() {
method String (line 259) | func (x *Cart) String() string {
method ProtoMessage (line 263) | func (*Cart) ProtoMessage() {}
method ProtoReflect (line 265) | func (x *Cart) ProtoReflect() protoreflect.Message {
method Descriptor (line 278) | func (*Cart) Descriptor() ([]byte, []int) {
method GetUserId (line 282) | func (x *Cart) GetUserId() string {
method GetItems (line 289) | func (x *Cart) GetItems() []*CartItem {
type Empty (line 296) | type Empty struct
method Reset (line 302) | func (x *Empty) Reset() {
method String (line 311) | func (x *Empty) String() string {
method ProtoMessage (line 315) | func (*Empty) ProtoMessage() {}
method ProtoReflect (line 317) | func (x *Empty) ProtoReflect() protoreflect.Message {
method Descriptor (line 330) | func (*Empty) Descriptor() ([]byte, []int) {
type ListRecommendationsRequest (line 334) | type ListRecommendationsRequest struct
method Reset (line 343) | func (x *ListRecommendationsRequest) Reset() {
method String (line 352) | func (x *ListRecommendationsRequest) String() string {
method ProtoMessage (line 356) | func (*ListRecommendationsRequest) ProtoMessage() {}
method ProtoReflect (line 358) | func (x *ListRecommendationsRequest) ProtoReflect() protoreflect.Messa...
method Descriptor (line 371) | func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 375) | func (x *ListRecommendationsRequest) GetUserId() string {
method GetProductIds (line 382) | func (x *ListRecommendationsRequest) GetProductIds() []string {
type ListRecommendationsResponse (line 389) | type ListRecommendationsResponse struct
method Reset (line 397) | func (x *ListRecommendationsResponse) Reset() {
method String (line 406) | func (x *ListRecommendationsResponse) String() string {
method ProtoMessage (line 410) | func (*ListRecommendationsResponse) ProtoMessage() {}
method ProtoReflect (line 412) | func (x *ListRecommendationsResponse) ProtoReflect() protoreflect.Mess...
method Descriptor (line 425) | func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
method GetProductIds (line 429) | func (x *ListRecommendationsResponse) GetProductIds() []string {
type Product (line 436) | type Product struct
method Reset (line 451) | func (x *Product) Reset() {
method String (line 460) | func (x *Product) String() string {
method ProtoMessage (line 464) | func (*Product) ProtoMessage() {}
method ProtoReflect (line 466) | func (x *Product) ProtoReflect() protoreflect.Message {
method Descriptor (line 479) | func (*Product) Descriptor() ([]byte, []int) {
method GetId (line 483) | func (x *Product) GetId() string {
method GetName (line 490) | func (x *Product) GetName() string {
method GetDescription (line 497) | func (x *Product) GetDescription() string {
method GetPicture (line 504) | func (x *Product) GetPicture() string {
method GetPriceUsd (line 511) | func (x *Product) GetPriceUsd() *Money {
method GetCategories (line 518) | func (x *Product) GetCategories() []string {
type ListProductsResponse (line 525) | type ListProductsResponse struct
method Reset (line 533) | func (x *ListProductsResponse) Reset() {
method String (line 542) | func (x *ListProductsResponse) String() string {
method ProtoMessage (line 546) | func (*ListProductsResponse) ProtoMessage() {}
method ProtoReflect (line 548) | func (x *ListProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 561) | func (*ListProductsResponse) Descriptor() ([]byte, []int) {
method GetProducts (line 565) | func (x *ListProductsResponse) GetProducts() []*Product {
type GetProductRequest (line 572) | type GetProductRequest struct
method Reset (line 580) | func (x *GetProductRequest) Reset() {
method String (line 589) | func (x *GetProductRequest) String() string {
method ProtoMessage (line 593) | func (*GetProductRequest) ProtoMessage() {}
method ProtoReflect (line 595) | func (x *GetProductRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 608) | func (*GetProductRequest) Descriptor() ([]byte, []int) {
method GetId (line 612) | func (x *GetProductRequest) GetId() string {
type SearchProductsRequest (line 619) | type SearchProductsRequest struct
method Reset (line 627) | func (x *SearchProductsRequest) Reset() {
method String (line 636) | func (x *SearchProductsRequest) String() string {
method ProtoMessage (line 640) | func (*SearchProductsRequest) ProtoMessage() {}
method ProtoReflect (line 642) | func (x *SearchProductsRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 655) | func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
method GetQuery (line 659) | func (x *SearchProductsRequest) GetQuery() string {
type SearchProductsResponse (line 666) | type SearchProductsResponse struct
method Reset (line 674) | func (x *SearchProductsResponse) Reset() {
method String (line 683) | func (x *SearchProductsResponse) String() string {
method ProtoMessage (line 687) | func (*SearchProductsResponse) ProtoMessage() {}
method ProtoReflect (line 689) | func (x *SearchProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 702) | func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
method GetResults (line 706) | func (x *SearchProductsResponse) GetResults() []*Product {
type GetQuoteRequest (line 713) | type GetQuoteRequest struct
method Reset (line 722) | func (x *GetQuoteRequest) Reset() {
method String (line 731) | func (x *GetQuoteRequest) String() string {
method ProtoMessage (line 735) | func (*GetQuoteRequest) ProtoMessage() {}
method ProtoReflect (line 737) | func (x *GetQuoteRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 750) | func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 754) | func (x *GetQuoteRequest) GetAddress() *Address {
method GetItems (line 761) | func (x *GetQuoteRequest) GetItems() []*CartItem {
type GetQuoteResponse (line 768) | type GetQuoteResponse struct
method Reset (line 776) | func (x *GetQuoteResponse) Reset() {
method String (line 785) | func (x *GetQuoteResponse) String() string {
method ProtoMessage (line 789) | func (*GetQuoteResponse) ProtoMessage() {}
method ProtoReflect (line 791) | func (x *GetQuoteResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 804) | func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
method GetCostUsd (line 808) | func (x *GetQuoteResponse) GetCostUsd() *Money {
type ShipOrderRequest (line 815) | type ShipOrderRequest struct
method Reset (line 824) | func (x *ShipOrderRequest) Reset() {
method String (line 833) | func (x *ShipOrderRequest) String() string {
method ProtoMessage (line 837) | func (*ShipOrderRequest) ProtoMessage() {}
method ProtoReflect (line 839) | func (x *ShipOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 852) | func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 856) | func (x *ShipOrderRequest) GetAddress() *Address {
method GetItems (line 863) | func (x *ShipOrderRequest) GetItems() []*CartItem {
type ShipOrderResponse (line 870) | type ShipOrderResponse struct
method Reset (line 878) | func (x *ShipOrderResponse) Reset() {
method String (line 887) | func (x *ShipOrderResponse) String() string {
method ProtoMessage (line 891) | func (*ShipOrderResponse) ProtoMessage() {}
method ProtoReflect (line 893) | func (x *ShipOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 906) | func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
method GetTrackingId (line 910) | func (x *ShipOrderResponse) GetTrackingId() string {
type Address (line 917) | type Address struct
method Reset (line 929) | func (x *Address) Reset() {
method String (line 938) | func (x *Address) String() string {
method ProtoMessage (line 942) | func (*Address) ProtoMessage() {}
method ProtoReflect (line 944) | func (x *Address) ProtoReflect() protoreflect.Message {
method Descriptor (line 957) | func (*Address) Descriptor() ([]byte, []int) {
method GetStreetAddress (line 961) | func (x *Address) GetStreetAddress() string {
method GetCity (line 968) | func (x *Address) GetCity() string {
method GetState (line 975) | func (x *Address) GetState() string {
method GetCountry (line 982) | func (x *Address) GetCountry() string {
method GetZipCode (line 989) | func (x *Address) GetZipCode() int32 {
type Money (line 997) | type Money struct
method Reset (line 1016) | func (x *Money) Reset() {
method String (line 1025) | func (x *Money) String() string {
method ProtoMessage (line 1029) | func (*Money) ProtoMessage() {}
method ProtoReflect (line 1031) | func (x *Money) ProtoReflect() protoreflect.Message {
method Descriptor (line 1044) | func (*Money) Descriptor() ([]byte, []int) {
method GetCurrencyCode (line 1048) | func (x *Money) GetCurrencyCode() string {
method GetUnits (line 1055) | func (x *Money) GetUnits() int64 {
method GetNanos (line 1062) | func (x *Money) GetNanos() int32 {
type GetSupportedCurrenciesResponse (line 1069) | type GetSupportedCurrenciesResponse struct
method Reset (line 1078) | func (x *GetSupportedCurrenciesResponse) Reset() {
method String (line 1087) | func (x *GetSupportedCurrenciesResponse) String() string {
method ProtoMessage (line 1091) | func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
method ProtoReflect (line 1093) | func (x *GetSupportedCurrenciesResponse) ProtoReflect() protoreflect.M...
method Descriptor (line 1106) | func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
method GetCurrencyCodes (line 1110) | func (x *GetSupportedCurrenciesResponse) GetCurrencyCodes() []string {
type CurrencyConversionRequest (line 1117) | type CurrencyConversionRequest struct
method Reset (line 1127) | func (x *CurrencyConversionRequest) Reset() {
method String (line 1136) | func (x *CurrencyConversionRequest) String() string {
method ProtoMessage (line 1140) | func (*CurrencyConversionRequest) ProtoMessage() {}
method ProtoReflect (line 1142) | func (x *CurrencyConversionRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1155) | func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
method GetFrom (line 1159) | func (x *CurrencyConversionRequest) GetFrom() *Money {
method GetToCode (line 1166) | func (x *CurrencyConversionRequest) GetToCode() string {
type CreditCardInfo (line 1173) | type CreditCardInfo struct
method Reset (line 1184) | func (x *CreditCardInfo) Reset() {
method String (line 1193) | func (x *CreditCardInfo) String() string {
method ProtoMessage (line 1197) | func (*CreditCardInfo) ProtoMessage() {}
method ProtoReflect (line 1199) | func (x *CreditCardInfo) ProtoReflect() protoreflect.Message {
method Descriptor (line 1212) | func (*CreditCardInfo) Descriptor() ([]byte, []int) {
method GetCreditCardNumber (line 1216) | func (x *CreditCardInfo) GetCreditCardNumber() string {
method GetCreditCardCvv (line 1223) | func (x *CreditCardInfo) GetCreditCardCvv() int32 {
method GetCreditCardExpirationYear (line 1230) | func (x *CreditCardInfo) GetCreditCardExpirationYear() int32 {
method GetCreditCardExpirationMonth (line 1237) | func (x *CreditCardInfo) GetCreditCardExpirationMonth() int32 {
type ChargeRequest (line 1244) | type ChargeRequest struct
method Reset (line 1253) | func (x *ChargeRequest) Reset() {
method String (line 1262) | func (x *ChargeRequest) String() string {
method ProtoMessage (line 1266) | func (*ChargeRequest) ProtoMessage() {}
method ProtoReflect (line 1268) | func (x *ChargeRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1281) | func (*ChargeRequest) Descriptor() ([]byte, []int) {
method GetAmount (line 1285) | func (x *ChargeRequest) GetAmount() *Money {
method GetCreditCard (line 1292) | func (x *ChargeRequest) GetCreditCard() *CreditCardInfo {
type ChargeResponse (line 1299) | type ChargeResponse struct
method Reset (line 1307) | func (x *ChargeResponse) Reset() {
method String (line 1316) | func (x *ChargeResponse) String() string {
method ProtoMessage (line 1320) | func (*ChargeResponse) ProtoMessage() {}
method ProtoReflect (line 1322) | func (x *ChargeResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1335) | func (*ChargeResponse) Descriptor() ([]byte, []int) {
method GetTransactionId (line 1339) | func (x *ChargeResponse) GetTransactionId() string {
type OrderItem (line 1346) | type OrderItem struct
method Reset (line 1355) | func (x *OrderItem) Reset() {
method String (line 1364) | func (x *OrderItem) String() string {
method ProtoMessage (line 1368) | func (*OrderItem) ProtoMessage() {}
method ProtoReflect (line 1370) | func (x *OrderItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 1383) | func (*OrderItem) Descriptor() ([]byte, []int) {
method GetItem (line 1387) | func (x *OrderItem) GetItem() *CartItem {
method GetCost (line 1394) | func (x *OrderItem) GetCost() *Money {
type OrderResult (line 1401) | type OrderResult struct
method Reset (line 1413) | func (x *OrderResult) Reset() {
method String (line 1422) | func (x *OrderResult) String() string {
method ProtoMessage (line 1426) | func (*OrderResult) ProtoMessage() {}
method ProtoReflect (line 1428) | func (x *OrderResult) ProtoReflect() protoreflect.Message {
method Descriptor (line 1441) | func (*OrderResult) Descriptor() ([]byte, []int) {
method GetOrderId (line 1445) | func (x *OrderResult) GetOrderId() string {
method GetShippingTrackingId (line 1452) | func (x *OrderResult) GetShippingTrackingId() string {
method GetShippingCost (line 1459) | func (x *OrderResult) GetShippingCost() *Money {
method GetShippingAddress (line 1466) | func (x *OrderResult) GetShippingAddress() *Address {
method GetItems (line 1473) | func (x *OrderResult) GetItems() []*OrderItem {
type SendOrderConfirmationRequest (line 1480) | type SendOrderConfirmationRequest struct
method Reset (line 1489) | func (x *SendOrderConfirmationRequest) Reset() {
method String (line 1498) | func (x *SendOrderConfirmationRequest) String() string {
method ProtoMessage (line 1502) | func (*SendOrderConfirmationRequest) ProtoMessage() {}
method ProtoReflect (line 1504) | func (x *SendOrderConfirmationRequest) ProtoReflect() protoreflect.Mes...
method Descriptor (line 1517) | func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
method GetEmail (line 1521) | func (x *SendOrderConfirmationRequest) GetEmail() string {
method GetOrder (line 1528) | func (x *SendOrderConfirmationRequest) GetOrder() *OrderResult {
type PlaceOrderRequest (line 1535) | type PlaceOrderRequest struct
method Reset (line 1547) | func (x *PlaceOrderRequest) Reset() {
method String (line 1556) | func (x *PlaceOrderRequest) String() string {
method ProtoMessage (line 1560) | func (*PlaceOrderRequest) ProtoMessage() {}
method ProtoReflect (line 1562) | func (x *PlaceOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1575) | func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 1579) | func (x *PlaceOrderRequest) GetUserId() string {
method GetUserCurrency (line 1586) | func (x *PlaceOrderRequest) GetUserCurrency() string {
method GetAddress (line 1593) | func (x *PlaceOrderRequest) GetAddress() *Address {
method GetEmail (line 1600) | func (x *PlaceOrderRequest) GetEmail() string {
method GetCreditCard (line 1607) | func (x *PlaceOrderRequest) GetCreditCard() *CreditCardInfo {
type PlaceOrderResponse (line 1614) | type PlaceOrderResponse struct
method Reset (line 1622) | func (x *PlaceOrderResponse) Reset() {
method String (line 1631) | func (x *PlaceOrderResponse) String() string {
method ProtoMessage (line 1635) | func (*PlaceOrderResponse) ProtoMessage() {}
method ProtoReflect (line 1637) | func (x *PlaceOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1650) | func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
method GetOrder (line 1654) | func (x *PlaceOrderResponse) GetOrder() *OrderResult {
type AdRequest (line 1661) | type AdRequest struct
method Reset (line 1670) | func (x *AdRequest) Reset() {
method String (line 1679) | func (x *AdRequest) String() string {
method ProtoMessage (line 1683) | func (*AdRequest) ProtoMessage() {}
method ProtoReflect (line 1685) | func (x *AdRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1698) | func (*AdRequest) Descriptor() ([]byte, []int) {
method GetContextKeys (line 1702) | func (x *AdRequest) GetContextKeys() []string {
type AdResponse (line 1709) | type AdResponse struct
method Reset (line 1717) | func (x *AdResponse) Reset() {
method String (line 1726) | func (x *AdResponse) String() string {
method ProtoMessage (line 1730) | func (*AdResponse) ProtoMessage() {}
method ProtoReflect (line 1732) | func (x *AdResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1745) | func (*AdResponse) Descriptor() ([]byte, []int) {
method GetAds (line 1749) | func (x *AdResponse) GetAds() []*Ad {
type Ad (line 1756) | type Ad struct
method Reset (line 1767) | func (x *Ad) Reset() {
method String (line 1776) | func (x *Ad) String() string {
method ProtoMessage (line 1780) | func (*Ad) ProtoMessage() {}
method ProtoReflect (line 1782) | func (x *Ad) ProtoReflect() protoreflect.Message {
method Descriptor (line 1795) | func (*Ad) Descriptor() ([]byte, []int) {
method GetRedirectUrl (line 1799) | func (x *Ad) GetRedirectUrl() string {
method GetText (line 1806) | func (x *Ad) GetText() string {
function file_demo_proto_rawDescGZIP (line 2098) | func file_demo_proto_rawDescGZIP() []byte {
function init (line 2201) | func init() { file_demo_proto_init() }
function file_demo_proto_init (line 2202) | func file_demo_proto_init() {
FILE: src/checkoutservice/genproto/demo_grpc.pb.go
constant _ (line 33) | _ = grpc.SupportPackageIsVersion9
constant CartService_AddItem_FullMethodName (line 36) | CartService_AddItem_FullMethodName = "/hipstershop.CartService/AddItem"
constant CartService_GetCart_FullMethodName (line 37) | CartService_GetCart_FullMethodName = "/hipstershop.CartService/GetCart"
constant CartService_EmptyCart_FullMethodName (line 38) | CartService_EmptyCart_FullMethodName = "/hipstershop.CartService/EmptyCart"
type CartServiceClient (line 44) | type CartServiceClient interface
type cartServiceClient (line 50) | type cartServiceClient struct
method AddItem (line 58) | func (c *cartServiceClient) AddItem(ctx context.Context, in *AddItemRe...
method GetCart (line 68) | func (c *cartServiceClient) GetCart(ctx context.Context, in *GetCartRe...
method EmptyCart (line 78) | func (c *cartServiceClient) EmptyCart(ctx context.Context, in *EmptyCa...
function NewCartServiceClient (line 54) | func NewCartServiceClient(cc grpc.ClientConnInterface) CartServiceClient {
type CartServiceServer (line 91) | type CartServiceServer interface
type UnimplementedCartServiceServer (line 103) | type UnimplementedCartServiceServer struct
method AddItem (line 105) | func (UnimplementedCartServiceServer) AddItem(context.Context, *AddIte...
method GetCart (line 108) | func (UnimplementedCartServiceServer) GetCart(context.Context, *GetCar...
method EmptyCart (line 111) | func (UnimplementedCartServiceServer) EmptyCart(context.Context, *Empt...
method mustEmbedUnimplementedCartServiceServer (line 114) | func (UnimplementedCartServiceServer) mustEmbedUnimplementedCartServic...
method testEmbeddedByValue (line 115) | func (UnimplementedCartServiceServer) testEmbeddedByValue() ...
type UnsafeCartServiceServer (line 120) | type UnsafeCartServiceServer interface
function RegisterCartServiceServer (line 124) | func RegisterCartServiceServer(s grpc.ServiceRegistrar, srv CartServiceS...
function _CartService_AddItem_Handler (line 135) | func _CartService_AddItem_Handler(srv interface{}, ctx context.Context, ...
function _CartService_GetCart_Handler (line 153) | func _CartService_GetCart_Handler(srv interface{}, ctx context.Context, ...
function _CartService_EmptyCart_Handler (line 171) | func _CartService_EmptyCart_Handler(srv interface{}, ctx context.Context...
constant RecommendationService_ListRecommendations_FullMethodName (line 214) | RecommendationService_ListRecommendations_FullMethodName = "/hipstershop...
type RecommendationServiceClient (line 220) | type RecommendationServiceClient interface
type recommendationServiceClient (line 224) | type recommendationServiceClient struct
method ListRecommendations (line 232) | func (c *recommendationServiceClient) ListRecommendations(ctx context....
function NewRecommendationServiceClient (line 228) | func NewRecommendationServiceClient(cc grpc.ClientConnInterface) Recomme...
type RecommendationServiceServer (line 245) | type RecommendationServiceServer interface
type UnimplementedRecommendationServiceServer (line 255) | type UnimplementedRecommendationServiceServer struct
method ListRecommendations (line 257) | func (UnimplementedRecommendationServiceServer) ListRecommendations(co...
method mustEmbedUnimplementedRecommendationServiceServer (line 260) | func (UnimplementedRecommendationServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 261) | func (UnimplementedRecommendationServiceServer) testEmbeddedByValue() ...
type UnsafeRecommendationServiceServer (line 266) | type UnsafeRecommendationServiceServer interface
function RegisterRecommendationServiceServer (line 270) | func RegisterRecommendationServiceServer(s grpc.ServiceRegistrar, srv Re...
function _RecommendationService_ListRecommendations_Handler (line 281) | func _RecommendationService_ListRecommendations_Handler(srv interface{},...
constant ProductCatalogService_ListProducts_FullMethodName (line 316) | ProductCatalogService_ListProducts_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_GetProduct_FullMethodName (line 317) | ProductCatalogService_GetProduct_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_SearchProducts_FullMethodName (line 318) | ProductCatalogService_SearchProducts_FullMethodName = "/hipstershop.Prod...
type ProductCatalogServiceClient (line 324) | type ProductCatalogServiceClient interface
type productCatalogServiceClient (line 330) | type productCatalogServiceClient struct
method ListProducts (line 338) | func (c *productCatalogServiceClient) ListProducts(ctx context.Context...
method GetProduct (line 348) | func (c *productCatalogServiceClient) GetProduct(ctx context.Context, ...
method SearchProducts (line 358) | func (c *productCatalogServiceClient) SearchProducts(ctx context.Conte...
function NewProductCatalogServiceClient (line 334) | func NewProductCatalogServiceClient(cc grpc.ClientConnInterface) Product...
type ProductCatalogServiceServer (line 371) | type ProductCatalogServiceServer interface
type UnimplementedProductCatalogServiceServer (line 383) | type UnimplementedProductCatalogServiceServer struct
method ListProducts (line 385) | func (UnimplementedProductCatalogServiceServer) ListProducts(context.C...
method GetProduct (line 388) | func (UnimplementedProductCatalogServiceServer) GetProduct(context.Con...
method SearchProducts (line 391) | func (UnimplementedProductCatalogServiceServer) SearchProducts(context...
method mustEmbedUnimplementedProductCatalogServiceServer (line 394) | func (UnimplementedProductCatalogServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 395) | func (UnimplementedProductCatalogServiceServer) testEmbeddedByValue() ...
type UnsafeProductCatalogServiceServer (line 400) | type UnsafeProductCatalogServiceServer interface
function RegisterProductCatalogServiceServer (line 404) | func RegisterProductCatalogServiceServer(s grpc.ServiceRegistrar, srv Pr...
function _ProductCatalogService_ListProducts_Handler (line 415) | func _ProductCatalogService_ListProducts_Handler(srv interface{}, ctx co...
function _ProductCatalogService_GetProduct_Handler (line 433) | func _ProductCatalogService_GetProduct_Handler(srv interface{}, ctx cont...
function _ProductCatalogService_SearchProducts_Handler (line 451) | func _ProductCatalogService_SearchProducts_Handler(srv interface{}, ctx ...
constant ShippingService_GetQuote_FullMethodName (line 494) | ShippingService_GetQuote_FullMethodName = "/hipstershop.ShippingService...
constant ShippingService_ShipOrder_FullMethodName (line 495) | ShippingService_ShipOrder_FullMethodName = "/hipstershop.ShippingService...
type ShippingServiceClient (line 501) | type ShippingServiceClient interface
type shippingServiceClient (line 506) | type shippingServiceClient struct
method GetQuote (line 514) | func (c *shippingServiceClient) GetQuote(ctx context.Context, in *GetQ...
method ShipOrder (line 524) | func (c *shippingServiceClient) ShipOrder(ctx context.Context, in *Shi...
function NewShippingServiceClient (line 510) | func NewShippingServiceClient(cc grpc.ClientConnInterface) ShippingServi...
type ShippingServiceServer (line 537) | type ShippingServiceServer interface
type UnimplementedShippingServiceServer (line 548) | type UnimplementedShippingServiceServer struct
method GetQuote (line 550) | func (UnimplementedShippingServiceServer) GetQuote(context.Context, *G...
method ShipOrder (line 553) | func (UnimplementedShippingServiceServer) ShipOrder(context.Context, *...
method mustEmbedUnimplementedShippingServiceServer (line 556) | func (UnimplementedShippingServiceServer) mustEmbedUnimplementedShippi...
method testEmbeddedByValue (line 557) | func (UnimplementedShippingServiceServer) testEmbeddedByValue() ...
type UnsafeShippingServiceServer (line 562) | type UnsafeShippingServiceServer interface
function RegisterShippingServiceServer (line 566) | func RegisterShippingServiceServer(s grpc.ServiceRegistrar, srv Shipping...
function _ShippingService_GetQuote_Handler (line 577) | func _ShippingService_GetQuote_Handler(srv interface{}, ctx context.Cont...
function _ShippingService_ShipOrder_Handler (line 595) | func _ShippingService_ShipOrder_Handler(srv interface{}, ctx context.Con...
constant CurrencyService_GetSupportedCurrencies_FullMethodName (line 634) | CurrencyService_GetSupportedCurrencies_FullMethodName = "/hipstershop.Cu...
constant CurrencyService_Convert_FullMethodName (line 635) | CurrencyService_Convert_FullMethodName = "/hipstershop.Cu...
type CurrencyServiceClient (line 641) | type CurrencyServiceClient interface
type currencyServiceClient (line 646) | type currencyServiceClient struct
method GetSupportedCurrencies (line 654) | func (c *currencyServiceClient) GetSupportedCurrencies(ctx context.Con...
method Convert (line 664) | func (c *currencyServiceClient) Convert(ctx context.Context, in *Curre...
function NewCurrencyServiceClient (line 650) | func NewCurrencyServiceClient(cc grpc.ClientConnInterface) CurrencyServi...
type CurrencyServiceServer (line 677) | type CurrencyServiceServer interface
type UnimplementedCurrencyServiceServer (line 688) | type UnimplementedCurrencyServiceServer struct
method GetSupportedCurrencies (line 690) | func (UnimplementedCurrencyServiceServer) GetSupportedCurrencies(conte...
method Convert (line 693) | func (UnimplementedCurrencyServiceServer) Convert(context.Context, *Cu...
method mustEmbedUnimplementedCurrencyServiceServer (line 696) | func (UnimplementedCurrencyServiceServer) mustEmbedUnimplementedCurren...
method testEmbeddedByValue (line 697) | func (UnimplementedCurrencyServiceServer) testEmbeddedByValue() ...
type UnsafeCurrencyServiceServer (line 702) | type UnsafeCurrencyServiceServer interface
function RegisterCurrencyServiceServer (line 706) | func RegisterCurrencyServiceServer(s grpc.ServiceRegistrar, srv Currency...
function _CurrencyService_GetSupportedCurrencies_Handler (line 717) | func _CurrencyService_GetSupportedCurrencies_Handler(srv interface{}, ct...
function _CurrencyService_Convert_Handler (line 735) | func _CurrencyService_Convert_Handler(srv interface{}, ctx context.Conte...
constant PaymentService_Charge_FullMethodName (line 774) | PaymentService_Charge_FullMethodName = "/hipstershop.PaymentService/Charge"
type PaymentServiceClient (line 780) | type PaymentServiceClient interface
type paymentServiceClient (line 784) | type paymentServiceClient struct
method Charge (line 792) | func (c *paymentServiceClient) Charge(ctx context.Context, in *ChargeR...
function NewPaymentServiceClient (line 788) | func NewPaymentServiceClient(cc grpc.ClientConnInterface) PaymentService...
type PaymentServiceServer (line 805) | type PaymentServiceServer interface
type UnimplementedPaymentServiceServer (line 815) | type UnimplementedPaymentServiceServer struct
method Charge (line 817) | func (UnimplementedPaymentServiceServer) Charge(context.Context, *Char...
method mustEmbedUnimplementedPaymentServiceServer (line 820) | func (UnimplementedPaymentServiceServer) mustEmbedUnimplementedPayment...
method testEmbeddedByValue (line 821) | func (UnimplementedPaymentServiceServer) testEmbeddedByValue() ...
type UnsafePaymentServiceServer (line 826) | type UnsafePaymentServiceServer interface
function RegisterPaymentServiceServer (line 830) | func RegisterPaymentServiceServer(s grpc.ServiceRegistrar, srv PaymentSe...
function _PaymentService_Charge_Handler (line 841) | func _PaymentService_Charge_Handler(srv interface{}, ctx context.Context...
constant EmailService_SendOrderConfirmation_FullMethodName (line 876) | EmailService_SendOrderConfirmation_FullMethodName = "/hipstershop.EmailS...
type EmailServiceClient (line 882) | type EmailServiceClient interface
type emailServiceClient (line 886) | type emailServiceClient struct
method SendOrderConfirmation (line 894) | func (c *emailServiceClient) SendOrderConfirmation(ctx context.Context...
function NewEmailServiceClient (line 890) | func NewEmailServiceClient(cc grpc.ClientConnInterface) EmailServiceClie...
type EmailServiceServer (line 907) | type EmailServiceServer interface
type UnimplementedEmailServiceServer (line 917) | type UnimplementedEmailServiceServer struct
method SendOrderConfirmation (line 919) | func (UnimplementedEmailServiceServer) SendOrderConfirmation(context.C...
method mustEmbedUnimplementedEmailServiceServer (line 922) | func (UnimplementedEmailServiceServer) mustEmbedUnimplementedEmailServ...
method testEmbeddedByValue (line 923) | func (UnimplementedEmailServiceServer) testEmbeddedByValue() ...
type UnsafeEmailServiceServer (line 928) | type UnsafeEmailServiceServer interface
function RegisterEmailServiceServer (line 932) | func RegisterEmailServiceServer(s grpc.ServiceRegistrar, srv EmailServic...
function _EmailService_SendOrderConfirmation_Handler (line 943) | func _EmailService_SendOrderConfirmation_Handler(srv interface{}, ctx co...
constant CheckoutService_PlaceOrder_FullMethodName (line 978) | CheckoutService_PlaceOrder_FullMethodName = "/hipstershop.CheckoutServic...
type CheckoutServiceClient (line 984) | type CheckoutServiceClient interface
type checkoutServiceClient (line 988) | type checkoutServiceClient struct
method PlaceOrder (line 996) | func (c *checkoutServiceClient) PlaceOrder(ctx context.Context, in *Pl...
function NewCheckoutServiceClient (line 992) | func NewCheckoutServiceClient(cc grpc.ClientConnInterface) CheckoutServi...
type CheckoutServiceServer (line 1009) | type CheckoutServiceServer interface
type UnimplementedCheckoutServiceServer (line 1019) | type UnimplementedCheckoutServiceServer struct
method PlaceOrder (line 1021) | func (UnimplementedCheckoutServiceServer) PlaceOrder(context.Context, ...
method mustEmbedUnimplementedCheckoutServiceServer (line 1024) | func (UnimplementedCheckoutServiceServer) mustEmbedUnimplementedChecko...
method testEmbeddedByValue (line 1025) | func (UnimplementedCheckoutServiceServer) testEmbeddedByValue() ...
type UnsafeCheckoutServiceServer (line 1030) | type UnsafeCheckoutServiceServer interface
function RegisterCheckoutServiceServer (line 1034) | func RegisterCheckoutServiceServer(s grpc.ServiceRegistrar, srv Checkout...
function _CheckoutService_PlaceOrder_Handler (line 1045) | func _CheckoutService_PlaceOrder_Handler(srv interface{}, ctx context.Co...
constant AdService_GetAds_FullMethodName (line 1080) | AdService_GetAds_FullMethodName = "/hipstershop.AdService/GetAds"
type AdServiceClient (line 1086) | type AdServiceClient interface
type adServiceClient (line 1090) | type adServiceClient struct
method GetAds (line 1098) | func (c *adServiceClient) GetAds(ctx context.Context, in *AdRequest, o...
function NewAdServiceClient (line 1094) | func NewAdServiceClient(cc grpc.ClientConnInterface) AdServiceClient {
type AdServiceServer (line 1111) | type AdServiceServer interface
type UnimplementedAdServiceServer (line 1121) | type UnimplementedAdServiceServer struct
method GetAds (line 1123) | func (UnimplementedAdServiceServer) GetAds(context.Context, *AdRequest...
method mustEmbedUnimplementedAdServiceServer (line 1126) | func (UnimplementedAdServiceServer) mustEmbedUnimplementedAdServiceSer...
method testEmbeddedByValue (line 1127) | func (UnimplementedAdServiceServer) testEmbeddedByValue() ...
type UnsafeAdServiceServer (line 1132) | type UnsafeAdServiceServer interface
function RegisterAdServiceServer (line 1136) | func RegisterAdServiceServer(s grpc.ServiceRegistrar, srv AdServiceServe...
function _AdService_GetAds_Handler (line 1147) | func _AdService_GetAds_Handler(srv interface{}, ctx context.Context, dec...
FILE: src/checkoutservice/main.go
constant listenPort (line 46) | listenPort = "5050"
constant usdCurrency (line 47) | usdCurrency = "USD"
function init (line 52) | func init() {
type checkoutService (line 66) | type checkoutService struct
method Check (line 222) | func (cs *checkoutService) Check(ctx context.Context, req *healthpb.He...
method Watch (line 226) | func (cs *checkoutService) Watch(req *healthpb.HealthCheckRequest, ws ...
method PlaceOrder (line 230) | func (cs *checkoutService) PlaceOrder(ctx context.Context, req *pb.Pla...
method prepareOrderItemsAndShippingQuoteFromCart (line 288) | func (cs *checkoutService) prepareOrderItemsAndShippingQuoteFromCart(c...
method quoteShipping (line 313) | func (cs *checkoutService) quoteShipping(ctx context.Context, address ...
method getUserCart (line 324) | func (cs *checkoutService) getUserCart(ctx context.Context, userID str...
method emptyUserCart (line 332) | func (cs *checkoutService) emptyUserCart(ctx context.Context, userID s...
method prepOrderItems (line 339) | func (cs *checkoutService) prepOrderItems(ctx context.Context, items [...
method convertCurrency (line 359) | func (cs *checkoutService) convertCurrency(ctx context.Context, from *...
method chargeCard (line 369) | func (cs *checkoutService) chargeCard(ctx context.Context, amount *pb....
method sendOrderConfirmation (line 379) | func (cs *checkoutService) sendOrderConfirmation(ctx context.Context, ...
method shipOrder (line 386) | func (cs *checkoutService) shipOrder(ctx context.Context, address *pb....
function main (line 88) | func main() {
function initStats (line 150) | func initStats() {
function initTracing (line 154) | func initTracing() {
function initProfiling (line 180) | func initProfiling(service, version string) {
function mustMapEnv (line 202) | func mustMapEnv(target *string, envKey string) {
function mustConnGRPC (line 210) | func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr stri...
type orderPrep (line 282) | type orderPrep struct
FILE: src/checkoutservice/money/money.go
constant nanosMin (line 24) | nanosMin = -999999999
constant nanosMax (line 25) | nanosMax = +999999999
constant nanosMod (line 26) | nanosMod = 1000000000
function IsValid (line 35) | func IsValid(m pb.Money) bool {
function signMatches (line 39) | func signMatches(m pb.Money) bool {
function validNanos (line 43) | func validNanos(nanos int32) bool { return nanosMin <= nanos && nanos <=...
function IsZero (line 46) | func IsZero(m pb.Money) bool { return m.GetUnits() == 0 && m.GetNanos() ...
function IsPositive (line 50) | func IsPositive(m pb.Money) bool {
function IsNegative (line 56) | func IsNegative(m pb.Money) bool {
function AreSameCurrency (line 62) | func AreSameCurrency(l, r pb.Money) bool {
function AreEquals (line 68) | func AreEquals(l, r pb.Money) bool {
function Negate (line 74) | func Negate(m pb.Money) pb.Money {
function Must (line 83) | func Must(v pb.Money, err error) pb.Money {
function Sum (line 93) | func Sum(l, r pb.Money) (pb.Money, error) {
function MultiplySlow (line 125) | func MultiplySlow(m pb.Money, n uint32) pb.Money {
FILE: src/checkoutservice/money/money_test.go
function mmc (line 25) | func mmc(u int64, n int32, c string) pb.Money { return pb.Money{Units: u...
function mm (line 26) | func mm(u int64, n int32) pb.Money { return mmc(u, n, "") }
function TestIsValid (line 28) | func TestIsValid(t *testing.T) {
function TestIsZero (line 52) | func TestIsZero(t *testing.T) {
function TestIsPositive (line 73) | func TestIsPositive(t *testing.T) {
function TestIsNegative (line 94) | func TestIsNegative(t *testing.T) {
function TestAreSameCurrency (line 115) | func TestAreSameCurrency(t *testing.T) {
function TestAreEquals (line 140) | func TestAreEquals(t *testing.T) {
function TestNegate (line 165) | func TestNegate(t *testing.T) {
function TestMust_pass (line 185) | func TestMust_pass(t *testing.T) {
function TestMust_panic (line 192) | func TestMust_panic(t *testing.T) {
function TestSum (line 202) | func TestSum(t *testing.T) {
FILE: src/currencyservice/client.js
constant PROTO_PATH (line 24) | const PROTO_PATH = path.join(__dirname, './proto/demo.proto');
constant PORT (line 25) | const PORT = 7000;
method level (line 35) | level (logLevelString, logLevelNum) {
function _moneyToString (line 50) | function _moneyToString (m) {
FILE: src/currencyservice/server.js
method level (line 22) | level (logLevelString, logLevelNum) {
constant MAIN_PROTO_PATH (line 80) | const MAIN_PROTO_PATH = path.join(__dirname, './proto/demo.proto');
constant HEALTH_PROTO_PATH (line 81) | const HEALTH_PROTO_PATH = path.join(__dirname, './proto/grpc/health/v1/h...
constant PORT (line 83) | const PORT = process.env.PORT;
function _loadProto (line 91) | function _loadProto (path) {
function _getCurrencyData (line 109) | function _getCurrencyData (callback) {
function _carry (line 117) | function _carry (amount) {
function getSupportedCurrencies (line 128) | function getSupportedCurrencies (call, callback) {
function convert (line 138) | function convert (call, callback) {
function check (line 174) | function check (call, callback) {
function main (line 182) | function main () {
FILE: src/emailservice/demo_pb2_grpc.py
class CartServiceStub (line 24) | class CartServiceStub(object):
method __init__ (line 29) | def __init__(self, channel):
class CartServiceServicer (line 52) | class CartServiceServicer(object):
method AddItem (line 57) | def AddItem(self, request, context):
method GetCart (line 63) | def GetCart(self, request, context):
method EmptyCart (line 69) | def EmptyCart(self, request, context):
function add_CartServiceServicer_to_server (line 76) | def add_CartServiceServicer_to_server(servicer, server):
class CartService (line 100) | class CartService(object):
method AddItem (line 106) | def AddItem(request,
method GetCart (line 123) | def GetCart(request,
method EmptyCart (line 140) | def EmptyCart(request,
class RecommendationServiceStub (line 157) | class RecommendationServiceStub(object):
method __init__ (line 162) | def __init__(self, channel):
class RecommendationServiceServicer (line 175) | class RecommendationServiceServicer(object):
method ListRecommendations (line 180) | def ListRecommendations(self, request, context):
function add_RecommendationServiceServicer_to_server (line 187) | def add_RecommendationServiceServicer_to_server(servicer, server):
class RecommendationService (line 201) | class RecommendationService(object):
method ListRecommendations (line 207) | def ListRecommendations(request,
class ProductCatalogServiceStub (line 224) | class ProductCatalogServiceStub(object):
method __init__ (line 229) | def __init__(self, channel):
class ProductCatalogServiceServicer (line 252) | class ProductCatalogServiceServicer(object):
method ListProducts (line 257) | def ListProducts(self, request, context):
method GetProduct (line 263) | def GetProduct(self, request, context):
method SearchProducts (line 269) | def SearchProducts(self, request, context):
function add_ProductCatalogServiceServicer_to_server (line 276) | def add_ProductCatalogServiceServicer_to_server(servicer, server):
class ProductCatalogService (line 300) | class ProductCatalogService(object):
method ListProducts (line 306) | def ListProducts(request,
method GetProduct (line 323) | def GetProduct(request,
method SearchProducts (line 340) | def SearchProducts(request,
class ShippingServiceStub (line 357) | class ShippingServiceStub(object):
method __init__ (line 362) | def __init__(self, channel):
class ShippingServiceServicer (line 380) | class ShippingServiceServicer(object):
method GetQuote (line 385) | def GetQuote(self, request, context):
method ShipOrder (line 391) | def ShipOrder(self, request, context):
function add_ShippingServiceServicer_to_server (line 398) | def add_ShippingServiceServicer_to_server(servicer, server):
class ShippingService (line 417) | class ShippingService(object):
method GetQuote (line 423) | def GetQuote(request,
method ShipOrder (line 440) | def ShipOrder(request,
class CurrencyServiceStub (line 457) | class CurrencyServiceStub(object):
method __init__ (line 462) | def __init__(self, channel):
class CurrencyServiceServicer (line 480) | class CurrencyServiceServicer(object):
method GetSupportedCurrencies (line 485) | def GetSupportedCurrencies(self, request, context):
method Convert (line 491) | def Convert(self, request, context):
function add_CurrencyServiceServicer_to_server (line 498) | def add_CurrencyServiceServicer_to_server(servicer, server):
class CurrencyService (line 517) | class CurrencyService(object):
method GetSupportedCurrencies (line 523) | def GetSupportedCurrencies(request,
method Convert (line 540) | def Convert(request,
class PaymentServiceStub (line 557) | class PaymentServiceStub(object):
method __init__ (line 562) | def __init__(self, channel):
class PaymentServiceServicer (line 575) | class PaymentServiceServicer(object):
method Charge (line 580) | def Charge(self, request, context):
function add_PaymentServiceServicer_to_server (line 587) | def add_PaymentServiceServicer_to_server(servicer, server):
class PaymentService (line 601) | class PaymentService(object):
method Charge (line 607) | def Charge(request,
class EmailServiceStub (line 624) | class EmailServiceStub(object):
method __init__ (line 629) | def __init__(self, channel):
class EmailServiceServicer (line 642) | class EmailServiceServicer(object):
method SendOrderConfirmation (line 647) | def SendOrderConfirmation(self, request, context):
function add_EmailServiceServicer_to_server (line 654) | def add_EmailServiceServicer_to_server(servicer, server):
class EmailService (line 668) | class EmailService(object):
method SendOrderConfirmation (line 674) | def SendOrderConfirmation(request,
class CheckoutServiceStub (line 691) | class CheckoutServiceStub(object):
method __init__ (line 696) | def __init__(self, channel):
class CheckoutServiceServicer (line 709) | class CheckoutServiceServicer(object):
method PlaceOrder (line 714) | def PlaceOrder(self, request, context):
function add_CheckoutServiceServicer_to_server (line 721) | def add_CheckoutServiceServicer_to_server(servicer, server):
class CheckoutService (line 735) | class CheckoutService(object):
method PlaceOrder (line 741) | def PlaceOrder(request,
class AdServiceStub (line 758) | class AdServiceStub(object):
method __init__ (line 763) | def __init__(self, channel):
class AdServiceServicer (line 776) | class AdServiceServicer(object):
method GetAds (line 781) | def GetAds(self, request, context):
function add_AdServiceServicer_to_server (line 788) | def add_AdServiceServicer_to_server(servicer, server):
class AdService (line 802) | class AdService(object):
method GetAds (line 808) | def GetAds(request,
FILE: src/emailservice/email_client.py
function send_confirmation_email (line 25) | def send_confirmation_email(email, order):
FILE: src/emailservice/email_server.py
class BaseEmailService (line 52) | class BaseEmailService(demo_pb2_grpc.EmailServiceServicer):
method Check (line 53) | def Check(self, request, context):
method Watch (line 57) | def Watch(self, request, context):
class EmailService (line 61) | class EmailService(BaseEmailService):
method __init__ (line 62) | def __init__(self):
method send_email (line 67) | def send_email(client, email_address, content):
method SendOrderConfirmation (line 86) | def SendOrderConfirmation(self, request, context):
class DummyEmailService (line 108) | class DummyEmailService(BaseEmailService):
method SendOrderConfirmation (line 109) | def SendOrderConfirmation(self, request, context):
class HealthCheck (line 113) | class HealthCheck():
method Check (line 114) | def Check(self, request, context):
function start (line 118) | def start(dummy_mode):
function initStackdriverProfiling (line 139) | def initStackdriverProfiling():
FILE: src/emailservice/logger.py
class CustomJsonFormatter (line 23) | class CustomJsonFormatter(jsonlogger.JsonFormatter):
method add_fields (line 24) | def add_fields(self, log_record, record, message_dict):
function getJSONLogger (line 33) | def getJSONLogger(name):
FILE: src/frontend/deployment_details.go
function init (line 15) | func init() {
function initializeLogger (line 22) | func initializeLogger() {
function loadDeploymentDetails (line 36) | func loadDeploymentDetails() {
FILE: src/frontend/genproto/demo.pb.go
constant _ (line 32) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 34) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type CartItem (line 37) | type CartItem struct
method Reset (line 46) | func (x *CartItem) Reset() {
method String (line 55) | func (x *CartItem) String() string {
method ProtoMessage (line 59) | func (*CartItem) ProtoMessage() {}
method ProtoReflect (line 61) | func (x *CartItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 74) | func (*CartItem) Descriptor() ([]byte, []int) {
method GetProductId (line 78) | func (x *CartItem) GetProductId() string {
method GetQuantity (line 85) | func (x *CartItem) GetQuantity() int32 {
type AddItemRequest (line 92) | type AddItemRequest struct
method Reset (line 101) | func (x *AddItemRequest) Reset() {
method String (line 110) | func (x *AddItemRequest) String() string {
method ProtoMessage (line 114) | func (*AddItemRequest) ProtoMessage() {}
method ProtoReflect (line 116) | func (x *AddItemRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 129) | func (*AddItemRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 133) | func (x *AddItemRequest) GetUserId() string {
method GetItem (line 140) | func (x *AddItemRequest) GetItem() *CartItem {
type EmptyCartRequest (line 147) | type EmptyCartRequest struct
method Reset (line 155) | func (x *EmptyCartRequest) Reset() {
method String (line 164) | func (x *EmptyCartRequest) String() string {
method ProtoMessage (line 168) | func (*EmptyCartRequest) ProtoMessage() {}
method ProtoReflect (line 170) | func (x *EmptyCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 183) | func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 187) | func (x *EmptyCartRequest) GetUserId() string {
type GetCartRequest (line 194) | type GetCartRequest struct
method Reset (line 202) | func (x *GetCartRequest) Reset() {
method String (line 211) | func (x *GetCartRequest) String() string {
method ProtoMessage (line 215) | func (*GetCartRequest) ProtoMessage() {}
method ProtoReflect (line 217) | func (x *GetCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 230) | func (*GetCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 234) | func (x *GetCartRequest) GetUserId() string {
type Cart (line 241) | type Cart struct
method Reset (line 250) | func (x *Cart) Reset() {
method String (line 259) | func (x *Cart) String() string {
method ProtoMessage (line 263) | func (*Cart) ProtoMessage() {}
method ProtoReflect (line 265) | func (x *Cart) ProtoReflect() protoreflect.Message {
method Descriptor (line 278) | func (*Cart) Descriptor() ([]byte, []int) {
method GetUserId (line 282) | func (x *Cart) GetUserId() string {
method GetItems (line 289) | func (x *Cart) GetItems() []*CartItem {
type Empty (line 296) | type Empty struct
method Reset (line 302) | func (x *Empty) Reset() {
method String (line 311) | func (x *Empty) String() string {
method ProtoMessage (line 315) | func (*Empty) ProtoMessage() {}
method ProtoReflect (line 317) | func (x *Empty) ProtoReflect() protoreflect.Message {
method Descriptor (line 330) | func (*Empty) Descriptor() ([]byte, []int) {
type ListRecommendationsRequest (line 334) | type ListRecommendationsRequest struct
method Reset (line 343) | func (x *ListRecommendationsRequest) Reset() {
method String (line 352) | func (x *ListRecommendationsRequest) String() string {
method ProtoMessage (line 356) | func (*ListRecommendationsRequest) ProtoMessage() {}
method ProtoReflect (line 358) | func (x *ListRecommendationsRequest) ProtoReflect() protoreflect.Messa...
method Descriptor (line 371) | func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 375) | func (x *ListRecommendationsRequest) GetUserId() string {
method GetProductIds (line 382) | func (x *ListRecommendationsRequest) GetProductIds() []string {
type ListRecommendationsResponse (line 389) | type ListRecommendationsResponse struct
method Reset (line 397) | func (x *ListRecommendationsResponse) Reset() {
method String (line 406) | func (x *ListRecommendationsResponse) String() string {
method ProtoMessage (line 410) | func (*ListRecommendationsResponse) ProtoMessage() {}
method ProtoReflect (line 412) | func (x *ListRecommendationsResponse) ProtoReflect() protoreflect.Mess...
method Descriptor (line 425) | func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
method GetProductIds (line 429) | func (x *ListRecommendationsResponse) GetProductIds() []string {
type Product (line 436) | type Product struct
method Reset (line 451) | func (x *Product) Reset() {
method String (line 460) | func (x *Product) String() string {
method ProtoMessage (line 464) | func (*Product) ProtoMessage() {}
method ProtoReflect (line 466) | func (x *Product) ProtoReflect() protoreflect.Message {
method Descriptor (line 479) | func (*Product) Descriptor() ([]byte, []int) {
method GetId (line 483) | func (x *Product) GetId() string {
method GetName (line 490) | func (x *Product) GetName() string {
method GetDescription (line 497) | func (x *Product) GetDescription() string {
method GetPicture (line 504) | func (x *Product) GetPicture() string {
method GetPriceUsd (line 511) | func (x *Product) GetPriceUsd() *Money {
method GetCategories (line 518) | func (x *Product) GetCategories() []string {
type ListProductsResponse (line 525) | type ListProductsResponse struct
method Reset (line 533) | func (x *ListProductsResponse) Reset() {
method String (line 542) | func (x *ListProductsResponse) String() string {
method ProtoMessage (line 546) | func (*ListProductsResponse) ProtoMessage() {}
method ProtoReflect (line 548) | func (x *ListProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 561) | func (*ListProductsResponse) Descriptor() ([]byte, []int) {
method GetProducts (line 565) | func (x *ListProductsResponse) GetProducts() []*Product {
type GetProductRequest (line 572) | type GetProductRequest struct
method Reset (line 580) | func (x *GetProductRequest) Reset() {
method String (line 589) | func (x *GetProductRequest) String() string {
method ProtoMessage (line 593) | func (*GetProductRequest) ProtoMessage() {}
method ProtoReflect (line 595) | func (x *GetProductRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 608) | func (*GetProductRequest) Descriptor() ([]byte, []int) {
method GetId (line 612) | func (x *GetProductRequest) GetId() string {
type SearchProductsRequest (line 619) | type SearchProductsRequest struct
method Reset (line 627) | func (x *SearchProductsRequest) Reset() {
method String (line 636) | func (x *SearchProductsRequest) String() string {
method ProtoMessage (line 640) | func (*SearchProductsRequest) ProtoMessage() {}
method ProtoReflect (line 642) | func (x *SearchProductsRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 655) | func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
method GetQuery (line 659) | func (x *SearchProductsRequest) GetQuery() string {
type SearchProductsResponse (line 666) | type SearchProductsResponse struct
method Reset (line 674) | func (x *SearchProductsResponse) Reset() {
method String (line 683) | func (x *SearchProductsResponse) String() string {
method ProtoMessage (line 687) | func (*SearchProductsResponse) ProtoMessage() {}
method ProtoReflect (line 689) | func (x *SearchProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 702) | func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
method GetResults (line 706) | func (x *SearchProductsResponse) GetResults() []*Product {
type GetQuoteRequest (line 713) | type GetQuoteRequest struct
method Reset (line 722) | func (x *GetQuoteRequest) Reset() {
method String (line 731) | func (x *GetQuoteRequest) String() string {
method ProtoMessage (line 735) | func (*GetQuoteRequest) ProtoMessage() {}
method ProtoReflect (line 737) | func (x *GetQuoteRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 750) | func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 754) | func (x *GetQuoteRequest) GetAddress() *Address {
method GetItems (line 761) | func (x *GetQuoteRequest) GetItems() []*CartItem {
type GetQuoteResponse (line 768) | type GetQuoteResponse struct
method Reset (line 776) | func (x *GetQuoteResponse) Reset() {
method String (line 785) | func (x *GetQuoteResponse) String() string {
method ProtoMessage (line 789) | func (*GetQuoteResponse) ProtoMessage() {}
method ProtoReflect (line 791) | func (x *GetQuoteResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 804) | func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
method GetCostUsd (line 808) | func (x *GetQuoteResponse) GetCostUsd() *Money {
type ShipOrderRequest (line 815) | type ShipOrderRequest struct
method Reset (line 824) | func (x *ShipOrderRequest) Reset() {
method String (line 833) | func (x *ShipOrderRequest) String() string {
method ProtoMessage (line 837) | func (*ShipOrderRequest) ProtoMessage() {}
method ProtoReflect (line 839) | func (x *ShipOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 852) | func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 856) | func (x *ShipOrderRequest) GetAddress() *Address {
method GetItems (line 863) | func (x *ShipOrderRequest) GetItems() []*CartItem {
type ShipOrderResponse (line 870) | type ShipOrderResponse struct
method Reset (line 878) | func (x *ShipOrderResponse) Reset() {
method String (line 887) | func (x *ShipOrderResponse) String() string {
method ProtoMessage (line 891) | func (*ShipOrderResponse) ProtoMessage() {}
method ProtoReflect (line 893) | func (x *ShipOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 906) | func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
method GetTrackingId (line 910) | func (x *ShipOrderResponse) GetTrackingId() string {
type Address (line 917) | type Address struct
method Reset (line 929) | func (x *Address) Reset() {
method String (line 938) | func (x *Address) String() string {
method ProtoMessage (line 942) | func (*Address) ProtoMessage() {}
method ProtoReflect (line 944) | func (x *Address) ProtoReflect() protoreflect.Message {
method Descriptor (line 957) | func (*Address) Descriptor() ([]byte, []int) {
method GetStreetAddress (line 961) | func (x *Address) GetStreetAddress() string {
method GetCity (line 968) | func (x *Address) GetCity() string {
method GetState (line 975) | func (x *Address) GetState() string {
method GetCountry (line 982) | func (x *Address) GetCountry() string {
method GetZipCode (line 989) | func (x *Address) GetZipCode() int32 {
type Money (line 997) | type Money struct
method Reset (line 1016) | func (x *Money) Reset() {
method String (line 1025) | func (x *Money) String() string {
method ProtoMessage (line 1029) | func (*Money) ProtoMessage() {}
method ProtoReflect (line 1031) | func (x *Money) ProtoReflect() protoreflect.Message {
method Descriptor (line 1044) | func (*Money) Descriptor() ([]byte, []int) {
method GetCurrencyCode (line 1048) | func (x *Money) GetCurrencyCode() string {
method GetUnits (line 1055) | func (x *Money) GetUnits() int64 {
method GetNanos (line 1062) | func (x *Money) GetNanos() int32 {
type GetSupportedCurrenciesResponse (line 1069) | type GetSupportedCurrenciesResponse struct
method Reset (line 1078) | func (x *GetSupportedCurrenciesResponse) Reset() {
method String (line 1087) | func (x *GetSupportedCurrenciesResponse) String() string {
method ProtoMessage (line 1091) | func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
method ProtoReflect (line 1093) | func (x *GetSupportedCurrenciesResponse) ProtoReflect() protoreflect.M...
method Descriptor (line 1106) | func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
method GetCurrencyCodes (line 1110) | func (x *GetSupportedCurrenciesResponse) GetCurrencyCodes() []string {
type CurrencyConversionRequest (line 1117) | type CurrencyConversionRequest struct
method Reset (line 1127) | func (x *CurrencyConversionRequest) Reset() {
method String (line 1136) | func (x *CurrencyConversionRequest) String() string {
method ProtoMessage (line 1140) | func (*CurrencyConversionRequest) ProtoMessage() {}
method ProtoReflect (line 1142) | func (x *CurrencyConversionRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1155) | func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
method GetFrom (line 1159) | func (x *CurrencyConversionRequest) GetFrom() *Money {
method GetToCode (line 1166) | func (x *CurrencyConversionRequest) GetToCode() string {
type CreditCardInfo (line 1173) | type CreditCardInfo struct
method Reset (line 1184) | func (x *CreditCardInfo) Reset() {
method String (line 1193) | func (x *CreditCardInfo) String() string {
method ProtoMessage (line 1197) | func (*CreditCardInfo) ProtoMessage() {}
method ProtoReflect (line 1199) | func (x *CreditCardInfo) ProtoReflect() protoreflect.Message {
method Descriptor (line 1212) | func (*CreditCardInfo) Descriptor() ([]byte, []int) {
method GetCreditCardNumber (line 1216) | func (x *CreditCardInfo) GetCreditCardNumber() string {
method GetCreditCardCvv (line 1223) | func (x *CreditCardInfo) GetCreditCardCvv() int32 {
method GetCreditCardExpirationYear (line 1230) | func (x *CreditCardInfo) GetCreditCardExpirationYear() int32 {
method GetCreditCardExpirationMonth (line 1237) | func (x *CreditCardInfo) GetCreditCardExpirationMonth() int32 {
type ChargeRequest (line 1244) | type ChargeRequest struct
method Reset (line 1253) | func (x *ChargeRequest) Reset() {
method String (line 1262) | func (x *ChargeRequest) String() string {
method ProtoMessage (line 1266) | func (*ChargeRequest) ProtoMessage() {}
method ProtoReflect (line 1268) | func (x *ChargeRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1281) | func (*ChargeRequest) Descriptor() ([]byte, []int) {
method GetAmount (line 1285) | func (x *ChargeRequest) GetAmount() *Money {
method GetCreditCard (line 1292) | func (x *ChargeRequest) GetCreditCard() *CreditCardInfo {
type ChargeResponse (line 1299) | type ChargeResponse struct
method Reset (line 1307) | func (x *ChargeResponse) Reset() {
method String (line 1316) | func (x *ChargeResponse) String() string {
method ProtoMessage (line 1320) | func (*ChargeResponse) ProtoMessage() {}
method ProtoReflect (line 1322) | func (x *ChargeResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1335) | func (*ChargeResponse) Descriptor() ([]byte, []int) {
method GetTransactionId (line 1339) | func (x *ChargeResponse) GetTransactionId() string {
type OrderItem (line 1346) | type OrderItem struct
method Reset (line 1355) | func (x *OrderItem) Reset() {
method String (line 1364) | func (x *OrderItem) String() string {
method ProtoMessage (line 1368) | func (*OrderItem) ProtoMessage() {}
method ProtoReflect (line 1370) | func (x *OrderItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 1383) | func (*OrderItem) Descriptor() ([]byte, []int) {
method GetItem (line 1387) | func (x *OrderItem) GetItem() *CartItem {
method GetCost (line 1394) | func (x *OrderItem) GetCost() *Money {
type OrderResult (line 1401) | type OrderResult struct
method Reset (line 1413) | func (x *OrderResult) Reset() {
method String (line 1422) | func (x *OrderResult) String() string {
method ProtoMessage (line 1426) | func (*OrderResult) ProtoMessage() {}
method ProtoReflect (line 1428) | func (x *OrderResult) ProtoReflect() protoreflect.Message {
method Descriptor (line 1441) | func (*OrderResult) Descriptor() ([]byte, []int) {
method GetOrderId (line 1445) | func (x *OrderResult) GetOrderId() string {
method GetShippingTrackingId (line 1452) | func (x *OrderResult) GetShippingTrackingId() string {
method GetShippingCost (line 1459) | func (x *OrderResult) GetShippingCost() *Money {
method GetShippingAddress (line 1466) | func (x *OrderResult) GetShippingAddress() *Address {
method GetItems (line 1473) | func (x *OrderResult) GetItems() []*OrderItem {
type SendOrderConfirmationRequest (line 1480) | type SendOrderConfirmationRequest struct
method Reset (line 1489) | func (x *SendOrderConfirmationRequest) Reset() {
method String (line 1498) | func (x *SendOrderConfirmationRequest) String() string {
method ProtoMessage (line 1502) | func (*SendOrderConfirmationRequest) ProtoMessage() {}
method ProtoReflect (line 1504) | func (x *SendOrderConfirmationRequest) ProtoReflect() protoreflect.Mes...
method Descriptor (line 1517) | func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
method GetEmail (line 1521) | func (x *SendOrderConfirmationRequest) GetEmail() string {
method GetOrder (line 1528) | func (x *SendOrderConfirmationRequest) GetOrder() *OrderResult {
type PlaceOrderRequest (line 1535) | type PlaceOrderRequest struct
method Reset (line 1547) | func (x *PlaceOrderRequest) Reset() {
method String (line 1556) | func (x *PlaceOrderRequest) String() string {
method ProtoMessage (line 1560) | func (*PlaceOrderRequest) ProtoMessage() {}
method ProtoReflect (line 1562) | func (x *PlaceOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1575) | func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 1579) | func (x *PlaceOrderRequest) GetUserId() string {
method GetUserCurrency (line 1586) | func (x *PlaceOrderRequest) GetUserCurrency() string {
method GetAddress (line 1593) | func (x *PlaceOrderRequest) GetAddress() *Address {
method GetEmail (line 1600) | func (x *PlaceOrderRequest) GetEmail() string {
method GetCreditCard (line 1607) | func (x *PlaceOrderRequest) GetCreditCard() *CreditCardInfo {
type PlaceOrderResponse (line 1614) | type PlaceOrderResponse struct
method Reset (line 1622) | func (x *PlaceOrderResponse) Reset() {
method String (line 1631) | func (x *PlaceOrderResponse) String() string {
method ProtoMessage (line 1635) | func (*PlaceOrderResponse) ProtoMessage() {}
method ProtoReflect (line 1637) | func (x *PlaceOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1650) | func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
method GetOrder (line 1654) | func (x *PlaceOrderResponse) GetOrder() *OrderResult {
type AdRequest (line 1661) | type AdRequest struct
method Reset (line 1670) | func (x *AdRequest) Reset() {
method String (line 1679) | func (x *AdRequest) String() string {
method ProtoMessage (line 1683) | func (*AdRequest) ProtoMessage() {}
method ProtoReflect (line 1685) | func (x *AdRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1698) | func (*AdRequest) Descriptor() ([]byte, []int) {
method GetContextKeys (line 1702) | func (x *AdRequest) GetContextKeys() []string {
type AdResponse (line 1709) | type AdResponse struct
method Reset (line 1717) | func (x *AdResponse) Reset() {
method String (line 1726) | func (x *AdResponse) String() string {
method ProtoMessage (line 1730) | func (*AdResponse) ProtoMessage() {}
method ProtoReflect (line 1732) | func (x *AdResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1745) | func (*AdResponse) Descriptor() ([]byte, []int) {
method GetAds (line 1749) | func (x *AdResponse) GetAds() []*Ad {
type Ad (line 1756) | type Ad struct
method Reset (line 1767) | func (x *Ad) Reset() {
method String (line 1776) | func (x *Ad) String() string {
method ProtoMessage (line 1780) | func (*Ad) ProtoMessage() {}
method ProtoReflect (line 1782) | func (x *Ad) ProtoReflect() protoreflect.Message {
method Descriptor (line 1795) | func (*Ad) Descriptor() ([]byte, []int) {
method GetRedirectUrl (line 1799) | func (x *Ad) GetRedirectUrl() string {
method GetText (line 1806) | func (x *Ad) GetText() string {
function file_demo_proto_rawDescGZIP (line 2098) | func file_demo_proto_rawDescGZIP() []byte {
function init (line 2201) | func init() { file_demo_proto_init() }
function file_demo_proto_init (line 2202) | func file_demo_proto_init() {
FILE: src/frontend/genproto/demo_grpc.pb.go
constant _ (line 33) | _ = grpc.SupportPackageIsVersion9
constant CartService_AddItem_FullMethodName (line 36) | CartService_AddItem_FullMethodName = "/hipstershop.CartService/AddItem"
constant CartService_GetCart_FullMethodName (line 37) | CartService_GetCart_FullMethodName = "/hipstershop.CartService/GetCart"
constant CartService_EmptyCart_FullMethodName (line 38) | CartService_EmptyCart_FullMethodName = "/hipstershop.CartService/EmptyCart"
type CartServiceClient (line 44) | type CartServiceClient interface
type cartServiceClient (line 50) | type cartServiceClient struct
method AddItem (line 58) | func (c *cartServiceClient) AddItem(ctx context.Context, in *AddItemRe...
method GetCart (line 68) | func (c *cartServiceClient) GetCart(ctx context.Context, in *GetCartRe...
method EmptyCart (line 78) | func (c *cartServiceClient) EmptyCart(ctx context.Context, in *EmptyCa...
function NewCartServiceClient (line 54) | func NewCartServiceClient(cc grpc.ClientConnInterface) CartServiceClient {
type CartServiceServer (line 91) | type CartServiceServer interface
type UnimplementedCartServiceServer (line 103) | type UnimplementedCartServiceServer struct
method AddItem (line 105) | func (UnimplementedCartServiceServer) AddItem(context.Context, *AddIte...
method GetCart (line 108) | func (UnimplementedCartServiceServer) GetCart(context.Context, *GetCar...
method EmptyCart (line 111) | func (UnimplementedCartServiceServer) EmptyCart(context.Context, *Empt...
method mustEmbedUnimplementedCartServiceServer (line 114) | func (UnimplementedCartServiceServer) mustEmbedUnimplementedCartServic...
method testEmbeddedByValue (line 115) | func (UnimplementedCartServiceServer) testEmbeddedByValue() ...
type UnsafeCartServiceServer (line 120) | type UnsafeCartServiceServer interface
function RegisterCartServiceServer (line 124) | func RegisterCartServiceServer(s grpc.ServiceRegistrar, srv CartServiceS...
function _CartService_AddItem_Handler (line 135) | func _CartService_AddItem_Handler(srv interface{}, ctx context.Context, ...
function _CartService_GetCart_Handler (line 153) | func _CartService_GetCart_Handler(srv interface{}, ctx context.Context, ...
function _CartService_EmptyCart_Handler (line 171) | func _CartService_EmptyCart_Handler(srv interface{}, ctx context.Context...
constant RecommendationService_ListRecommendations_FullMethodName (line 214) | RecommendationService_ListRecommendations_FullMethodName = "/hipstershop...
type RecommendationServiceClient (line 220) | type RecommendationServiceClient interface
type recommendationServiceClient (line 224) | type recommendationServiceClient struct
method ListRecommendations (line 232) | func (c *recommendationServiceClient) ListRecommendations(ctx context....
function NewRecommendationServiceClient (line 228) | func NewRecommendationServiceClient(cc grpc.ClientConnInterface) Recomme...
type RecommendationServiceServer (line 245) | type RecommendationServiceServer interface
type UnimplementedRecommendationServiceServer (line 255) | type UnimplementedRecommendationServiceServer struct
method ListRecommendations (line 257) | func (UnimplementedRecommendationServiceServer) ListRecommendations(co...
method mustEmbedUnimplementedRecommendationServiceServer (line 260) | func (UnimplementedRecommendationServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 261) | func (UnimplementedRecommendationServiceServer) testEmbeddedByValue() ...
type UnsafeRecommendationServiceServer (line 266) | type UnsafeRecommendationServiceServer interface
function RegisterRecommendationServiceServer (line 270) | func RegisterRecommendationServiceServer(s grpc.ServiceRegistrar, srv Re...
function _RecommendationService_ListRecommendations_Handler (line 281) | func _RecommendationService_ListRecommendations_Handler(srv interface{},...
constant ProductCatalogService_ListProducts_FullMethodName (line 316) | ProductCatalogService_ListProducts_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_GetProduct_FullMethodName (line 317) | ProductCatalogService_GetProduct_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_SearchProducts_FullMethodName (line 318) | ProductCatalogService_SearchProducts_FullMethodName = "/hipstershop.Prod...
type ProductCatalogServiceClient (line 324) | type ProductCatalogServiceClient interface
type productCatalogServiceClient (line 330) | type productCatalogServiceClient struct
method ListProducts (line 338) | func (c *productCatalogServiceClient) ListProducts(ctx context.Context...
method GetProduct (line 348) | func (c *productCatalogServiceClient) GetProduct(ctx context.Context, ...
method SearchProducts (line 358) | func (c *productCatalogServiceClient) SearchProducts(ctx context.Conte...
function NewProductCatalogServiceClient (line 334) | func NewProductCatalogServiceClient(cc grpc.ClientConnInterface) Product...
type ProductCatalogServiceServer (line 371) | type ProductCatalogServiceServer interface
type UnimplementedProductCatalogServiceServer (line 383) | type UnimplementedProductCatalogServiceServer struct
method ListProducts (line 385) | func (UnimplementedProductCatalogServiceServer) ListProducts(context.C...
method GetProduct (line 388) | func (UnimplementedProductCatalogServiceServer) GetProduct(context.Con...
method SearchProducts (line 391) | func (UnimplementedProductCatalogServiceServer) SearchProducts(context...
method mustEmbedUnimplementedProductCatalogServiceServer (line 394) | func (UnimplementedProductCatalogServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 395) | func (UnimplementedProductCatalogServiceServer) testEmbeddedByValue() ...
type UnsafeProductCatalogServiceServer (line 400) | type UnsafeProductCatalogServiceServer interface
function RegisterProductCatalogServiceServer (line 404) | func RegisterProductCatalogServiceServer(s grpc.ServiceRegistrar, srv Pr...
function _ProductCatalogService_ListProducts_Handler (line 415) | func _ProductCatalogService_ListProducts_Handler(srv interface{}, ctx co...
function _ProductCatalogService_GetProduct_Handler (line 433) | func _ProductCatalogService_GetProduct_Handler(srv interface{}, ctx cont...
function _ProductCatalogService_SearchProducts_Handler (line 451) | func _ProductCatalogService_SearchProducts_Handler(srv interface{}, ctx ...
constant ShippingService_GetQuote_FullMethodName (line 494) | ShippingService_GetQuote_FullMethodName = "/hipstershop.ShippingService...
constant ShippingService_ShipOrder_FullMethodName (line 495) | ShippingService_ShipOrder_FullMethodName = "/hipstershop.ShippingService...
type ShippingServiceClient (line 501) | type ShippingServiceClient interface
type shippingServiceClient (line 506) | type shippingServiceClient struct
method GetQuote (line 514) | func (c *shippingServiceClient) GetQuote(ctx context.Context, in *GetQ...
method ShipOrder (line 524) | func (c *shippingServiceClient) ShipOrder(ctx context.Context, in *Shi...
function NewShippingServiceClient (line 510) | func NewShippingServiceClient(cc grpc.ClientConnInterface) ShippingServi...
type ShippingServiceServer (line 537) | type ShippingServiceServer interface
type UnimplementedShippingServiceServer (line 548) | type UnimplementedShippingServiceServer struct
method GetQuote (line 550) | func (UnimplementedShippingServiceServer) GetQuote(context.Context, *G...
method ShipOrder (line 553) | func (UnimplementedShippingServiceServer) ShipOrder(context.Context, *...
method mustEmbedUnimplementedShippingServiceServer (line 556) | func (UnimplementedShippingServiceServer) mustEmbedUnimplementedShippi...
method testEmbeddedByValue (line 557) | func (UnimplementedShippingServiceServer) testEmbeddedByValue() ...
type UnsafeShippingServiceServer (line 562) | type UnsafeShippingServiceServer interface
function RegisterShippingServiceServer (line 566) | func RegisterShippingServiceServer(s grpc.ServiceRegistrar, srv Shipping...
function _ShippingService_GetQuote_Handler (line 577) | func _ShippingService_GetQuote_Handler(srv interface{}, ctx context.Cont...
function _ShippingService_ShipOrder_Handler (line 595) | func _ShippingService_ShipOrder_Handler(srv interface{}, ctx context.Con...
constant CurrencyService_GetSupportedCurrencies_FullMethodName (line 634) | CurrencyService_GetSupportedCurrencies_FullMethodName = "/hipstershop.Cu...
constant CurrencyService_Convert_FullMethodName (line 635) | CurrencyService_Convert_FullMethodName = "/hipstershop.Cu...
type CurrencyServiceClient (line 641) | type CurrencyServiceClient interface
type currencyServiceClient (line 646) | type currencyServiceClient struct
method GetSupportedCurrencies (line 654) | func (c *currencyServiceClient) GetSupportedCurrencies(ctx context.Con...
method Convert (line 664) | func (c *currencyServiceClient) Convert(ctx context.Context, in *Curre...
function NewCurrencyServiceClient (line 650) | func NewCurrencyServiceClient(cc grpc.ClientConnInterface) CurrencyServi...
type CurrencyServiceServer (line 677) | type CurrencyServiceServer interface
type UnimplementedCurrencyServiceServer (line 688) | type UnimplementedCurrencyServiceServer struct
method GetSupportedCurrencies (line 690) | func (UnimplementedCurrencyServiceServer) GetSupportedCurrencies(conte...
method Convert (line 693) | func (UnimplementedCurrencyServiceServer) Convert(context.Context, *Cu...
method mustEmbedUnimplementedCurrencyServiceServer (line 696) | func (UnimplementedCurrencyServiceServer) mustEmbedUnimplementedCurren...
method testEmbeddedByValue (line 697) | func (UnimplementedCurrencyServiceServer) testEmbeddedByValue() ...
type UnsafeCurrencyServiceServer (line 702) | type UnsafeCurrencyServiceServer interface
function RegisterCurrencyServiceServer (line 706) | func RegisterCurrencyServiceServer(s grpc.ServiceRegistrar, srv Currency...
function _CurrencyService_GetSupportedCurrencies_Handler (line 717) | func _CurrencyService_GetSupportedCurrencies_Handler(srv interface{}, ct...
function _CurrencyService_Convert_Handler (line 735) | func _CurrencyService_Convert_Handler(srv interface{}, ctx context.Conte...
constant PaymentService_Charge_FullMethodName (line 774) | PaymentService_Charge_FullMethodName = "/hipstershop.PaymentService/Charge"
type PaymentServiceClient (line 780) | type PaymentServiceClient interface
type paymentServiceClient (line 784) | type paymentServiceClient struct
method Charge (line 792) | func (c *paymentServiceClient) Charge(ctx context.Context, in *ChargeR...
function NewPaymentServiceClient (line 788) | func NewPaymentServiceClient(cc grpc.ClientConnInterface) PaymentService...
type PaymentServiceServer (line 805) | type PaymentServiceServer interface
type UnimplementedPaymentServiceServer (line 815) | type UnimplementedPaymentServiceServer struct
method Charge (line 817) | func (UnimplementedPaymentServiceServer) Charge(context.Context, *Char...
method mustEmbedUnimplementedPaymentServiceServer (line 820) | func (UnimplementedPaymentServiceServer) mustEmbedUnimplementedPayment...
method testEmbeddedByValue (line 821) | func (UnimplementedPaymentServiceServer) testEmbeddedByValue() ...
type UnsafePaymentServiceServer (line 826) | type UnsafePaymentServiceServer interface
function RegisterPaymentServiceServer (line 830) | func RegisterPaymentServiceServer(s grpc.ServiceRegistrar, srv PaymentSe...
function _PaymentService_Charge_Handler (line 841) | func _PaymentService_Charge_Handler(srv interface{}, ctx context.Context...
constant EmailService_SendOrderConfirmation_FullMethodName (line 876) | EmailService_SendOrderConfirmation_FullMethodName = "/hipstershop.EmailS...
type EmailServiceClient (line 882) | type EmailServiceClient interface
type emailServiceClient (line 886) | type emailServiceClient struct
method SendOrderConfirmation (line 894) | func (c *emailServiceClient) SendOrderConfirmation(ctx context.Context...
function NewEmailServiceClient (line 890) | func NewEmailServiceClient(cc grpc.ClientConnInterface) EmailServiceClie...
type EmailServiceServer (line 907) | type EmailServiceServer interface
type UnimplementedEmailServiceServer (line 917) | type UnimplementedEmailServiceServer struct
method SendOrderConfirmation (line 919) | func (UnimplementedEmailServiceServer) SendOrderConfirmation(context.C...
method mustEmbedUnimplementedEmailServiceServer (line 922) | func (UnimplementedEmailServiceServer) mustEmbedUnimplementedEmailServ...
method testEmbeddedByValue (line 923) | func (UnimplementedEmailServiceServer) testEmbeddedByValue() ...
type UnsafeEmailServiceServer (line 928) | type UnsafeEmailServiceServer interface
function RegisterEmailServiceServer (line 932) | func RegisterEmailServiceServer(s grpc.ServiceRegistrar, srv EmailServic...
function _EmailService_SendOrderConfirmation_Handler (line 943) | func _EmailService_SendOrderConfirmation_Handler(srv interface{}, ctx co...
constant CheckoutService_PlaceOrder_FullMethodName (line 978) | CheckoutService_PlaceOrder_FullMethodName = "/hipstershop.CheckoutServic...
type CheckoutServiceClient (line 984) | type CheckoutServiceClient interface
type checkoutServiceClient (line 988) | type checkoutServiceClient struct
method PlaceOrder (line 996) | func (c *checkoutServiceClient) PlaceOrder(ctx context.Context, in *Pl...
function NewCheckoutServiceClient (line 992) | func NewCheckoutServiceClient(cc grpc.ClientConnInterface) CheckoutServi...
type CheckoutServiceServer (line 1009) | type CheckoutServiceServer interface
type UnimplementedCheckoutServiceServer (line 1019) | type UnimplementedCheckoutServiceServer struct
method PlaceOrder (line 1021) | func (UnimplementedCheckoutServiceServer) PlaceOrder(context.Context, ...
method mustEmbedUnimplementedCheckoutServiceServer (line 1024) | func (UnimplementedCheckoutServiceServer) mustEmbedUnimplementedChecko...
method testEmbeddedByValue (line 1025) | func (UnimplementedCheckoutServiceServer) testEmbeddedByValue() ...
type UnsafeCheckoutServiceServer (line 1030) | type UnsafeCheckoutServiceServer interface
function RegisterCheckoutServiceServer (line 1034) | func RegisterCheckoutServiceServer(s grpc.ServiceRegistrar, srv Checkout...
function _CheckoutService_PlaceOrder_Handler (line 1045) | func _CheckoutService_PlaceOrder_Handler(srv interface{}, ctx context.Co...
constant AdService_GetAds_FullMethodName (line 1080) | AdService_GetAds_FullMethodName = "/hipstershop.AdService/GetAds"
type AdServiceClient (line 1086) | type AdServiceClient interface
type adServiceClient (line 1090) | type adServiceClient struct
method GetAds (line 1098) | func (c *adServiceClient) GetAds(ctx context.Context, in *AdRequest, o...
function NewAdServiceClient (line 1094) | func NewAdServiceClient(cc grpc.ClientConnInterface) AdServiceClient {
type AdServiceServer (line 1111) | type AdServiceServer interface
type UnimplementedAdServiceServer (line 1121) | type UnimplementedAdServiceServer struct
method GetAds (line 1123) | func (UnimplementedAdServiceServer) GetAds(context.Context, *AdRequest...
method mustEmbedUnimplementedAdServiceServer (line 1126) | func (UnimplementedAdServiceServer) mustEmbedUnimplementedAdServiceSer...
method testEmbeddedByValue (line 1127) | func (UnimplementedAdServiceServer) testEmbeddedByValue() ...
type UnsafeAdServiceServer (line 1132) | type UnsafeAdServiceServer interface
function RegisterAdServiceServer (line 1136) | func RegisterAdServiceServer(s grpc.ServiceRegistrar, srv AdServiceServe...
function _AdService_GetAds_Handler (line 1147) | func _AdService_GetAds_Handler(srv interface{}, ctx context.Context, dec...
FILE: src/frontend/handlers.go
type platformDetails (line 40) | type platformDetails struct
method setPlatformDetails (line 122) | func (plat *platformDetails) setPlatformDetails(env string) {
method homeHandler (line 59) | func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Req...
method productHandler (line 144) | func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http....
method addToCartHandler (line 211) | func (fe *frontendServer) addToCartHandler(w http.ResponseWriter, r *htt...
method emptyCartHandler (line 239) | func (fe *frontendServer) emptyCartHandler(w http.ResponseWriter, r *htt...
method viewCartHandler (line 251) | func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http...
method placeOrderHandler (line 320) | func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *ht...
method assistantHandler (line 403) | func (fe *frontendServer) assistantHandler(w http.ResponseWriter, r *htt...
method logoutHandler (line 418) | func (fe *frontendServer) logoutHandler(w http.ResponseWriter, r *http.R...
method getProductByID (line 430) | func (fe *frontendServer) getProductByID(w http.ResponseWriter, r *http....
method chatBotHandler (line 451) | func (fe *frontendServer) chatBotHandler(w http.ResponseWriter, r *http....
method setCurrencyHandler (line 499) | func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *h...
method chooseAd (line 527) | func (fe *frontendServer) chooseAd(ctx context.Context, ctxKeys []string...
function renderHTTPError (line 536) | func renderHTTPError(log logrus.FieldLogger, r *http.Request, w http.Res...
function injectCommonTemplateData (line 551) | func injectCommonTemplateData(r *http.Request, payload map[string]interf...
function currentCurrency (line 573) | func currentCurrency(r *http.Request) string {
function sessionID (line 581) | func sessionID(r *http.Request) string {
function cartIDs (line 589) | func cartIDs(c []*pb.CartItem) []string {
function cartSize (line 598) | func cartSize(c []*pb.CartItem) int {
function renderMoney (line 606) | func renderMoney(money pb.Money) string {
function renderCurrencyLogo (line 611) | func renderCurrencyLogo(currencyCode string) string {
function stringinSlice (line 628) | func stringinSlice(slice []string, val string) bool {
FILE: src/frontend/main.go
constant port (line 39) | port = "8080"
constant defaultCurrency (line 40) | defaultCurrency = "USD"
constant cookieMaxAge (line 41) | cookieMaxAge = 60 * 60 * 48
constant cookiePrefix (line 43) | cookiePrefix = "shop_"
constant cookieSessionID (line 44) | cookieSessionID = cookiePrefix + "session-id"
constant cookieCurrency (line 45) | cookieCurrency = cookiePrefix + "currency"
type ctxKeySessionID (line 61) | type ctxKeySessionID struct
type frontendServer (line 63) | type frontendServer struct
function main (line 91) | func main() {
function initStats (line 173) | func initStats(log logrus.FieldLogger) {
function initTracing (line 177) | func initTracing(log logrus.FieldLogger, ctx context.Context, svc *front...
function initProfiling (line 194) | func initProfiling(log logrus.FieldLogger, service, version string) {
function mustMapEnv (line 217) | func mustMapEnv(target *string, envKey string) {
function mustConnGRPC (line 225) | func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr stri...
FILE: src/frontend/middleware.go
type ctxKeyLog (line 27) | type ctxKeyLog struct
type ctxKeyRequestID (line 28) | type ctxKeyRequestID struct
type logHandler (line 30) | type logHandler struct
method ServeHTTP (line 57) | func (lh *logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
type responseRecorder (line 35) | type responseRecorder struct
method Header (line 41) | func (r *responseRecorder) Header() http.Header { return r.w.Header() }
method Write (line 43) | func (r *responseRecorder) Write(p []byte) (int, error) {
method WriteHeader (line 52) | func (r *responseRecorder) WriteHeader(statusCode int) {
function ensureSessionID (line 85) | func ensureSessionID(next http.Handler) http.HandlerFunc {
FILE: src/frontend/money/money.go
constant nanosMin (line 24) | nanosMin = -999999999
constant nanosMax (line 25) | nanosMax = +999999999
constant nanosMod (line 26) | nanosMod = 1000000000
function IsValid (line 35) | func IsValid(m pb.Money) bool {
function signMatches (line 39) | func signMatches(m pb.Money) bool {
function validNanos (line 43) | func validNanos(nanos int32) bool { return nanosMin <= nanos && nanos <=...
function IsZero (line 46) | func IsZero(m pb.Money) bool { return m.GetUnits() == 0 && m.GetNanos() ...
function IsPositive (line 50) | func IsPositive(m pb.Money) bool {
function IsNegative (line 56) | func IsNegative(m pb.Money) bool {
function AreSameCurrency (line 62) | func AreSameCurrency(l, r pb.Money) bool {
function AreEquals (line 68) | func AreEquals(l, r pb.Money) bool {
function Negate (line 74) | func Negate(m pb.Money) pb.Money {
function Must (line 83) | func Must(v pb.Money, err error) pb.Money {
function Sum (line 93) | func Sum(l, r pb.Money) (pb.Money, error) {
function MultiplySlow (line 125) | func MultiplySlow(m pb.Money, n uint32) pb.Money {
FILE: src/frontend/money/money_test.go
function mmc (line 25) | func mmc(u int64, n int32, c string) pb.Money { return pb.Money{Units: u...
function mm (line 26) | func mm(u int64, n int32) pb.Money { return mmc(u, n, "") }
function TestIsValid (line 28) | func TestIsValid(t *testing.T) {
function TestIsZero (line 52) | func TestIsZero(t *testing.T) {
function TestIsPositive (line 73) | func TestIsPositive(t *testing.T) {
function TestIsNegative (line 94) | func TestIsNegative(t *testing.T) {
function TestAreSameCurrency (line 115) | func TestAreSameCurrency(t *testing.T) {
function TestAreEquals (line 140) | func TestAreEquals(t *testing.T) {
function TestNegate (line 165) | func TestNegate(t *testing.T) {
function TestMust_pass (line 185) | func TestMust_pass(t *testing.T) {
function TestMust_panic (line 192) | func TestMust_panic(t *testing.T) {
function TestSum (line 202) | func TestSum(t *testing.T) {
FILE: src/frontend/packaging_info.go
type PackagingInfo (line 34) | type PackagingInfo struct
function init (line 42) | func init() {
function isPackagingServiceConfigured (line 46) | func isPackagingServiceConfigured() bool {
function httpGetPackagingInfo (line 50) | func httpGetPackagingInfo(productId string) (*PackagingInfo, error) {
FILE: src/frontend/rpc.go
constant avoidNoopCurrencyConversionRPC (line 27) | avoidNoopCurrencyConversionRPC = false
method getCurrencies (line 30) | func (fe *frontendServer) getCurrencies(ctx context.Context) ([]string, ...
method getProducts (line 45) | func (fe *frontendServer) getProducts(ctx context.Context) ([]*pb.Produc...
method getProduct (line 51) | func (fe *frontendServer) getProduct(ctx context.Context, id string) (*p...
method getCart (line 57) | func (fe *frontendServer) getCart(ctx context.Context, userID string) ([...
method emptyCart (line 62) | func (fe *frontendServer) emptyCart(ctx context.Context, userID string) ...
method insertCart (line 67) | func (fe *frontendServer) insertCart(ctx context.Context, userID, produc...
method convertCurrency (line 77) | func (fe *frontendServer) convertCurrency(ctx context.Context, money *pb...
method getShippingQuote (line 87) | func (fe *frontendServer) getShippingQuote(ctx context.Context, items []...
method getRecommendations (line 99) | func (fe *frontendServer) getRecommendations(ctx context.Context, userID...
method getAd (line 119) | func (fe *frontendServer) getAd(ctx context.Context, ctxKeys []string) (...
FILE: src/frontend/validator/validator.go
function init (line 29) | func init() {
type Payload (line 33) | type Payload interface
type AddToCartPayload (line 37) | type AddToCartPayload struct
method Validate (line 60) | func (ad *AddToCartPayload) Validate() error {
type PlaceOrderPayload (line 42) | type PlaceOrderPayload struct
method Validate (line 64) | func (po *PlaceOrderPayload) Validate() error {
type SetCurrencyPayload (line 55) | type SetCurrencyPayload struct
method Validate (line 68) | func (sc *SetCurrencyPayload) Validate() error {
function ValidationErrorResponse (line 73) | func ValidationErrorResponse(err error) error {
FILE: src/frontend/validator/validator_test.go
function TestPlaceOrderPassesValidation (line 22) | func TestPlaceOrderPassesValidation(t *testing.T) {
function TestPlaceOrderFailsValidation (line 59) | func TestPlaceOrderFailsValidation(t *testing.T) {
function TestAddToCartPassesValidation (line 106) | func TestAddToCartPassesValidation(t *testing.T) {
function TestAddToCartFailsValidation (line 125) | func TestAddToCartFailsValidation(t *testing.T) {
function TestSetCurrencyPassesValidation (line 146) | func TestSetCurrencyPassesValidation(t *testing.T) {
function TestSetCurrencyFailsValidation (line 168) | func TestSetCurrencyFailsValidation(t *testing.T) {
FILE: src/loadgenerator/locustfile.py
function index (line 34) | def index(l):
function setCurrency (line 37) | def setCurrency(l):
function browseProduct (line 42) | def browseProduct(l):
function viewCart (line 45) | def viewCart(l):
function addToCart (line 48) | def addToCart(l):
function empty_cart (line 55) | def empty_cart(l):
function checkout (line 58) | def checkout(l):
function logout (line 74) | def logout(l):
class UserBehavior (line 78) | class UserBehavior(TaskSet):
method on_start (line 80) | def on_start(self):
class WebsiteUser (line 90) | class WebsiteUser(FastHttpUser):
FILE: src/paymentservice/charge.js
method level (line 23) | level (logLevelString, logLevelNum) {
class CreditCardError (line 30) | class CreditCardError extends Error {
method constructor (line 31) | constructor (message) {
class InvalidCreditCard (line 37) | class InvalidCreditCard extends CreditCardError {
method constructor (line 38) | constructor (cardType) {
class UnacceptedCreditCard (line 43) | class UnacceptedCreditCard extends CreditCardError {
method constructor (line 44) | constructor (cardType) {
class ExpiredCreditCard (line 49) | class ExpiredCreditCard extends CreditCardError {
method constructor (line 50) | constructor (number, month, year) {
FILE: src/paymentservice/index.js
constant PORT (line 70) | const PORT = process.env['PORT'];
constant PROTO_PATH (line 71) | const PROTO_PATH = path.join(__dirname, '/proto/');
FILE: src/paymentservice/logger.js
method level (line 23) | level (logLevelString, logLevelNum) {
FILE: src/paymentservice/server.js
class HipsterShopServer (line 23) | class HipsterShopServer {
method constructor (line 24) | constructor(protoRoot, port = HipsterShopServer.PORT) {
method ChargeServiceHandler (line 41) | static ChargeServiceHandler(call, callback) {
method CheckHandler (line 52) | static CheckHandler(call, callback) {
method listen (line 57) | listen() {
method loadProto (line 70) | loadProto(path) {
method loadAllProtos (line 84) | loadAllProtos(protoRoot) {
FILE: src/productcatalogservice/catalog_loader.go
function loadCatalog (line 33) | func loadCatalog(catalog *pb.ListProductsResponse) error {
function loadCatalogFromLocalFile (line 44) | func loadCatalogFromLocalFile(catalog *pb.ListProductsResponse) error {
function getSecretPayload (line 62) | func getSecretPayload(project, secret, version string) (string, error) {
function loadCatalogFromAlloyDB (line 85) | func loadCatalogFromAlloyDB(catalog *pb.ListProductsResponse) error {
FILE: src/productcatalogservice/genproto/demo.pb.go
constant _ (line 32) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 34) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type CartItem (line 37) | type CartItem struct
method Reset (line 46) | func (x *CartItem) Reset() {
method String (line 55) | func (x *CartItem) String() string {
method ProtoMessage (line 59) | func (*CartItem) ProtoMessage() {}
method ProtoReflect (line 61) | func (x *CartItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 74) | func (*CartItem) Descriptor() ([]byte, []int) {
method GetProductId (line 78) | func (x *CartItem) GetProductId() string {
method GetQuantity (line 85) | func (x *CartItem) GetQuantity() int32 {
type AddItemRequest (line 92) | type AddItemRequest struct
method Reset (line 101) | func (x *AddItemRequest) Reset() {
method String (line 110) | func (x *AddItemRequest) String() string {
method ProtoMessage (line 114) | func (*AddItemRequest) ProtoMessage() {}
method ProtoReflect (line 116) | func (x *AddItemRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 129) | func (*AddItemRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 133) | func (x *AddItemRequest) GetUserId() string {
method GetItem (line 140) | func (x *AddItemRequest) GetItem() *CartItem {
type EmptyCartRequest (line 147) | type EmptyCartRequest struct
method Reset (line 155) | func (x *EmptyCartRequest) Reset() {
method String (line 164) | func (x *EmptyCartRequest) String() string {
method ProtoMessage (line 168) | func (*EmptyCartRequest) ProtoMessage() {}
method ProtoReflect (line 170) | func (x *EmptyCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 183) | func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 187) | func (x *EmptyCartRequest) GetUserId() string {
type GetCartRequest (line 194) | type GetCartRequest struct
method Reset (line 202) | func (x *GetCartRequest) Reset() {
method String (line 211) | func (x *GetCartRequest) String() string {
method ProtoMessage (line 215) | func (*GetCartRequest) ProtoMessage() {}
method ProtoReflect (line 217) | func (x *GetCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 230) | func (*GetCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 234) | func (x *GetCartRequest) GetUserId() string {
type Cart (line 241) | type Cart struct
method Reset (line 250) | func (x *Cart) Reset() {
method String (line 259) | func (x *Cart) String() string {
method ProtoMessage (line 263) | func (*Cart) ProtoMessage() {}
method ProtoReflect (line 265) | func (x *Cart) ProtoReflect() protoreflect.Message {
method Descriptor (line 278) | func (*Cart) Descriptor() ([]byte, []int) {
method GetUserId (line 282) | func (x *Cart) GetUserId() string {
method GetItems (line 289) | func (x *Cart) GetItems() []*CartItem {
type Empty (line 296) | type Empty struct
method Reset (line 302) | func (x *Empty) Reset() {
method String (line 311) | func (x *Empty) String() string {
method ProtoMessage (line 315) | func (*Empty) ProtoMessage() {}
method ProtoReflect (line 317) | func (x *Empty) ProtoReflect() protoreflect.Message {
method Descriptor (line 330) | func (*Empty) Descriptor() ([]byte, []int) {
type ListRecommendationsRequest (line 334) | type ListRecommendationsRequest struct
method Reset (line 343) | func (x *ListRecommendationsRequest) Reset() {
method String (line 352) | func (x *ListRecommendationsRequest) String() string {
method ProtoMessage (line 356) | func (*ListRecommendationsRequest) ProtoMessage() {}
method ProtoReflect (line 358) | func (x *ListRecommendationsRequest) ProtoReflect() protoreflect.Messa...
method Descriptor (line 371) | func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 375) | func (x *ListRecommendationsRequest) GetUserId() string {
method GetProductIds (line 382) | func (x *ListRecommendationsRequest) GetProductIds() []string {
type ListRecommendationsResponse (line 389) | type ListRecommendationsResponse struct
method Reset (line 397) | func (x *ListRecommendationsResponse) Reset() {
method String (line 406) | func (x *ListRecommendationsResponse) String() string {
method ProtoMessage (line 410) | func (*ListRecommendationsResponse) ProtoMessage() {}
method ProtoReflect (line 412) | func (x *ListRecommendationsResponse) ProtoReflect() protoreflect.Mess...
method Descriptor (line 425) | func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
method GetProductIds (line 429) | func (x *ListRecommendationsResponse) GetProductIds() []string {
type Product (line 436) | type Product struct
method Reset (line 451) | func (x *Product) Reset() {
method String (line 460) | func (x *Product) String() string {
method ProtoMessage (line 464) | func (*Product) ProtoMessage() {}
method ProtoReflect (line 466) | func (x *Product) ProtoReflect() protoreflect.Message {
method Descriptor (line 479) | func (*Product) Descriptor() ([]byte, []int) {
method GetId (line 483) | func (x *Product) GetId() string {
method GetName (line 490) | func (x *Product) GetName() string {
method GetDescription (line 497) | func (x *Product) GetDescription() string {
method GetPicture (line 504) | func (x *Product) GetPicture() string {
method GetPriceUsd (line 511) | func (x *Product) GetPriceUsd() *Money {
method GetCategories (line 518) | func (x *Product) GetCategories() []string {
type ListProductsResponse (line 525) | type ListProductsResponse struct
method Reset (line 533) | func (x *ListProductsResponse) Reset() {
method String (line 542) | func (x *ListProductsResponse) String() string {
method ProtoMessage (line 546) | func (*ListProductsResponse) ProtoMessage() {}
method ProtoReflect (line 548) | func (x *ListProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 561) | func (*ListProductsResponse) Descriptor() ([]byte, []int) {
method GetProducts (line 565) | func (x *ListProductsResponse) GetProducts() []*Product {
type GetProductRequest (line 572) | type GetProductRequest struct
method Reset (line 580) | func (x *GetProductRequest) Reset() {
method String (line 589) | func (x *GetProductRequest) String() string {
method ProtoMessage (line 593) | func (*GetProductRequest) ProtoMessage() {}
method ProtoReflect (line 595) | func (x *GetProductRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 608) | func (*GetProductRequest) Descriptor() ([]byte, []int) {
method GetId (line 612) | func (x *GetProductRequest) GetId() string {
type SearchProductsRequest (line 619) | type SearchProductsRequest struct
method Reset (line 627) | func (x *SearchProductsRequest) Reset() {
method String (line 636) | func (x *SearchProductsRequest) String() string {
method ProtoMessage (line 640) | func (*SearchProductsRequest) ProtoMessage() {}
method ProtoReflect (line 642) | func (x *SearchProductsRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 655) | func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
method GetQuery (line 659) | func (x *SearchProductsRequest) GetQuery() string {
type SearchProductsResponse (line 666) | type SearchProductsResponse struct
method Reset (line 674) | func (x *SearchProductsResponse) Reset() {
method String (line 683) | func (x *SearchProductsResponse) String() string {
method ProtoMessage (line 687) | func (*SearchProductsResponse) ProtoMessage() {}
method ProtoReflect (line 689) | func (x *SearchProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 702) | func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
method GetResults (line 706) | func (x *SearchProductsResponse) GetResults() []*Product {
type GetQuoteRequest (line 713) | type GetQuoteRequest struct
method Reset (line 722) | func (x *GetQuoteRequest) Reset() {
method String (line 731) | func (x *GetQuoteRequest) String() string {
method ProtoMessage (line 735) | func (*GetQuoteRequest) ProtoMessage() {}
method ProtoReflect (line 737) | func (x *GetQuoteRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 750) | func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 754) | func (x *GetQuoteRequest) GetAddress() *Address {
method GetItems (line 761) | func (x *GetQuoteRequest) GetItems() []*CartItem {
type GetQuoteResponse (line 768) | type GetQuoteResponse struct
method Reset (line 776) | func (x *GetQuoteResponse) Reset() {
method String (line 785) | func (x *GetQuoteResponse) String() string {
method ProtoMessage (line 789) | func (*GetQuoteResponse) ProtoMessage() {}
method ProtoReflect (line 791) | func (x *GetQuoteResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 804) | func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
method GetCostUsd (line 808) | func (x *GetQuoteResponse) GetCostUsd() *Money {
type ShipOrderRequest (line 815) | type ShipOrderRequest struct
method Reset (line 824) | func (x *ShipOrderRequest) Reset() {
method String (line 833) | func (x *ShipOrderRequest) String() string {
method ProtoMessage (line 837) | func (*ShipOrderRequest) ProtoMessage() {}
method ProtoReflect (line 839) | func (x *ShipOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 852) | func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 856) | func (x *ShipOrderRequest) GetAddress() *Address {
method GetItems (line 863) | func (x *ShipOrderRequest) GetItems() []*CartItem {
type ShipOrderResponse (line 870) | type ShipOrderResponse struct
method Reset (line 878) | func (x *ShipOrderResponse) Reset() {
method String (line 887) | func (x *ShipOrderResponse) String() string {
method ProtoMessage (line 891) | func (*ShipOrderResponse) ProtoMessage() {}
method ProtoReflect (line 893) | func (x *ShipOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 906) | func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
method GetTrackingId (line 910) | func (x *ShipOrderResponse) GetTrackingId() string {
type Address (line 917) | type Address struct
method Reset (line 929) | func (x *Address) Reset() {
method String (line 938) | func (x *Address) String() string {
method ProtoMessage (line 942) | func (*Address) ProtoMessage() {}
method ProtoReflect (line 944) | func (x *Address) ProtoReflect() protoreflect.Message {
method Descriptor (line 957) | func (*Address) Descriptor() ([]byte, []int) {
method GetStreetAddress (line 961) | func (x *Address) GetStreetAddress() string {
method GetCity (line 968) | func (x *Address) GetCity() string {
method GetState (line 975) | func (x *Address) GetState() string {
method GetCountry (line 982) | func (x *Address) GetCountry() string {
method GetZipCode (line 989) | func (x *Address) GetZipCode() int32 {
type Money (line 997) | type Money struct
method Reset (line 1016) | func (x *Money) Reset() {
method String (line 1025) | func (x *Money) String() string {
method ProtoMessage (line 1029) | func (*Money) ProtoMessage() {}
method ProtoReflect (line 1031) | func (x *Money) ProtoReflect() protoreflect.Message {
method Descriptor (line 1044) | func (*Money) Descriptor() ([]byte, []int) {
method GetCurrencyCode (line 1048) | func (x *Money) GetCurrencyCode() string {
method GetUnits (line 1055) | func (x *Money) GetUnits() int64 {
method GetNanos (line 1062) | func (x *Money) GetNanos() int32 {
type GetSupportedCurrenciesResponse (line 1069) | type GetSupportedCurrenciesResponse struct
method Reset (line 1078) | func (x *GetSupportedCurrenciesResponse) Reset() {
method String (line 1087) | func (x *GetSupportedCurrenciesResponse) String() string {
method ProtoMessage (line 1091) | func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
method ProtoReflect (line 1093) | func (x *GetSupportedCurrenciesResponse) ProtoReflect() protoreflect.M...
method Descriptor (line 1106) | func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
method GetCurrencyCodes (line 1110) | func (x *GetSupportedCurrenciesResponse) GetCurrencyCodes() []string {
type CurrencyConversionRequest (line 1117) | type CurrencyConversionRequest struct
method Reset (line 1127) | func (x *CurrencyConversionRequest) Reset() {
method String (line 1136) | func (x *CurrencyConversionRequest) String() string {
method ProtoMessage (line 1140) | func (*CurrencyConversionRequest) ProtoMessage() {}
method ProtoReflect (line 1142) | func (x *CurrencyConversionRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1155) | func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
method GetFrom (line 1159) | func (x *CurrencyConversionRequest) GetFrom() *Money {
method GetToCode (line 1166) | func (x *CurrencyConversionRequest) GetToCode() string {
type CreditCardInfo (line 1173) | type CreditCardInfo struct
method Reset (line 1184) | func (x *CreditCardInfo) Reset() {
method String (line 1193) | func (x *CreditCardInfo) String() string {
method ProtoMessage (line 1197) | func (*CreditCardInfo) ProtoMessage() {}
method ProtoReflect (line 1199) | func (x *CreditCardInfo) ProtoReflect() protoreflect.Message {
method Descriptor (line 1212) | func (*CreditCardInfo) Descriptor() ([]byte, []int) {
method GetCreditCardNumber (line 1216) | func (x *CreditCardInfo) GetCreditCardNumber() string {
method GetCreditCardCvv (line 1223) | func (x *CreditCardInfo) GetCreditCardCvv() int32 {
method GetCreditCardExpirationYear (line 1230) | func (x *CreditCardInfo) GetCreditCardExpirationYear() int32 {
method GetCreditCardExpirationMonth (line 1237) | func (x *CreditCardInfo) GetCreditCardExpirationMonth() int32 {
type ChargeRequest (line 1244) | type ChargeRequest struct
method Reset (line 1253) | func (x *ChargeRequest) Reset() {
method String (line 1262) | func (x *ChargeRequest) String() string {
method ProtoMessage (line 1266) | func (*ChargeRequest) ProtoMessage() {}
method ProtoReflect (line 1268) | func (x *ChargeRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1281) | func (*ChargeRequest) Descriptor() ([]byte, []int) {
method GetAmount (line 1285) | func (x *ChargeRequest) GetAmount() *Money {
method GetCreditCard (line 1292) | func (x *ChargeRequest) GetCreditCard() *CreditCardInfo {
type ChargeResponse (line 1299) | type ChargeResponse struct
method Reset (line 1307) | func (x *ChargeResponse) Reset() {
method String (line 1316) | func (x *ChargeResponse) String() string {
method ProtoMessage (line 1320) | func (*ChargeResponse) ProtoMessage() {}
method ProtoReflect (line 1322) | func (x *ChargeResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1335) | func (*ChargeResponse) Descriptor() ([]byte, []int) {
method GetTransactionId (line 1339) | func (x *ChargeResponse) GetTransactionId() string {
type OrderItem (line 1346) | type OrderItem struct
method Reset (line 1355) | func (x *OrderItem) Reset() {
method String (line 1364) | func (x *OrderItem) String() string {
method ProtoMessage (line 1368) | func (*OrderItem) ProtoMessage() {}
method ProtoReflect (line 1370) | func (x *OrderItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 1383) | func (*OrderItem) Descriptor() ([]byte, []int) {
method GetItem (line 1387) | func (x *OrderItem) GetItem() *CartItem {
method GetCost (line 1394) | func (x *OrderItem) GetCost() *Money {
type OrderResult (line 1401) | type OrderResult struct
method Reset (line 1413) | func (x *OrderResult) Reset() {
method String (line 1422) | func (x *OrderResult) String() string {
method ProtoMessage (line 1426) | func (*OrderResult) ProtoMessage() {}
method ProtoReflect (line 1428) | func (x *OrderResult) ProtoReflect() protoreflect.Message {
method Descriptor (line 1441) | func (*OrderResult) Descriptor() ([]byte, []int) {
method GetOrderId (line 1445) | func (x *OrderResult) GetOrderId() string {
method GetShippingTrackingId (line 1452) | func (x *OrderResult) GetShippingTrackingId() string {
method GetShippingCost (line 1459) | func (x *OrderResult) GetShippingCost() *Money {
method GetShippingAddress (line 1466) | func (x *OrderResult) GetShippingAddress() *Address {
method GetItems (line 1473) | func (x *OrderResult) GetItems() []*OrderItem {
type SendOrderConfirmationRequest (line 1480) | type SendOrderConfirmationRequest struct
method Reset (line 1489) | func (x *SendOrderConfirmationRequest) Reset() {
method String (line 1498) | func (x *SendOrderConfirmationRequest) String() string {
method ProtoMessage (line 1502) | func (*SendOrderConfirmationRequest) ProtoMessage() {}
method ProtoReflect (line 1504) | func (x *SendOrderConfirmationRequest) ProtoReflect() protoreflect.Mes...
method Descriptor (line 1517) | func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
method GetEmail (line 1521) | func (x *SendOrderConfirmationRequest) GetEmail() string {
method GetOrder (line 1528) | func (x *SendOrderConfirmationRequest) GetOrder() *OrderResult {
type PlaceOrderRequest (line 1535) | type PlaceOrderRequest struct
method Reset (line 1547) | func (x *PlaceOrderRequest) Reset() {
method String (line 1556) | func (x *PlaceOrderRequest) String() string {
method ProtoMessage (line 1560) | func (*PlaceOrderRequest) ProtoMessage() {}
method ProtoReflect (line 1562) | func (x *PlaceOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1575) | func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 1579) | func (x *PlaceOrderRequest) GetUserId() string {
method GetUserCurrency (line 1586) | func (x *PlaceOrderRequest) GetUserCurrency() string {
method GetAddress (line 1593) | func (x *PlaceOrderRequest) GetAddress() *Address {
method GetEmail (line 1600) | func (x *PlaceOrderRequest) GetEmail() string {
method GetCreditCard (line 1607) | func (x *PlaceOrderRequest) GetCreditCard() *CreditCardInfo {
type PlaceOrderResponse (line 1614) | type PlaceOrderResponse struct
method Reset (line 1622) | func (x *PlaceOrderResponse) Reset() {
method String (line 1631) | func (x *PlaceOrderResponse) String() string {
method ProtoMessage (line 1635) | func (*PlaceOrderResponse) ProtoMessage() {}
method ProtoReflect (line 1637) | func (x *PlaceOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1650) | func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
method GetOrder (line 1654) | func (x *PlaceOrderResponse) GetOrder() *OrderResult {
type AdRequest (line 1661) | type AdRequest struct
method Reset (line 1670) | func (x *AdRequest) Reset() {
method String (line 1679) | func (x *AdRequest) String() string {
method ProtoMessage (line 1683) | func (*AdRequest) ProtoMessage() {}
method ProtoReflect (line 1685) | func (x *AdRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1698) | func (*AdRequest) Descriptor() ([]byte, []int) {
method GetContextKeys (line 1702) | func (x *AdRequest) GetContextKeys() []string {
type AdResponse (line 1709) | type AdResponse struct
method Reset (line 1717) | func (x *AdResponse) Reset() {
method String (line 1726) | func (x *AdResponse) String() string {
method ProtoMessage (line 1730) | func (*AdResponse) ProtoMessage() {}
method ProtoReflect (line 1732) | func (x *AdResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1745) | func (*AdResponse) Descriptor() ([]byte, []int) {
method GetAds (line 1749) | func (x *AdResponse) GetAds() []*Ad {
type Ad (line 1756) | type Ad struct
method Reset (line 1767) | func (x *Ad) Reset() {
method String (line 1776) | func (x *Ad) String() string {
method ProtoMessage (line 1780) | func (*Ad) ProtoMessage() {}
method ProtoReflect (line 1782) | func (x *Ad) ProtoReflect() protoreflect.Message {
method Descriptor (line 1795) | func (*Ad) Descriptor() ([]byte, []int) {
method GetRedirectUrl (line 1799) | func (x *Ad) GetRedirectUrl() string {
method GetText (line 1806) | func (x *Ad) GetText() string {
function file_demo_proto_rawDescGZIP (line 2098) | func file_demo_proto_rawDescGZIP() []byte {
function init (line 2201) | func init() { file_demo_proto_init() }
function file_demo_proto_init (line 2202) | func file_demo_proto_init() {
FILE: src/productcatalogservice/genproto/demo_grpc.pb.go
constant _ (line 33) | _ = grpc.SupportPackageIsVersion9
constant CartService_AddItem_FullMethodName (line 36) | CartService_AddItem_FullMethodName = "/hipstershop.CartService/AddItem"
constant CartService_GetCart_FullMethodName (line 37) | CartService_GetCart_FullMethodName = "/hipstershop.CartService/GetCart"
constant CartService_EmptyCart_FullMethodName (line 38) | CartService_EmptyCart_FullMethodName = "/hipstershop.CartService/EmptyCart"
type CartServiceClient (line 44) | type CartServiceClient interface
type cartServiceClient (line 50) | type cartServiceClient struct
method AddItem (line 58) | func (c *cartServiceClient) AddItem(ctx context.Context, in *AddItemRe...
method GetCart (line 68) | func (c *cartServiceClient) GetCart(ctx context.Context, in *GetCartRe...
method EmptyCart (line 78) | func (c *cartServiceClient) EmptyCart(ctx context.Context, in *EmptyCa...
function NewCartServiceClient (line 54) | func NewCartServiceClient(cc grpc.ClientConnInterface) CartServiceClient {
type CartServiceServer (line 91) | type CartServiceServer interface
type UnimplementedCartServiceServer (line 103) | type UnimplementedCartServiceServer struct
method AddItem (line 105) | func (UnimplementedCartServiceServer) AddItem(context.Context, *AddIte...
method GetCart (line 108) | func (UnimplementedCartServiceServer) GetCart(context.Context, *GetCar...
method EmptyCart (line 111) | func (UnimplementedCartServiceServer) EmptyCart(context.Context, *Empt...
method mustEmbedUnimplementedCartServiceServer (line 114) | func (UnimplementedCartServiceServer) mustEmbedUnimplementedCartServic...
method testEmbeddedByValue (line 115) | func (UnimplementedCartServiceServer) testEmbeddedByValue() ...
type UnsafeCartServiceServer (line 120) | type UnsafeCartServiceServer interface
function RegisterCartServiceServer (line 124) | func RegisterCartServiceServer(s grpc.ServiceRegistrar, srv CartServiceS...
function _CartService_AddItem_Handler (line 135) | func _CartService_AddItem_Handler(srv interface{}, ctx context.Context, ...
function _CartService_GetCart_Handler (line 153) | func _CartService_GetCart_Handler(srv interface{}, ctx context.Context, ...
function _CartService_EmptyCart_Handler (line 171) | func _CartService_EmptyCart_Handler(srv interface{}, ctx context.Context...
constant RecommendationService_ListRecommendations_FullMethodName (line 214) | RecommendationService_ListRecommendations_FullMethodName = "/hipstershop...
type RecommendationServiceClient (line 220) | type RecommendationServiceClient interface
type recommendationServiceClient (line 224) | type recommendationServiceClient struct
method ListRecommendations (line 232) | func (c *recommendationServiceClient) ListRecommendations(ctx context....
function NewRecommendationServiceClient (line 228) | func NewRecommendationServiceClient(cc grpc.ClientConnInterface) Recomme...
type RecommendationServiceServer (line 245) | type RecommendationServiceServer interface
type UnimplementedRecommendationServiceServer (line 255) | type UnimplementedRecommendationServiceServer struct
method ListRecommendations (line 257) | func (UnimplementedRecommendationServiceServer) ListRecommendations(co...
method mustEmbedUnimplementedRecommendationServiceServer (line 260) | func (UnimplementedRecommendationServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 261) | func (UnimplementedRecommendationServiceServer) testEmbeddedByValue() ...
type UnsafeRecommendationServiceServer (line 266) | type UnsafeRecommendationServiceServer interface
function RegisterRecommendationServiceServer (line 270) | func RegisterRecommendationServiceServer(s grpc.ServiceRegistrar, srv Re...
function _RecommendationService_ListRecommendations_Handler (line 281) | func _RecommendationService_ListRecommendations_Handler(srv interface{},...
constant ProductCatalogService_ListProducts_FullMethodName (line 316) | ProductCatalogService_ListProducts_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_GetProduct_FullMethodName (line 317) | ProductCatalogService_GetProduct_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_SearchProducts_FullMethodName (line 318) | ProductCatalogService_SearchProducts_FullMethodName = "/hipstershop.Prod...
type ProductCatalogServiceClient (line 324) | type ProductCatalogServiceClient interface
type productCatalogServiceClient (line 330) | type productCatalogServiceClient struct
method ListProducts (line 338) | func (c *productCatalogServiceClient) ListProducts(ctx context.Context...
method GetProduct (line 348) | func (c *productCatalogServiceClient) GetProduct(ctx context.Context, ...
method SearchProducts (line 358) | func (c *productCatalogServiceClient) SearchProducts(ctx context.Conte...
function NewProductCatalogServiceClient (line 334) | func NewProductCatalogServiceClient(cc grpc.ClientConnInterface) Product...
type ProductCatalogServiceServer (line 371) | type ProductCatalogServiceServer interface
type UnimplementedProductCatalogServiceServer (line 383) | type UnimplementedProductCatalogServiceServer struct
method ListProducts (line 385) | func (UnimplementedProductCatalogServiceServer) ListProducts(context.C...
method GetProduct (line 388) | func (UnimplementedProductCatalogServiceServer) GetProduct(context.Con...
method SearchProducts (line 391) | func (UnimplementedProductCatalogServiceServer) SearchProducts(context...
method mustEmbedUnimplementedProductCatalogServiceServer (line 394) | func (UnimplementedProductCatalogServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 395) | func (UnimplementedProductCatalogServiceServer) testEmbeddedByValue() ...
type UnsafeProductCatalogServiceServer (line 400) | type UnsafeProductCatalogServiceServer interface
function RegisterProductCatalogServiceServer (line 404) | func RegisterProductCatalogServiceServer(s grpc.ServiceRegistrar, srv Pr...
function _ProductCatalogService_ListProducts_Handler (line 415) | func _ProductCatalogService_ListProducts_Handler(srv interface{}, ctx co...
function _ProductCatalogService_GetProduct_Handler (line 433) | func _ProductCatalogService_GetProduct_Handler(srv interface{}, ctx cont...
function _ProductCatalogService_SearchProducts_Handler (line 451) | func _ProductCatalogService_SearchProducts_Handler(srv interface{}, ctx ...
constant ShippingService_GetQuote_FullMethodName (line 494) | ShippingService_GetQuote_FullMethodName = "/hipstershop.ShippingService...
constant ShippingService_ShipOrder_FullMethodName (line 495) | ShippingService_ShipOrder_FullMethodName = "/hipstershop.ShippingService...
type ShippingServiceClient (line 501) | type ShippingServiceClient interface
type shippingServiceClient (line 506) | type shippingServiceClient struct
method GetQuote (line 514) | func (c *shippingServiceClient) GetQuote(ctx context.Context, in *GetQ...
method ShipOrder (line 524) | func (c *shippingServiceClient) ShipOrder(ctx context.Context, in *Shi...
function NewShippingServiceClient (line 510) | func NewShippingServiceClient(cc grpc.ClientConnInterface) ShippingServi...
type ShippingServiceServer (line 537) | type ShippingServiceServer interface
type UnimplementedShippingServiceServer (line 548) | type UnimplementedShippingServiceServer struct
method GetQuote (line 550) | func (UnimplementedShippingServiceServer) GetQuote(context.Context, *G...
method ShipOrder (line 553) | func (UnimplementedShippingServiceServer) ShipOrder(context.Context, *...
method mustEmbedUnimplementedShippingServiceServer (line 556) | func (UnimplementedShippingServiceServer) mustEmbedUnimplementedShippi...
method testEmbeddedByValue (line 557) | func (UnimplementedShippingServiceServer) testEmbeddedByValue() ...
type UnsafeShippingServiceServer (line 562) | type UnsafeShippingServiceServer interface
function RegisterShippingServiceServer (line 566) | func RegisterShippingServiceServer(s grpc.ServiceRegistrar, srv Shipping...
function _ShippingService_GetQuote_Handler (line 577) | func _ShippingService_GetQuote_Handler(srv interface{}, ctx context.Cont...
function _ShippingService_ShipOrder_Handler (line 595) | func _ShippingService_ShipOrder_Handler(srv interface{}, ctx context.Con...
constant CurrencyService_GetSupportedCurrencies_FullMethodName (line 634) | CurrencyService_GetSupportedCurrencies_FullMethodName = "/hipstershop.Cu...
constant CurrencyService_Convert_FullMethodName (line 635) | CurrencyService_Convert_FullMethodName = "/hipstershop.Cu...
type CurrencyServiceClient (line 641) | type CurrencyServiceClient interface
type currencyServiceClient (line 646) | type currencyServiceClient struct
method GetSupportedCurrencies (line 654) | func (c *currencyServiceClient) GetSupportedCurrencies(ctx context.Con...
method Convert (line 664) | func (c *currencyServiceClient) Convert(ctx context.Context, in *Curre...
function NewCurrencyServiceClient (line 650) | func NewCurrencyServiceClient(cc grpc.ClientConnInterface) CurrencyServi...
type CurrencyServiceServer (line 677) | type CurrencyServiceServer interface
type UnimplementedCurrencyServiceServer (line 688) | type UnimplementedCurrencyServiceServer struct
method GetSupportedCurrencies (line 690) | func (UnimplementedCurrencyServiceServer) GetSupportedCurrencies(conte...
method Convert (line 693) | func (UnimplementedCurrencyServiceServer) Convert(context.Context, *Cu...
method mustEmbedUnimplementedCurrencyServiceServer (line 696) | func (UnimplementedCurrencyServiceServer) mustEmbedUnimplementedCurren...
method testEmbeddedByValue (line 697) | func (UnimplementedCurrencyServiceServer) testEmbeddedByValue() ...
type UnsafeCurrencyServiceServer (line 702) | type UnsafeCurrencyServiceServer interface
function RegisterCurrencyServiceServer (line 706) | func RegisterCurrencyServiceServer(s grpc.ServiceRegistrar, srv Currency...
function _CurrencyService_GetSupportedCurrencies_Handler (line 717) | func _CurrencyService_GetSupportedCurrencies_Handler(srv interface{}, ct...
function _CurrencyService_Convert_Handler (line 735) | func _CurrencyService_Convert_Handler(srv interface{}, ctx context.Conte...
constant PaymentService_Charge_FullMethodName (line 774) | PaymentService_Charge_FullMethodName = "/hipstershop.PaymentService/Charge"
type PaymentServiceClient (line 780) | type PaymentServiceClient interface
type paymentServiceClient (line 784) | type paymentServiceClient struct
method Charge (line 792) | func (c *paymentServiceClient) Charge(ctx context.Context, in *ChargeR...
function NewPaymentServiceClient (line 788) | func NewPaymentServiceClient(cc grpc.ClientConnInterface) PaymentService...
type PaymentServiceServer (line 805) | type PaymentServiceServer interface
type UnimplementedPaymentServiceServer (line 815) | type UnimplementedPaymentServiceServer struct
method Charge (line 817) | func (UnimplementedPaymentServiceServer) Charge(context.Context, *Char...
method mustEmbedUnimplementedPaymentServiceServer (line 820) | func (UnimplementedPaymentServiceServer) mustEmbedUnimplementedPayment...
method testEmbeddedByValue (line 821) | func (UnimplementedPaymentServiceServer) testEmbeddedByValue() ...
type UnsafePaymentServiceServer (line 826) | type UnsafePaymentServiceServer interface
function RegisterPaymentServiceServer (line 830) | func RegisterPaymentServiceServer(s grpc.ServiceRegistrar, srv PaymentSe...
function _PaymentService_Charge_Handler (line 841) | func _PaymentService_Charge_Handler(srv interface{}, ctx context.Context...
constant EmailService_SendOrderConfirmation_FullMethodName (line 876) | EmailService_SendOrderConfirmation_FullMethodName = "/hipstershop.EmailS...
type EmailServiceClient (line 882) | type EmailServiceClient interface
type emailServiceClient (line 886) | type emailServiceClient struct
method SendOrderConfirmation (line 894) | func (c *emailServiceClient) SendOrderConfirmation(ctx context.Context...
function NewEmailServiceClient (line 890) | func NewEmailServiceClient(cc grpc.ClientConnInterface) EmailServiceClie...
type EmailServiceServer (line 907) | type EmailServiceServer interface
type UnimplementedEmailServiceServer (line 917) | type UnimplementedEmailServiceServer struct
method SendOrderConfirmation (line 919) | func (UnimplementedEmailServiceServer) SendOrderConfirmation(context.C...
method mustEmbedUnimplementedEmailServiceServer (line 922) | func (UnimplementedEmailServiceServer) mustEmbedUnimplementedEmailServ...
method testEmbeddedByValue (line 923) | func (UnimplementedEmailServiceServer) testEmbeddedByValue() ...
type UnsafeEmailServiceServer (line 928) | type UnsafeEmailServiceServer interface
function RegisterEmailServiceServer (line 932) | func RegisterEmailServiceServer(s grpc.ServiceRegistrar, srv EmailServic...
function _EmailService_SendOrderConfirmation_Handler (line 943) | func _EmailService_SendOrderConfirmation_Handler(srv interface{}, ctx co...
constant CheckoutService_PlaceOrder_FullMethodName (line 978) | CheckoutService_PlaceOrder_FullMethodName = "/hipstershop.CheckoutServic...
type CheckoutServiceClient (line 984) | type CheckoutServiceClient interface
type checkoutServiceClient (line 988) | type checkoutServiceClient struct
method PlaceOrder (line 996) | func (c *checkoutServiceClient) PlaceOrder(ctx context.Context, in *Pl...
function NewCheckoutServiceClient (line 992) | func NewCheckoutServiceClient(cc grpc.ClientConnInterface) CheckoutServi...
type CheckoutServiceServer (line 1009) | type CheckoutServiceServer interface
type UnimplementedCheckoutServiceServer (line 1019) | type UnimplementedCheckoutServiceServer struct
method PlaceOrder (line 1021) | func (UnimplementedCheckoutServiceServer) PlaceOrder(context.Context, ...
method mustEmbedUnimplementedCheckoutServiceServer (line 1024) | func (UnimplementedCheckoutServiceServer) mustEmbedUnimplementedChecko...
method testEmbeddedByValue (line 1025) | func (UnimplementedCheckoutServiceServer) testEmbeddedByValue() ...
type UnsafeCheckoutServiceServer (line 1030) | type UnsafeCheckoutServiceServer interface
function RegisterCheckoutServiceServer (line 1034) | func RegisterCheckoutServiceServer(s grpc.ServiceRegistrar, srv Checkout...
function _CheckoutService_PlaceOrder_Handler (line 1045) | func _CheckoutService_PlaceOrder_Handler(srv interface{}, ctx context.Co...
constant AdService_GetAds_FullMethodName (line 1080) | AdService_GetAds_FullMethodName = "/hipstershop.AdService/GetAds"
type AdServiceClient (line 1086) | type AdServiceClient interface
type adServiceClient (line 1090) | type adServiceClient struct
method GetAds (line 1098) | func (c *adServiceClient) GetAds(ctx context.Context, in *AdRequest, o...
function NewAdServiceClient (line 1094) | func NewAdServiceClient(cc grpc.ClientConnInterface) AdServiceClient {
type AdServiceServer (line 1111) | type AdServiceServer interface
type UnimplementedAdServiceServer (line 1121) | type UnimplementedAdServiceServer struct
method GetAds (line 1123) | func (UnimplementedAdServiceServer) GetAds(context.Context, *AdRequest...
method mustEmbedUnimplementedAdServiceServer (line 1126) | func (UnimplementedAdServiceServer) mustEmbedUnimplementedAdServiceSer...
method testEmbeddedByValue (line 1127) | func (UnimplementedAdServiceServer) testEmbeddedByValue() ...
type UnsafeAdServiceServer (line 1132) | type UnsafeAdServiceServer interface
function RegisterAdServiceServer (line 1136) | func RegisterAdServiceServer(s grpc.ServiceRegistrar, srv AdServiceServe...
function _AdService_GetAds_Handler (line 1147) | func _AdService_GetAds_Handler(srv interface{}, ctx context.Context, dec...
FILE: src/productcatalogservice/product_catalog.go
type productCatalog (line 28) | type productCatalog struct
method Check (line 33) | func (p *productCatalog) Check(ctx context.Context, req *healthpb.Heal...
method Watch (line 37) | func (p *productCatalog) Watch(req *healthpb.HealthCheckRequest, ws he...
method ListProducts (line 41) | func (p *productCatalog) ListProducts(context.Context, *pb.Empty) (*pb...
method GetProduct (line 47) | func (p *productCatalog) GetProduct(ctx context.Context, req *pb.GetPr...
method SearchProducts (line 63) | func (p *productCatalog) SearchProducts(ctx context.Context, req *pb.S...
method parseCatalog (line 77) | func (p *productCatalog) parseCatalog() []*pb.Product {
FILE: src/productcatalogservice/product_catalog_test.go
function TestMain (line 31) | func TestMain(m *testing.M) {
function TestGetProductExists (line 58) | func TestGetProductExists(t *testing.T) {
function TestGetProductNotFound (line 70) | func TestGetProductNotFound(t *testing.T) {
function TestListProducts (line 79) | func TestListProducts(t *testing.T) {
function TestSearchProducts (line 91) | func TestSearchProducts(t *testing.T) {
FILE: src/productcatalogservice/server.go
function init (line 54) | func init() {
function main (line 68) | func main() {
function run (line 123) | func run(port string) string {
function initStats (line 151) | func initStats() {
function initTracing (line 155) | func initTracing() error {
function initProfiling (line 179) | func initProfiling(service, version string) {
function mustMapEnv (line 199) | func mustMapEnv(target *string, envKey string) {
function mustConnGRPC (line 207) | func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr stri...
FILE: src/recommendationservice/demo_pb2_grpc.py
class CartServiceStub (line 24) | class CartServiceStub(object):
method __init__ (line 29) | def __init__(self, channel):
class CartServiceServicer (line 52) | class CartServiceServicer(object):
method AddItem (line 57) | def AddItem(self, request, context):
method GetCart (line 63) | def GetCart(self, request, context):
method EmptyCart (line 69) | def EmptyCart(self, request, context):
function add_CartServiceServicer_to_server (line 76) | def add_CartServiceServicer_to_server(servicer, server):
class CartService (line 100) | class CartService(object):
method AddItem (line 106) | def AddItem(request,
method GetCart (line 123) | def GetCart(request,
method EmptyCart (line 140) | def EmptyCart(request,
class RecommendationServiceStub (line 157) | class RecommendationServiceStub(object):
method __init__ (line 162) | def __init__(self, channel):
class RecommendationServiceServicer (line 175) | class RecommendationServiceServicer(object):
method ListRecommendations (line 180) | def ListRecommendations(self, request, context):
function add_RecommendationServiceServicer_to_server (line 187) | def add_RecommendationServiceServicer_to_server(servicer, server):
class RecommendationService (line 201) | class RecommendationService(object):
method ListRecommendations (line 207) | def ListRecommendations(request,
class ProductCatalogServiceStub (line 224) | class ProductCatalogServiceStub(object):
method __init__ (line 229) | def __init__(self, channel):
class ProductCatalogServiceServicer (line 252) | class ProductCatalogServiceServicer(object):
method ListProducts (line 257) | def ListProducts(self, request, context):
method GetProduct (line 263) | def GetProduct(self, request, context):
method SearchProducts (line 269) | def SearchProducts(self, request, context):
function add_ProductCatalogServiceServicer_to_server (line 276) | def add_ProductCatalogServiceServicer_to_server(servicer, server):
class ProductCatalogService (line 300) | class ProductCatalogService(object):
method ListProducts (line 306) | def ListProducts(request,
method GetProduct (line 323) | def GetProduct(request,
method SearchProducts (line 340) | def SearchProducts(request,
class ShippingServiceStub (line 357) | class ShippingServiceStub(object):
method __init__ (line 362) | def __init__(self, channel):
class ShippingServiceServicer (line 380) | class ShippingServiceServicer(object):
method GetQuote (line 385) | def GetQuote(self, request, context):
method ShipOrder (line 391) | def ShipOrder(self, request, context):
function add_ShippingServiceServicer_to_server (line 398) | def add_ShippingServiceServicer_to_server(servicer, server):
class ShippingService (line 417) | class ShippingService(object):
method GetQuote (line 423) | def GetQuote(request,
method ShipOrder (line 440) | def ShipOrder(request,
class CurrencyServiceStub (line 457) | class CurrencyServiceStub(object):
method __init__ (line 462) | def __init__(self, channel):
class CurrencyServiceServicer (line 480) | class CurrencyServiceServicer(object):
method GetSupportedCurrencies (line 485) | def GetSupportedCurrencies(self, request, context):
method Convert (line 491) | def Convert(self, request, context):
function add_CurrencyServiceServicer_to_server (line 498) | def add_CurrencyServiceServicer_to_server(servicer, server):
class CurrencyService (line 517) | class CurrencyService(object):
method GetSupportedCurrencies (line 523) | def GetSupportedCurrencies(request,
method Convert (line 540) | def Convert(request,
class PaymentServiceStub (line 557) | class PaymentServiceStub(object):
method __init__ (line 562) | def __init__(self, channel):
class PaymentServiceServicer (line 575) | class PaymentServiceServicer(object):
method Charge (line 580) | def Charge(self, request, context):
function add_PaymentServiceServicer_to_server (line 587) | def add_PaymentServiceServicer_to_server(servicer, server):
class PaymentService (line 601) | class PaymentService(object):
method Charge (line 607) | def Charge(request,
class EmailServiceStub (line 624) | class EmailServiceStub(object):
method __init__ (line 629) | def __init__(self, channel):
class EmailServiceServicer (line 642) | class EmailServiceServicer(object):
method SendOrderConfirmation (line 647) | def SendOrderConfirmation(self, request, context):
function add_EmailServiceServicer_to_server (line 654) | def add_EmailServiceServicer_to_server(servicer, server):
class EmailService (line 668) | class EmailService(object):
method SendOrderConfirmation (line 674) | def SendOrderConfirmation(request,
class CheckoutServiceStub (line 691) | class CheckoutServiceStub(object):
method __init__ (line 696) | def __init__(self, channel):
class CheckoutServiceServicer (line 709) | class CheckoutServiceServicer(object):
method PlaceOrder (line 714) | def PlaceOrder(self, request, context):
function add_CheckoutServiceServicer_to_server (line 721) | def add_CheckoutServiceServicer_to_server(servicer, server):
class CheckoutService (line 735) | class CheckoutService(object):
method PlaceOrder (line 741) | def PlaceOrder(request,
class AdServiceStub (line 758) | class AdServiceStub(object):
method __init__ (line 763) | def __init__(self, channel):
class AdServiceServicer (line 776) | class AdServiceServicer(object):
method GetAds (line 781) | def GetAds(self, request, context):
function add_AdServiceServicer_to_server (line 788) | def add_AdServiceServicer_to_server(servicer, server):
class AdService (line 802) | class AdService(object):
method GetAds (line 808) | def GetAds(request,
FILE: src/recommendationservice/logger.py
class CustomJsonFormatter (line 23) | class CustomJsonFormatter(jsonlogger.JsonFormatter):
method add_fields (line 24) | def add_fields(self, log_record, record, message_dict):
function getJSONLogger (line 33) | def getJSONLogger(name):
FILE: src/recommendationservice/recommendation_server.py
function initStackdriverProfiling (line 43) | def initStackdriverProfiling():
class RecommendationService (line 69) | class RecommendationService(demo_pb2_grpc.RecommendationServiceServicer):
method ListRecommendations (line 70) | def ListRecommendations(self, request, context):
method Check (line 88) | def Check(self, request, context):
method Watch (line 92) | def Watch(self, request, context):
FILE: src/shippingservice/genproto/demo.pb.go
constant _ (line 32) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 34) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type CartItem (line 37) | type CartItem struct
method Reset (line 46) | func (x *CartItem) Reset() {
method String (line 55) | func (x *CartItem) String() string {
method ProtoMessage (line 59) | func (*CartItem) ProtoMessage() {}
method ProtoReflect (line 61) | func (x *CartItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 74) | func (*CartItem) Descriptor() ([]byte, []int) {
method GetProductId (line 78) | func (x *CartItem) GetProductId() string {
method GetQuantity (line 85) | func (x *CartItem) GetQuantity() int32 {
type AddItemRequest (line 92) | type AddItemRequest struct
method Reset (line 101) | func (x *AddItemRequest) Reset() {
method String (line 110) | func (x *AddItemRequest) String() string {
method ProtoMessage (line 114) | func (*AddItemRequest) ProtoMessage() {}
method ProtoReflect (line 116) | func (x *AddItemRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 129) | func (*AddItemRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 133) | func (x *AddItemRequest) GetUserId() string {
method GetItem (line 140) | func (x *AddItemRequest) GetItem() *CartItem {
type EmptyCartRequest (line 147) | type EmptyCartRequest struct
method Reset (line 155) | func (x *EmptyCartRequest) Reset() {
method String (line 164) | func (x *EmptyCartRequest) String() string {
method ProtoMessage (line 168) | func (*EmptyCartRequest) ProtoMessage() {}
method ProtoReflect (line 170) | func (x *EmptyCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 183) | func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 187) | func (x *EmptyCartRequest) GetUserId() string {
type GetCartRequest (line 194) | type GetCartRequest struct
method Reset (line 202) | func (x *GetCartRequest) Reset() {
method String (line 211) | func (x *GetCartRequest) String() string {
method ProtoMessage (line 215) | func (*GetCartRequest) ProtoMessage() {}
method ProtoReflect (line 217) | func (x *GetCartRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 230) | func (*GetCartRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 234) | func (x *GetCartRequest) GetUserId() string {
type Cart (line 241) | type Cart struct
method Reset (line 250) | func (x *Cart) Reset() {
method String (line 259) | func (x *Cart) String() string {
method ProtoMessage (line 263) | func (*Cart) ProtoMessage() {}
method ProtoReflect (line 265) | func (x *Cart) ProtoReflect() protoreflect.Message {
method Descriptor (line 278) | func (*Cart) Descriptor() ([]byte, []int) {
method GetUserId (line 282) | func (x *Cart) GetUserId() string {
method GetItems (line 289) | func (x *Cart) GetItems() []*CartItem {
type Empty (line 296) | type Empty struct
method Reset (line 302) | func (x *Empty) Reset() {
method String (line 311) | func (x *Empty) String() string {
method ProtoMessage (line 315) | func (*Empty) ProtoMessage() {}
method ProtoReflect (line 317) | func (x *Empty) ProtoReflect() protoreflect.Message {
method Descriptor (line 330) | func (*Empty) Descriptor() ([]byte, []int) {
type ListRecommendationsRequest (line 334) | type ListRecommendationsRequest struct
method Reset (line 343) | func (x *ListRecommendationsRequest) Reset() {
method String (line 352) | func (x *ListRecommendationsRequest) String() string {
method ProtoMessage (line 356) | func (*ListRecommendationsRequest) ProtoMessage() {}
method ProtoReflect (line 358) | func (x *ListRecommendationsRequest) ProtoReflect() protoreflect.Messa...
method Descriptor (line 371) | func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 375) | func (x *ListRecommendationsRequest) GetUserId() string {
method GetProductIds (line 382) | func (x *ListRecommendationsRequest) GetProductIds() []string {
type ListRecommendationsResponse (line 389) | type ListRecommendationsResponse struct
method Reset (line 397) | func (x *ListRecommendationsResponse) Reset() {
method String (line 406) | func (x *ListRecommendationsResponse) String() string {
method ProtoMessage (line 410) | func (*ListRecommendationsResponse) ProtoMessage() {}
method ProtoReflect (line 412) | func (x *ListRecommendationsResponse) ProtoReflect() protoreflect.Mess...
method Descriptor (line 425) | func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
method GetProductIds (line 429) | func (x *ListRecommendationsResponse) GetProductIds() []string {
type Product (line 436) | type Product struct
method Reset (line 451) | func (x *Product) Reset() {
method String (line 460) | func (x *Product) String() string {
method ProtoMessage (line 464) | func (*Product) ProtoMessage() {}
method ProtoReflect (line 466) | func (x *Product) ProtoReflect() protoreflect.Message {
method Descriptor (line 479) | func (*Product) Descriptor() ([]byte, []int) {
method GetId (line 483) | func (x *Product) GetId() string {
method GetName (line 490) | func (x *Product) GetName() string {
method GetDescription (line 497) | func (x *Product) GetDescription() string {
method GetPicture (line 504) | func (x *Product) GetPicture() string {
method GetPriceUsd (line 511) | func (x *Product) GetPriceUsd() *Money {
method GetCategories (line 518) | func (x *Product) GetCategories() []string {
type ListProductsResponse (line 525) | type ListProductsResponse struct
method Reset (line 533) | func (x *ListProductsResponse) Reset() {
method String (line 542) | func (x *ListProductsResponse) String() string {
method ProtoMessage (line 546) | func (*ListProductsResponse) ProtoMessage() {}
method ProtoReflect (line 548) | func (x *ListProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 561) | func (*ListProductsResponse) Descriptor() ([]byte, []int) {
method GetProducts (line 565) | func (x *ListProductsResponse) GetProducts() []*Product {
type GetProductRequest (line 572) | type GetProductRequest struct
method Reset (line 580) | func (x *GetProductRequest) Reset() {
method String (line 589) | func (x *GetProductRequest) String() string {
method ProtoMessage (line 593) | func (*GetProductRequest) ProtoMessage() {}
method ProtoReflect (line 595) | func (x *GetProductRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 608) | func (*GetProductRequest) Descriptor() ([]byte, []int) {
method GetId (line 612) | func (x *GetProductRequest) GetId() string {
type SearchProductsRequest (line 619) | type SearchProductsRequest struct
method Reset (line 627) | func (x *SearchProductsRequest) Reset() {
method String (line 636) | func (x *SearchProductsRequest) String() string {
method ProtoMessage (line 640) | func (*SearchProductsRequest) ProtoMessage() {}
method ProtoReflect (line 642) | func (x *SearchProductsRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 655) | func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
method GetQuery (line 659) | func (x *SearchProductsRequest) GetQuery() string {
type SearchProductsResponse (line 666) | type SearchProductsResponse struct
method Reset (line 674) | func (x *SearchProductsResponse) Reset() {
method String (line 683) | func (x *SearchProductsResponse) String() string {
method ProtoMessage (line 687) | func (*SearchProductsResponse) ProtoMessage() {}
method ProtoReflect (line 689) | func (x *SearchProductsResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 702) | func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
method GetResults (line 706) | func (x *SearchProductsResponse) GetResults() []*Product {
type GetQuoteRequest (line 713) | type GetQuoteRequest struct
method Reset (line 722) | func (x *GetQuoteRequest) Reset() {
method String (line 731) | func (x *GetQuoteRequest) String() string {
method ProtoMessage (line 735) | func (*GetQuoteRequest) ProtoMessage() {}
method ProtoReflect (line 737) | func (x *GetQuoteRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 750) | func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 754) | func (x *GetQuoteRequest) GetAddress() *Address {
method GetItems (line 761) | func (x *GetQuoteRequest) GetItems() []*CartItem {
type GetQuoteResponse (line 768) | type GetQuoteResponse struct
method Reset (line 776) | func (x *GetQuoteResponse) Reset() {
method String (line 785) | func (x *GetQuoteResponse) String() string {
method ProtoMessage (line 789) | func (*GetQuoteResponse) ProtoMessage() {}
method ProtoReflect (line 791) | func (x *GetQuoteResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 804) | func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
method GetCostUsd (line 808) | func (x *GetQuoteResponse) GetCostUsd() *Money {
type ShipOrderRequest (line 815) | type ShipOrderRequest struct
method Reset (line 824) | func (x *ShipOrderRequest) Reset() {
method String (line 833) | func (x *ShipOrderRequest) String() string {
method ProtoMessage (line 837) | func (*ShipOrderRequest) ProtoMessage() {}
method ProtoReflect (line 839) | func (x *ShipOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 852) | func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
method GetAddress (line 856) | func (x *ShipOrderRequest) GetAddress() *Address {
method GetItems (line 863) | func (x *ShipOrderRequest) GetItems() []*CartItem {
type ShipOrderResponse (line 870) | type ShipOrderResponse struct
method Reset (line 878) | func (x *ShipOrderResponse) Reset() {
method String (line 887) | func (x *ShipOrderResponse) String() string {
method ProtoMessage (line 891) | func (*ShipOrderResponse) ProtoMessage() {}
method ProtoReflect (line 893) | func (x *ShipOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 906) | func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
method GetTrackingId (line 910) | func (x *ShipOrderResponse) GetTrackingId() string {
type Address (line 917) | type Address struct
method Reset (line 929) | func (x *Address) Reset() {
method String (line 938) | func (x *Address) String() string {
method ProtoMessage (line 942) | func (*Address) ProtoMessage() {}
method ProtoReflect (line 944) | func (x *Address) ProtoReflect() protoreflect.Message {
method Descriptor (line 957) | func (*Address) Descriptor() ([]byte, []int) {
method GetStreetAddress (line 961) | func (x *Address) GetStreetAddress() string {
method GetCity (line 968) | func (x *Address) GetCity() string {
method GetState (line 975) | func (x *Address) GetState() string {
method GetCountry (line 982) | func (x *Address) GetCountry() string {
method GetZipCode (line 989) | func (x *Address) GetZipCode() int32 {
type Money (line 997) | type Money struct
method Reset (line 1016) | func (x *Money) Reset() {
method String (line 1025) | func (x *Money) String() string {
method ProtoMessage (line 1029) | func (*Money) ProtoMessage() {}
method ProtoReflect (line 1031) | func (x *Money) ProtoReflect() protoreflect.Message {
method Descriptor (line 1044) | func (*Money) Descriptor() ([]byte, []int) {
method GetCurrencyCode (line 1048) | func (x *Money) GetCurrencyCode() string {
method GetUnits (line 1055) | func (x *Money) GetUnits() int64 {
method GetNanos (line 1062) | func (x *Money) GetNanos() int32 {
type GetSupportedCurrenciesResponse (line 1069) | type GetSupportedCurrenciesResponse struct
method Reset (line 1078) | func (x *GetSupportedCurrenciesResponse) Reset() {
method String (line 1087) | func (x *GetSupportedCurrenciesResponse) String() string {
method ProtoMessage (line 1091) | func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
method ProtoReflect (line 1093) | func (x *GetSupportedCurrenciesResponse) ProtoReflect() protoreflect.M...
method Descriptor (line 1106) | func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
method GetCurrencyCodes (line 1110) | func (x *GetSupportedCurrenciesResponse) GetCurrencyCodes() []string {
type CurrencyConversionRequest (line 1117) | type CurrencyConversionRequest struct
method Reset (line 1127) | func (x *CurrencyConversionRequest) Reset() {
method String (line 1136) | func (x *CurrencyConversionRequest) String() string {
method ProtoMessage (line 1140) | func (*CurrencyConversionRequest) ProtoMessage() {}
method ProtoReflect (line 1142) | func (x *CurrencyConversionRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1155) | func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
method GetFrom (line 1159) | func (x *CurrencyConversionRequest) GetFrom() *Money {
method GetToCode (line 1166) | func (x *CurrencyConversionRequest) GetToCode() string {
type CreditCardInfo (line 1173) | type CreditCardInfo struct
method Reset (line 1184) | func (x *CreditCardInfo) Reset() {
method String (line 1193) | func (x *CreditCardInfo) String() string {
method ProtoMessage (line 1197) | func (*CreditCardInfo) ProtoMessage() {}
method ProtoReflect (line 1199) | func (x *CreditCardInfo) ProtoReflect() protoreflect.Message {
method Descriptor (line 1212) | func (*CreditCardInfo) Descriptor() ([]byte, []int) {
method GetCreditCardNumber (line 1216) | func (x *CreditCardInfo) GetCreditCardNumber() string {
method GetCreditCardCvv (line 1223) | func (x *CreditCardInfo) GetCreditCardCvv() int32 {
method GetCreditCardExpirationYear (line 1230) | func (x *CreditCardInfo) GetCreditCardExpirationYear() int32 {
method GetCreditCardExpirationMonth (line 1237) | func (x *CreditCardInfo) GetCreditCardExpirationMonth() int32 {
type ChargeRequest (line 1244) | type ChargeRequest struct
method Reset (line 1253) | func (x *ChargeRequest) Reset() {
method String (line 1262) | func (x *ChargeRequest) String() string {
method ProtoMessage (line 1266) | func (*ChargeRequest) ProtoMessage() {}
method ProtoReflect (line 1268) | func (x *ChargeRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1281) | func (*ChargeRequest) Descriptor() ([]byte, []int) {
method GetAmount (line 1285) | func (x *ChargeRequest) GetAmount() *Money {
method GetCreditCard (line 1292) | func (x *ChargeRequest) GetCreditCard() *CreditCardInfo {
type ChargeResponse (line 1299) | type ChargeResponse struct
method Reset (line 1307) | func (x *ChargeResponse) Reset() {
method String (line 1316) | func (x *ChargeResponse) String() string {
method ProtoMessage (line 1320) | func (*ChargeResponse) ProtoMessage() {}
method ProtoReflect (line 1322) | func (x *ChargeResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1335) | func (*ChargeResponse) Descriptor() ([]byte, []int) {
method GetTransactionId (line 1339) | func (x *ChargeResponse) GetTransactionId() string {
type OrderItem (line 1346) | type OrderItem struct
method Reset (line 1355) | func (x *OrderItem) Reset() {
method String (line 1364) | func (x *OrderItem) String() string {
method ProtoMessage (line 1368) | func (*OrderItem) ProtoMessage() {}
method ProtoReflect (line 1370) | func (x *OrderItem) ProtoReflect() protoreflect.Message {
method Descriptor (line 1383) | func (*OrderItem) Descriptor() ([]byte, []int) {
method GetItem (line 1387) | func (x *OrderItem) GetItem() *CartItem {
method GetCost (line 1394) | func (x *OrderItem) GetCost() *Money {
type OrderResult (line 1401) | type OrderResult struct
method Reset (line 1413) | func (x *OrderResult) Reset() {
method String (line 1422) | func (x *OrderResult) String() string {
method ProtoMessage (line 1426) | func (*OrderResult) ProtoMessage() {}
method ProtoReflect (line 1428) | func (x *OrderResult) ProtoReflect() protoreflect.Message {
method Descriptor (line 1441) | func (*OrderResult) Descriptor() ([]byte, []int) {
method GetOrderId (line 1445) | func (x *OrderResult) GetOrderId() string {
method GetShippingTrackingId (line 1452) | func (x *OrderResult) GetShippingTrackingId() string {
method GetShippingCost (line 1459) | func (x *OrderResult) GetShippingCost() *Money {
method GetShippingAddress (line 1466) | func (x *OrderResult) GetShippingAddress() *Address {
method GetItems (line 1473) | func (x *OrderResult) GetItems() []*OrderItem {
type SendOrderConfirmationRequest (line 1480) | type SendOrderConfirmationRequest struct
method Reset (line 1489) | func (x *SendOrderConfirmationRequest) Reset() {
method String (line 1498) | func (x *SendOrderConfirmationRequest) String() string {
method ProtoMessage (line 1502) | func (*SendOrderConfirmationRequest) ProtoMessage() {}
method ProtoReflect (line 1504) | func (x *SendOrderConfirmationRequest) ProtoReflect() protoreflect.Mes...
method Descriptor (line 1517) | func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
method GetEmail (line 1521) | func (x *SendOrderConfirmationRequest) GetEmail() string {
method GetOrder (line 1528) | func (x *SendOrderConfirmationRequest) GetOrder() *OrderResult {
type PlaceOrderRequest (line 1535) | type PlaceOrderRequest struct
method Reset (line 1547) | func (x *PlaceOrderRequest) Reset() {
method String (line 1556) | func (x *PlaceOrderRequest) String() string {
method ProtoMessage (line 1560) | func (*PlaceOrderRequest) ProtoMessage() {}
method ProtoReflect (line 1562) | func (x *PlaceOrderRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1575) | func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
method GetUserId (line 1579) | func (x *PlaceOrderRequest) GetUserId() string {
method GetUserCurrency (line 1586) | func (x *PlaceOrderRequest) GetUserCurrency() string {
method GetAddress (line 1593) | func (x *PlaceOrderRequest) GetAddress() *Address {
method GetEmail (line 1600) | func (x *PlaceOrderRequest) GetEmail() string {
method GetCreditCard (line 1607) | func (x *PlaceOrderRequest) GetCreditCard() *CreditCardInfo {
type PlaceOrderResponse (line 1614) | type PlaceOrderResponse struct
method Reset (line 1622) | func (x *PlaceOrderResponse) Reset() {
method String (line 1631) | func (x *PlaceOrderResponse) String() string {
method ProtoMessage (line 1635) | func (*PlaceOrderResponse) ProtoMessage() {}
method ProtoReflect (line 1637) | func (x *PlaceOrderResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1650) | func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
method GetOrder (line 1654) | func (x *PlaceOrderResponse) GetOrder() *OrderResult {
type AdRequest (line 1661) | type AdRequest struct
method Reset (line 1670) | func (x *AdRequest) Reset() {
method String (line 1679) | func (x *AdRequest) String() string {
method ProtoMessage (line 1683) | func (*AdRequest) ProtoMessage() {}
method ProtoReflect (line 1685) | func (x *AdRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 1698) | func (*AdRequest) Descriptor() ([]byte, []int) {
method GetContextKeys (line 1702) | func (x *AdRequest) GetContextKeys() []string {
type AdResponse (line 1709) | type AdResponse struct
method Reset (line 1717) | func (x *AdResponse) Reset() {
method String (line 1726) | func (x *AdResponse) String() string {
method ProtoMessage (line 1730) | func (*AdResponse) ProtoMessage() {}
method ProtoReflect (line 1732) | func (x *AdResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 1745) | func (*AdResponse) Descriptor() ([]byte, []int) {
method GetAds (line 1749) | func (x *AdResponse) GetAds() []*Ad {
type Ad (line 1756) | type Ad struct
method Reset (line 1767) | func (x *Ad) Reset() {
method String (line 1776) | func (x *Ad) String() string {
method ProtoMessage (line 1780) | func (*Ad) ProtoMessage() {}
method ProtoReflect (line 1782) | func (x *Ad) ProtoReflect() protoreflect.Message {
method Descriptor (line 1795) | func (*Ad) Descriptor() ([]byte, []int) {
method GetRedirectUrl (line 1799) | func (x *Ad) GetRedirectUrl() string {
method GetText (line 1806) | func (x *Ad) GetText() string {
function file_demo_proto_rawDescGZIP (line 2098) | func file_demo_proto_rawDescGZIP() []byte {
function init (line 2201) | func init() { file_demo_proto_init() }
function file_demo_proto_init (line 2202) | func file_demo_proto_init() {
FILE: src/shippingservice/genproto/demo_grpc.pb.go
constant _ (line 33) | _ = grpc.SupportPackageIsVersion9
constant CartService_AddItem_FullMethodName (line 36) | CartService_AddItem_FullMethodName = "/hipstershop.CartService/AddItem"
constant CartService_GetCart_FullMethodName (line 37) | CartService_GetCart_FullMethodName = "/hipstershop.CartService/GetCart"
constant CartService_EmptyCart_FullMethodName (line 38) | CartService_EmptyCart_FullMethodName = "/hipstershop.CartService/EmptyCart"
type CartServiceClient (line 44) | type CartServiceClient interface
type cartServiceClient (line 50) | type cartServiceClient struct
method AddItem (line 58) | func (c *cartServiceClient) AddItem(ctx context.Context, in *AddItemRe...
method GetCart (line 68) | func (c *cartServiceClient) GetCart(ctx context.Context, in *GetCartRe...
method EmptyCart (line 78) | func (c *cartServiceClient) EmptyCart(ctx context.Context, in *EmptyCa...
function NewCartServiceClient (line 54) | func NewCartServiceClient(cc grpc.ClientConnInterface) CartServiceClient {
type CartServiceServer (line 91) | type CartServiceServer interface
type UnimplementedCartServiceServer (line 103) | type UnimplementedCartServiceServer struct
method AddItem (line 105) | func (UnimplementedCartServiceServer) AddItem(context.Context, *AddIte...
method GetCart (line 108) | func (UnimplementedCartServiceServer) GetCart(context.Context, *GetCar...
method EmptyCart (line 111) | func (UnimplementedCartServiceServer) EmptyCart(context.Context, *Empt...
method mustEmbedUnimplementedCartServiceServer (line 114) | func (UnimplementedCartServiceServer) mustEmbedUnimplementedCartServic...
method testEmbeddedByValue (line 115) | func (UnimplementedCartServiceServer) testEmbeddedByValue() ...
type UnsafeCartServiceServer (line 120) | type UnsafeCartServiceServer interface
function RegisterCartServiceServer (line 124) | func RegisterCartServiceServer(s grpc.ServiceRegistrar, srv CartServiceS...
function _CartService_AddItem_Handler (line 135) | func _CartService_AddItem_Handler(srv interface{}, ctx context.Context, ...
function _CartService_GetCart_Handler (line 153) | func _CartService_GetCart_Handler(srv interface{}, ctx context.Context, ...
function _CartService_EmptyCart_Handler (line 171) | func _CartService_EmptyCart_Handler(srv interface{}, ctx context.Context...
constant RecommendationService_ListRecommendations_FullMethodName (line 214) | RecommendationService_ListRecommendations_FullMethodName = "/hipstershop...
type RecommendationServiceClient (line 220) | type RecommendationServiceClient interface
type recommendationServiceClient (line 224) | type recommendationServiceClient struct
method ListRecommendations (line 232) | func (c *recommendationServiceClient) ListRecommendations(ctx context....
function NewRecommendationServiceClient (line 228) | func NewRecommendationServiceClient(cc grpc.ClientConnInterface) Recomme...
type RecommendationServiceServer (line 245) | type RecommendationServiceServer interface
type UnimplementedRecommendationServiceServer (line 255) | type UnimplementedRecommendationServiceServer struct
method ListRecommendations (line 257) | func (UnimplementedRecommendationServiceServer) ListRecommendations(co...
method mustEmbedUnimplementedRecommendationServiceServer (line 260) | func (UnimplementedRecommendationServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 261) | func (UnimplementedRecommendationServiceServer) testEmbeddedByValue() ...
type UnsafeRecommendationServiceServer (line 266) | type UnsafeRecommendationServiceServer interface
function RegisterRecommendationServiceServer (line 270) | func RegisterRecommendationServiceServer(s grpc.ServiceRegistrar, srv Re...
function _RecommendationService_ListRecommendations_Handler (line 281) | func _RecommendationService_ListRecommendations_Handler(srv interface{},...
constant ProductCatalogService_ListProducts_FullMethodName (line 316) | ProductCatalogService_ListProducts_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_GetProduct_FullMethodName (line 317) | ProductCatalogService_GetProduct_FullMethodName = "/hipstershop.Prod...
constant ProductCatalogService_SearchProducts_FullMethodName (line 318) | ProductCatalogService_SearchProducts_FullMethodName = "/hipstershop.Prod...
type ProductCatalogServiceClient (line 324) | type ProductCatalogServiceClient interface
type productCatalogServiceClient (line 330) | type productCatalogServiceClient struct
method ListProducts (line 338) | func (c *productCatalogServiceClient) ListProducts(ctx context.Context...
method GetProduct (line 348) | func (c *productCatalogServiceClient) GetProduct(ctx context.Context, ...
method SearchProducts (line 358) | func (c *productCatalogServiceClient) SearchProducts(ctx context.Conte...
function NewProductCatalogServiceClient (line 334) | func NewProductCatalogServiceClient(cc grpc.ClientConnInterface) Product...
type ProductCatalogServiceServer (line 371) | type ProductCatalogServiceServer interface
type UnimplementedProductCatalogServiceServer (line 383) | type UnimplementedProductCatalogServiceServer struct
method ListProducts (line 385) | func (UnimplementedProductCatalogServiceServer) ListProducts(context.C...
method GetProduct (line 388) | func (UnimplementedProductCatalogServiceServer) GetProduct(context.Con...
method SearchProducts (line 391) | func (UnimplementedProductCatalogServiceServer) SearchProducts(context...
method mustEmbedUnimplementedProductCatalogServiceServer (line 394) | func (UnimplementedProductCatalogServiceServer) mustEmbedUnimplemented...
method testEmbeddedByValue (line 395) | func (UnimplementedProductCatalogServiceServer) testEmbeddedByValue() ...
type UnsafeProductCatalogServiceServer (line 400) | type UnsafeProductCatalogServiceServer interface
function RegisterProductCatalogServiceServer (line 404) | func RegisterProductCatalogServiceServer(s grpc.ServiceRegistrar, srv Pr...
function _ProductCatalogService_ListProducts_Handler (line 415) | func _ProductCatalogService_ListProducts_Handler(srv interface{}, ctx co...
function _ProductCatalogService_GetProduct_Handler (line 433) | func _ProductCatalogService_GetProduct_Handler(srv interface{}, ctx cont...
function _ProductCatalogService_SearchProducts_Handler (line 451) | func _ProductCatalogService_SearchProducts_Handler(srv interface{}, ctx ...
constant ShippingService_GetQuote_FullMethodName (line 494) | ShippingService_GetQuote_FullMethodName = "/hipstershop.ShippingService...
constant ShippingService_ShipOrder_FullMethodName (line 495) | ShippingService_ShipOrder_FullMethodName = "/hipstershop.ShippingService...
type ShippingServiceClient (line 501) | type ShippingServiceClient interface
type shippingServiceClient (line 506) | type shippingServiceClient struct
method GetQuote (line 514) | func (c *shippingServiceClient) GetQuote(ctx context.Context, in *GetQ...
method ShipOrder (line 524) | func (c *shippingServiceClient) ShipOrder(ctx context.Context, in *Shi...
function NewShippingServiceClient (line 510) | func NewShippingServiceClient(cc grpc.ClientConnInterface) ShippingServi...
type ShippingServiceServer (line 537) | type ShippingServiceServer interface
type UnimplementedShippingServiceServer (line 548) | type UnimplementedShippingServiceServer struct
method GetQuote (line 550) | func (UnimplementedShippingServiceServer) GetQuote(context.Context, *G...
method ShipOrder (line 553) | func (UnimplementedShippingServiceServer) ShipOrder(context.Context, *...
method mustEmbedUnimplementedShippingServiceServer (line 556) | func (UnimplementedShippingServiceServer) mustEmbedUnimplementedShippi...
method testEmbeddedByValue (line 557) | func (UnimplementedShippingServiceServer) testEmbeddedByValue() ...
type UnsafeShippingServiceServer (line 562) | type UnsafeShippingServiceServer interface
function RegisterShippingServiceServer (line 566) | func RegisterShippingServiceServer(s grpc.ServiceRegistrar, srv Shipping...
function _ShippingService_GetQuote_Handler (line 577) | func _ShippingService_GetQuote_Handler(srv interface{}, ctx context.Cont...
function _ShippingService_ShipOrder_Handler (line 595) | func _ShippingService_ShipOrder_Handler(srv interface{}, ctx context.Con...
constant CurrencyService_GetSupportedCurrencies_FullMethodName (line 634) | CurrencyService_GetSupportedCurrencies_FullMethodName = "/hipstershop.Cu...
constant CurrencyService_Convert_FullMethodName (line 635) | CurrencyService_Convert_FullMethodName = "/hipstershop.Cu...
type CurrencyServiceClient (line 641) | type CurrencyServiceClient interface
type currencyServiceClient (line 646) | type currencyServiceClient struct
method GetSupportedCurrencies (line 654) | func (c *currencyServiceClient) GetSupportedCurrencies(ctx context.Con...
method Convert (line 664) | func (c *currencyServiceClient) Convert(ctx context.Context, in *Curre...
function NewCurrencyServiceClient (line 650) | func NewCurrencyServiceClient(cc grpc.ClientConnInterface) CurrencyServi...
type CurrencyServiceServer (line 677) | type CurrencyServiceServer interface
type UnimplementedCurrencyServiceServer (line 688) | type UnimplementedCurrencyServiceServer struct
method GetSupportedCurrencies (line 690) | func (UnimplementedCurrencyServiceServer) GetSupportedCurrencies(conte...
method Convert (line 693) | func (UnimplementedCurrencyServiceServer) Convert(context.Context, *Cu...
method mustEmbedUnimplementedCurrencyServiceServer (line 696) | func (UnimplementedCurrencyServiceServer) mustEmbedUnimplementedCurren...
method testEmbeddedByValue (line 697) | func (UnimplementedCurrencyServiceServer) testEmbeddedByValue() ...
type UnsafeCurrencyServiceServer (line 702) | type UnsafeCurrencyServiceServer interface
function RegisterCurrencyServiceServer (line 706) | func RegisterCurrencyServiceServer(s grpc.ServiceRegistrar, srv Currency...
function _CurrencyService_GetSupportedCurrencies_Handler (line 717) | func _CurrencyService_GetSupportedCurrencies_Handler(srv interface{}, ct...
function _CurrencyService_Convert_Handler (line 735) | func _CurrencyService_Convert_Handler(srv interface{}, ctx context.Conte...
constant PaymentService_Charge_FullMethodName (line 774) | PaymentService_Charge_FullMethodName = "/hipstershop.PaymentService/Charge"
type PaymentServiceClient (line 780) | type PaymentServiceClient interface
type paymentServiceClient (line 784) | type paymentServiceClient struct
method Charge (line 792) | func (c *paymentServiceClient) Charge(ctx context.Context, in *ChargeR...
function NewPaymentServiceClient (line 788) | func NewPaymentServiceClient(cc grpc.ClientConnInterface) PaymentService...
type PaymentServiceServer (line 805) | type PaymentServiceServer interface
type UnimplementedPaymentServiceServer (line 815) | type UnimplementedPaymentServiceServer struct
method Charge (line 817) | func (UnimplementedPaymentServiceServer) Charge(context.Context, *Char...
method mustEmbedUnimplementedPaymentServiceServer (line 820) | func (UnimplementedPaymentServiceServer) mustEmbedUnimplementedPayment...
method testEmbeddedByValue (line 821) | func (UnimplementedPaymentServiceServer) testEmbeddedByValue() ...
type UnsafePaymentServiceServer (line 826) | type UnsafePaymentServiceServer interface
function RegisterPaymentServiceServer (line 830) | func RegisterPaymentServiceServer(s grpc.ServiceRegistrar, srv PaymentSe...
function _PaymentService_Charge_Handler (line 841) | func _PaymentService_Charge_Handler(srv interface{}, ctx context.Context...
constant EmailService_SendOrderConfirmation_FullMethodName (line 876) | EmailService_SendOrderConfirmation_FullMethodName = "/hipstershop.EmailS...
type EmailServiceClient (line 882) | type EmailServiceClient interface
type emailServiceClient (line 886) | type emailServiceClient struct
method SendOrderConfirmation (line 894) | func (c *emailServiceClient) SendOrderConfirmation(ctx context.Context...
function NewEmailServiceClient (line 890) | func NewEmailServiceClient(cc grpc.ClientConnInterface) EmailServiceClie...
type EmailServiceServer (line 907) | type EmailServiceServer interface
type UnimplementedEmailServiceServer (line 917) | type UnimplementedEmailServiceServer struct
method SendOrderConfirmation (line 919) | func (UnimplementedEmailServiceServer) SendOrderConfirmation(context.C...
method mustEmbedUnimplementedEmailServiceServer (line 922) | func (UnimplementedEmailServiceServer) mustEmbedUnimplementedEmailServ...
method testEmbeddedByValue (line 923) | func (UnimplementedEmailServiceServer) testEmbeddedByValue() ...
type UnsafeEmailServiceServer (line 928) | type UnsafeEmailServiceServer interface
function RegisterEmailServiceServer (line 932) | func RegisterEmailServiceServer(s grpc.ServiceRegistrar, srv EmailServic...
function _EmailService_SendOrderConfirmation_Handler (line 943) | func _EmailService_SendOrderConfirmation_Handler(srv interface{}, ctx co...
constant CheckoutService_PlaceOrder_FullMethodName (line 978) | CheckoutService_PlaceOrder_FullMethodName = "/hipstershop.CheckoutServic...
type CheckoutServiceClient (line 984) | type CheckoutServiceClient interface
type checkoutServiceClient (line 988) | type checkoutServiceClient struct
method PlaceOrder (line 996) | func (c *checkoutServiceClient) PlaceOrder(ctx context.Context, in *Pl...
function NewCheckoutServiceClient (line 992) | func NewCheckoutServiceClient(cc grpc.ClientConnInterface) CheckoutServi...
type CheckoutServiceServer (line 1009) | type CheckoutServiceServer interface
type UnimplementedCheckoutServiceServer (line 1019) | type UnimplementedCheckoutServiceServer struct
method PlaceOrder (line 1021) | func (UnimplementedCheckoutServiceServer) PlaceOrder(context.Context, ...
method mustEmbedUnimplementedCheckoutServiceServer (line 1024) | func (UnimplementedCheckoutServiceServer) mustEmbedUnimplementedChecko...
method testEmbeddedByValue (line 1025) | func (UnimplementedCheckoutServiceServer) testEmbeddedByValue() ...
type UnsafeCheckoutServiceServer (line 1030) | type UnsafeCheckoutServiceServer interface
function RegisterCheckoutServiceServer (line 1034) | func RegisterCheckoutServiceServer(s grpc.ServiceRegistrar, srv Checkout...
function _CheckoutService_PlaceOrder_Handler (line 1045) | func _CheckoutService_PlaceOrder_Handler(srv interface{}, ctx context.Co...
constant AdService_GetAds_FullMethodName (line 1080) | AdService_GetAds_FullMethodName = "/hipstershop.AdService/GetAds"
type AdServiceClient (line 1086) | type AdServiceClient interface
type adServiceClient (line 1090) | type adServiceClient struct
method GetAds (line 1098) | func (c *adServiceClient) GetAds(ctx context.Context, in *AdRequest, o...
function NewAdServiceClient (line 1094) | func NewAdServiceClient(cc grpc.ClientConnInterface) AdServiceClient {
type AdServiceServer (line 1111) | type AdServiceServer interface
type UnimplementedAdServiceServer (line 1121) | type UnimplementedAdServiceServer struct
method GetAds (line 1123) | func (UnimplementedAdServiceServer) GetAds(context.Context, *AdRequest...
method mustEmbedUnimplementedAdServiceServer (line 1126) | func (UnimplementedAdServiceServer) mustEmbedUnimplementedAdServiceSer...
method testEmbeddedByValue (line 1127) | func (UnimplementedAdServiceServer) testEmbeddedByValue() ...
type UnsafeAdServiceServer (line 1132) | type UnsafeAdServiceServer interface
function RegisterAdServiceServer (line 1136) | func RegisterAdServiceServer(s grpc.ServiceRegistrar, srv AdServiceServe...
function _AdService_GetAds_Handler (line 1147) | func _AdService_GetAds_Handler(srv interface{}, ctx context.Context, dec...
FILE: src/shippingservice/main.go
constant defaultPort (line 37) | defaultPort = "50051"
function init (line 42) | func init() {
function main (line 56) | func main() {
type server (line 105) | type server struct
method Check (line 110) | func (s *server) Check(ctx context.Context, req *healthpb.HealthCheckR...
method Watch (line 114) | func (s *server) Watch(req *healthpb.HealthCheckRequest, ws healthpb.H...
method GetQuote (line 119) | func (s *server) GetQuote(ctx context.Context, in *pb.GetQuoteRequest)...
method ShipOrder (line 142) | func (s *server) ShipOrder(ctx context.Context, in *pb.ShipOrderReques...
function initStats (line 155) | func initStats() {
function initTracing (line 159) | func initTracing() {
function initProfiling (line 163) | func initProfiling(service, version string) {
FILE: src/shippingservice/quote.go
type Quote (line 23) | type Quote struct
method String (line 29) | func (q Quote) String() string {
function CreateQuoteFromCount (line 34) | func CreateQuoteFromCount(count int) Quote {
function CreateQuoteFromFloat (line 42) | func CreateQuoteFromFloat(value float64) Quote {
FILE: src/shippingservice/shippingservice_test.go
function TestGetQuote (line 27) | func TestGetQuote(t *testing.T) {
function TestGetQuoteEmptyCart (line 60) | func TestGetQuoteEmptyCart(t *testing.T) {
function TestShipOrder (line 83) | func TestShipOrder(t *testing.T) {
function TestTrackingIdFormat (line 116) | func TestTrackingIdFormat(t *testing.T) {
function TestTrackingIdUniqueness (line 128) | func TestTrackingIdUniqueness(t *testing.T) {
function TestCreateQuoteFromFloat (line 140) | func TestCreateQuoteFromFloat(t *testing.T) {
function TestCreateQuoteFromCount (line 166) | func TestCreateQuoteFromCount(t *testing.T) {
function TestGetRandomLetterCode (line 179) | func TestGetRandomLetterCode(t *testing.T) {
function TestGetRandomNumber (line 189) | func TestGetRandomNumber(t *testing.T) {
function TestQuoteString (line 200) | func TestQuoteString(t *testing.T) {
FILE: src/shippingservice/tracker.go
function CreateTrackingId (line 23) | func CreateTrackingId(salt string) string {
function getRandomLetterCode (line 35) | func getRandomLetterCode() uint32 {
function getRandomNumber (line 40) | func getRandomNumber(digits int) string {
FILE: src/shoppingassistantservice/shoppingassistantservice.py
function create_app (line 62) | def create_app():
Condensed preview — 316 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,613K chars).
[
{
"path": ".deploystack/deploystack.yaml",
"chars": 518,
"preview": "# The fields inside this deploystack.yaml file are documented in https://github.com/GoogleCloudPlatform/deploystack.\n\nti"
},
{
"path": ".deploystack/messages/description.txt",
"chars": 247,
"preview": "Online Boutique is a cloud-first microservices demo application. Online Boutique\nconsists of an 11-tier microservices ap"
},
{
"path": ".deploystack/messages/success.txt",
"chars": 168,
"preview": "Congrats!\nYou have successfully provisioned a GKE (Google Kubernetes Engine) cluster and\ndeployed Online Boutique's 11 m"
},
{
"path": ".deploystack/scripts/preinit.sh",
"chars": 664,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".deploystack/test",
"chars": 7228,
"preview": "#! /bin/bash\n# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may n"
},
{
"path": ".deploystack/test.yaml",
"chars": 1211,
"preview": "# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".editorconfig",
"chars": 401,
"preview": "# The .editorconfig is used to maintain consistent code style.\n# The .editorconfig file is supported by most text editor"
},
{
"path": ".gitattributes",
"chars": 199,
"preview": "# This file configures the git settings for this repository.\n\n# Converts \"CR + LF\" to \"LF\", for all \"text\" files — for l"
},
{
"path": ".github/CODEOWNERS",
"chars": 282,
"preview": "# See https://help.github.com/en/articles/about-code-owners\n# for more info about CODEOWNERS file.\n\n# These owners will "
},
{
"path": ".github/CODE_OF_CONDUCT.md",
"chars": 1981,
"preview": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project,\nand in the interest of fostering an open"
},
{
"path": ".github/CONTRIBUTING.md",
"chars": 2163,
"preview": "# How to Contribute\n\nThank you so much for your interest in contributing to Online Boutique.\nBefore contributing, you mu"
},
{
"path": ".github/ISSUE_TEMPLATE/bug-report.md",
"chars": 871,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n### Describe the"
},
{
"path": ".github/ISSUE_TEMPLATE/feature-request.md",
"chars": 291,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n### Describe "
},
{
"path": ".github/ISSUE_TEMPLATE/other.md",
"chars": 198,
"preview": "---\nname: Other\nabout: Have a question or need clarification?\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n### Write down you"
},
{
"path": ".github/SECURITY.md",
"chars": 329,
"preview": "# Security Policy\n\nTo report a security issue, please use [g.co/vulnz](https://g.co/vulnz).\n\nThe Google Security Team wi"
},
{
"path": ".github/auto-approve.yml",
"chars": 841,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/header-checker-lint.yml",
"chars": 1530,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/pull_request_template.md",
"chars": 422,
"preview": "### Background \n<!-- What was happening before this PR, and the problem(s) it solves -->\n\n### Fixes \n<!-- Link the issue"
},
{
"path": ".github/release-cluster/README.md",
"chars": 2472,
"preview": "# cymbal-shops.retail.cymbal.dev manifests\n\nThis directory contains extra deploy manifests for configuring Online Boutiq"
},
{
"path": ".github/release-cluster/backend-config.yaml",
"chars": 736,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/release-cluster/frontend-config.yaml",
"chars": 809,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/release-cluster/frontend-ingress.yaml",
"chars": 1170,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/release-cluster/frontend-service.yaml",
"chars": 883,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/release-cluster/managed-cert.yaml",
"chars": 735,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/renovate.json5",
"chars": 514,
"preview": "{\n extends: [\n 'github>GoogleCloudPlatform/kubernetes-engine-samples//.github/renovate-configs/dee-platform-ops.json"
},
{
"path": ".github/snippet-bot.yml",
"chars": 576,
"preview": "\n# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this "
},
{
"path": ".github/terraform/README.md",
"chars": 997,
"preview": "This folder contains the Terraform for some of the infrastructure used by the CICD (continuous integration and continuou"
},
{
"path": ".github/terraform/main.tf",
"chars": 4317,
"preview": "/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": ".github/terraform/variables.tf",
"chars": 844,
"preview": "/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": ".github/terraform/versions.tf",
"chars": 750,
"preview": "/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
},
{
"path": ".github/workflows/README.md",
"chars": 3784,
"preview": "# GitHub Actions Workflows\n\nThis page describes the CI/CD workflows for the Online Boutique app, which run in [Github Ac"
},
{
"path": ".github/workflows/ci-main.yaml",
"chars": 4721,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/ci-pr.yaml",
"chars": 6041,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/cleanup.yaml",
"chars": 1484,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/helm-chart-ci.yaml",
"chars": 4491,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/install-dependencies.sh",
"chars": 2595,
"preview": "#!/bin/bash\n# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may no"
},
{
"path": ".github/workflows/kubevious-manifests-ci.yaml",
"chars": 1614,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/kustomize-build-ci.yaml",
"chars": 1419,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".github/workflows/terraform-validate-ci.yaml",
"chars": 1130,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": ".gitignore",
"chars": 310,
"preview": ".DS_Store\n.eclipse.buildship.core.prefs\n.gradle/\n.idea/\n.kubernetes-manifests-*/\n.project\n.skaffold-*.yaml\n.terraform.lo"
},
{
"path": "LICENSE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 12219,
"preview": "<!-- <p align=\"center\">\n<img src=\"/src/frontend/static/icons/Hipster_HeroLogoMaroon.svg\" width=\"300\" alt=\"Online Boutiqu"
},
{
"path": "cloudbuild.yaml",
"chars": 1490,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "docs/adding-new-microservice.md",
"chars": 3052,
"preview": "# Adding a new microservice\n\nThis document outlines the steps required to add a new microservice to the Online Boutique "
},
{
"path": "docs/cloudshell-tutorial.md",
"chars": 4935,
"preview": "# Online Boutique quickstart\n\nThis tutorial shows you how to deploy **[Online Boutique](https://github.com/GoogleCloudPl"
},
{
"path": "docs/deploystack.md",
"chars": 1033,
"preview": "## Deploy Online Boutique with DeployStack\n\nThe \"Open in Google Cloud Shell\" button below will use [DeployStack](https:/"
},
{
"path": "docs/development-guide.md",
"chars": 4683,
"preview": "# Development Guide \n\nThis doc explains how to build and run the Online Boutique source code locally using the `skaffold"
},
{
"path": "docs/product-requirements.md",
"chars": 2550,
"preview": "## Product Requirements\n\nThis document contains a list of requirements that every change made to this repository should "
},
{
"path": "docs/purpose.md",
"chars": 694,
"preview": "## Purpose\n\nToday, the primary purpose of Online Boutique is to demonstrate:\n\n* [Google Kubernetes Engine (GKE)](https:/"
},
{
"path": "docs/releasing/README.md",
"chars": 5024,
"preview": "# Releasing Online Boutique\n\nThis document walks through the process of creating a new release of Online Boutique.\n\n## P"
},
{
"path": "docs/releasing/license_header.txt",
"chars": 575,
"preview": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "docs/releasing/make-docker-images.sh",
"chars": 1792,
"preview": "#!/usr/bin/env bash\n\n# Copyright 2019 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
},
{
"path": "docs/releasing/make-helm-chart.sh",
"chars": 1232,
"preview": "#!/usr/bin/env bash\n\n# Copyright 2019 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
},
{
"path": "docs/releasing/make-release-artifacts.sh",
"chars": 4257,
"preview": "#!/usr/bin/env bash\n\n# Copyright 2019 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
},
{
"path": "docs/releasing/make-release.sh",
"chars": 2144,
"preview": "#!/usr/bin/env bash\n\n# Copyright 2019 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# y"
},
{
"path": "helm-chart/Chart.yaml",
"chars": 1747,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/README.md",
"chars": 2066,
"preview": "# Helm chart for Online Boutique\n\nIf you'd like to deploy Online Boutique via its Helm chart, you could leverage the fol"
},
{
"path": "helm-chart/templates/NOTES.txt",
"chars": 960,
"preview": "{{- if and .Values.frontend.create .Values.frontend.externalService }}\nNote: It may take a few minutes for the LoadBalan"
},
{
"path": "helm-chart/templates/adservice.yaml",
"chars": 4630,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/cartservice.yaml",
"chars": 11557,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/checkoutservice.yaml",
"chars": 6204,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/common.yaml",
"chars": 1009,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/currencyservice.yaml",
"chars": 5413,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/emailservice.yaml",
"chars": 5172,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/frontend.yaml",
"chars": 8919,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/loadgenerator.yaml",
"chars": 4775,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/opentelemetry-collector.yaml",
"chars": 8513,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/paymentservice.yaml",
"chars": 5151,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/productcatalogservice.yaml",
"chars": 5799,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/recommendationservice.yaml",
"chars": 5538,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/templates/shippingservice.yaml",
"chars": 4981,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "helm-chart/values.yaml",
"chars": 5282,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "istio-manifests/allow-egress-googleapis.yaml",
"chars": 1192,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "istio-manifests/frontend-gateway.yaml",
"chars": 1103,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "istio-manifests/frontend.yaml",
"chars": 817,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/README.md",
"chars": 317,
"preview": "# ./kubernetes-manifests\n\n:warning: Kubernetes manifests provided in this directory are not directly\ndeployable to a clu"
},
{
"path": "kubernetes-manifests/adservice.yaml",
"chars": 2033,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/cartservice.yaml",
"chars": 3391,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/checkoutservice.yaml",
"chars": 2474,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/currencyservice.yaml",
"chars": 2043,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/emailservice.yaml",
"chars": 2046,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/frontend.yaml",
"chars": 4032,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/kustomization.yaml",
"chars": 1460,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/loadgenerator.yaml",
"chars": 2809,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/paymentservice.yaml",
"chars": 2018,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/productcatalogservice.yaml",
"chars": 2082,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/recommendationservice.yaml",
"chars": 2228,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kubernetes-manifests/shippingservice.yaml",
"chars": 2016,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/README.md",
"chars": 7575,
"preview": "# Use Online Boutique with Kustomize\n\nThis page contains instructions on deploying variations of the [Online Boutique](h"
},
{
"path": "kustomize/base/adservice.yaml",
"chars": 2102,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/cartservice.yaml",
"chars": 3460,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/checkoutservice.yaml",
"chars": 2543,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/currencyservice.yaml",
"chars": 2112,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/emailservice.yaml",
"chars": 2115,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/frontend.yaml",
"chars": 4101,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/kustomization.yaml",
"chars": 893,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/loadgenerator.yaml",
"chars": 2878,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/paymentservice.yaml",
"chars": 2087,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/productcatalogservice.yaml",
"chars": 2151,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/recommendationservice.yaml",
"chars": 2297,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/base/shippingservice.yaml",
"chars": 2085,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/alloydb/README.md",
"chars": 7496,
"preview": "# Integrate Online Boutique with AlloyDB\n\nBy default the `cartservice` stores its data in an in-cluster Redis database. "
},
{
"path": "kustomize/components/alloydb/kustomization.yaml",
"chars": 3245,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/container-images-registry/README.md",
"chars": 1473,
"preview": "# Update the container registry of the Online Boutique apps\n\nBy default, Online Boutique's services' container images ar"
},
{
"path": "kustomize/components/container-images-registry/kustomization.yaml",
"chars": 2198,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/container-images-tag/README.md",
"chars": 1702,
"preview": "# Update the container image tag of the Online Boutique apps\n\nBy default, the Online Boutique apps are targeting the lat"
},
{
"path": "kustomize/components/container-images-tag/kustomization.yaml",
"chars": 1910,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/container-images-tag-suffix/README.md",
"chars": 2245,
"preview": "# Add a suffix to the image tag of the Online Boutique container images\n\nYou may want to add a suffix to the Online Bout"
},
{
"path": "kustomize/components/container-images-tag-suffix/kustomization.yaml",
"chars": 2019,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/custom-base-url/README.md",
"chars": 1808,
"preview": "# Customize the Base URL for Online Boutique\n\nThis component allows you to change the base URL for the Online Boutique a"
},
{
"path": "kustomize/components/custom-base-url/kustomization.yaml",
"chars": 1100,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/cymbal-branding/README.md",
"chars": 1402,
"preview": "# Change the Online Boutique theme to the Cymbal Shops Branding\n\nBy default, when you deploy this sample app, the \"Onlin"
},
{
"path": "kustomize/components/cymbal-branding/kustomization.yaml",
"chars": 906,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/google-cloud-operations/README.md",
"chars": 5688,
"preview": "# Integrate Online Boutique with Google Cloud Operations\n\nBy default, [Google Cloud Operations](https://cloud.google.com"
},
{
"path": "kustomize/components/google-cloud-operations/kustomization.yaml",
"chars": 4932,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/google-cloud-operations/otel-collector.yaml",
"chars": 4063,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/memorystore/README.md",
"chars": 2710,
"preview": "# Integrate Online Boutique with Memorystore (Redis)\n\nBy default the `cartservice` app is serializing the data in an in-"
},
{
"path": "kustomize/components/memorystore/kustomization.yaml",
"chars": 1310,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/README.md",
"chars": 3436,
"preview": "# Secure Online Boutique with Network Policies\n\nYou can use [Network Policies](https://kubernetes.io/docs/concepts/servi"
},
{
"path": "kustomize/components/network-policies/kustomization.yaml",
"chars": 1114,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-adservice.yaml",
"chars": 905,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-cartservice.yaml",
"chars": 980,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-checkoutservice.yaml",
"chars": 917,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-currencyservice.yaml",
"chars": 988,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-deny-all.yaml",
"chars": 718,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-emailservice.yaml",
"chars": 918,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-frontend.yaml",
"chars": 786,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-loadgenerator.yaml",
"chars": 766,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-paymentservice.yaml",
"chars": 923,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-productcatalogservice.yaml",
"chars": 1077,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-recommendationservice.yaml",
"chars": 929,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-redis.yaml",
"chars": 911,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/network-policies/network-policy-shippingservice.yaml",
"chars": 989,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/non-public-frontend/README.md",
"chars": 1008,
"preview": "# Remove the public exposure of Online Boutique's frontend\n\nBy default, when you deploy Online Boutique, a `Service` (na"
},
{
"path": "kustomize/components/non-public-frontend/kustomization.yaml",
"chars": 804,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/service-mesh-istio/README.md",
"chars": 12742,
"preview": "# Service mesh with Istio\n\nYou can use [Istio](https://istio.io) to enable [service mesh features](https://cloud.google."
},
{
"path": "kustomize/components/service-mesh-istio/allow-egress-googleapis.yaml",
"chars": 1192,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/service-mesh-istio/frontend-gateway.yaml",
"chars": 1063,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/service-mesh-istio/frontend.yaml",
"chars": 817,
"preview": "# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/service-mesh-istio/kustomization.yaml",
"chars": 932,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/shopping-assistant/README.md",
"chars": 5338,
"preview": "# Shopping Assistant with RAG & AlloyDB\n\nThis demo adds a new service to Online Boutique called `shoppingassistantservic"
},
{
"path": "kustomize/components/shopping-assistant/kustomization.yaml",
"chars": 951,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/shopping-assistant/scripts/1_deploy_alloydb_infra.sh",
"chars": 7176,
"preview": "#!/bin/sh\n#\n# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may no"
},
{
"path": "kustomize/components/shopping-assistant/scripts/2_create_populate_alloydb_tables.sh",
"chars": 2912,
"preview": "#!/bin/sh\n#\n# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may no"
},
{
"path": "kustomize/components/shopping-assistant/scripts/generate_sql_from_products.py",
"chars": 1666,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/shopping-assistant/shoppingassistantservice.yaml",
"chars": 2550,
"preview": "# Copyright 2024 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/single-shared-session/README.md",
"chars": 1071,
"preview": "# Manage a single shared session for the Online Boutique apps\n\nBy default, when you deploy this sample app, the Online B"
},
{
"path": "kustomize/components/single-shared-session/kustomization.yaml",
"chars": 969,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/spanner/README.md",
"chars": 4328,
"preview": "# Integrate Online Boutique with Spanner\n\nBy default the `cartservice` stores its data in an in-cluster Redis database.\n"
},
{
"path": "kustomize/components/spanner/kustomization.yaml",
"chars": 1698,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/components/without-loadgenerator/README.md",
"chars": 1065,
"preview": "# Exclude the loadgenerator\n\nBy default, when you deploy Online Boutique, its [loadgenerator](/src/loadgenerator/) will "
},
{
"path": "kustomize/components/without-loadgenerator/delete-loadgenerator.patch.yaml",
"chars": 84,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: loadgenerator\n$patch: delete\n"
},
{
"path": "kustomize/components/without-loadgenerator/kustomization.yaml",
"chars": 686,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/kustomization.yaml",
"chars": 1183,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/tests/README.md",
"chars": 210,
"preview": "This directory contains a list of scenarios (different combinations of Kustomize Components) used for testing.\nSee [/.gi"
},
{
"path": "kustomize/tests/memorystore-with-all-components/kustomization.yaml",
"chars": 821,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/tests/service-mesh-istio-with-all-components/kustomization.yaml",
"chars": 828,
"preview": "# Copyright 2023 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "kustomize/tests/spanner-with-all-components/kustomization.yaml",
"chars": 817,
"preview": "# Copyright 2022 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "protos/demo.proto",
"chars": 6155,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "protos/grpc/health/v1/health.proto",
"chars": 1288,
"preview": "// Copyright 2015 The gRPC Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "release/istio-manifests.yaml",
"chars": 2244,
"preview": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "release/kubernetes-manifests.yaml",
"chars": 22522,
"preview": "# Copyright 2025 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "skaffold.yaml",
"chars": 3412,
"preview": "# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "src/adservice/Dockerfile",
"chars": 1584,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "src/adservice/README.md",
"chars": 634,
"preview": "# Ad Service\n\nThe Ad service provides advertisement based on context keys. If no context keys are provided then it retur"
},
{
"path": "src/adservice/build.gradle",
"chars": 3628,
"preview": "plugins {\n id 'com.google.protobuf' version '0.9.6'\n id 'com.github.sherter.google-java-format' version '0.9'\n "
},
{
"path": "src/adservice/genproto.sh",
"chars": 796,
"preview": "#!/bin/bash -eu\n#\n# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you "
},
{
"path": "src/adservice/gradle/wrapper/gradle-wrapper.properties",
"chars": 253,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "src/adservice/gradlew",
"chars": 8710,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "src/adservice/gradlew.bat",
"chars": 2843,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "src/adservice/settings.gradle",
"chars": 33,
"preview": "rootProject.name = 'hipstershop'\n"
},
{
"path": "src/adservice/src/main/java/hipstershop/AdService.java",
"chars": 7891,
"preview": "/*\n * Copyright 2018, Google LLC.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not u"
},
{
"path": "src/adservice/src/main/java/hipstershop/AdServiceClient.java",
"chars": 3864,
"preview": "/*\n * Copyright 2018, Google LLC.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not u"
},
{
"path": "src/adservice/src/main/proto/demo.proto",
"chars": 6069,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/adservice/src/main/resources/log4j2.xml",
"chars": 1850,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n Copyright 2020 Google LLC\n\n Licensed under the Apache License, Version 2.0 "
},
{
"path": "src/cartservice/cartservice.sln",
"chars": 2807,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.26124.0\nMini"
},
{
"path": "src/cartservice/src/.dockerignore",
"chars": 52,
"preview": "**/*.sh\n**/*.bat\n**/bin/\n**/obj/\n**/out/\nDockerfile*"
},
{
"path": "src/cartservice/src/Dockerfile",
"chars": 1589,
"preview": "# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "src/cartservice/src/Dockerfile.debug",
"chars": 1312,
"preview": "# Copyright 2021 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "src/cartservice/src/Program.cs",
"chars": 928,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/Startup.cs",
"chars": 3293,
"preview": "using System;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Diagnostics.HealthChecks;\nusing Microsoft.A"
},
{
"path": "src/cartservice/src/appsettings.json",
"chars": 288,
"preview": "{\n \"Logging\": {\n \"LogLevel\": {\n \"Default\": \"Information\",\n \"Microsoft\": \"Warning\",\n \"Micros"
},
{
"path": "src/cartservice/src/cartservice.csproj",
"chars": 714,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n <PropertyGroup>\n <TargetFramework>net10.0</TargetFramework>\n </PropertyGrou"
},
{
"path": "src/cartservice/src/cartstore/AlloyDBCartStore.cs",
"chars": 6653,
"preview": "// Copyright 2021 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/cartstore/ICartStore.cs",
"chars": 898,
"preview": "// Copyright 2018 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/cartstore/RedisCartStore.cs",
"chars": 3930,
"preview": "// Copyright 2018 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/cartstore/SpannerCartStore.cs",
"chars": 7609,
"preview": "// Copyright 2021 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/protos/Cart.proto",
"chars": 1210,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/services/CartService.cs",
"chars": 1707,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/src/services/HealthCheckService.cs",
"chars": 1415,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/tests/CartServiceTests.cs",
"chars": 5196,
"preview": "// Copyright 2018 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/cartservice/tests/cartservice.tests.csproj",
"chars": 646,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>net10.0</TargetFramework>\n\n <IsPackable>fal"
},
{
"path": "src/checkoutservice/.dockerignore",
"chars": 8,
"preview": "vendor/\n"
},
{
"path": "src/checkoutservice/Dockerfile",
"chars": 1543,
"preview": "# Copyright 2020 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this f"
},
{
"path": "src/checkoutservice/README.md",
"chars": 123,
"preview": "# checkoutservice\n\nRun the following command to restore dependencies to `vendor/` directory:\n\n dep ensure --vendor-on"
},
{
"path": "src/checkoutservice/genproto/demo.pb.go",
"chars": 89615,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/checkoutservice/genproto/demo_grpc.pb.go",
"chars": 47595,
"preview": "// Copyright 2020 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "src/checkoutservice/genproto.sh",
"chars": 905,
"preview": "#!/bin/bash -eu\n#\n# Copyright 2018 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you "
},
{
"path": "src/checkoutservice/go.mod",
"chars": 2110,
"preview": "module github.com/GoogleCloudPlatform/microservices-demo/src/checkoutservice\n\ngo 1.25.0\n\ntoolchain go1.26.1\n\nrequire (\n\t"
},
{
"path": "src/checkoutservice/go.sum",
"chars": 18908,
"preview": "cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=\ncel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX"
}
]
// ... and 116 more files (download for full content)
About this extraction
This page contains the full source code of the GoogleCloudPlatform/microservices-demo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 316 files (1.4 MB), approximately 478.0k tokens, and a symbol index with 2102 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.