diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c46b598..b5f57fa 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,6 +22,9 @@ jobs: file: score-k8s version: latest token: ${{ secrets.GITHUB_TOKEN }} + - name: setup-kind-cluster + run: | + .scripts/setup-kind-cluster.sh - name: test-provisioners run: | .scripts/test-score-files.sh diff --git a/.scripts/test-score-files.sh b/.scripts/test-score-files.sh index 4e794d0..d4c7d38 100755 --- a/.scripts/test-score-files.sh +++ b/.scripts/test-score-files.sh @@ -11,10 +11,15 @@ do do echo "#### For ${feature}:" cd $feature - score-compose init --no-sample - score-compose generate score.yaml - score-k8s init --no-sample - score-k8s generate score.yaml + if [[ "$category" = "samples/" ]]; then + make compose-test + make k8s-test + else + score-compose init --no-sample + score-compose generate score.yaml + score-k8s init --no-sample + score-k8s generate score.yaml + fi cd .. done cd .. diff --git a/README.md b/README.md index e573791..b2926ce 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # Score examples - [Specification](./specification/) -- [Resources](./resources/) \ No newline at end of file +- [Resources](./resources/) +- [Samples](./samples/) + - [OnlineBoutique](./samples/onlineboutique/) \ No newline at end of file diff --git a/samples/onlineboutique/Makefile b/samples/onlineboutique/Makefile new file mode 100644 index 0000000..83f62b3 --- /dev/null +++ b/samples/onlineboutique/Makefile @@ -0,0 +1,113 @@ +# Disable all the default make stuff +MAKEFLAGS += --no-builtin-rules +.SUFFIXES: + +## Display a list of the documented make targets +.PHONY: help +help: + @echo Documented Make targets: + @perl -e 'undef $$/; while (<>) { while ($$_ =~ /## (.*?)(?:\n# .*)*\n.PHONY:\s+(\S+).*/mg) { printf "\033[36m%-30s\033[0m %s\n", $$2, $$1 } }' $(MAKEFILE_LIST) | sort + +.PHONY: .FORCE +.FORCE: + +.score-compose/state.yaml: + score-compose init \ + --no-sample \ + --provisioners https://raw.githubusercontent.com/score-spec/community-provisioners/refs/heads/main/service/score-compose/10-service.provisioners.yaml \ + --patch-templates https://raw.githubusercontent.com/score-spec/community-patchers/refs/heads/main/score-compose/unprivileged.tpl + +compose.yaml: ad/score.yaml cart/score.yaml currency/score.yaml email/score.yaml payment/score.yaml productcatalog/score.yaml recommendation/score.yaml shipping/score.yaml checkout/score.yaml frontend/score.yaml loadgenerator/score.yaml .score-compose/state.yaml Makefile + score-compose generate \ + ad/score.yaml \ + cart/score.yaml \ + currency/score.yaml \ + email/score.yaml \ + payment/score.yaml \ + productcatalog/score.yaml \ + recommendation/score.yaml \ + shipping/score.yaml \ + checkout/score.yaml + score-compose generate \ + frontend/score.yaml \ + --override-property containers.frontend.variables.FRONTEND_MESSAGE="Hello, Score Compose!" + score-compose generate \ + loadgenerator/score.yaml + +## Generate a compose.yaml file from the score spec and launch it. +.PHONY: compose-up +compose-up: compose.yaml + docker compose up --build -d --remove-orphans + sleep 5 + +## Generate a compose.yaml file from the score spec, launch it and test (curl) the exposed frontend container. +.PHONY: compose-test +compose-test: compose-up + curl $$(score-compose resources get-outputs dns.default#frontend.dns --format '{{ .host }}:8080') | grep "Hello, Score Compose!" + +## Delete the containers running via compose down. +.PHONY: compose-down +compose-down: + docker compose down -v --remove-orphans || true + +.score-k8s/state.yaml: + score-k8s init \ + --no-sample \ + --provisioners https://raw.githubusercontent.com/score-spec/community-provisioners/refs/heads/main/service/score-k8s/10-service.provisioners.yaml \ + --patch-templates https://raw.githubusercontent.com/score-spec/community-patchers/refs/heads/main/score-k8s/unprivileged.tpl + +manifests.yaml: ad/score.yaml cart/score.yaml currency/score.yaml email/score.yaml payment/score.yaml productcatalog/score.yaml recommendation/score.yaml shipping/score.yaml checkout/score.yaml frontend/score.yaml loadgenerator/score.yaml .score-k8s/state.yaml Makefile + score-k8s generate \ + ad/score.yaml \ + cart/score.yaml \ + currency/score.yaml \ + email/score.yaml \ + payment/score.yaml \ + productcatalog/score.yaml \ + recommendation/score.yaml \ + shipping/score.yaml \ + checkout/score.yaml + score-k8s generate \ + frontend/score.yaml \ + --override-property containers.frontend.variables.FRONTEND_MESSAGE="Hello, Score Kubernetes!" + score-k8s generate \ + loadgenerator/score.yaml + +## Create a local Kind cluster. +.PHONY: kind-create-cluster +kind-create-cluster: + ./scripts/setup-kind-cluster.sh + +## Load the local container image in the current Kind cluster. +.PHONY: kind-load-image +kind-load-image: + kind load docker-image ${CONTAINER_IMAGE} + +NAMESPACE ?= default +## Generate a manifests.yaml file from the score spec, deploy it to Kubernetes and wait for the Pods to be Ready. +.PHONY: k8s-up +k8s-up: manifests.yaml + kubectl apply \ + -f manifests.yaml \ + -n ${NAMESPACE} + kubectl wait deployments/frontend \ + -n ${NAMESPACE} \ + --for condition=Available \ + --timeout=90s + kubectl wait pods \ + -n ${NAMESPACE} \ + -l app.kubernetes.io/name=frontend \ + --for condition=Ready \ + --timeout=90s + +## Test the expose frontend app +.PHONY: k8s-test +k8s-test: k8s-up + curl $$(score-k8s resources get-outputs dns.default#frontend.dns --format '{{ .host }}') | grep "Hello, Score Kubernetes!" + +## Delete the deployment of the local container in Kubernetes. +.PHONY: k8s-down +k8s-down: + kubectl delete \ + -f manifests.yaml \ + -n ${NAMESPACE} \ No newline at end of file diff --git a/samples/onlineboutique/README.md b/samples/onlineboutique/README.md new file mode 100644 index 0000000..864e45d --- /dev/null +++ b/samples/onlineboutique/README.md @@ -0,0 +1,27 @@ +```bash +score-compose init --no-sample \ + --provisioners https://raw.githubusercontent.com/score-spec/community-provisioners/refs/heads/main/service/score-compose/10-service.provisioners.yaml +``` + +```bash +score-compose generate \ + ad/score.yaml \ + cart/score.yaml \ + currency/score.yaml \ + email/score.yaml \ + payment/score.yaml \ + productcatalog/score.yaml \ + recommendation/score.yaml \ + shipping/score.yaml \ + checkout/score.yaml \ + frontend/score.yaml \ + loadgenerator/score.yaml +``` + +```bash +docker compose up --build -d --remove-orphans +``` + +```bash +curl $$(score-compose resources get-outputs dns.default#frontend.dns --format '{{ .host }}:8080') +``` \ No newline at end of file diff --git a/samples/onlineboutique/ad/score.yaml b/samples/onlineboutique/ad/score.yaml new file mode 100644 index 0000000..75b5dbd --- /dev/null +++ b/samples/onlineboutique/ad/score.yaml @@ -0,0 +1,22 @@ +apiVersion: score.dev/v1b1 +metadata: + name: ad + annotations: + tags: "java,backend,grpc" +containers: + ad: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/adservice:v0.10.4 + variables: + PORT: "9555" + resources: + limits: + memory: "150Mi" + cpu: "280m" + requests: + memory: "120Mi" + cpu: "250m" +service: + ports: + grpc: + port: 9555 + targetPort: 9555 \ No newline at end of file diff --git a/samples/onlineboutique/cart/score.yaml b/samples/onlineboutique/cart/score.yaml new file mode 100644 index 0000000..5cd2e7c --- /dev/null +++ b/samples/onlineboutique/cart/score.yaml @@ -0,0 +1,25 @@ +apiVersion: score.dev/v1b1 +metadata: + name: cart + annotations: + tags: "dotnet,backend,grpc" +containers: + cart: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/cartservice:v0.10.4 + variables: + REDIS_ADDR: "${resources.redis-cart.host}:${resources.redis-cart.port},user=${resources.redis-cart.username},password=${resources.redis-cart.password}" + resources: + limits: + memory: "90Mi" + cpu: "220m" + requests: + memory: "70Mi" + cpu: "200m" +resources: + redis-cart: + type: redis +service: + ports: + grpc: + port: 7070 + targetPort: 7070 \ No newline at end of file diff --git a/samples/onlineboutique/checkout/score.yaml b/samples/onlineboutique/checkout/score.yaml new file mode 100644 index 0000000..c4a3eaf --- /dev/null +++ b/samples/onlineboutique/checkout/score.yaml @@ -0,0 +1,41 @@ +apiVersion: score.dev/v1b1 +metadata: + name: checkout + annotations: + tags: "golang,backend,grpc" +containers: + checkout: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/checkoutservice:v0.10.4 + variables: + CART_SERVICE_ADDR: "${resources.cart.name}:7070" + CURRENCY_SERVICE_ADDR: "${resources.currency.name}:7000" + EMAIL_SERVICE_ADDR: "${resources.email.name}:5000" + PAYMENT_SERVICE_ADDR: "${resources.payment.name}:50051" + PORT: "5050" + PRODUCT_CATALOG_SERVICE_ADDR: "${resources.productcatalog.name}:3550" + SHIPPING_SERVICE_ADDR: "${resources.shipping.name}:50051" + resources: + limits: + memory: "80Mi" + cpu: "60m" + requests: + memory: "60Mi" + cpu: "40m" +resources: + cart: + type: service + currency: + type: service + email: + type: service + payment: + type: service + productcatalog: + type: service + shipping: + type: service +service: + ports: + grpc: + port: 5050 + targetPort: 5050 \ No newline at end of file diff --git a/samples/onlineboutique/currency/score.yaml b/samples/onlineboutique/currency/score.yaml new file mode 100644 index 0000000..541b437 --- /dev/null +++ b/samples/onlineboutique/currency/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +metadata: + name: currency + annotations: + tags: "node,backend,grpc" +containers: + currency: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/currencyservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "7000" + resources: + limits: + memory: "90Mi" + cpu: "140m" + requests: + memory: "70Mi" + cpu: "120m" +service: + ports: + grpc: + port: 7000 + targetPort: 7000 \ No newline at end of file diff --git a/samples/onlineboutique/email/score.yaml b/samples/onlineboutique/email/score.yaml new file mode 100644 index 0000000..e166264 --- /dev/null +++ b/samples/onlineboutique/email/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +metadata: + name: email + annotations: + tags: "python,backend,grpc" +containers: + email: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/emailservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "8080" + resources: + limits: + memory: "70Mi" + cpu: "130m" + requests: + memory: "50Mi" + cpu: "110m" +service: + ports: + grpc: + port: 5000 + targetPort: 8080 \ No newline at end of file diff --git a/samples/onlineboutique/frontend/score.yaml b/samples/onlineboutique/frontend/score.yaml new file mode 100644 index 0000000..d9a0868 --- /dev/null +++ b/samples/onlineboutique/frontend/score.yaml @@ -0,0 +1,74 @@ +apiVersion: score.dev/v1b1 +metadata: + name: frontend + annotations: + tags: "golang,html,css,ui,http,website" +containers: + frontend: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/frontend:v0.10.4 + livenessProbe: + httpGet: + path: /_healthz + port: 8080 + httpHeaders: + - name: Cookie + value: shop_session-id=x-liveness-probe + readinessProbe: + httpGet: + path: /_healthz + port: 8080 + httpHeaders: + - name: Cookie + value: shop_session-id=x-readiness-probe + variables: + AD_SERVICE_ADDR: "${resources.ad.name}:9555" + CART_SERVICE_ADDR: "${resources.cart.name}:7070" + CHECKOUT_SERVICE_ADDR: "${resources.checkout.name}:5050" + CURRENCY_SERVICE_ADDR: "${resources.currency.name}:7000" + ENABLE_PROFILER: "0" + PAYMENT_SERVICE_ADDR: "${resources.payment.name}:50051" + PORT: "8080" + PRODUCT_CATALOG_SERVICE_ADDR: "${resources.productcatalog.name}:3550" + RECOMMENDATION_SERVICE_ADDR: "${resources.recommendation.name}:8080" + SHIPPING_SERVICE_ADDR: "${resources.shipping.name}:50051" + SHOPPING_ASSISTANT_SERVICE_ADDR: "not-used-yet:8080" + CYMBAL_BRANDING: "false" + FRONTEND_MESSAGE: "" + ENABLE_ASSISTANT: "false" + resources: + limits: + memory: "50Mi" + cpu: "50m" + requests: + memory: "30Mi" + cpu: "30m" +resources: + ad: + type: service + cart: + type: service + checkout: + type: service + currency: + type: service + dns: + type: dns + route: + type: route + params: + host: ${resources.dns.host} + path: / + port: 8080 + payment: + type: service + productcatalog: + type: service + recommendation: + type: service + shipping: + type: service +service: + ports: + http: + port: 8080 + targetPort: 8080 \ No newline at end of file diff --git a/samples/onlineboutique/loadgenerator/score.yaml b/samples/onlineboutique/loadgenerator/score.yaml new file mode 100644 index 0000000..224bc69 --- /dev/null +++ b/samples/onlineboutique/loadgenerator/score.yaml @@ -0,0 +1,21 @@ +apiVersion: score.dev/v1b1 +metadata: + name: loadgenerator + annotations: + tags: "python" +containers: + loadgenerator: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/loadgenerator:v0.10.4 + variables: + FRONTEND_ADDR: "${resources.frontend.name}:80" + USERS: "10" + resources: + limits: + memory: "220Mi" + cpu: "100m" + requests: + memory: "200Mi" + cpu: "80m" +resources: + frontend: + type: service \ No newline at end of file diff --git a/samples/onlineboutique/payment/score.yaml b/samples/onlineboutique/payment/score.yaml new file mode 100644 index 0000000..776d380 --- /dev/null +++ b/samples/onlineboutique/payment/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +metadata: + name: payment + annotations: + tags: "node,backend,grpc" +containers: + payment: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/paymentservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "50051" + resources: + limits: + memory: "50Mi" + cpu: "30m" + requests: + memory: "30Mi" + cpu: "10m" +service: + ports: + grpc: + port: 50051 + targetPort: 50051 \ No newline at end of file diff --git a/samples/onlineboutique/productcatalog/score.yaml b/samples/onlineboutique/productcatalog/score.yaml new file mode 100644 index 0000000..0f5429f --- /dev/null +++ b/samples/onlineboutique/productcatalog/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +metadata: + name: productcatalog + annotations: + tags: "golang,backend,grpc" +containers: + productcatalog: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/productcatalogservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "3550" + resources: + limits: + memory: "40Mi" + cpu: "30m" + requests: + memory: "20Mi" + cpu: "10m" +service: + ports: + grpc: + port: 3550 + targetPort: 3550 \ No newline at end of file diff --git a/samples/onlineboutique/recommendation/score.yaml b/samples/onlineboutique/recommendation/score.yaml new file mode 100644 index 0000000..45c5f6a --- /dev/null +++ b/samples/onlineboutique/recommendation/score.yaml @@ -0,0 +1,27 @@ +apiVersion: score.dev/v1b1 +metadata: + name: recommendation + annotations: + tags: "golang,backend,grpc" +containers: + recommendation: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/recommendationservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "8080" + PRODUCT_CATALOG_SERVICE_ADDR: "${resources.productcatalog.name}:3550" + resources: + limits: + memory: "70Mi" + cpu: "30m" + requests: + memory: "50Mi" + cpu: "10m" +service: + ports: + grpc: + port: 8080 + targetPort: 8080 +resources: + productcatalog: + type: service \ No newline at end of file diff --git a/samples/onlineboutique/shipping/score.yaml b/samples/onlineboutique/shipping/score.yaml new file mode 100644 index 0000000..5ded526 --- /dev/null +++ b/samples/onlineboutique/shipping/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +metadata: + name: shipping + annotations: + tags: "golang,backend,grpc" +containers: + shipping: + image: us-central1-docker.pkg.dev/google-samples/microservices-demo/shippingservice:v0.10.4 + variables: + DISABLE_PROFILER: "1" + PORT: "50051" + resources: + limits: + memory: "30Mi" + cpu: "30m" + requests: + memory: "10Mi" + cpu: "10m" +service: + ports: + grpc: + port: 50051 + targetPort: 50051 \ No newline at end of file