{"id":20695091,"url":"https://github.com/ibm-cloud-architecture/vaccine-order-optimizer","last_synced_at":"2025-09-27T07:30:47.710Z","repository":{"id":52878454,"uuid":"289039967","full_name":"ibm-cloud-architecture/vaccine-order-optimizer","owner":"ibm-cloud-architecture","description":null,"archived":false,"fork":false,"pushed_at":"2024-09-16T12:09:48.000Z","size":766,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-17T00:07:55.042Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ibm-cloud-architecture.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-08-20T15:18:49.000Z","updated_at":"2021-04-15T11:40:28.000Z","dependencies_parsed_at":"2022-08-23T04:31:12.578Z","dependency_job_id":null,"html_url":"https://github.com/ibm-cloud-architecture/vaccine-order-optimizer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Fvaccine-order-optimizer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Fvaccine-order-optimizer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Fvaccine-order-optimizer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ibm-cloud-architecture%2Fvaccine-order-optimizer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ibm-cloud-architecture","download_url":"https://codeload.github.com/ibm-cloud-architecture/vaccine-order-optimizer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234406523,"owners_count":18827618,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-17T00:07:59.878Z","updated_at":"2025-09-27T07:30:42.404Z","avatar_url":"https://github.com/ibm-cloud-architecture.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vaccine Order \u0026 Reefer Optimization\n\nThe use case and business problem addressed in this repository is described in [this article](https://ibm-cloud-architecture.github.io/vaccine-solution-main/design/voro/) of the main vaccine solution repository.\n\nThis repository is the implementation of a microservice that exposes API to do the order and refrigerated tank shipping plan optimization. This component works as event consumers to get orders, vaccine lots manufactured, and transportation information and as a producer for the shipment plans. The optimization is done with a small model with [Decision Optimization Cplex for python](https://pypi.org/project/docplex/) running in the same process, in production and bigger data model CPLEX needs to run on Cloud Pak for Data. \n\nThe following diagram illustrates all the components working together to support an event-driven shipment plan optimization:\n\n![](./docs/images/voro-components.png)\n\nIn term of Kafka processing this component illustrates the use of AVRO schema and schema registry.\n\n## Code Explanation\n\nThe [app.py](https://github.com/ibm-cloud-architecture/vaccine-order-optimizer/blob/master/app.py) includes the main code to start a Flask server. It defines APIs, starts the different Kafka Consumers:\n\n* ReeferConsumer: for getting information about the refrigerator release and availability\n* InventoryConsumer: about vaccine lot inventory\n* TransportationConsumer: getting transportation constraints.\n* OrderConsumer: get the orders from the order command service.\n\nThe code exposes a POST order operation to simplify testing, combined with a POST populate test data for quick demonstration and then produces updated shipment plan to integrate the new order.\n\nThe `data/avro` folder includes the different schema definition.\n\n## Build\n\nSimply build the docker image with the command `./script/buildAdd.sh` which does:\n\n```shell\ndocker build -t ibmcase/vaccine-order-optimizer .\ndocker push ibmcase/vaccine-order-optimizer\n```\n\nThe `./scripts/buildAll.sh` perform the previous steps.\n\nThe repository includes a [github action workflow](https://github.com/ibm-cloud-architecture/vaccine-order-optimizer/blob/master/.github/workflows/dockerbuild.yaml) to build and push the image automatically to the [public docker registry.](https://hub.docker.com/repository/docker/ibmcase/vaccine-order-optimizer)\n\nThe flow uses a set of secrets in the git repo:\n\n* DOCKER_IMAGE_NAME = vaccine-order-optimizer\n* DOCKER_REPOSITORY = ibmcase\n* DOCKER_USERNAME and DOCKER_PASSWORD\n* DOCKER_REGISTRY = quay.io\n\n## Run locally with docker compose\n\nStarts Apicurio, Kafka, Zookeeper and the Optimizer.\n\n```shell\ndocker-compose up -d\n```\n\n## Run locally\n\nTo run the application locally but remote connected to Kafka deployed on OpenShift do the following:\n\n* Get the Kafka URL, schema registry URL, the user and password and any pem file containing the server certificate.\n* The certificate needs to be under certs folder.\n* Copy the script/setenv-tmpl.sh  to script/setenv.sh\n* Modify the environment variables.\n\n```shell\nsource ./script/setenv.sh\n\ndocker run -ti -e KAFKA_BROKERS=$KAFKA_BROKERS -e SCHEMA_REGISTRY_URL=$SCHEMA_REGISTRY_URL -e REEFER_TOPIC=$REEFER_TOPIC -e INVENTORY_TOPIC=$INVENTORY_TOPIC -e TRANSPORTATION_TOPIC=$TRANSPORTATION_TOPIC -e KAFKA_USER=$KAFKA_USER -e KAFKA_PASSWORD=$KAFKA_PASSWORD -e KAFKA_CERT=$KAFKA_CERT -p 5000:5000  ibmcase/vaccine-order-optimizer\n```\n\nThe swagger looks like:\n\n![](./docs/images/oro-swagger.png)\n\nIf you want to run this image and be able to continuously update the code, run the docker container with:\n\n```shell\ndocker run -ti -e KAFKA_BROKERS=$KAFKA_BROKERS -e SCHEMA_REGISTRY_URL=$SCHEMA_REGISTRY_URL -e REEFER_TOPIC=$REEFER_TOPIC -e INVENTORY_TOPIC=$INVENTORY_TOPIC -e TRANSPORTATION_TOPIC=$TRANSPORTATION_TOPIC -e KAFKA_USER=$KAFKA_USER -e KAFKA_PASSWORD=$KAFKA_PASSWORD -e KAFKA_CERT=$KAFKA_CERT -p 5000:5000  -v ${pwd}:/app ibmcase/vaccine-order-optimizer bash\n```\n\n## Deploy to OpenShift with Strimzi\n\nThe [vaccine-gitops](https://github.com/ibm-cloud-architecture/vaccine-gitops) project includes all the needed Kustomization manifests to deploy Kafka, and the Vaccine Order Optimizer component.\n\nIt can be summarized as:\n\n```shell\n\n```\n\n## Deploy to OpenShift with EventStreams as Kafka\n\nTB refresh\n* Connect to the vaccine project using: `oc project vaccine`\n* Modify the kubernetes/configmap.yaml with the Kafka Broker URL you are using, and if you changed the topic names too. Then do:\n\n ```shell\n oc apply -f kubernetes/configmap.yaml\n ```\n\n* Get pem certificate from eventstreams or the Kafka cluster project to the local vaccine project with a command like:\n\n ```shell\n oc get secret light-es-cluster-cert-pem  -n eventstreams --export -o yaml | oc apply -f - \n ```\n \n This pem file is mounted to the pod via the secret as:\n\n   ```yaml\n   volumeMounts:\n  - mountPath: /certs\n    name: eventstreams-cert-pem\n  volumes:\n  - name: eventstreams-cert-pem\n    secret:\n      secretName: light-es-cluster-cert-pem\n  ```\n\n and the path for the python code to access this pem file is defined in the environment variable: \n\n ```yaml\n  - name: KAFKA_CERT\n    value: /app/certs/es-cert.pem\n ```\n\n the name of the file is equal to the name of the {.data.es-cert.pem} field in the secret.\n \n ```yaml\n Name:         eventstreams-cert-pem\n Namespace:    vaccine\n Labels:       \u003cnone\u003e\n Annotations:  \u003cnone\u003e\n\n Type:  Opaque\n\n Data\n ====\n es-cert.pem:  1164 bytes\n ```\n\n* Copy the Kafka user's secret from the `eventstreams` or Kafka project to the current vaccine project. This secret has two data fields: username and password\n\n ```shell\n oc get secret eventstreams-cred -n eventstreams --export -o yaml | oc apply -f - \n ```\n\nThey are used in the Deployment configuration as:\n\n ```yaml\n - name: KAFKA_USER\n    valueFrom:\n      secretKeyRef:\n        key: username\n        name: eventstreams-cred\n  - name: KAFKA_PASSWORD\n    valueFrom:\n      secretKeyRef:\n        key: password\n        name: eventstreams-cred\n ```\n\n* Deploy the application using: `oc apply -f kubernetes/app-deployment.yaml`\n* Get the routes to the external exposed URL:\n\n ```shell\n  oc describe routes vaccine-order-optimizer \n ```\n \n* Validate the swagger by accessing the route: `http://vaccine-order-optimizer-vaccine......cloud/apidocs/`\n* Trigger the data loading with the operation:\n \n ```shell\n curl -X POST  http://vaccine-order-optimizer-vaccine......cloud/api/v1/optimize/loadData\"\n ```\n\n* Send a new order\n\n ```shell\n curl -X POST -H \"Content-Type: application/json\" http://vaccine-order-optimizer-vaccine......cloud/    --data \"@./data/order1.json\"\n ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-cloud-architecture%2Fvaccine-order-optimizer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fibm-cloud-architecture%2Fvaccine-order-optimizer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fibm-cloud-architecture%2Fvaccine-order-optimizer/lists"}