Endpoint
backend-openapi.yaml
(view on GitHub)
:
---
openapi: 3.0.2
info:
title: Order Service API
version: 0.1.0
description: Simple Order Service API
contact:
name: Laurent Broudoux
url: https://github.com/lbroudoux
email: laurent@microcks.io
license:
name: MIT License
url: https://opensource.org/licenses/MIT
paths:
/orders:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/OrderInfo'
examples:
valid_order:
value:
customerId: lbroudoux
productQuantities:
- productName: Millefeuille
quantity: 1
- productName: Eclair Cafe
quantity: 2
totalPrice: 9.4
invalid_order:
value:
customerId: lbroudoux
productQuantities:
- productName: Millefeuille
quantity: 1
- productName: Eclair Chocolat
quantity: 1
totalPrice: 4.8
responses:
"201":
content:
application/json:
schema:
$ref: '#/components/schemas/OrderInfo'
examples:
valid_order:
value:
id: 5455c8e8-087a-426e-8440-65c8c005d871
status: CREATED
customerId: lbroudoux
productQuantities:
- productName: Millefeuille
quantity: 1
- productName: Eclair Cafe
quantity: 2
totalPrice: 9.4
description: Order is correct and has been created
"422":
content:
application/json:
schema:
$ref: '#/components/schemas/UnavailableProduct'
examples:
invalid_order:
value:
productName: Eclair Chocolat
details: Eclair Chocolat are not available at the moment
description: "Order cannot be processed because of a validation error (ex:\
\ unavailable product)"
operationId: PlaceOrder
summary: Place a new Order
description: Place a new Order in the system. Will perform extra checks before
saving Order to detect invalid demand
components:
schemas:
OrderInfo:
description: Represents info needed for creating an Order
required:
- customerId
- productQuantities
- totalPrice
type: object
properties:
customerId:
description: Identifier of customer of this order
type: string
productQuantities:
description: Desired products and quantities for this order
type: array
items:
$ref: '#/components/schemas/ProductQuantity'
totalPrice:
format: double
description: Total price of the order
type: number
ProductQuantity:
description: Association of product name with quantity
required:
- productName
- quantity
type: object
properties:
productName:
description: Desired product name
type: string
quantity:
description: Desired quantity
type: integer
Order:
description: Full created Order with all informations
type: object
allOf:
- required:
- id
- status
type: object
properties:
id:
description: Unique identifier of order
type: string
status:
description: Status of Order
enum:
- CREATED
- VALIDATED
- CANCELED
- FAILED
type: string
- $ref: '#/components/schemas/OrderInfo'
UnavailableProduct:
description: ""
required:
- productName
type: object
properties:
productName:
description: ""
type: string
details:
description: Details of unavailability
type: string
score.yaml
(view on GitHub)
:
apiVersion: score.dev/v1b1
metadata:
name: frontend
containers:
frontend:
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo Hello $SERVICE_DEP!; sleep 5; done"]
variables:
SERVICE_DEP: ${resources.backend.url}/0.1.0/orders
service:
ports:
tcp:
port: 8080
targetPort: 80
resources:
backend:
type: endpoint
params:
port: 8181
openapi_file: ./backend-openapi.yaml
openapi_title: Order Service API
10-endpoint-with-microcks.provisioners.yaml
(view on GitHub)
:
- uri: template://custom-provisioners/endpoint-with-microcks
type: endpoint
description: Outputs an endpoint URL for connecting to an other workload (a Microcks mock is generated if not found).
init: |
hostname: {{ splitList "." .Id | last }}
{{ $parsedPath := .Params.openapi_file | splitList "/" }}
{{ if eq (len $parsedPath) 0 }}
resourcesPath: "."
{{ else }}
resourcesPath: {{ trimSuffix (last $parsedPath) .Params.openapi_file | trimSuffix "/" }}
{{ end }}
supported_params:
- port
- openapi_file
- openapi_title
outputs: |
{{ $w := (index .WorkloadServices .Init.hostname) }}
{{ if or (not $w) (not $w.ServiceName) }}
url: http://localhost:9090/rest/{{ .Params.openapi_title | replace " " "+" }}
{{ else }}
url: http://{{ .Init.hostname }}:{{ .Params.port }}
{{ end }}
expected_outputs:
- url
services: |
{{ $w := (index .WorkloadServices .Init.hostname) }}
{{ if or (not $w) (not $w.ServiceName) }}
{{ .Init.hostname }}-mock:
image: quay.io/microcks/microcks-cli:latest
restart: always
entrypoint:
- "microcks-cli"
- "import"
- "{{ .Params.openapi_file }}:true"
- "--microcksURL=http://microcks:8080/api"
- "--insecure"
- "--keycloakClientId=foo"
- "--keycloakClientSecret=bar"
cap_drop:
- ALL
read_only: true
user: "65532"
volumes:
- type: bind
source: {{ .Init.resourcesPath }}
target: /resources
read_only: true
depends_on:
microcks:
condition: service_started
required: true
{{ end }}
Initialize your local workspace, by importing a specific community provisioner:
score-compose init --provisioners REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml
Note: you need to replace REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml by the actual provisioner file you want to use and import. More information here.
Get the provisioners definition:
score-compose provisioners list
Generate the platform specific manifests:
score-compose generate score.yaml
See the resource outputs:
score-compose resources list
You can run the following command on each resource listed with the previous command to get their outputs:
score-compose resources get-outputs
Deploy the generated manifests:
docker compose up -d
See the running containers:
docker ps
10-endpoint-with-microcks-cli.provisioners.yaml
(view on GitHub)
:
- uri: cmd://bash#endpoint-with-microcks-cli
type: endpoint
description: Outputs an endpoint URL for connecting to an other workload (a Microcks mock is generated if not found).
supported_params:
- port
- openapi_file
expected_outputs:
- url
args:
- -c
- |
STDIN=$(cat)
PARAM_PORT=$(echo $STDIN | yq eval -p json '.resource_params.port')
PARAM_OPENAPI_FILE=$(echo $STDIN | yq eval -p json '.resource_params.openapi_file')
WORKLOAD=$(echo $STDIN | yq eval -p json '.resource_id | split(".") | .[-1]')
WORKLOAD_EXISTS=$(echo $STDIN | WORKLOAD=${WORKLOAD} yq eval -p json '.workload_services | has(strenv(WORKLOAD))')
URL_HOSTNAME=${WORKLOAD}:${PARAM_PORT}
URL_SCHEME="http"
URL_PATH=""
if [ "$WORKLOAD_EXISTS" != "true" ]; then
URL_HOSTNAME="microcks.127.0.0.1.nip.io"
URL_SCHEME="https"
SPEC_FILE="${PARAM_OPENAPI_FILE}"
URL_PATH=/rest/$(cat $SPEC_FILE | yq eval '.info.title' | yq '. |= sub(" ", "+")')
set -eu -o pipefail
microcks import ${SPEC_FILE}:true --microcksURL=https://${URL_HOSTNAME} --insecure-tls --keycloakClientId=foo --keycloakClientSecret=bar >&2
fi
OUTPUTS='{"resource_outputs":{"url":"%s://%s%s"},"manifests":[]}'
printf "$OUTPUTS" "$URL_SCHEME" "$URL_HOSTNAME" "$URL_PATH"
README.md
(view on GitHub)
:
Prerequisites:
- Have `yq` installed to load resource's params.
- Have `microcks` CLI installed to import the API service into Microcks.
Initialize your local workspace, by importing a specific community provisioner:
score-k8s init --provisioners REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml
Note: you need to replace REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml by the actual provisioner file you want to use and import. More information here.
Get the provisioners definition:
score-k8s provisioners list
Generate the platform specific manifests:
score-k8s generate score.yaml
See the resource outputs:
score-k8s resources list
You can run the following command on each resource listed with the previous command to get their outputs:
score-k8s resources get-outputs
Deploy the generated manifests:
kubectl apply -f manifests.yaml
See the running containers:
kubectl get all