Online Boutique, mapped from the code.
Google's microservices demo: eleven services in Go, C#, Node, Python and Java talking gRPC. Kuuhaku read its source at commit 38e7348, with no configuration and no hand-fixing, and found 12 services in Java, Go, JavaScript and Python, and 16 connections: 14 over gRPC and 2 over HTTP. Each one below says how it was found.
Services
Every repo or deployable the scanner found, with how many connections leave it and reach it.
| Service | Stack | Role | Calls | Called by |
|---|---|---|---|---|
frontend | Go · Go · mux | service | 8 | 1 |
checkoutservice | Go | service | 6 | 1 |
productcatalogservice | Go | service | 0 | 3 |
cartservice | not read: unknown only | service | 0 | 2 |
currencyservice | JavaScript · Node | service | 0 | 2 |
recommendationservice | Python | service | 1 | 1 |
shippingservice | Go | service | 0 | 2 |
adservice | Java | service | 0 | 1 |
emailservice | Python | service | 0 | 1 |
loadgenerator | Python · Flask | consumer | 1 | 0 |
paymentservice | JavaScript · Node | service | 0 | 1 |
shoppingassistantservice | Python · Flask | service | 0 | 1 |
Connections
config: the address is written in configuration (an env file, a compose file, a proxy route) and the call is matched to it. inferred: the call's path matches a route of the target and nothing contradicts it. Call sites count the places in the code that make the call.
| From | To | Type | Evidence | Call sites | How it was found |
|---|---|---|---|---|---|
checkoutservice | cartservice | gRPC | config | 3 | CART_SERVICE_ADDR = cartservice:7070 in checkoutservice.yaml; CartService client in main.go, served in cartservice/src/services/CartService.cs |
checkoutservice | currencyservice | gRPC | config | 2 | CURRENCY_SERVICE_ADDR = currencyservice:7000 in checkoutservice.yaml; CurrencyService client in main.go, served in currencyservice/server.js |
checkoutservice | emailservice | gRPC | config | 2 | EMAIL_SERVICE_ADDR = emailservice:5000 in checkoutservice.yaml; EmailService client in main.go, served in emailservice/email_server.py |
checkoutservice | paymentservice | gRPC | config | 2 | PAYMENT_SERVICE_ADDR = paymentservice:50051 in checkoutservice.yaml; PaymentService client in main.go, served in paymentservice/server.js |
checkoutservice | productcatalogservice | gRPC | config | 2 | PRODUCT_CATALOG_SERVICE_ADDR = productcatalogservice:3550 in checkoutservice.yaml; ProductCatalogService client in main.go, served in productcatalogservice/server.go |
checkoutservice | shippingservice | gRPC | config | 3 | SHIPPING_SERVICE_ADDR = shippingservice:50051 in checkoutservice.yaml; ShippingService client in main.go, served in shippingservice/main.go |
frontend | adservice | gRPC | config | 2 | AD_SERVICE_ADDR = adservice:9555 in frontend.yaml; AdService client in rpc.go, served in adservice/src/main/java/hipstershop/AdService.java |
frontend | cartservice | gRPC | config | 4 | CART_SERVICE_ADDR = cartservice:7070 in frontend.yaml; CartService client in rpc.go, served in cartservice/src/services/CartService.cs |
frontend | checkoutservice | gRPC | config | 2 | CHECKOUT_SERVICE_ADDR = checkoutservice:5050 in frontend.yaml; CheckoutService client in handlers.go, served in checkoutservice/main.go |
frontend | currencyservice | gRPC | config | 3 | CURRENCY_SERVICE_ADDR = currencyservice:7000 in frontend.yaml; CurrencyService client in rpc.go, served in currencyservice/server.js |
frontend | productcatalogservice | gRPC | config | 3 | PRODUCT_CATALOG_SERVICE_ADDR = productcatalogservice:3550 in frontend.yaml; ProductCatalogService client in rpc.go, served in productcatalogservice/server.go |
frontend | recommendationservice | gRPC | config | 2 | RECOMMENDATION_SERVICE_ADDR = recommendationservice:8080 in frontend.yaml; RecommendationService client in rpc.go, served in recommendationservice/recommendation_server.py |
frontend | shippingservice | gRPC | config | 2 | SHIPPING_SERVICE_ADDR = shippingservice:50051 in frontend.yaml; ShippingService client in rpc.go, served in shippingservice/main.go |
frontend | shoppingassistantservice | HTTP | config | 1 | SHOPPING_ASSISTANT_SERVICE_ADDR = shoppingassistantservice:80 in frontend.yaml |
loadgenerator | frontend | HTTP | config | 1 | FRONTEND_ADDR = frontend:80 in loadgenerator.yaml |
recommendationservice | productcatalogservice | gRPC | config | 2 | PRODUCT_CATALOG_SERVICE_ADDR = productcatalogservice:3550 in recommendationservice.yaml; ProductCatalogService client in recommendation_server.py, served in productcatalogservice/server.go |
Left for a person
2 items the scanner would not settle on its own and put in the review inbox instead of guessing:
httpinfrontend: base URL assigned at runtime (handlers.go:465)clientinloadgenerator: base URL assigned at runtime (locustfile.py:35)
Other systems
- OpenTelemetry Demo: 23 services, 30 connections
- Train Ticket: 48 services, 140 connections
- eShop: 19 services, 31 connections
- Robot Shop: 9 services, 12 connections
- Sock Shop: 8 services, 7 connections
- Bank of Anthos: 8 services, 9 connections
- Quarkus Super Heroes: 7 services, 6 connections
- Spring PetClinic Microservices: 7 services, 14 connections
Your own system
Run npx kuuhaku scan . in a folder of repos: it reads the code on your machine and only the graph leaves it. Or connect GitHub or Bitbucket and let the hosted runner scan with a read-only key. The map, a page per repo, a review inbox and a check on every pull request follow. Start free.