{"id":22164795,"url":"https://github.com/halkyonio/primaza-poc","last_synced_at":"2025-07-26T11:31:39.528Z","repository":{"id":62632317,"uuid":"551417624","full_name":"halkyonio/primaza-poc","owner":"halkyonio","description":"Quarkus Primaza Application - POC","archived":false,"fork":false,"pushed_at":"2024-05-06T10:22:29.000Z","size":1281,"stargazers_count":1,"open_issues_count":20,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-05-06T11:36:01.636Z","etag":null,"topics":["discovery-service","kubernetes","service-binding","vault"],"latest_commit_sha":null,"homepage":"","language":"HTML","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/halkyonio.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-14T11:09:56.000Z","updated_at":"2024-05-06T10:22:33.000Z","dependencies_parsed_at":"2023-02-09T02:00:22.473Z","dependency_job_id":"2e48b97e-5434-4ce4-9f11-2b5d9fa290d3","html_url":"https://github.com/halkyonio/primaza-poc","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halkyonio%2Fprimaza-poc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halkyonio%2Fprimaza-poc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halkyonio%2Fprimaza-poc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halkyonio%2Fprimaza-poc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/halkyonio","download_url":"https://codeload.github.com/halkyonio/primaza-poc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227674005,"owners_count":17802303,"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":["discovery-service","kubernetes","service-binding","vault"],"created_at":"2024-12-02T05:10:28.851Z","updated_at":"2024-12-02T05:10:29.443Z","avatar_url":"https://github.com/halkyonio.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/halkyonio/primaza-poc/graphs/contributors\" alt=\"Contributors\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/contributors/halkyonio/primaza-poc\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/halkyonio/primaza-poc/pulse\" alt=\"Activity\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/commit-activity/m/halkyonio/primaza-poc\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/halkyonio/primaza-poc/actions/workflows/push.yml\" alt=\"Build Status\"\u003e\n        \u003cimg src=\"https://github.com/halkyonio/primaza-poc/actions/workflows/push.yml/badge.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nTable of Contents\n=================\n\n* [Introduction](#introduction)\n* [Primaza initiative](#primaza-initiative)\n  * [How it works](#how-it-works)\n  * [How to play/demo](#how-to-playdemo)\n    * [Running the application locally](#running-the-application-locally)\n    * [Using Primaza on a k8s cluster](#using-primaza-on-a-k8s-cluster)\n  * [Demo time](#demo-time)\n  * [Use cases](#use-cases)\n    * [Service discovered](#service-discovered)\n    * [Service deployed using Crossplane](#service-deployed-using-crossplane)\n\n# Introduction\n\nModern runtime applications designed to be `Cloud Native` must also been able to connect to `backend` systems (SQL, NoSQL, Broker, etc) as this is the case for applications\nrunning on physical or virtual machines.\n\nTo access a system, it is needed to configure different resources (e.g. Datasource) and to declare different parameters (e.g jdbc url, username, password, database name) using\nby example for Spring Boot or Quarkus runtimes such a configuration config file: `application.properties` able to configure the connection with a SQL database.\n\nTo avoid to hard code such parameters, we use mostly a kubernetes secret and pass the needed information as a list of key/value pairs.\n\n```text\ntype: postgresql\nprovider: bitnami\ndatabase: fruits_database\nuri: postgresql:5432\nusername: healthy\npassword: healthy\n```\n\nThis approach is subject to different problems as:\n- Creating a YAML file to pass the information is `error prone`,\n- It is sometimes not trivial to figure out for a user, according to the target platforms (dev, test, etc), the parameters,\n- It exposes some sensitive data like the password to persons which are not authorized to access a backend system,\n- The consumer of the backend service must spend time to discover how the service will or has been installed to collect the parameters and to map them to their `application.properties`\n- The Service provider do not use a stadardize way to set the different properties according to a standard. \n- The [Service Binding spec](https://github.com/servicebinding/spec#well-known-secret-entries) do not even recommend how, according to a service type (SQL, etc) the parameters should be named\n\n# Primaza initiative\n\nPrimaza name comes from the Greek word πρυμάτσα, which represent a `stern line` used to tie [boats](https://en.wikipedia.org/wiki/Mooring) to the dock.\n\nPrimaza aims to support the discoverability, life cycle management \u0026 connection of services running in Kubernetes (or outside) with a runtime applications.\n\nPrimaza introduces new concepts supporting such a vision:\n\n- Claim: corresponds to a way for an application developer to express which service, version, environment, etc their application requires to access and how they would like to get back the information.\n- Service Identity: represents things like a SQL, NoSQL database, messaging brokers, LDAP server, contains metadata information able for Primaza to search/discover service deployed in an environment (e.g. dev cluster)\n- Credential: local storage of username \u0026 passwords to access a Service or path to access the information to fetch them from an external Secret store engine (e.g. vault)\n- Cluster: is a Kubernetes cluster config and will be used as target environment (dev, test, prod, etc) where services should be discovered\n\n## How it works \n\nTo bind a service to a runtime, it is needed to create a Claim CR. This claim contains the name of the service, its version and optional some additional parameters like: role, target environment.\n\nWhen the controller detects such a new Claim CR, then it will populate a request and will call the Primaza Claim REST endpoint.\n\nAccording to the information received, Primaza will check if a match exists between a `claim` and a `service` registered and will discover it on the target cluster (dev test, etc).\n\nTo determine if a kubernetes service is available, Primaza will use the service endpoint definition and more specifically the `protocol:port` of the service to be watched.\n\nNext, the credential associated with the service will be retrieved locally or using a secret store and a secret will be created containing as information:\n\n```text\ntype     // Service Type: postgresql, mysql\nprovider // Service provider: bitnami, etc\nuri      // kubernetes DNS name and port\nusername // user to be used to access the service\npassword // Password to be used to access the service\ndatabase // (optional): Database name to connect to a SQL database\n```\nThe secret is created under the namespace of the application and a volume is created, part of the application to mount the secret using the [workload projection](https://github.com/servicebinding/spec#workload-projection) convention.\n\n## How to play/demo\n\nTo use `primaza`, it is needed to perform a couple of things like:\n\n- Setup a kubernetes cluster\n- Deploy a backend service such as MySQL, Postgresql, etc on a k8s cluster (minikube, kind, etc)\n- Install Primaza (or run it locally)\n- Tell to Primaza how to access the different clusters `http://localhost:8080/clusters/new`\n- Define the Service `http://localhost:8080/services/new` to let Primaza to discover it\n- Create the Credential or path to access the credential from a secret store `http://localhost:8080/credentials/new`\n- Create a claim to bind the backend service to your application `http://localhost:8080/claims/new`\n\n### Running the application locally\n\nYou can run the quarkus primaza application in dev mode using the command:\n```shell script\ncd app\n./mvnw compile quarkus:dev\n```\nThe command will launch the runtime at the following address: `http://localhost:8080` \nbut will also run different containers:  database (h2) \u0026 vault secret engine if your docker or podman daemon is running locally !\n\nYou can discover the [quarkus dev services](https://quarkus.io/guides/dev-services) and injected config by pressing on the key `c` within your terminal.\n\nNext follow then the instructions of the [Demo time](#demo-time) section :-)\n\n### Using Primaza on a k8s cluster\n\nIn order to use Primaza on kubernetes, it is needed first to setup a cluster (kind, minikube, etc) and to install an ingress controller.\nYou can use the following script able to install using kind a kubernetes cluster locally:\n```bash\ncurl -s -L \"https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/kind.sh\" | bash -s install\n```\n\u003e **Remark**: To see all the options proposed by the script, use the command `curl -s -L \"https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/kind.sh\" | bash -s -h`\n\nIf the cluster is up and running, install vault using the following script `./scripts/vault.sh`. We recommend to use this script as it is needed to perform different steps\npost vault installation such as: \n- unseal, \n- store root token within the local folder `.vault/cluster-keys.json`, \n- install kv2 secret engine, \n- populate a policy, \n- assign the policy to a user `bob` and password` sinclair`\n\n\u003e **Note**: If creation of the vault's pod is taking more than 60s as the container image must be downloaded, then the process will stop.\nIn this case, remove the helm chart `./scripts/vault.sh remove` and repeat the operation.\n\n\u003e **Tip**: Notice the messages displayed within the terminal as they told you how to get the root token and where they are stored, where to access the keys, etc !\n\nWe can now install Crossplane and its Helm provider\n```bash\n./scripts/crossplane.sh\n```\n\u003e **Tip**: Script usage is available using the `-h` parameter\n\nCreate the primaza namespace\n```bash\nkubectl create namespace primaza\n```\nSet the `VAULT_URL` variable to let primaza to access storage engine using the Kubernetes DNS service name:\n```bash\nexport VAULT_URL=http://vault-internal.vault:8200\n```\nNext, deploy Primaza and its Postgresql DB using the following helm chart\n```bash\nhelm install \\\n  --devel \\\n  --repo https://halkyonio.github.io/helm-charts \\\n  primaza-app \\\n  primaza-app \\\n  -n primaza \\\n  --set app.image=\u003cCONTAINER_REGISTRY\u003e/\u003cORG\u003e/primaza-app:latest \\\n  --set app.host=primaza.${VM_IP}.nip.io \\\n  --set app.envs.vault.url=${VAULT_URL}\n```\n\u003e **Tip**: When the pod is started, you can access Primaza using its ingress host url: `http://primaza.\u003cVM_IP\u003e.nip.io`\n\nIf you prefer to install everything all-in-one, use our bash scripts on a `kind` k8s cluster:\n```bash\nVM_IP=\u003cVM_IP\u003e\nexport VAULT_URL=http://vault-internal.vault:8200\nexport PRIMAZA_IMAGE_NAME=kind-registry:5000/local/primaza-app\n$(pwd)/scripts/vault.sh\n$(pwd)/scripts/crossplane.sh\n$(pwd)/scripts/primaza.sh build\n$(pwd)/scripts/primaza.sh localdeploy\n```\n\n\u003e **Note**: If you prefer to use the helm chart pushed on [Halkyon repository](https://github.com/halkyonio/helm-charts), don't use the parameters `build` and `localdeploy`\n\nAnd now, you can demo it ;-)\n\n## Demo time\n\nTo play with Primaza, you can use the following scenario: \n\n- Launch `primaza` locally and open your browser at the address `http://localhost:8080`\n- Create the `cluster` and `service` records\n- Go to the screen of the `discover`. It should be empty as no backend service currently runs\n- Install a database backend service (e.g Postgresql)\n- Go back to the screen of the `discover`. It should be there\n- Create for the `registered service` its `credential`\n- Install the Quarkus Atomic Fruits application\n- When the application will start, then it will crash as atomic fruits cannot yet access the `fruits` database\n- Create a `claim` to tell to Primaza that the Atomic fruits app would like to access a Posgresql DB\n- Select the `Quarkus Fruits application` from the screen `applications` and click on the button `claim`\n- Select the claim to bind from the list\n- If the binding succeeded, then the status should be `bound` and the ingress URL should be displayed\n\nEverything is in place to claim a Service using the following commands:\n\n- Deploy the Quarkus Fruits application within the namespace `app`\n  ```bash\n  helm install fruits-app halkyonio/fruits-app \\\n    -n app --create-namespace \\\n    --set app.image=quay.io/halkyonio/atomic-fruits:latest \\\n    --set app.host=atomic-fruits.\u003cVM_IP\u003e.nip.io \\\n    --set app.serviceBinding.enabled=false \\\n    --set db.enabled=false\n  ```\n- Create an entry within the secret store engine at the path `primaza/fruits`. This path will be used to configure the credentials to access the `fruits_database`.\n  ```bash\n  // When vault runs on kubernetes\n  export VAULT_ADDR=http://vault.\u003cVM_IP\u003e.nip.io\n  vault login -method=userpass username=bob password=sinclair\n  \n  // When using mvn quarkus:dev\n  export VAULT_TOKEN=root\n  export VAULT_ADDR=http://localhost:\u003cVAULT_PORT\u003e\n  \n  // Next create the key that we need to access the Postgresql fruits db\n  vault kv put -mount=secret primaza/fruits username=healthy password=healthy database=fruits_database\n  vault kv get -mount=secret primaza/fruits\n  ```\n  \n- Create now different records to let Primaza to access the local cluster, discover the services, claim a service using the credentials stored under vault\n  ```bash\n  // When deployed on kubernetes\n  export PRIMAZA_URL=primaza.\u003cVM_IP\u003e.nip.io \n  \n  // When using quarkus:dev\n  export PRIMAZA_URL=localhost:8080\n  \n  // To be executed when steps are done manually or when using quarkus:dev\n  export KIND_URL=$(kubectl config view -o json | jq -r --arg ctx kind-kind '.clusters[] | select(.name == $ctx) | .cluster.server')\n  $(pwd)/scripts/data/cluster.sh\n  \n  // Common steps\n  $(pwd)/scripts/data/services.sh\n  $(pwd)/scripts/data/credentials.sh\n  $(pwd)/scripts/data/claims.sh\n  ```\n\n- Open the browser ate the address: `http://localhost:8080`   \n- Click on the different UI screens to verify if the cluster has been well registered and if its status is `OK`, that the application `atomic fruits`, if primaza has discovered the postgresql db\n- Select the `Atomic Fruits application` from the screen `applications` and click on the button `claim`\n- Select the claim `fruits-claim` to bind from the list and click on the button `bind`\n- Wait 1-2 seconds and refresh the screen\n- If the binding succeeded, then the status should be `bound` and the ingress URL should be displayed\n- Click on the URL to access the application's screen\n- Alternatively `curl` or `httpie` the URL (`http http://atomic-fruits.127.0.0.1.nip.io/fruits`)\n- Enjoy :-)\n\n## Use cases\n\nThis section describes different use cases that you can play manually top of a k8s cluster where:\n- Primaza, vault and crossplane have been deployed\n- Service catalog, cluster and credentials records has been populated (use for that purpose the scripts of: ./scripts/data/*.sh)\n- Vault path has been created: `vault kv put -mount=secret primaza/fruits username=healthy password=healthy database=fruits_database`\n- Deploy the Atomic Fruits helm chart\n```bash\nVM_IP=127.0.0.1\nhelm uninstall fruits-app -n app\nhelm install fruits-app halkyonio/fruits-app \\\n  -n app --create-namespace \\\n  --set app.image=quay.io/halkyonio/atomic-fruits:latest \\\n  --set app.host=atomic-fruits.$VM_IP.nip.io \\\n  --set app.serviceBinding.enabled=false \\\n  --set db.enabled=false\n```\n\n### Service discovered\n\n- Install a Helm chart (or a YAML static file) of a service part of the catalog (e.g. postgresql)\n```bash\nDB_PASSWORD=healthy\nDB_DATABASE=fruits_database\nRELEASE_NAME=postgresql\nVERSION=11.9.13\n\nhelm uninstall postgresql -n db\nkubectl delete pvc -lapp.kubernetes.io/name=$RELEASE_NAME -n db\n\nhelm install $RELEASE_NAME bitnami/postgresql \\\n  --version $VERSION \\\n  --set auth.username=$DB_USERNAME \\\n  --set auth.password=$DB_PASSWORD \\\n  --set auth.database=$DB_DATABASE \\\n  --create-namespace \\\n  -n db\n```\n- Open the primaza `applications` screen and next to the line of the `fruits` application, click on the claim button\n- Create a new claim\n- Wait a few moments till the status is `bound` and open the ingress URL\n\n### Service deployed using Crossplane\n\n- Open the primaza `services catalog` screen and click on the `installable` checkbox of the service `postgresql`\n- If not yet done, specify the Helm repo `https://charts.bitnami.com/bitnami`, chart name `postgresql` and version `11.9.13` to be deployed\n- Next, open the primaza `applications` screen and next to the line of the `fruits` application, click on the claim button\n- Create a new claim\n- Wait a few moments till the status is `bound` and open the ingress URL\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalkyonio%2Fprimaza-poc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalkyonio%2Fprimaza-poc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalkyonio%2Fprimaza-poc/lists"}