diff --git a/README.md b/README.md index de28c2b..b3c1525 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # java-backend ## How to run springboot application - +### IntelliJ IDEA 1. Install Lombok Plugin - Install Lombok plugin - should be suggested in the bottom right corner of IntelliJ @@ -16,6 +16,7 @@ - If the green arrow in top right corner is grey find main class: src/main/java/com/backend/BackendApplication.java and click on the green arrow next to a main class - From now on, you can use the green arrow in top right corner +### Terminal / browser / dev 4. Test the Application - Go to http://localhost:8080/hello/ @@ -24,21 +25,24 @@ 5. Unit tests - test are automaticly run by a ci workflow, do not merge until you pass them -6. Docker -- On merge to main docker image is build and pushed to dockerhub with latest tag -- See https://hub.docker.com/repository/docker/haniazipser2004/awesome-amazing-project -- docker pull haniazipser2004/awesome-amazing-project:latest -- docker run -p 8080:8080 haniazipser2004/awesome-amazing-project:latest (or different port mapping if 8080 is in use) +6. Migrations +- We use flyway for database migrations, which means that if you want to update the database schema, +you need to create a new migration file in src/main/resources/db/migration. +- If you manage to "break" the database, you can reset it by running `docker compose down -v` (this will remove the postgres data volume associated with the compose file 7. Docker compose - If you want to run whole backend (java + python + keycloak): -- clone this repo -- run compose.yaml + +**If you want to run whole backend locally, fast (java + keycloak + rabbitmq + postgres db)**: +- run compose.yaml (see pt. 2 of `6. Migrations`) +- run spring boot application (see `3. Run Spring Boot Application`) - Java backend -> http://localhost:8080 - Keycloak -> http://localhost:8081 -- Python microservice -> http://localhost:8000 +- POSTGRES DB shell -> `docker exec -it psql -U postgres` (use `docker ps` to find container id) + +If you want to run the backend with the containerized version of java as a sanity check: +- run full_compose.yaml with `docker compose -f full_compose.yaml up` -7. Documentation +9. Documentation - Documentation is generated under http://localhost:8080/swagger-ui/index.html - To add custom descrtptions see example controller diff --git a/ai/01-postgres_migration/01-DEVELOPER_WORKFLOW.md b/ai/01-postgres_migration/01-DEVELOPER_WORKFLOW.md new file mode 100644 index 0000000..053ba51 --- /dev/null +++ b/ai/01-postgres_migration/01-DEVELOPER_WORKFLOW.md @@ -0,0 +1,89 @@ +# Developer Workflow + +## Manual Testing (Frontend + Backend) + +**Start infrastructure once:** +```bash +docker compose up postgres keycloak rabbitmq elasticSearch -d +``` +Then run the backend from your IDE or terminal (`dev` profile). The app connects to all services via `localhost`. Flyway runs automatically on startup and applies any pending migrations. + +**What you need to worry about:** +- Docker must be running +- If you changed the schema, write a new migration file first (see [Schema Changes](#schema-changes)) — the app won't start if `ddl-auto=validate` detects a mismatch + +**What is taken care of:** +- Schema is created and kept up to date by Flyway at every app startup +- Seed data (restaurants, dishes, etc.) is loaded once by Flyway and persists across restarts +- No Docker image rebuild needed — edit code, restart app, done + +--- + +## Unit & Integration Tests + +```bash +mvn test +``` + +Tests currently use an **H2 in-memory database** with Flyway disabled. Hibernate manages the schema directly via `ddl-auto=create-drop`, creating a fresh schema at the start of each test run and dropping it at the end. This is configured in `src/test/resources/application.properties`. + +**What you need to worry about:** +- Nothing — no external database or Docker required to run tests + +**What is taken care of:** +- Tests are fully isolated — each run starts from a clean schema +- CI runs these same tests identically without any database infrastructure + +> **Planned:** Once Flyway is confirmed working end-to-end, the test setup will be migrated to **Testcontainers**, which spins up a real PostgreSQL Docker container automatically for the test run and tears it down when done. Flyway migrations will run inside that container, so tests will always run against the real schema. When that is done, Docker must be running to execute tests, and the `src/test/resources/application.properties` override will be removed. + +--- + +## Schema Changes + +Whenever you modify an entity (add a column, rename a field, add a table, etc.): + +1. **Create a new migration file** in `src/main/resources/db/migration/`: + ``` + V{next_number}__{short_description}.sql + ``` + Example: `V3__add_user_preferences_table.sql` + +2. **Never edit an existing migration file.** Flyway checksums every applied migration — modifying one will cause a checksum mismatch and the app (and tests) will refuse to start. + +3. Restart the app locally — Flyway applies the new migration automatically. + +Everything downstream (tests, staging, production) picks up the migration without additional steps. + +--- + +## Deploying to Staging + +Triggered automatically on merge to the `staging` branch (or equivalent) via GitHub Actions: + +1. Build & test (`mvn verify` — includes Testcontainers tests) +2. Build and push Docker image +3. **Run `mvn flyway:migrate` against the staging database** using secrets stored in GitHub — migration runs and is verified *before* the app is deployed +4. `helm upgrade` rolls out the new image to AKS + +**What you need to worry about:** +- Your migration SQL must be correct before merging — if `flyway:migrate` fails, the pipeline stops and the old version keeps running untouched + +**What is taken care of:** +- Database is migrated before any pod restarts +- No manual database access required +- Rollback: if migration fails, deployment does not proceed + +--- + +## Deploying to Production + +Same pipeline as staging, triggered on merge to `main` (or a release tag), using production secrets. + +**What you need to worry about:** +- Migration was already validated on staging — verify staging is healthy before promoting to production +- Migrations are **irreversible by default** — dropping a column or table cannot be undone automatically; plan destructive changes carefully + +**What is taken care of:** +- CI runs the migration against the production database before deploying +- No developer needs direct production database access for routine deployments +- Zero-downtime is achieved by ensuring migrations are backwards-compatible (old pods can still run while new pods start) diff --git a/ai/01-postgres_migration/02-POSTGRES_MIGRATION.md b/ai/01-postgres_migration/02-POSTGRES_MIGRATION.md new file mode 100644 index 0000000..7c357ae --- /dev/null +++ b/ai/01-postgres_migration/02-POSTGRES_MIGRATION.md @@ -0,0 +1,214 @@ +# Context + +The project currently uses H2 in-memory database configured identically across all three Spring profiles (dev, compose, k8s). The task "move to a proper database" means replacing H2 with PostgreSQL everywhere — including adding a Postgres container to docker-compose for local development, and provisioning Postgres for AKS. The schema is entirely auto-generated by Hibernate (`ddl-auto=create`), there are no migrations, and seed data is loaded via `data.sql` on every startup. + +--- + +## How I Interpret the Task + +**Full scope:** +1. Add the PostgreSQL JDBC driver to `pom.xml` (replace H2) +2. Add a Flyway migration system (critical — see below) +3. Update all three profile property files to point at PostgreSQL +4. Add a `postgres` service to `docker/compose.yaml` +5. Wire PostgreSQL credentials into the K8s Helm chart via a Secret +6. Keep H2 scoped to tests only, so unit tests run without a real DB + +--- + +## Non-Obvious Things You Need to Know + +### 1. You must add Flyway (or Liquibase) — this is the biggest non-obvious item +Right now Hibernate creates the schema fresh every restart (`ddl-auto=create`). That's fine for H2 because the data is gone anyway. With a real PostgreSQL database, the data persists — so you can never use `create` again in compose/k8s (it drops and recreates every table, wiping all data). You need a migration tool like Flyway that tracks schema changes in versioned SQL files. Each change to the schema becomes a new migration file (e.g., `V1__init.sql`, `V2__add_column.sql`). Flyway applies only the ones that haven't been applied yet. + +### 2. `data.sql` behavior changes completely +Currently, `data.sql` re-seeds the database every startup. With PostgreSQL and persistent data, that will fail on duplicate key errors after the first run. The seed data should either: +- Move into a Flyway migration file (e.g., `V2__seed_data.sql`) that only runs once +- Or be guarded with `INSERT ... ON CONFLICT DO NOTHING` + +You also need to change `spring.sql.init.mode=always` to `never` in compose/k8s profiles once Flyway is managing the schema. + +### 3. `ddl-auto` must differ per environment +- **dev (local, no Docker):** Can keep `create` against a local H2 if you want, or `validate` against a local Postgres +- **compose:** Should be `validate` (let Flyway handle schema) or `none` +- **k8s:** Must be `validate` or `none` — never `create` or `update` in production + +### 4. The compose service needs a `healthcheck` and `depends_on` condition +Docker Compose `depends_on` by default only waits for the container to *start*, not for Postgres to be *ready to accept connections*. The java-backend will crash-loop on startup if it connects before Postgres finishes initializing. You need: +```yaml +postgres: + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + +java-backend: + depends_on: + postgres: + condition: service_healthy +``` + +### 5. PostgreSQL credentials should be a Kubernetes Secret — not hardcoded +The Helm chart already does this correctly for RabbitMQ (uses `secretKeyRef`). PostgreSQL connection details (URL, username, password) should follow the same pattern. Do not put a real password in `values.yaml` — that file is checked into git. + +### 6. For AKS production: consider Azure Database for PostgreSQL (managed) +Running Postgres as a pod in AKS means you are responsible for backups, high availability, upgrades, and persistent volume claims. Azure offers a managed PostgreSQL service (Azure Database for PostgreSQL - Flexible Server) that handles all of this. For a student/small project, the in-cluster container is fine to start, but the managed service is the production-grade path. This also affects how you configure the `SPRING_DATASOURCE_URL` in the Helm chart — it would point at the Azure-managed hostname rather than a service name. + +### 7. UUID columns: no code changes needed, but know what Hibernate is doing +Your entities use `UUID` IDs. PostgreSQL has a native `uuid` type; H2 stored them as `VARCHAR`. Hibernate with PostgreSQL dialect maps Java `UUID` to the native type automatically. This is handled for you — just be aware the column type will change if you're looking at the schema. + +### 8. Keep H2 scoped to tests +The test suite should continue running without a real database. Add a `src/test/resources/application.properties` that overrides the datasource back to H2, so `@DataJpaTest` and integration tests keep working in CI without needing a running Postgres container. + +--- + +## Implementation Steps + +### Step 1 — `pom.xml` +- Add `org.postgresql:postgresql` runtime dependency +- Add `org.flywaydb:flyway-core` dependency +- Keep `com.h2database:h2` but change scope to `test` + +### Step 2 — Flyway migration files +Create `src/main/resources/db/migration/`: +- `V1__init_schema.sql` — DDL for all tables (generate from current Hibernate schema or write by hand from entity inspection) +- `V2__seed_data.sql` — move the contents of `data.sql` here (seed restaurants, opening hours, dishes, etc.), guarded with `ON CONFLICT DO NOTHING` + +### Step 3 — Update property files +**`application-dev.properties`** (local dev without Docker): +```properties +spring.datasource.url=jdbc:postgresql://localhost:5432/jucaneat +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.jpa.hibernate.ddl-auto=validate +spring.sql.init.mode=never +# remove h2 console lines +``` + +**`application-compose.properties`** (Docker Compose): +```properties +spring.datasource.url=jdbc:postgresql://postgres:5432/jucaneat +spring.datasource.driver-class-name=org.postgresql.Driver +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.jpa.hibernate.ddl-auto=validate +spring.sql.init.mode=never +``` + +**`application-k8s.properties`** (AKS): +```properties +# Use env vars injected by Helm — override via environment block, not hardcoded here +spring.jpa.hibernate.ddl-auto=validate +spring.sql.init.mode=never +``` +The actual URL/credentials come from the K8s Secret via env vars. + +### Step 4 — `docker/compose.yaml` +Add the `postgres` service and wire `java-backend` to it: +```yaml +postgres: + image: postgres:17 + environment: + POSTGRES_DB: jucaneat + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + volumes: + - postgres-data:/var/lib/postgresql/data + +# Add to java-backend depends_on: +depends_on: + postgres: + condition: service_healthy + keycloak: ... # existing + ... + +volumes: + postgres-data: # alongside existing elasticsearch-data +``` + +Also add `SPRING_DATASOURCE_*` env vars to the `java-backend` service block to override the compose profile properties (or rely on the profile file — either works, but env vars in compose are more visible). + +### Step 5 — K8s Helm chart (`k8s/helm/java-backend/`) +Create a `postgres-secret.yaml` template (or apply it separately): +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: postgres-credentials +type: Opaque +stringData: + url: jdbc:postgresql://postgres:5432/jucaneat + username: postgres + password: +``` + +Add to `values.yaml` env block: +```yaml +- name: SPRING_DATASOURCE_URL + valueFrom: + secretKeyRef: + name: postgres-credentials + key: url +- name: SPRING_DATASOURCE_USERNAME + valueFrom: + secretKeyRef: + name: postgres-credentials + key: username +- name: SPRING_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: postgres-credentials + key: password +- name: SPRING_PROFILES_ACTIVE + value: k8s +``` + +If using Azure Database for PostgreSQL, the URL hostname changes to the Azure-managed endpoint. + +### Step 6 — Test configuration +Create `src/test/resources/application.properties`: +```properties +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.hibernate.ddl-auto=create-drop +spring.sql.init.mode=never +``` +This keeps tests isolated from the real DB. + +--- + +## Critical Files to Modify + +| File | Change | +|------|--------| +| `pom.xml` | Add postgres driver, Flyway; move H2 to test scope | +| `src/main/resources/application-dev.properties` | Switch to PostgreSQL datasource | +| `src/main/resources/application-compose.properties` | Switch to PostgreSQL datasource | +| `src/main/resources/application-k8s.properties` | Use env-var-driven datasource | +| `docker/compose.yaml` | Add postgres service + volume + healthcheck | +| `k8s/helm/java-backend/values.yaml` | Add DB env vars from secret | +| `k8s/helm/java-backend/templates/` | Add postgres Secret template (or apply manually) | +| `src/main/resources/db/migration/V1__init_schema.sql` | New: schema DDL | +| `src/main/resources/db/migration/V2__seed_data.sql` | New: moved from data.sql | +| `src/test/resources/application.properties` | New: keep H2 for tests | + +--- + +## Verification + +1. **Local compose:** `docker compose up` → all services start → `curl localhost:8080/health` returns 200 → data endpoints return restaurants/dishes +2. **Flyway ran:** Connect to the Postgres container (`psql -h localhost -U postgres jucaneat`) → `SELECT * FROM flyway_schema_history;` shows V1 and V2 applied +3. **Data persistence:** Stop and restart compose → data still present (was previously lost on every restart with H2) +4. **Tests still pass:** `mvn test` — unit/integration tests pass using H2 in-memory without needing Postgres running +5. **K8s:** `helm upgrade --install java-backend ./k8s/helm/java-backend` → pod starts, Flyway applies migrations on first boot, app serves traffic diff --git a/ai/01-postgres_migration/03-SCHEMA_MANAGEMENT.md b/ai/01-postgres_migration/03-SCHEMA_MANAGEMENT.md new file mode 100644 index 0000000..935258e --- /dev/null +++ b/ai/01-postgres_migration/03-SCHEMA_MANAGEMENT.md @@ -0,0 +1,61 @@ +# Schema Management with Flyway + +## Generating the Initial Schema (V1) + +Once Flyway is added, the first migration file (`V1__init_schema.sql`) needs to exactly match +what Hibernate would create from the current entity annotations. Rather than hand-rolling this +DDL, let Hibernate generate it for you. + +Add these properties temporarily to your dev config, run the app once, then remove them: + +```properties +spring.flyway.enabled=false +spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=V1__init_schema.sql +spring.jpa.hibernate.ddl-auto=create +``` + +The file will be written to the project root. Move it to `src/main/resources/db/migration/` and +it becomes your baseline migration. This guarantees V1 matches the entities exactly with no +manual transcription errors. + +--- + +## Entity Changes Now Require a Migration File — Always + +Before Flyway, Hibernate managed the schema automatically via `ddl-auto=create`. Every restart +recreated all tables from entity annotations. This is no longer the case. + +With Flyway and `ddl-auto=validate`, **Hibernate no longer modifies the database schema**. +It only checks that the database matches the entity annotations at startup — and refuses to start +if there is a mismatch. + +This means: **every change to an entity that affects the database structure must be accompanied +by a new Flyway migration file.** This is unavoidable and by design. + +Examples of changes that require a migration: +- Adding or removing a field that maps to a column +- Renaming a field (without `@Column(name=...)` keeping the old name) +- Adding a new entity class (new table) +- Changing a relationship (e.g., `@OneToMany` to `@ManyToMany`, which changes join tables) +- Adding or removing `@Column` constraints (nullable, length, unique) + +Examples that do NOT require a migration: +- Adding or changing business logic in a method +- Adding a transient field (`@Transient`) +- Changing validation annotations that don't affect the schema (`@NotNull` on the Java side only) + +### The new workflow for entity changes + +1. Update the entity class +2. Write `V{next}__{description}.sql` in `src/main/resources/db/migration/` +3. Restart the app — Flyway applies the migration, Hibernate validates and passes + +If you skip step 2, the app will fail to start with a schema validation error. This is the +safety net that prevents schema drift between environments. + +### Never edit an existing migration file + +Flyway checksums every migration it has applied. Editing an applied file causes a checksum +mismatch and the app will refuse to start across all environments, including production. +Always add a new file — never modify an old one. diff --git a/ai/01-postgres_migration/04-POSTGRES_SETUP_STEPS.md b/ai/01-postgres_migration/04-POSTGRES_SETUP_STEPS.md new file mode 100644 index 0000000..c9323a6 --- /dev/null +++ b/ai/01-postgres_migration/04-POSTGRES_SETUP_STEPS.md @@ -0,0 +1,80 @@ +# PostgreSQL Setup Steps + +These are one-time or per-environment steps required after the Flyway migration was introduced. +They are not automated — a developer must perform them manually. + +--- + +## 1. Generate V1 Schema Migration (one-time) + +Hibernate no longer manages the schema, so the initial schema must be captured as a Flyway +migration file. Do this once when first setting up the PostgreSQL migration. + +Temporarily add these lines to `src/main/resources/application-dev.properties`: + +```properties +spring.flyway.enabled=false +spring.jpa.hibernate.ddl-auto=create +spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create +spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=V1__init_schema.sql +``` + +Flyway must be disabled here because Spring Boot runs Flyway before Hibernate's DDL auto. +Without this, Flyway tries to apply V2 (seed data) before the tables exist and fails. + +Start PostgreSQL: +```bash +docker compose up postgres -d +``` + +Run the app. A file named `V1__init_schema.sql` will appear in the project root. + +Move it to `src/main/resources/db/migration/`: +```bash +mv V1__init_schema.sql src/main/resources/db/migration/V1__init_schema.sql +``` + +Remove all four temporary lines from `application-dev.properties`. + +--- + +## 2. Start PostgreSQL for Local Development + +The `postgres` service in `docker/compose.yaml` automatically creates the `jucaneat` database +via the `POSTGRES_DB` environment variable. Simply run: + +```bash +docker compose up postgres -d +``` + +To start only postgres without the full stack. + +To start everything without building a docker image (time-consuming, long latency): +```bash +docker compose up postgres keycloak rabbitmq elasticSearch -d +``` + +Then run the Spring Boot app directly from your IDE or: +```bash +mvn spring-boot:run +``` + +Flyway will apply all pending migrations automatically on startup. + +--- + +## 3. Deploy to Kubernetes (Staging / Production) + +Credentials must be passed at deploy time via `--set` flags. Never commit real credentials +to `values.yaml` or any file tracked by git. + +```bash +helm upgrade --install java-backend ./k8s/helm/java-backend \ + --set postgres.url=jdbc:postgresql://:5432/jucaneat \ + --set postgres.username= \ + --set postgres.password= +``` + +For staging and production, the CI pipeline (GitHub Actions) runs Flyway migrations as an +explicit step before `helm upgrade`. The app starts with `spring.flyway.enabled=false` in the +`k8s` profile — the database is always migrated by CI, not by the pod itself. diff --git a/ai/01-postgres_migration/05-POST_COPILOT_NOTES.md b/ai/01-postgres_migration/05-POST_COPILOT_NOTES.md new file mode 100644 index 0000000..4908ef0 --- /dev/null +++ b/ai/01-postgres_migration/05-POST_COPILOT_NOTES.md @@ -0,0 +1,165 @@ +# Plan: Address Copilot Review + Add Backend Postgres to external/charts + +## Context + +We migrated the java-backend from H2 to PostgreSQL with Flyway (PR #61, branch `proper-db`). +Copilot reviewed the PR and found 12 issues. A structural problem was also discovered: +the Helm chart changes we made live in `k8s/`, but **`external/charts` (JUCanEat/Charts submodule) +is the authoritative umbrella chart for AKS deployment**. The `k8s/` folder is legacy/local-dev config. + +Postgres is expected to run **inside the cluster** (not Azure managed), matching the pattern used +for Keycloak's Postgres already in external/charts. + +## Is k8s/ relevant? + +**No, not for AKS.** `external/charts/charts/backend/` is the correct location for the backend +Helm config. The `k8s/` folder uses NodePort services, nip.io domains, and hardcoded creds — +it is local/minikube-only. Leave it as-is; add the correct changes to `external/charts`. + +--- + +## Proposed Changes + +### 1. Add Backend Postgres to `external/charts` (umbrella chart level) + +**New file:** `external/charts/templates/backend-postgres.yaml` + +Follows the same pattern as `templates/keycloak/keycloak.yaml` (lines 184–260): +- `PersistentVolumeClaim`: `backend-postgres-pvc` (2Gi, ReadWriteOnce) +- `Deployment`: named `backend-postgres`, image `mirror.gcr.io/postgres:17` + - `POSTGRES_USER` / `POSTGRES_PASSWORD` from secret `backend-postgres-secret` + - `POSTGRES_DB=jucaneat` + - `PGDATA=/var/lib/postgresql/data/pgdata` + - PVC mounted at `/var/lib/postgresql/data/pgdata` +- `Service`: ClusterIP, name `backend-postgres`, port 5432 + +Secret (`backend-postgres-secret`) holds `username` and `password`. +It will be created by the backend subchart's secret template (see §2) using values injected at deploy time. + +--- + +### 2. Add Postgres Secret + Env Vars to `external/charts/charts/backend/` + +**New file:** `external/charts/charts/backend/templates/postgres-secret.yaml` +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: backend-postgres-secret +type: Opaque +stringData: + username: {{ required "postgres.username is required" .Values.postgres.username }} + password: {{ required "postgres.password is required" .Values.postgres.password }} +``` +Name `backend-postgres-secret` is fixed (not release-scoped) because the postgres Deployment in +the umbrella chart references it by this name. This is consistent with how `postgres-secret` works +for Keycloak. + +**Edit:** `external/charts/charts/backend/values.yaml` +- Add `postgres:` section: + ```yaml + postgres: + username: "" + password: "" + ``` +- Add to the `env:` block: + ```yaml + - name: SPRING_PROFILES_ACTIVE + value: k8s + - name: SPRING_DATASOURCE_URL + value: jdbc:postgresql://backend-postgres:5432/jucaneat + - name: SPRING_DATASOURCE_USERNAME + valueFrom: + secretKeyRef: + name: backend-postgres-secret + key: username + - name: SPRING_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: backend-postgres-secret + key: password + ``` + +Deploy command: +```bash +helm upgrade --install jucaneat ./external/charts \ + --set backend.postgres.username= \ + --set backend.postgres.password= +``` + +--- + +### 3. Fix Flyway Migration Schema — `V1__init_schema.sql` (Copilot #2, #3) + +V1 has never been applied to a real Postgres instance (still in PR), so we can edit it directly. + +**Edit:** `src/main/resources/db/migration/V1__init_schema.sql` +- Add `PRIMARY KEY (daily_menu_id, dish_id)` to `daily_menu_dishes` — enables `ON CONFLICT DO NOTHING` in V2 +- Add `PRIMARY KEY (dish_id, allergen)` to `dish_allergens` — same reason + +--- + +### 4. Fix `application-dev.properties` (Copilot #5) + +**Edit:** `src/main/resources/application-dev.properties` +- Add: `spring.jpa.hibernate.ddl-auto=validate` + +--- + +### 5. Fix `application-k8s.properties` (Copilot #10, #12) + +**Edit:** `src/main/resources/application-k8s.properties` +- Fix Keycloak port: `http://keycloak:8080` → `http://keycloak:8081` +- Replace hardcoded RabbitMQ credentials: + ```properties + spring.rabbitmq.username=${RABBITMQ_USERNAME} + spring.rabbitmq.password=${RABBITMQ_PASSWORD} + ``` + (Already injected from `rabbitmq-default-user` secret by the backend chart.) + +--- + +### 6. Pin Flyway Maven Plugin Version (Copilot #11) + +**Edit:** `pom.xml` +- Add `` matching the `flyway-core` version already declared in the pom. + +--- + +### 7. Fix Documentation in `ai/01-postgres_migration/` (Copilot #4, #7, #8, #9) + +- **`01-DEVELOPER_WORKFLOW.md`** (#4): Remove Testcontainers references; describe actual test setup (H2 in-memory, Flyway disabled, Hibernate create-drop). +- **`02-POSTGRES_MIGRATION.md`** (#9): Change `postgres:16` → `postgres:17`. +- **`03-SCHEMA_MANAGEMENT.md`** (#7): Add `spring.flyway.enabled=false` to the temporary props block used when generating V1. +- **`04-POSTGRES_SETUP_STEPS.md`** (#8): Change "Remove the three temporary lines" → "Remove all four temporary lines". + +--- + +## Files to Modify + +| File | Change | +|------|--------| +| `external/charts/templates/backend-postgres.yaml` | NEW — PVC + Deployment + Service for backend postgres | +| `external/charts/charts/backend/templates/postgres-secret.yaml` | NEW — backend-postgres-secret | +| `external/charts/charts/backend/values.yaml` | Add postgres section + 4 env vars | +| `src/main/resources/db/migration/V1__init_schema.sql` | Add composite PKs to junction tables | +| `src/main/resources/application-dev.properties` | Add ddl-auto=validate | +| `src/main/resources/application-k8s.properties` | Fix Keycloak port, fix RabbitMQ creds | +| `pom.xml` | Pin Flyway Maven plugin version | +| `ai/01-postgres_migration/01-DEVELOPER_WORKFLOW.md` | Fix Testcontainers reference | +| `ai/01-postgres_migration/02-POSTGRES_MIGRATION.md` | Fix postgres:16 → postgres:17 | +| `ai/01-postgres_migration/03-SCHEMA_MANAGEMENT.md` | Add spring.flyway.enabled=false to temp props | +| `ai/01-postgres_migration/04-POSTGRES_SETUP_STEPS.md` | Fix "three" → "four" | + +### Files NOT changed +- `k8s/` — left as-is for local/minikube dev +- `V2__seed_data.sql` — no change needed once V1 has the PKs + +--- + +## Verification + +1. `./mvnw test` — all tests pass (H2, Flyway disabled) +2. `docker compose up` — app connects to postgres:17, Flyway runs V1+V2 cleanly +3. `helm template ./external/charts --set backend.postgres.username=x --set backend.postgres.password=x` — verify secret, postgres deployment, and env vars render correctly +4. Confirm all Copilot review comments are resolved before merging PR #61 diff --git a/docker/compose.yaml b/docker/compose.yaml index b82b62b..be5cb3d 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -1,25 +1,22 @@ services: - java-backend: - image: haniazipser2004/awesome-amazing-project:latest - ports: - - "8080:8080" - pull_policy: always - depends_on: - - keycloak - - rabbitmq + postgres: + image: postgres:17 environment: - - SPRING_PROFILES_ACTIVE=compose - - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://localhost:8081/realms/JuCanEat - - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI=http://keycloak:8080/realms/JuCanEat/protocol/openid-connect/certs - - SPRING_RABBITMQ_HOST=rabbitmq - - SPRING_RABBITMQ_PORT=5672 - - SPRING_RABBITMQ_USERNAME=admin - - SPRING_RABBITMQ_PASSWORD=admin - - LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY=DEBUG - - KEYCLOAK_AUTH_SERVER_URL=http://localhost:8081 - - KEYCLOAK_REALM=JuCanEat - extra_hosts: - - "localhost:host-gateway" + - POSTGRES_DB=keycloak + - POSTGRES_USER=keycloak + - POSTGRES_PASSWORD=keycloak + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U keycloak"] + interval: 5s + timeout: 5s + retries: 5 + volumes: + - postgres-data:/var/lib/postgresql/data + - ./multiple-db:/docker-entrypoint-initdb.d + networks: + - jucaneat-net keycloak: image: quay.io/keycloak/keycloak:24.0.1 @@ -28,10 +25,23 @@ services: environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=admin + - KC_DB=postgres + - KC_DB_URL_HOST=postgres + - KC_DB_USERNAME=keycloak + - KC_DB_PASSWORD=keycloak + - KC_DB_URL_DATABASE=keycloak + - KC_HOSTNAME=localhost + - KC_PROXY=edge + - KC_HTTP_ENABLED=true command: start-dev --import-realm + depends_on: + postgres: + condition: service_healthy volumes: - ./imports:/opt/keycloak/data/import - ./providers:/opt/keycloak/providers + networks: + - jucaneat-net rabbitmq: image: 'rabbitmq:latest' @@ -41,26 +51,13 @@ services: ports: - "5672:5672" - "15672:15672" - prometheus: - image: prom/prometheus:latest - ports: - - "9090:9090" - volumes: - - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - depends_on: - - java-backend + networks: + - jucaneat-net - grafana: - image: grafana/grafana:latest - ports: - - "3001:3000" - volumes: - - ./monitoring/provisioning/dashboards:/etc/grafana/provisioning/dashboards - - ./monitoring/provisioning/datasources:/etc/grafana/provisioning/datasources - - ./monitoring/dashboards:/var/lib/grafana/dashboards - environment: - - GF_SECURITY_ADMIN_USER=admin - - GF_SECURITY_ADMIN_PASSWORD=admin - depends_on: - - prometheus +volumes: + postgres-data: + elasticsearch-data: +networks: + jucaneat-net: + driver: bridge \ No newline at end of file diff --git a/docker/full-compose.yaml b/docker/full-compose.yaml new file mode 100644 index 0000000..158e9c4 --- /dev/null +++ b/docker/full-compose.yaml @@ -0,0 +1,82 @@ +services: + java-backend: + image: haniazipser2004/awesome-amazing-project:latest + ports: + - "8080:8080" + pull_policy: always + depends_on: + postgres: + condition: service_healthy + keycloak: + condition: service_started + rabbitmq: + condition: service_started + elasticSearch: + condition: service_started + environment: + - SPRING_PROFILES_ACTIVE=compose + - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://localhost:8081/realms/JuCanEat + - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI=http://keycloak:8080/realms/JuCanEat/protocol/openid-connect/certs + - SPRING_RABBITMQ_HOST=rabbitmq + - SPRING_RABBITMQ_PORT=5672 + - SPRING_RABBITMQ_USERNAME=admin + - SPRING_RABBITMQ_PASSWORD=admin + - LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY=DEBUG + - KEYCLOAK_AUTH_SERVER_URL=http://localhost:8081 + - KEYCLOAK_REALM=JuCanEat + - DEEPL_API_KEY=placeholder + extra_hosts: + - "localhost:host-gateway" # makes localhost in container resolve to host IP + + postgres: + image: postgres:17 + environment: + - POSTGRES_DB=java_backend + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 5s + timeout: 5s + retries: 5 + volumes: + - postgres-data:/var/lib/postgresql/data + + keycloak: + image: quay.io/keycloak/keycloak:24.0.1 + ports: + - "8081:8080" + environment: + - KEYCLOAK_ADMIN=admin + - KEYCLOAK_ADMIN_PASSWORD=admin + command: start-dev --import-realm + volumes: + - ./imports:/opt/keycloak/data/import + - ./keycloak/themes:/opt/keycloak/themes + + rabbitmq: + image: 'rabbitmq:latest' + environment: + - RABBITMQ_DEFAULT_PASS=admin + - RABBITMQ_DEFAULT_USER=admin + ports: + - "5672:5672" + - "15672:15672" + + elasticSearch: + image: elasticsearch:8.11.1 + ports: + - "9200:9200" + - "9300:9300" + environment: + - discovery.type=single-node + - xpack.security.enabled=false + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + volumes: + - elasticsearch-data:/usr/share/elasticsearch/data + +volumes: + postgres-data: + elasticsearch-data: diff --git a/docker/multiple-db/script.sh b/docker/multiple-db/script.sh new file mode 100644 index 0000000..f386afa --- /dev/null +++ b/docker/multiple-db/script.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e +set -u + +echo "setting up"; + +PGPASSWORD="${POSTGRES_PASSWORD}" psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE USER java_backend PASSWORD 'java_backend'; + CREATE DATABASE java_backend; + GRANT ALL PRIVILEGES ON DATABASE java_backend TO java_backend; +EOSQL + +# GRANT ... ON DATABASE does not cover existing schemas inside that database, +# so java_backend would fail to create any tables (e.g. flyway_schema_history) without this. +PGPASSWORD="${POSTGRES_PASSWORD}" psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "java_backend" <<-EOSQL + GRANT ALL ON SCHEMA public TO java_backend; +EOSQL + +echo "setup done"; \ No newline at end of file diff --git a/external/charts b/external/charts new file mode 160000 index 0000000..636ad6c --- /dev/null +++ b/external/charts @@ -0,0 +1 @@ +Subproject commit 636ad6c7d640dae625a460d3a2f34bad9cf0a4dc diff --git a/k8s/helm/java-backend/.helmignore b/k8s/helm/java-backend/.helmignore deleted file mode 100644 index 0e8a0eb..0000000 --- a/k8s/helm/java-backend/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/k8s/helm/java-backend/Chart.yaml b/k8s/helm/java-backend/Chart.yaml deleted file mode 100644 index 7da724c..0000000 --- a/k8s/helm/java-backend/Chart.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: v2 -name: java-backend -description: A Helm chart for Kubernetes - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -appVersion: "1.16.0" diff --git a/k8s/helm/java-backend/keycloak-imports.yaml b/k8s/helm/java-backend/keycloak-imports.yaml deleted file mode 100644 index 3fc1083..0000000 --- a/k8s/helm/java-backend/keycloak-imports.yaml +++ /dev/null @@ -1,2354 +0,0 @@ -apiVersion: v1 -data: - realm.json: |- - { - "id": "b86a8962-27a6-4dbb-82b6-4f910cd4108d", - "realm": "JuCanEat", - "notBefore": 0, - "defaultSignatureAlgorithm": "RS256", - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 300, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 1800, - "ssoSessionMaxLifespan": 36000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 300, - "oauth2DeviceCodeLifespan": 600, - "oauth2DevicePollingInterval": 5, - "enabled": true, - "sslRequired": "external", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxTemporaryLockouts": 0, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "roles": { - "realm": [ - { - "id": "3f274104-018e-4422-a8a8-a220ca3c4dbe", - "name": "offline_access", - "description": "${role_offline-access}", - "composite": false, - "clientRole": false, - "containerId": "b86a8962-27a6-4dbb-82b6-4f910cd4108d", - "attributes": {} - }, - { - "id": "c87df7d9-1b3a-4994-a4e5-6f44cfe8ae4a", - "name": "uma_authorization", - "description": "${role_uma_authorization}", - "composite": false, - "clientRole": false, - "containerId": "b86a8962-27a6-4dbb-82b6-4f910cd4108d", - "attributes": {} - }, - { - "id": "ece06b01-3397-4db9-bfff-5da6c0fc3fec", - "name": "restaurant_owner", - "description": "role for a restaurant owner", - "composite": false, - "clientRole": false, - "containerId": "b86a8962-27a6-4dbb-82b6-4f910cd4108d", - "attributes": {} - }, - { - "id": "c380ccf5-5931-46b9-9ec1-26069c19fafd", - "name": "default-roles-jucaneat", - "description": "${role_default-roles}", - "composite": true, - "composites": { - "realm": [ - "offline_access", - "uma_authorization" - ], - "client": { - "account": [ - "view-profile", - "manage-account" - ] - } - }, - "clientRole": false, - "containerId": "b86a8962-27a6-4dbb-82b6-4f910cd4108d", - "attributes": {} - } - ], - "client": { - "JuCanEat-frontend": [], - "realm-management": [ - { - "id": "4af87477-ea58-4636-9f19-6469632bdf14", - "name": "manage-clients", - "description": "${role_manage-clients}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "f1996b99-84f5-451b-85f4-fdb813725ce5", - "name": "manage-events", - "description": "${role_manage-events}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "36b36951-a9c9-4b63-a07e-05f4922b17c1", - "name": "realm-admin", - "description": "${role_realm-admin}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "manage-clients", - "manage-events", - "view-realm", - "query-users", - "view-users", - "view-authorization", - "manage-authorization", - "query-groups", - "view-events", - "query-realms", - "create-client", - "manage-users", - "manage-realm", - "view-identity-providers", - "view-clients", - "query-clients", - "impersonation", - "manage-identity-providers" - ] - } - }, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "982e668f-afd7-4dce-bc36-5c44b093811c", - "name": "view-realm", - "description": "${role_view-realm}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "d8e307b6-2fb6-4ee8-8623-d50318dbc701", - "name": "query-users", - "description": "${role_query-users}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "80a9dc59-1991-428c-bcc6-f725ec4c8c8d", - "name": "view-users", - "description": "${role_view-users}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-users", - "query-groups" - ] - } - }, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "958847ae-5ef9-4faa-9dc8-328484e8ed7a", - "name": "view-authorization", - "description": "${role_view-authorization}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "08b80d68-1c85-43b4-a0c5-f44cf10d073b", - "name": "manage-authorization", - "description": "${role_manage-authorization}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "ace45bf9-5da9-4193-b7dd-b9beca7e6a7d", - "name": "query-groups", - "description": "${role_query-groups}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "d28fff6e-475a-44f2-b402-616a0a249426", - "name": "view-events", - "description": "${role_view-events}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "9809d8e5-b668-4b17-92fb-f7f80ee8941d", - "name": "create-client", - "description": "${role_create-client}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "78f9c459-6d87-4cec-b0c0-b80e943e78f9", - "name": "query-realms", - "description": "${role_query-realms}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "fa4f509d-cb59-4024-848a-6fd8b650411f", - "name": "manage-users", - "description": "${role_manage-users}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "5aa3df8b-ed4a-4299-b1be-3f21c938f8e2", - "name": "manage-realm", - "description": "${role_manage-realm}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "90dabbff-c7f4-400e-8e37-aca510d9d706", - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "51ac87da-3bb3-4718-bc7d-4009ffc37de7", - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-clients" - ] - } - }, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "f42a29bb-29f5-47a1-b891-75fecca5874b", - "name": "query-clients", - "description": "${role_query-clients}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "bed5040c-c3e3-4dcb-a034-bccb7529047f", - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - }, - { - "id": "a6ea2100-dc13-4ca7-b1da-e0e592cebedb", - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "attributes": {} - } - ], - "security-admin-console": [], - "admin-cli": [], - "account-console": [], - "broker": [ - { - "id": "8ebf78bc-c684-4bbc-bf6a-f64ddb1ab0ba", - "name": "read-token", - "description": "${role_read-token}", - "composite": false, - "clientRole": true, - "containerId": "73158da6-1fb8-423a-85cc-bf6f6a3f2088", - "attributes": {} - } - ], - "account": [ - { - "id": "1ff6a423-31cd-47f2-ab94-5dbb5b066f3c", - "name": "view-groups", - "description": "${role_view-groups}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "2579c906-45db-4008-84f5-d3b2dd2c8a99", - "name": "manage-account-links", - "description": "${role_manage-account-links}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "8017fec5-7b1d-4eab-ae0c-12814e902781", - "name": "view-consent", - "description": "${role_view-consent}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "e451010d-05a6-4088-86ae-c78f9a429cc5", - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": [ - "manage-account-links" - ] - } - }, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "4a2d2d50-b6bc-4ecb-9a88-28c531f2924a", - "name": "manage-consent", - "description": "${role_manage-consent}", - "composite": true, - "composites": { - "client": { - "account": [ - "view-consent" - ] - } - }, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "686287d0-e806-4b79-ae5d-0c70483e669e", - "name": "view-profile", - "description": "${role_view-profile}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "fc5a3419-eea7-4886-aaaa-befa595d6af7", - "name": "delete-account", - "description": "${role_delete-account}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - }, - { - "id": "e0a63b53-43f1-47c0-b6ec-d3a4e31a7465", - "name": "view-applications", - "description": "${role_view-applications}", - "composite": false, - "clientRole": true, - "containerId": "0c978774-b905-4cb1-a814-29b07f615e9d", - "attributes": {} - } - ], - "JuCanEat-backend": [] - } - }, - "groups": [ - { - "id": "dcc62c4d-1d57-4455-8bca-fa1c02a7521d", - "name": "restaurant_owner", - "path": "/restaurant_owner", - "subGroups": [], - "attributes": {}, - "realmRoles": [ - "restaurant_owner" - ], - "clientRoles": {} - } - ], - "defaultRole": { - "id": "c380ccf5-5931-46b9-9ec1-26069c19fafd", - "name": "default-roles-jucaneat", - "description": "${role_default-roles}", - "composite": true, - "clientRole": false, - "containerId": "b86a8962-27a6-4dbb-82b6-4f910cd4108d" - }, - "requiredCredentials": [ - "password" - ], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpPolicyCodeReusable": false, - "otpSupportedApplications": [ - "totpAppFreeOTPName", - "totpAppGoogleName", - "totpAppMicrosoftAuthenticatorName" - ], - "localizationTexts": {}, - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyExtraOrigins": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "webAuthnPolicyPasswordlessExtraOrigins": [], - "users": [ - { - "id": "61f2316d-10cb-444c-8dfa-e69e469a864b", - "username": "service-account-jucaneat-backend", - "emailVerified": false, - "createdTimestamp": 1761660620982, - "enabled": true, - "totp": false, - "serviceAccountClientId": "JuCanEat-backend", - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": [ - "restaurant_owner", - "default-roles-jucaneat" - ], - "notBefore": 0, - "groups": [] - } - ], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": [ - "offline_access" - ] - } - ], - "clientScopeMappings": { - "account": [ - { - "client": "account-console", - "roles": [ - "manage-account", - "view-groups" - ] - } - ] - }, - "clients": [ - { - "id": "eed4fbba-90ef-40b5-a39b-5870aa4cea11", - "clientId": "JuCanEat-backend", - "name": "", - "description": "", - "rootUrl": "", - "adminUrl": "", - "baseUrl": "", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "**********", - "redirectUris": [ - "/*" - ], - "webOrigins": [ - "/*" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1761660620", - "backchannel.logout.session.required": "true", - "oauth2.device.authorization.grant.enabled": "false", - "display.on.consent.screen": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "fb52261b-7eb8-48b8-bf3f-015a6b7f958d", - "name": "Client IP Address", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientAddress", - "introspection.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientAddress", - "jsonType.label": "String" - } - }, - { - "id": "8cc15075-e760-460e-96b8-273f126ea138", - "name": "Client Host", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientHost", - "introspection.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientHost", - "jsonType.label": "String" - } - }, - { - "id": "ac474781-a715-409f-aa11-65d54fa7e29f", - "name": "Client ID", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "client_id", - "introspection.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "client_id", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "44d4a724-2040-4abb-b108-bd088f953d27", - "clientId": "JuCanEat-frontend", - "name": "JuCanEat-frontend", - "description": "", - "rootUrl": "", - "adminUrl": "", - "baseUrl": "", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "*" - ], - "webOrigins": [ - "" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "*", - "oauth2.device.authorization.grant.enabled": "false", - "display.on.consent.screen": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "0c978774-b905-4cb1-a814-29b07f615e9d", - "clientId": "account", - "name": "${client_account}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/JuCanEat/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/realms/JuCanEat/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "a3240370-b845-46e4-a260-42c2a95ef575", - "clientId": "account-console", - "name": "${client_account-console}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/JuCanEat/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/realms/JuCanEat/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "6f3981fa-c722-4b0d-9ad5-005fa89644a9", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "f46725e1-b0d1-4a37-8622-7cbb4fb7554d", - "clientId": "admin-cli", - "name": "${client_admin-cli}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "73158da6-1fb8-423a-85cc-bf6f6a3f2088", - "clientId": "broker", - "name": "${client_broker}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "53494aed-7686-4ad2-b888-ba8a8baf8064", - "clientId": "realm-management", - "name": "${client_realm-management}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": {}, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "ee212be5-8e75-48cd-a927-98cb4ea75876", - "clientId": "security-admin-console", - "name": "${client_security-admin-console}", - "rootUrl": "${authAdminUrl}", - "baseUrl": "/admin/JuCanEat/console/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/admin/JuCanEat/console/*" - ], - "webOrigins": [ - "+" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "b7b22099-086f-48e6-98b8-2f62338bfe96", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "roles", - "profile", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - } - ], - "clientScopes": [ - { - "id": "a6a872c3-7780-4f23-8ac9-b9d1be6c8f07", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "6d5ae9fb-4121-4973-aa13-4da419a134f1", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "access.token.claim": "true" - } - }, - { - "id": "abe0f80e-41b5-45cd-bb85-67ba4eff3227", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "multivalued": "true", - "userinfo.token.claim": "false", - "user.attribute": "foo", - "id.token.claim": "true", - "lightweight.claim": "false", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String" - } - }, - { - "id": "8e24095d-3358-4e69-b68b-00d4e84eb313", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "multivalued": "true", - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "d0a824a4-e518-41f9-8697-f773e9dd9848", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "3c1fcd55-7f78-4384-9686-12751c7bb5f4", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - }, - { - "id": "880bc276-7fa5-455b-8383-382da04be90a", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "8a0fc3e3-df07-4b98-9ce8-32dfcfcfa1c4", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "40f07fdd-b81b-4ca5-a86c-86a08dda4fcf", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "multivalued": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - }, - { - "id": "82344812-6dfa-44cc-88f9-6e060e7d6435", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "a2187b4c-f857-431e-b347-ba0c5c8dc32b", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "231ed7e7-6b53-4d6a-809f-81305d179095", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "access.token.claim": "true" - } - } - ] - }, - { - "id": "6ac8a582-eddb-440f-8a8b-af0cb44c8085", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "a43b676b-f5a8-4030-8557-34d54bc0a148", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "introspection.token.claim": "true", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "id": "c3aa6d86-a857-4a96-aa8b-329fe59e1d1c", - "name": "acr", - "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "4e6eed33-9bf9-46e6-9647-da1ec0ee528c", - "name": "acr loa level", - "protocol": "openid-connect", - "protocolMapper": "oidc-acr-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "introspection.token.claim": "true", - "access.token.claim": "true" - } - } - ] - }, - { - "id": "6509bc57-c52f-4082-acfc-5e4f0c47a8ff", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "453ab230-0b51-4ef6-8850-42e5caee065b", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - }, - { - "id": "71817422-fe78-4008-baa6-64895fe57c8a", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "87e3fe0d-aed9-43d1-867f-8d9b16d597e3", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "6f68174d-2a15-46ff-abd1-bb1825a3569c", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - }, - { - "id": "6b794fd5-a3ba-4143-ae0c-31d9e998281b", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "1ff18966-1678-448e-ac11-19a7dd47d904", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "e38a2bed-a820-4302-82a9-db5ac6d62d87", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "a55d8b10-2816-4418-9e18-4a4a0d5be047", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "34fd5f97-74c9-41c4-bdde-9c5865586a27", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "4c22f57d-914f-4a63-ad3c-7fb9be47e0a0", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - }, - { - "id": "e041428e-c041-4077-839e-6870b310e4c9", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "introspection.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "0a7b34ad-ee82-4857-b6ae-85d1f2df3b1a", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "d267cd25-24ac-4469-8ae7-6853798885db", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "9233c44b-9a21-4232-b77a-572604b86ee8", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "01d8d87a-877f-4dde-ab21-d9f3aab89c33", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "e16c4ce3-ca0f-4e7b-8b44-2bcd86d280db", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "long" - } - }, - { - "id": "648297eb-3416-4f3b-af84-beef6e547ada", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "introspection.token.claim": "true", - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "5ecbf6b7-ff00-48b5-87ab-0e0d8ecc923a", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } - }, - { - "id": "d6f4e876-8903-44b2-a9e6-70e54c943846", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "0fc00919-4813-4a72-b05e-96e301b33387", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } - } - ] - } - ], - "defaultDefaultClientScopes": [ - "role_list", - "profile", - "email", - "roles", - "web-origins", - "acr" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "address", - "phone", - "microprofile-jwt" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "referrerPolicy": "no-referrer", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" - }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "identityProviders": [], - "identityProviderMappers": [], - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "12bda67b-086d-4783-8b88-137a73d6c4ca", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "b9fd3f38-2001-4463-8a29-29b84b657e5f", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "a3806313-60c8-488b-b28e-21fd099be14b", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "saml-user-attribute-mapper", - "saml-user-property-mapper", - "oidc-usermodel-property-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-full-name-mapper", - "oidc-address-mapper", - "oidc-sha256-pairwise-sub-mapper", - "saml-role-list-mapper" - ] - } - }, - { - "id": "35c4c61b-7e2b-4816-abf4-c63f38f862a9", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-usermodel-property-mapper", - "saml-user-property-mapper", - "saml-user-attribute-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-address-mapper", - "saml-role-list-mapper", - "oidc-usermodel-attribute-mapper", - "oidc-full-name-mapper" - ] - } - }, - { - "id": "ad218a12-0a96-499e-bc19-d8fcba884cdd", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] - } - }, - { - "id": "2b7630d0-a296-4a90-812d-5a174cc01981", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": [ - "200" - ] - } - }, - { - "id": "0fdaab7e-e293-46f6-ab37-7e789202d84b", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "685cf24e-d4b9-4e8b-824d-99b5ccbb3a18", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "830b7ca8-c6ea-459e-8693-180f2ee44b66", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "RSA-OAEP" - ] - } - }, - { - "id": "16123c61-d73b-4502-a7ef-a07ce6264dca", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "9ad0d973-2cfd-4bf8-bbe1-7f8fd52f1372", - "name": "hmac-generated-hs512", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS512" - ] - } - }, - { - "id": "abd715c0-c34d-4f72-8f96-1a328fa7ff0f", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - } - ] - }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "fe0d47e1-a5c0-433e-b26c-b60e081e70f9", - "alias": "Account verification options", - "description": "Method with which to verity the existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false - } - ] - }, - { - "id": "478f40c5-5a77-4fae-b67f-5512947cfd22", - "alias": "Browser - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "eea858d7-1762-4b9b-91b1-e55244f3df20", - "alias": "Direct Grant - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "40a81475-653c-4e22-8366-2dfd2a251252", - "alias": "First broker login - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "ec02c6d2-d9ff-440a-838e-60ac64fc84b4", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Account verification options", - "userSetupAllowed": false - } - ] - }, - { - "id": "a0fe3d8b-41c4-4a4e-8f6e-f8efb666a220", - "alias": "Reset - Conditional OTP", - "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "0848a7d3-85fa-436e-b45e-7f00eba00c87", - "alias": "User creation or linking", - "description": "Flow for the existing/non-existing user alternatives", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false - } - ] - }, - { - "id": "3d0e1c79-1714-477d-8fb8-7fde933b98dc", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "abe5c897-fdd2-41f5-a284-f4b044340bb4", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "identity-provider-redirector", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 25, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "forms", - "userSetupAllowed": false - } - ] - }, - { - "id": "985ebbc3-6713-48b9-b371-ae99be600f4f", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-secret-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-x509", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "4490e90c-71b5-4d5c-a0fe-4357a1962b70", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "50aeebba-9eef-4f72-8815-8d78212e9e42", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "74d89c52-4190-48d5-a988-f4a1720e4a70", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "User creation or linking", - "userSetupAllowed": false - } - ] - }, - { - "id": "09ecd572-6368-416a-ac71-1a646e0be791", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "bf2e2894-f4e4-408c-bfc1-c39f4e7cefaf", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": true, - "flowAlias": "registration form", - "userSetupAllowed": false - } - ] - }, - { - "id": "9da194e9-9a13-4364-b4e3-b6ee7cb77eaf", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-password-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 50, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-recaptcha-action", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 60, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-terms-and-conditions", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 70, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "e8816ca4-46a9-41e3-98eb-b778a7cd62f1", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-credential-email", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 40, - "autheticatorFlow": true, - "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "2aa4b963-a4c2-4be7-9fcc-36dcc203320d", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - } - ], - "authenticatorConfig": [ - { - "id": "486ff019-8602-46f5-a020-894f8ee19282", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "8ca8a29e-6e5b-4b88-b0a0-790c5215e28b", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } - } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "TERMS_AND_CONDITIONS", - "name": "Terms and Conditions", - "providerId": "TERMS_AND_CONDITIONS", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "delete_account", - "name": "Delete Account", - "providerId": "delete_account", - "enabled": false, - "defaultAction": false, - "priority": 60, - "config": {} - }, - { - "alias": "webauthn-register", - "name": "Webauthn Register", - "providerId": "webauthn-register", - "enabled": true, - "defaultAction": false, - "priority": 70, - "config": {} - }, - { - "alias": "webauthn-register-passwordless", - "name": "Webauthn Register Passwordless", - "providerId": "webauthn-register-passwordless", - "enabled": true, - "defaultAction": false, - "priority": 80, - "config": {} - }, - { - "alias": "VERIFY_PROFILE", - "name": "Verify Profile", - "providerId": "VERIFY_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 90, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "firstBrokerLoginFlow": "first broker login", - "attributes": { - "cibaBackchannelTokenDeliveryMode": "poll", - "cibaExpiresIn": "120", - "cibaAuthRequestedUserHint": "login_hint", - "oauth2DeviceCodeLifespan": "600", - "oauth2DevicePollingInterval": "5", - "parRequestUriLifespan": "60", - "cibaInterval": "5", - "realmReusableOtpCode": "false" - }, - "keycloakVersion": "24.0.1", - "userManagedAccessAllowed": false, - "clientProfiles": { - "profiles": [] - }, - "clientPolicies": { - "policies": [] - } - } -kind: ConfigMap -metadata: - creationTimestamp: "2025-11-10T16:43:20Z" - name: keycloak-imports - namespace: default - resourceVersion: "85112" - uid: 951e2f1b-3ef4-4289-abc7-f722fd958077 \ No newline at end of file diff --git a/k8s/helm/java-backend/templates/_helpers.tpl b/k8s/helm/java-backend/templates/_helpers.tpl deleted file mode 100644 index 03bc751..0000000 --- a/k8s/helm/java-backend/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "java-backend.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "java-backend.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "java-backend.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "java-backend.labels" -}} -helm.sh/chart: {{ include "java-backend.chart" . }} -{{ include "java-backend.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "java-backend.selectorLabels" -}} -app.kubernetes.io/name: {{ include "java-backend.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "java-backend.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "java-backend.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/k8s/helm/java-backend/templates/deployment.yaml b/k8s/helm/java-backend/templates/deployment.yaml deleted file mode 100644 index 3f45d1d..0000000 --- a/k8s/helm/java-backend/templates/deployment.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "java-backend.fullname" . }} - labels: - {{- include "java-backend.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount | default 1 }} - selector: - matchLabels: - {{- include "java-backend.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - {{- include "java-backend.selectorLabels" . | nindent 8 }} - spec: - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} # ← DODAJ - ports: - - name: http - containerPort: {{ .Values.service.targetPort }} - protocol: TCP - livenessProbe: - httpGet: - path: {{ .Values.livenessProbe.httpGet.path }} - port: {{ .Values.livenessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} - readinessProbe: - httpGet: - path: {{ .Values.readinessProbe.httpGet.path }} - port: {{ .Values.readinessProbe.httpGet.port }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - - env: - {{- with .Values.env }} - {{- toYaml . | nindent 12 }} - {{- end }} \ No newline at end of file diff --git a/k8s/helm/java-backend/templates/service.yaml b/k8s/helm/java-backend/templates/service.yaml deleted file mode 100644 index 10c9d60..0000000 --- a/k8s/helm/java-backend/templates/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "java-backend.fullname" . }} - labels: - {{- include "java-backend.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: {{ .Values.service.targetPort }} - protocol: TCP - name: http - nodePort: 30007 - selector: - {{- include "java-backend.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/k8s/helm/java-backend/templates/tests/test-connection.yaml b/k8s/helm/java-backend/templates/tests/test-connection.yaml deleted file mode 100644 index 61c6909..0000000 --- a/k8s/helm/java-backend/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "java-backend.fullname" . }}-test-connection" - labels: - {{- include "java-backend.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "java-backend.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never diff --git a/k8s/helm/java-backend/values.yaml b/k8s/helm/java-backend/values.yaml deleted file mode 100644 index f366575..0000000 --- a/k8s/helm/java-backend/values.yaml +++ /dev/null @@ -1,192 +0,0 @@ - -replicaCount: 1 - - -image: - repository: haniazipser2004/awesome-amazing-project - pullPolicy: Always - tag: "latest" - -# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ -imagePullSecrets: [] -# This is to override the chart name. -nameOverride: "" -fullnameOverride: "" - -# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ -serviceAccount: - # Specifies whether a service account should be created - create: true - # Automatically mount a ServiceAccount's API credentials? - automount: true - # Annotations to add to the service account - annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -# This is for setting Kubernetes Annotations to a Pod. -# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ -podAnnotations: {} -# This is for setting Kubernetes Labels to a Pod. -# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ -podLabels: {} - -podSecurityContext: {} - # fsGroup: 2000 - -securityContext: {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - -# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ -service: - type: NodePort - port: 8080 - targetPort: 8080 - nodePort: 30007 - - -# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ -ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -# -- Expose the service via gateway-api HTTPRoute -# Requires Gateway API resources and suitable controller installed within the cluster -# (see: https://gateway-api.sigs.k8s.io/guides/) -httpRoute: - # HTTPRoute enabled. - enabled: false - # HTTPRoute annotations. - annotations: {} - # Which Gateways this Route is attached to. - parentRefs: - - name: gateway - sectionName: http - # namespace: default - # Hostnames matching HTTP header. - hostnames: - - chart-example.local - # List of rules and filters applied. - rules: - - matches: - - path: - type: PathPrefix - value: /headers - # filters: - # - type: RequestHeaderModifier - # requestHeaderModifier: - # set: - # - name: My-Overwrite-Header - # value: this-is-the-only-value - # remove: - # - User-Agent - # - matches: - # - path: - # type: PathPrefix - # value: /echo - # headers: - # - name: version - # value: v2 - -resources: {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - -healthCheck: - enabled: true - path: "/health" - port: 8080 - -livenessProbe: - enabled: true - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 60 - periodSeconds: 30 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - enabled: true - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 3 - failureThreshold: 3 - -# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/ -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -# Additional volumes on the output Deployment definition. -volumes: [] -# - name: foo -# secret: -# secretName: mysecret -# optional: false - -# Additional volumeMounts on the output Deployment definition. -volumeMounts: [] -# - name: foo -# mountPath: "/etc/foo" -# readOnly: true - -nodeSelector: {} - -tolerations: [] - -affinity: {} - -env: - - name: SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI - value: http://keycloak:8081/realms/JuCanEat - - name: SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI - value: http://keycloak:8081/realms/JuCanEat/protocol/openid-connect/certs - - name: SPRING_RABBITMQ_HOST - value: rabbitmq - - name: SPRING_RABBITMQ_PORT - value: "5672" - - name: SPRING_RABBITMQ_USERNAME - valueFrom: - secretKeyRef: - name: rabbitmq-default-user - key: username - - name: SPRING_RABBITMQ_PASSWORD - valueFrom: - secretKeyRef: - name: rabbitmq-default-user - key: password - diff --git a/k8s/helm/keycloak/keycloak-ingress.yaml b/k8s/helm/keycloak/keycloak-ingress.yaml deleted file mode 100644 index a4f6016..0000000 --- a/k8s/helm/keycloak/keycloak-ingress.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: keycloak -spec: - rules: - - host: keycloak.192.168.49.2.nip.io - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: keycloak - port: - number: 8080 \ No newline at end of file diff --git a/k8s/helm/keycloak/keycloak.yaml b/k8s/helm/keycloak/keycloak.yaml deleted file mode 100644 index 8ad8928..0000000 --- a/k8s/helm/keycloak/keycloak.yaml +++ /dev/null @@ -1,202 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: keycloak - labels: - app: keycloak -spec: - ports: - - protocol: TCP - port: 8081 - targetPort: http - name: http - selector: - app: keycloak - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: keycloak - name: keycloak-discovery -spec: - selector: - app: keycloak - clusterIP: None - type: ClusterIP ---- -apiVersion: apps/v1 -# Use a stateful setup to ensure that for a rolling update Pods are restarted with a rolling strategy one-by-one. -# This prevents losing in-memory information stored redundantly in two Pods. -kind: StatefulSet -metadata: - name: keycloak - labels: - app: keycloak -spec: - serviceName: keycloak-discovery - # Run with one replica to save resources, or with two replicas to allow for rolling updates for configuration changes - replicas: 1 - selector: - matchLabels: - app: keycloak - template: - metadata: - labels: - app: keycloak - spec: - containers: - - name: keycloak - image: quay.io/keycloak/keycloak:26.3.4 - args: ["start", "--import-realm"] - env: - - name: KC_BOOTSTRAP_ADMIN_USERNAME - value: "admin" - - name: KC_BOOTSTRAP_ADMIN_PASSWORD - value: "admin" - # In a production environment, add a TLS certificate to Keycloak to either end-to-end encrypt the traffic between - # the client or Keycloak, or to encrypt the traffic between your proxy and Keycloak. - # Respect the proxy headers forwarded by the reverse proxy - # In a production environment, verify which proxy type you are using, and restrict access to Keycloak - # from other sources than your proxy if you continue to use proxy headers. - - name: KC_PROXY_HEADERS - value: "xforwarded" - - name: KC_HTTP_ENABLED - value: "true" - # In this explorative setup, no strict hostname is set. - # For production environments, set a hostname for a secure setup. - - name: KC_HOSTNAME_STRICT - value: "false" - - name: KC_HEALTH_ENABLED - value: "true" - - name: 'KC_CACHE' - value: 'ispn' - # Passing the Pod's IP primary address to the JGroups clustering as this is required in IPv6 only setups - - name: POD_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - # Instruct JGroups which DNS hostname to use to discover other Keycloak nodes - # Needs to be unique for each Keycloak cluster - - name: JAVA_OPTS_APPEND - value: '-Djgroups.bind.address=$(POD_IP)' - - name: 'KC_DB_URL_DATABASE' - value: 'keycloak' - - name: 'KC_DB_URL_HOST' - value: 'postgres' - - name: 'KC_DB' - value: 'postgres' - # In a production environment, use a secret to store username and password to the database - - name: 'KC_DB_PASSWORD' - value: 'keycloak' - - name: 'KC_DB_USERNAME' - value: 'keycloak' - - name: 'KC_DB_URL_PORT' - value: '5432' - ports: - - name: http - containerPort: 8080 - startupProbe: - httpGet: - path: /health/started - port: 9000 - periodSeconds: 1 - failureThreshold: 600 - readinessProbe: - httpGet: - path: /health/ready - port: 9000 - periodSeconds: 10 - failureThreshold: 3 - livenessProbe: - httpGet: - path: /health/live - port: 9000 - periodSeconds: 10 - failureThreshold: 3 - resources: - limits: - cpu: 2000m - memory: 2000Mi - requests: - cpu: 500m - memory: 1700Mi - volumeMounts: - - name: keycloak-imports - mountPath: /opt/keycloak/data/import - volumes: - - name: keycloak-imports - configMap: - name: keycloak-imports ---- - -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: postgres-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi - ---- -# This is deployment of PostgreSQL with an ephemeral storage for testing: Once the Pod stops, the data is lost. -# For a production setup, replace it with a database setup that persists your data. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: postgres - labels: - app: postgres -spec: - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: mirror.gcr.io/postgres:17 - env: - - name: POSTGRES_USER - value: "keycloak" - - name: POSTGRES_PASSWORD - value: "keycloak" - - name: POSTGRES_DB - value: "keycloak" - - name: POSTGRES_LOG_STATEMENT - value: "all" - ports: - - name: postgres - containerPort: 5432 - volumeMounts: - # Using volume mount for PostgreSQL's data folder as it is otherwise not writable - - name: postgres-data - mountPath: /var/lib/postgresql/data - volumes: - - name: postgres-data - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: postgres - name: postgres -spec: - selector: - app: postgres - ports: - - protocol: TCP - port: 5432 - targetPort: 5432 - type: ClusterIP - diff --git a/k8s/helm/rabbitmq/cluster-operator.yml b/k8s/helm/rabbitmq/cluster-operator.yml deleted file mode 100644 index f309104..0000000 --- a/k8s/helm/rabbitmq/cluster-operator.yml +++ /dev/null @@ -1,5796 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-system - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-system ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.19.0 - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - servicebinding.io/provisioned-service: "true" - name: rabbitmqclusters.rabbitmq.com -spec: - group: rabbitmq.com - names: - categories: - - all - - rabbitmq - kind: RabbitmqCluster - listKind: RabbitmqClusterList - plural: rabbitmqclusters - shortNames: - - rmq - singular: rabbitmqcluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type == 'AllReplicasReady')].status - name: AllReplicasReady - type: string - - jsonPath: .status.conditions[?(@.type == 'ReconcileSuccess')].status - name: ReconcileSuccess - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 - schema: - openAPIV3Schema: - description: |- - RabbitmqCluster is the Schema for the RabbitmqCluster API. Each instance of this object - corresponds to a single RabbitMQ cluster. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the desired state of the RabbitmqCluster Custom Resource. - properties: - affinity: - description: Affinity scheduling rules to be applied on created Pods. - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the - pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with the - corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the corresponding - nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate - this pod in the same node, zone, etc. as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. - avoid putting this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and subtracting - "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - autoEnableAllFeatureFlags: - description: |- - Set to true to automatically enable all feature flags after each upgrade - For more information, see https://www.rabbitmq.com/docs/feature-flags - type: boolean - delayStartSeconds: - default: 30 - description: |- - DelayStartSeconds is the time the init container (`setup-container`) will sleep before terminating. - This effectively delays the time between starting the Pod and starting the `rabbitmq` container. - RabbitMQ relies on up-to-date DNS entries early during peer discovery. - The purpose of this artificial delay is to ensure that DNS entries are up-to-date when booting RabbitMQ. - For more information, see https://github.com/kubernetes/kubernetes/issues/92559 - If your Kubernetes DNS backend is configured with a low DNS cache value or publishes not ready addresses - promptly, you can decrase this value or set it to 0. - format: int32 - minimum: 0 - type: integer - image: - description: |- - Image is the name of the RabbitMQ docker image to use for RabbitMQ nodes in the RabbitmqCluster. - Must be provided together with ImagePullSecrets in order to use an image in a private registry. - type: string - imagePullSecrets: - description: List of Secret resource containing access credentials - to the registry for the RabbitMQ image. Required if the docker registry - is private. - items: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - type: array - override: - properties: - service: - properties: - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - spec: - properties: - allocateLoadBalancerNodePorts: - type: boolean - clusterIP: - type: string - clusterIPs: - items: - type: string - type: array - x-kubernetes-list-type: atomic - externalIPs: - items: - type: string - type: array - x-kubernetes-list-type: atomic - externalName: - type: string - externalTrafficPolicy: - type: string - healthCheckNodePort: - format: int32 - type: integer - internalTrafficPolicy: - type: string - ipFamilies: - items: - type: string - type: array - x-kubernetes-list-type: atomic - ipFamilyPolicy: - type: string - loadBalancerClass: - type: string - loadBalancerIP: - type: string - loadBalancerSourceRanges: - items: - type: string - type: array - x-kubernetes-list-type: atomic - ports: - items: - properties: - appProtocol: - type: string - name: - type: string - nodePort: - format: int32 - type: integer - port: - format: int32 - type: integer - protocol: - default: TCP - type: string - targetPort: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: array - x-kubernetes-list-map-keys: - - port - - protocol - x-kubernetes-list-type: map - publishNotReadyAddresses: - type: boolean - selector: - additionalProperties: - type: string - type: object - x-kubernetes-map-type: atomic - sessionAffinity: - type: string - sessionAffinityConfig: - properties: - clientIP: - properties: - timeoutSeconds: - format: int32 - type: integer - type: object - type: object - trafficDistribution: - type: string - type: - type: string - type: object - type: object - statefulSet: - properties: - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - spec: - properties: - minReadySeconds: - format: int32 - type: integer - persistentVolumeClaimRetentionPolicy: - properties: - whenDeleted: - type: string - whenScaled: - type: string - type: object - podManagementPolicy: - type: string - replicas: - format: int32 - type: integer - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - serviceName: - type: string - template: - properties: - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - name: - type: string - namespace: - type: string - type: object - spec: - properties: - activeDeadlineSeconds: - format: int64 - type: integer - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - automountServiceAccountToken: - type: boolean - containers: - items: - properties: - args: - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - fileKeyRef: - properties: - key: - type: string - optional: - default: false - type: boolean - path: - type: string - volumeName: - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - stopSignal: - type: string - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - default: TCP - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - resizePolicy: - items: - properties: - resourceName: - type: string - restartPolicy: - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - properties: - claims: - items: - properties: - name: - type: string - request: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - restartPolicy: - type: string - restartPolicyRules: - items: - properties: - action: - type: string - exitCodes: - properties: - operator: - type: string - values: - items: - format: int32 - type: integer - type: array - x-kubernetes-list-type: set - required: - - operator - type: object - required: - - action - type: object - type: array - x-kubernetes-list-type: atomic - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - appArmorProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - capabilities: - properties: - add: - items: - type: string - type: array - x-kubernetes-list-type: atomic - drop: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - hostProcess: - type: boolean - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - recursiveReadOnly: - type: string - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - dnsConfig: - properties: - nameservers: - items: - type: string - type: array - x-kubernetes-list-type: atomic - options: - items: - properties: - name: - type: string - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - searches: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - dnsPolicy: - type: string - enableServiceLinks: - type: boolean - ephemeralContainers: - items: - properties: - args: - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - fileKeyRef: - properties: - key: - type: string - optional: - default: false - type: boolean - path: - type: string - volumeName: - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - stopSignal: - type: string - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - default: TCP - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - resizePolicy: - items: - properties: - resourceName: - type: string - restartPolicy: - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - properties: - claims: - items: - properties: - name: - type: string - request: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - restartPolicy: - type: string - restartPolicyRules: - items: - properties: - action: - type: string - exitCodes: - properties: - operator: - type: string - values: - items: - format: int32 - type: integer - type: array - x-kubernetes-list-type: set - required: - - operator - type: object - required: - - action - type: object - type: array - x-kubernetes-list-type: atomic - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - appArmorProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - capabilities: - properties: - add: - items: - type: string - type: array - x-kubernetes-list-type: atomic - drop: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - hostProcess: - type: boolean - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - targetContainerName: - type: string - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - recursiveReadOnly: - type: string - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - hostAliases: - items: - properties: - hostnames: - items: - type: string - type: array - x-kubernetes-list-type: atomic - ip: - type: string - required: - - ip - type: object - type: array - x-kubernetes-list-map-keys: - - ip - x-kubernetes-list-type: map - hostIPC: - type: boolean - hostNetwork: - type: boolean - hostPID: - type: boolean - hostUsers: - type: boolean - hostname: - type: string - hostnameOverride: - type: string - imagePullSecrets: - items: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - initContainers: - items: - properties: - args: - items: - type: string - type: array - x-kubernetes-list-type: atomic - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - fileKeyRef: - properties: - key: - type: string - optional: - default: false - type: boolean - path: - type: string - volumeName: - type: string - required: - - key - - path - - volumeName - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - properties: - key: - type: string - name: - default: "" - type: string - optional: - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - envFrom: - items: - properties: - configMapRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - prefix: - type: string - secretRef: - properties: - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - type: object - type: array - x-kubernetes-list-type: atomic - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - sleep: - properties: - seconds: - format: int64 - type: integer - required: - - seconds - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - stopSignal: - type: string - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - default: TCP - type: string - required: - - containerPort - type: object - type: array - x-kubernetes-list-map-keys: - - containerPort - - protocol - x-kubernetes-list-type: map - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - resizePolicy: - items: - properties: - resourceName: - type: string - restartPolicy: - type: string - required: - - resourceName - - restartPolicy - type: object - type: array - x-kubernetes-list-type: atomic - resources: - properties: - claims: - items: - properties: - name: - type: string - request: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - restartPolicy: - type: string - restartPolicyRules: - items: - properties: - action: - type: string - exitCodes: - properties: - operator: - type: string - values: - items: - format: int32 - type: integer - type: array - x-kubernetes-list-type: set - required: - - operator - type: object - required: - - action - type: object - type: array - x-kubernetes-list-type: atomic - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - appArmorProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - capabilities: - properties: - add: - items: - type: string - type: array - x-kubernetes-list-type: atomic - drop: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - hostProcess: - type: boolean - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - failureThreshold: - format: int32 - type: integer - grpc: - properties: - port: - format: int32 - type: integer - service: - default: "" - type: string - required: - - port - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - terminationGracePeriodSeconds: - format: int64 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - devicePath - x-kubernetes-list-type: map - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - recursiveReadOnly: - type: string - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - x-kubernetes-list-map-keys: - - mountPath - x-kubernetes-list-type: map - workingDir: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - nodeName: - type: string - nodeSelector: - additionalProperties: - type: string - type: object - x-kubernetes-map-type: atomic - os: - properties: - name: - type: string - required: - - name - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - preemptionPolicy: - type: string - priority: - format: int32 - type: integer - priorityClassName: - type: string - readinessGates: - items: - properties: - conditionType: - type: string - required: - - conditionType - type: object - type: array - x-kubernetes-list-type: atomic - resourceClaims: - items: - properties: - name: - type: string - resourceClaimName: - type: string - resourceClaimTemplateName: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - resources: - properties: - claims: - items: - properties: - name: - type: string - request: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - restartPolicy: - type: string - runtimeClassName: - type: string - schedulerName: - type: string - schedulingGates: - items: - properties: - name: - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - securityContext: - properties: - appArmorProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - fsGroup: - format: int64 - type: integer - fsGroupChangePolicy: - type: string - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxChangePolicy: - type: string - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - x-kubernetes-list-type: atomic - supplementalGroupsPolicy: - type: string - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - x-kubernetes-list-type: atomic - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - hostProcess: - type: boolean - runAsUserName: - type: string - type: object - type: object - serviceAccount: - type: string - serviceAccountName: - type: string - setHostnameAsFQDN: - type: boolean - shareProcessNamespace: - type: boolean - subdomain: - type: string - terminationGracePeriodSeconds: - format: int64 - type: integer - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - x-kubernetes-list-type: atomic - topologySpreadConstraints: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - items: - type: string - type: array - x-kubernetes-list-type: atomic - maxSkew: - format: int32 - type: integer - minDomains: - format: int32 - type: integer - nodeAffinityPolicy: - type: string - nodeTaintsPolicy: - type: string - topologyKey: - type: string - whenUnsatisfiable: - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - x-kubernetes-list-map-keys: - - topologyKey - - whenUnsatisfiable - x-kubernetes-list-type: map - volumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - default: ext4 - type: string - kind: - type: string - readOnly: - default: false - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - x-kubernetes-list-type: atomic - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - volumeID: - type: string - required: - - volumeID - type: object - configMap: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - readOnly: - type: boolean - volumeAttributes: - additionalProperties: - type: string - type: object - required: - - driver - type: object - downwardAPI: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - properties: - volumeClaimTemplate: - properties: - metadata: - type: object - spec: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - required: - - spec - type: object - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - x-kubernetes-list-type: atomic - wwids: - items: - type: string - type: array - x-kubernetes-list-type: atomic - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - additionalProperties: - type: string - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - image: - properties: - pullPolicy: - type: string - reference: - type: string - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - default: default - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - x-kubernetes-list-type: atomic - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - targetPortal: - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - clusterTrustBundle: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - name: - type: string - optional: - type: boolean - path: - type: string - signerName: - type: string - required: - - path - type: object - configMap: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - downwardAPI: - properties: - items: - items: - properties: - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - mode: - format: int32 - type: integer - path: - type: string - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - required: - - path - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podCertificate: - properties: - certificateChainPath: - type: string - credentialBundlePath: - type: string - keyPath: - type: string - keyType: - type: string - maxExpirationSeconds: - format: int32 - type: integer - signerName: - type: string - required: - - keyType - - signerName - type: object - secret: - properties: - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - name: - default: "" - type: string - optional: - type: boolean - type: object - x-kubernetes-map-type: atomic - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - x-kubernetes-list-type: atomic - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - default: /etc/ceph/keyring - type: string - monitors: - items: - type: string - type: array - x-kubernetes-list-type: atomic - pool: - default: rbd - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - user: - default: admin - type: string - required: - - image - - monitors - type: object - scaleIO: - properties: - fsType: - default: xfs - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - sslEnabled: - type: boolean - storageMode: - default: ThinProvisioned - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - secretRef - - system - type: object - secret: - properties: - defaultMode: - format: int32 - type: integer - items: - items: - properties: - key: - type: string - mode: - format: int32 - type: integer - path: - type: string - required: - - key - - path - type: object - type: array - x-kubernetes-list-type: atomic - optional: - type: boolean - secretName: - type: string - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - default: "" - type: string - type: object - x-kubernetes-map-type: atomic - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - required: - - containers - type: object - type: object - updateStrategy: - properties: - rollingUpdate: - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - partition: - format: int32 - type: integer - type: object - type: - type: string - type: object - volumeClaimTemplates: - items: - properties: - apiVersion: - type: string - kind: - type: string - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - name: - type: string - namespace: - type: string - type: object - spec: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object - type: array - type: object - type: object - type: object - persistence: - default: - storage: 10Gi - description: The desired persistent storage configuration for each - Pod in the cluster. - properties: - storage: - anyOf: - - type: integer - - type: string - default: 10Gi - description: |- - The requested size of the persistent volume attached to each Pod in the RabbitmqCluster. - The format of this field matches that defined by kubernetes/apimachinery. - See https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity for more info on the format of this field. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - storageClassName: - description: The name of the StorageClass to claim a PersistentVolume - from. - type: string - type: object - rabbitmq: - description: Configuration options for RabbitMQ Pods created in the - cluster. - properties: - additionalConfig: - description: |- - Modify to add to the rabbitmq.conf file in addition to default configurations set by the operator. - Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime. - For more information on this config, see https://www.rabbitmq.com/configure.html#config-file - maxLength: 100000 - type: string - additionalPlugins: - description: 'List of plugins to enable in addition to essential - plugins: rabbitmq_management, rabbitmq_prometheus, and rabbitmq_peer_discovery_k8s.' - items: - description: A Plugin to enable on the RabbitmqCluster. - maxLength: 100 - pattern: ^\w+$ - type: string - maxItems: 100 - type: array - advancedConfig: - description: |- - Specify any rabbitmq advanced.config configurations to apply to the cluster. - For more information on advanced config, see https://www.rabbitmq.com/configure.html#advanced-config-file - maxLength: 100000 - type: string - envConfig: - description: |- - Modify to add to the rabbitmq-env.conf file. Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime. - For more information on env config, see https://www.rabbitmq.com/man/rabbitmq-env.conf.5.html - maxLength: 100000 - type: string - erlangInetConfig: - description: |- - Erlang Inet configuration to apply to the Erlang VM running rabbit. - See also: https://www.erlang.org/doc/apps/erts/inet_cfg.html - maxLength: 2000 - type: string - type: object - replicas: - default: 1 - description: |- - Replicas is the number of nodes in the RabbitMQ cluster. Each node is deployed as a Replica in a StatefulSet. Only 1, 3, 5 replicas clusters are tested. - This value should be an odd number to ensure the resultant cluster can establish exactly one quorum of nodes - in the event of a fragmenting network partition. - format: int32 - minimum: 0 - type: integer - resources: - default: - limits: - cpu: 2000m - memory: 2Gi - requests: - cpu: 1000m - memory: 2Gi - description: The desired compute resource requirements of Pods in - the cluster. - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This field depends on the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - secretBackend: - description: |- - Secret backend configuration for the RabbitmqCluster. - Enables to fetch default user credentials and certificates from K8s external secret stores. - properties: - externalSecret: - description: |- - LocalObjectReference contains enough information to let you locate the - referenced object inside the same namespace. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - vault: - description: |- - VaultSpec will add Vault annotations (see https://www.vaultproject.io/docs/platform/k8s/injector/annotations) - to RabbitMQ Pods. It requires a Vault Agent Sidecar Injector (https://www.vaultproject.io/docs/platform/k8s/injector) - to be installed in the K8s cluster. The injector is a K8s Mutation Webhook Controller that alters RabbitMQ Pod specifications - (based on the added Vault annotations) to include Vault Agent containers that render Vault secrets to the volume. - properties: - annotations: - additionalProperties: - type: string - description: |- - Vault annotations that override the Vault annotations set by the cluster-operator. - For a list of valid Vault annotations, see https://www.vaultproject.io/docs/platform/k8s/injector/annotations - type: object - defaultUserPath: - description: |- - Path in Vault to access a KV (Key-Value) secret with the fields username and password for the default user. - For example "secret/data/rabbitmq/config". - type: string - defaultUserUpdaterImage: - description: |- - Sidecar container that updates the default user's password in RabbitMQ when it changes in Vault. - Additionally, it updates /var/lib/rabbitmq/.rabbitmqadmin.conf (used by rabbitmqadmin CLI). - Set to empty string to disable the sidecar container. - type: string - role: - description: |- - Role in Vault. - If vault.defaultUserPath is set, this role must have capability to read the pre-created default user credential in Vault. - If vault.tls is set, this role must have capability to create and update certificates in the Vault PKI engine for the domains - "" and ".svc". - type: string - tls: - properties: - altNames: - description: |- - Specifies the requested Subject Alternative Names (SANs), in a comma-delimited list. - These will be appended to the SANs added by the cluster-operator. - The cluster-operator will add SANs: - "-server-.-nodes." for each pod, - e.g. "myrabbit-server-0.myrabbit-nodes.default". - type: string - commonName: - description: |- - Specifies the requested certificate Common Name (CN). - Defaults to ..svc if not provided. - type: string - ipSans: - description: Specifies the requested IP Subject Alternative - Names, in a comma-delimited list. - type: string - pkiIssuerPath: - description: |- - Path in Vault PKI engine. - For example "pki/issue/hashicorp-com". - required - type: string - pkiRootPath: - description: Specifies an optional path to retrieve the - root CA from vault. Useful if certificates are issued - by an intermediate CA - type: string - type: object - type: object - type: object - service: - default: - type: ClusterIP - description: The desired state of the Kubernetes Service to create - for the cluster. - properties: - annotations: - additionalProperties: - type: string - description: Annotations to add to the Service. - type: object - ipFamilyPolicy: - description: |- - IPFamilyPolicy represents the dual-stack-ness requested or required by a Service - See also: https://pkg.go.dev/k8s.io/api/core/v1#IPFamilyPolicy - enum: - - SingleStack - - PreferDualStack - - RequireDualStack - type: string - labels: - additionalProperties: - type: string - type: object - type: - default: ClusterIP - description: |- - Type of Service to create for the cluster. Must be one of: ClusterIP, LoadBalancer, NodePort. - For more info see https://pkg.go.dev/k8s.io/api/core/v1#ServiceType - enum: - - ClusterIP - - LoadBalancer - - NodePort - type: string - type: object - skipPostDeploySteps: - description: |- - If unset, or set to false, the cluster will run `rabbitmq-queues rebalance all` whenever the cluster is updated. - Set to true to prevent the operator rebalancing queue leaders after a cluster update. - Has no effect if the cluster only consists of one node. - For more information, see https://www.rabbitmq.com/rabbitmq-queues.8.html#rebalance - type: boolean - terminationGracePeriodSeconds: - default: 604800 - description: |- - TerminationGracePeriodSeconds is the timeout that each rabbitmqcluster pod will have to terminate gracefully. - It defaults to 604800 seconds ( a week long) to ensure that the container preStop lifecycle hook can finish running. - For more information, see: https://github.com/rabbitmq/cluster-operator/blob/main/docs/design/20200520-graceful-pod-termination.md - format: int64 - minimum: 0 - type: integer - tls: - description: TLS-related configuration for the RabbitMQ cluster. - properties: - caSecretName: - description: |- - Name of a Secret in the same Namespace as the RabbitmqCluster, containing the Certificate Authority's public certificate for TLS. - The Secret must store this as ca.crt. - This Secret can be created by running `kubectl create secret generic ca-secret --from-file=ca.crt=path/to/ca.crt` - Used for mTLS, and TLS for rabbitmq_web_stomp and rabbitmq_web_mqtt. - type: string - disableNonTLSListeners: - description: |- - When set to true, the RabbitmqCluster disables non-TLS listeners for RabbitMQ, management plugin and for any enabled plugins in the following list: stomp, mqtt, web_stomp, web_mqtt. - Only TLS-enabled clients will be able to connect. - type: boolean - secretName: - description: |- - Name of a Secret in the same Namespace as the RabbitmqCluster, containing the server's private key & public certificate for TLS. - The Secret must store these as tls.key and tls.crt, respectively. - This Secret can be created by running `kubectl create secret tls tls-secret --cert=path/to/tls.crt --key=path/to/tls.key` - type: string - type: object - tolerations: - description: Tolerations is the list of Toleration resources attached - to each Pod in the RabbitmqCluster. - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - status: - description: Status presents the observed state of RabbitmqCluster - properties: - binding: - description: |- - Binding exposes a secret containing the binding information for this - RabbitmqCluster. It implements the service binding Provisioned Service - duck type. See: https://github.com/servicebinding/spec#provisioned-service - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - conditions: - description: Set of Conditions describing the current state of the - RabbitmqCluster - items: - properties: - lastTransitionTime: - description: The last time this Condition type changed. - format: date-time - type: string - message: - description: Full text reason for current status of the condition. - type: string - reason: - description: One word, camel-case reason for current status - of the condition. - type: string - status: - description: True, False, or Unknown - type: string - type: - description: Type indicates the scope of RabbitmqCluster status - addressed by the condition. - type: string - required: - - status - - type - type: object - type: array - defaultUser: - description: Identifying information on internal resources - properties: - secretReference: - description: |- - Reference to the Kubernetes Secret containing the credentials of the default - user. - properties: - keys: - additionalProperties: - type: string - description: Key-value pairs in the Secret corresponding to - `username`, `password`, `host`, and `port` - type: object - name: - description: Name of the Secret containing the default user - credentials - type: string - namespace: - description: Namespace of the Secret containing the default - user credentials - type: string - required: - - keys - - name - - namespace - type: object - serviceReference: - description: Reference to the Kubernetes Service serving the cluster. - properties: - name: - description: Name of the Service serving the cluster - type: string - namespace: - description: Namespace of the Service serving the cluster - type: string - required: - - name - - namespace - type: object - type: object - observedGeneration: - description: |- - observedGeneration is the most recent successful generation observed for this RabbitmqCluster. It corresponds to the - RabbitmqCluster's generation, which is updated on mutation by the API Server. - format: int64 - type: integer - required: - - conditions - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: rabbitmq-cluster-operator - namespace: rabbitmq-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-cluster-leader-election-role - namespace: rabbitmq-system -rules: -- apiGroups: - - coordination.k8s.io - resources: - - leases - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiGroups: - - "" - resources: - - events - verbs: - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-cluster-operator-role -rules: -- apiGroups: - - "" - resources: - - configmaps - - persistentvolumeclaims - - secrets - - serviceaccounts - - services - verbs: - - create - - get - - list - - update - - watch -- apiGroups: - - "" - resources: - - endpoints - verbs: - - get - - list - - watch -- apiGroups: - - "" - resources: - - events - verbs: - - create - - get - - patch -- apiGroups: - - "" - resources: - - pods - verbs: - - get - - list - - update - - watch -- apiGroups: - - "" - resources: - - pods/exec - verbs: - - create -- apiGroups: - - apps - resources: - - statefulsets - verbs: - - create - - delete - - get - - list - - update - - watch -- apiGroups: - - rabbitmq.com - resources: - - rabbitmqclusters - verbs: - - create - - get - - list - - update - - watch -- apiGroups: - - rabbitmq.com - resources: - - rabbitmqclusters/finalizers - verbs: - - update -- apiGroups: - - rabbitmq.com - resources: - - rabbitmqclusters/status - verbs: - - get - - update -- apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - - roles - verbs: - - create - - get - - list - - update - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - servicebinding.io/controller: "true" - name: rabbitmq-cluster-service-binding-role -rules: -- apiGroups: - - rabbitmq.com - resources: - - rabbitmqclusters - verbs: - - get - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-cluster-leader-election-rolebinding - namespace: rabbitmq-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: rabbitmq-cluster-leader-election-role -subjects: -- kind: ServiceAccount - name: rabbitmq-cluster-operator - namespace: rabbitmq-system ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-cluster-operator-rolebinding -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: rabbitmq-cluster-operator-role -subjects: -- kind: ServiceAccount - name: rabbitmq-cluster-operator - namespace: rabbitmq-system ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - name: rabbitmq-cluster-operator - namespace: rabbitmq-system -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/name: rabbitmq-cluster-operator - template: - metadata: - labels: - app.kubernetes.io/component: rabbitmq-operator - app.kubernetes.io/name: rabbitmq-cluster-operator - app.kubernetes.io/part-of: rabbitmq - spec: - containers: - - command: - - /manager - env: - - name: OPERATOR_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - image: rabbitmqoperator/cluster-operator:2.17.0 - name: operator - ports: - - containerPort: 9782 - name: metrics - protocol: TCP - resources: - limits: - cpu: 200m - memory: 500Mi - requests: - cpu: 200m - memory: 500Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - All - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - serviceAccountName: rabbitmq-cluster-operator - terminationGracePeriodSeconds: 10 diff --git a/k8s/helm/rabbitmq/rabbitmq.yaml b/k8s/helm/rabbitmq/rabbitmq.yaml deleted file mode 100644 index abcbbda..0000000 --- a/k8s/helm/rabbitmq/rabbitmq.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: rabbitmq.com/v1beta1 -kind: RabbitmqCluster -metadata: - name: rabbitmq - namespace: default # <–– ważne: ten sam namespace co Twój backend -spec: - replicas: 1 - diff --git a/pom.xml b/pom.xml index 5df8603..f835e24 100644 --- a/pom.xml +++ b/pom.xml @@ -46,10 +46,26 @@ test + + org.postgresql + postgresql + runtime + + + + org.flywaydb + flyway-core + + + + org.flywaydb + flyway-database-postgresql + + com.h2database h2 - runtime + test @@ -136,6 +152,16 @@ + + org.flywaydb + flyway-maven-plugin + + ${env.SPRING_DATASOURCE_URL} + ${env.SPRING_DATASOURCE_USERNAME} + ${env.SPRING_DATASOURCE_PASSWORD} + + + com.diffplug.spotless spotless-maven-plugin diff --git a/src/main/resources/README.md b/src/main/resources/README.md new file mode 100644 index 0000000..9bff827 --- /dev/null +++ b/src/main/resources/README.md @@ -0,0 +1,16 @@ +# Application Configuration + +As of 01.04.2026, the application defaults to the `-dev` profile (set in `application.properties`) across all environments, +including the Kubernetes cluster. + +The Kubernetes cluster is what interests us in this README. +Rather than activating the `-k8s` profile, the Helm chart at `external/charts/charts/backend/values.yaml` injects +environment variables that override the dev profile's localhost defaults: +- redirecting the datasource to the in-cluster Postgres (`postgres:5432/java_backend`), +- pointing JWT validation at the cluster-internal Keycloak instance, +- wiring RabbitMQ credentials from a Kubernetes Secret, +- disabling Flyway (since migrations are intended to be run by a CI pipeline before deployment), +- ... + +The `-k8s` profile and its properties file are retained from an earlier unsuccessful attempt to set them up, +but are not actively used. diff --git a/src/main/resources/application-compose.properties b/src/main/resources/application-compose.properties index de003b8..ffd237a 100644 --- a/src/main/resources/application-compose.properties +++ b/src/main/resources/application-compose.properties @@ -1,18 +1,12 @@ -# H2 Database -spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.username=sa -spring.datasource.password=password -spring.datasource.driver-class-name=org.h2.Driver - -# H2 Console -spring.h2.console.enabled=true -spring.h2.console.settings.web-allow-others=true - -# JPA/Hibernate for development -spring.jpa.hibernate.ddl-auto=create +# PostgreSQL +spring.datasource.url=jdbc:postgresql://postgres:5432/java_backend +spring.datasource.username=java_backend +spring.datasource.password=java_backend +spring.datasource.driver-class-name=org.postgresql.Driver + +# JPA/Hibernate +spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true -spring.jpa.defer-datasource-initialization=true -spring.sql.init.mode=always microservice.url=http://python-microservice:8000 diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 5b49dbc..8064ee6 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,19 +1,14 @@ -# H2 Database -spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.username=sa -spring.datasource.password=password -spring.datasource.driver-class-name=org.h2.Driver +# PostgreSQL +spring.datasource.url=jdbc:postgresql://localhost:5432/java_backend +spring.datasource.username=java_backend +spring.datasource.password=java_backend +spring.datasource.driver-class-name=org.postgresql.Driver -# H2 Console -spring.h2.console.enabled=true - -# JPA/Hibernate for development -spring.jpa.hibernate.ddl-auto=create +# JPA/Hibernate +spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true -spring.jpa.defer-datasource-initialization=true -spring.sql.init.mode=always -#Keycloak +# Keycloak spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8081/realms/JuCanEat spring.servlet.multipart.max-file-size=10MB @@ -28,4 +23,6 @@ keycloak.auth-server-url=http://localhost:8081 keycloak.realm=JuCanEat #Ours -aiservice.mock-implementation-active=false \ No newline at end of file +aiservice.mock-implementation-active=false + +deepl.api-key=placeholder \ No newline at end of file diff --git a/src/main/resources/application-k8s.properties b/src/main/resources/application-k8s.properties index 5849be1..3fc91aa 100644 --- a/src/main/resources/application-k8s.properties +++ b/src/main/resources/application-k8s.properties @@ -1,19 +1,7 @@ -# H2 Database -spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.username=sa -spring.datasource.password=password -spring.datasource.driver-class-name=org.h2.Driver +# JPA/Hibernate - datasource injected via K8s Secret env vars +spring.jpa.hibernate.ddl-auto=validate -# H2 Console -spring.h2.console.enabled=true - -# JPA/Hibernate for development -spring.jpa.hibernate.ddl-auto=create -spring.jpa.show-sql=true -spring.jpa.defer-datasource-initialization=true -spring.sql.init.mode=always - -#Keycloak +# Keycloak spring.security.oauth2.resourceserver.jwt.issuer-uri=http://keycloak:8080/realms/JuCanEat spring.servlet.multipart.max-file-size=10MB diff --git a/src/main/resources/db/migration/V1__init_schema.sql b/src/main/resources/db/migration/V1__init_schema.sql new file mode 100644 index 0000000..74c2f61 --- /dev/null +++ b/src/main/resources/db/migration/V1__init_schema.sql @@ -0,0 +1,23 @@ +create table daily_menu (date date, id uuid not null, restaurant_id uuid, original_file_name varchar(255), status varchar(255) check (status in ('ACTIVE','SCHEDULED','INACTIVE','PROCESSING','DRAFT','FAILED')), primary key (id)); +create table daily_menu_dishes (daily_menu_id uuid not null, dish_id uuid not null); +create table dish (amount numeric(38,2), id uuid not null, restaurant_id uuid, category varchar(255) check (category in ('SOUP','MAIN_COURSE')), currency varchar(255), name varchar(255), primary key (id)); +create table dish_allergens (dish_id uuid not null, allergen varchar(255) check (allergen in ('NUTS','GLUTEN','MEAT','LACTOSE'))); +create table dish_translation (dish_id uuid not null, id uuid not null, language varchar(255) check (language in ('PL','EN')), name varchar(255), primary key (id), unique (dish_id, language)); +create table facility (id uuid not null, location_id uuid unique, facility_type varchar(31) not null, description varchar(255), name varchar(255), photo_path varchar(255), type varchar(255) check (type in ('SNACKS','COFFEE','LUNCH')), primary key (id)); +create table keycloak_user (id varchar(255) not null, primary key (id)); +create table location (latitude float(53), longitude float(53), id uuid not null, primary key (id)); +create table opening_hours (close_time time(6), open_time time(6), id uuid not null, restaurant_id uuid not null, day_of_week varchar(255) check (day_of_week in ('MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY','SUNDAY')), primary key (id)); +create table restaurant_owners (restaurant_id uuid not null, user_id varchar(255) not null, primary key (restaurant_id, user_id)); +create table user_favourite_facilities (facility_id uuid not null, user_id varchar(255) not null, primary key (facility_id, user_id)); +alter table if exists daily_menu add constraint FKe7utqbyts7hsynored0rqpjuh foreign key (restaurant_id) references facility; +alter table if exists daily_menu_dishes add constraint FKddoquy0ud3lkjjycersya25wn foreign key (dish_id) references dish; +alter table if exists daily_menu_dishes add constraint FKn2k4n306qn8l7imu1b3audn2g foreign key (daily_menu_id) references daily_menu; +alter table if exists dish add constraint FKs0g15st4ftlyi1ilw7c0symdi foreign key (restaurant_id) references facility; +alter table if exists dish_allergens add constraint FKm9q52lhbluv5a316ehhmhb57u foreign key (dish_id) references dish; +alter table if exists dish_translation add constraint FKml9k3370c7q33un7ij5b6sape foreign key (dish_id) references dish; +alter table if exists facility add constraint FKhbnsr6du6x8l5gd7b1my90tba foreign key (location_id) references location; +alter table if exists opening_hours add constraint FKptr5ari24emao5jbfk8q35c3y foreign key (restaurant_id) references facility; +alter table if exists restaurant_owners add constraint FKg2a3v64ytrdq5mrmy0svstr8q foreign key (user_id) references keycloak_user; +alter table if exists restaurant_owners add constraint FKonquof7sprq32mdlo7rjpolhd foreign key (restaurant_id) references facility; +alter table if exists user_favourite_facilities add constraint FK309q1e53sf3layh66pp6hcfe8 foreign key (facility_id) references facility; +alter table if exists user_favourite_facilities add constraint FK8kjs4i7tr7kkontbskug0c3r8 foreign key (user_id) references keycloak_user; diff --git a/src/main/resources/db/migration/V2__seed_data.sql b/src/main/resources/db/migration/V2__seed_data.sql new file mode 100644 index 0000000..0362bf0 --- /dev/null +++ b/src/main/resources/db/migration/V2__seed_data.sql @@ -0,0 +1,219 @@ +------------------------------------------------------------ +-- RESTAURANTS AND COORDINATES +------------------------------------------------------------ + +INSERT INTO location (id, latitude, longitude) +VALUES + ('550e8400-e29b-41d4-a716-446655440001', 50.030511999856294, 19.90718833360244), + ('550e8400-e29b-41d4-a716-446655440002', 50.030170829430276, 19.908160572569297), + ('550e8400-e29b-41d4-a716-446655440003', 50.027354360288484, 19.900980407813968), + ('550e8400-e29b-41d4-a716-446655440004', 50.03000205209573, 19.905736283744663), + ('550e8400-e29b-41d4-a716-446655440005', 50.02902509906889, 19.907067338269396) +ON CONFLICT (id) DO NOTHING; + +INSERT INTO facility (id, description, photo_path, location_id, facility_type, name) +VALUES + ('b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'Favourite place for CS students to eat', '/images/restaurants/bistro_swietlica.jpg', '550e8400-e29b-41d4-a716-446655440001', 'RESTAURANT', 'Bistro Świetlica'), + ('e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'Some food at WZiKS', '/images/restaurants/bistro_by_jelonek.jpg', '550e8400-e29b-41d4-a716-446655440002', 'RESTAURANT', 'Bistro by Jelonek'), + ('4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'Some food at IZ', '/images/restaurants/bistro4mat.jpg', '550e8400-e29b-41d4-a716-446655440003', 'RESTAURANT', 'Bistro4mat'), + ('76e4647b-cb56-460a-9f30-a6b3482fb93a', 'Some food at WFAIS', '/images/restaurants/bistro_11.jpg', '550e8400-e29b-41d4-a716-446655440004', 'RESTAURANT', 'Bistro 11'), + ('1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'Some food at WCh', '/images/restaurants/neon_bistro.jpg', '550e8400-e29b-41d4-a716-446655440005', 'RESTAURANT', 'Neon Bistro') +ON CONFLICT (id) DO NOTHING; + +------------------------------------------------------------ +-- OPENING HOURS +------------------------------------------------------------ + +INSERT INTO opening_hours (id, restaurant_id, day_of_week, open_time, close_time) +VALUES + ('2a1b0f8d-2d74-48f8-a5e4-2e6dcd42d501', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'MONDAY', '9:00', '16:00'), + ('4a3b6f9c-24c2-4d9f-bbc6-6718949b8af9', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'TUESDAY', '9:00', '16:00'), + ('7b4a3a2d-8a1b-478f-96b2-3c3b22f2ad40', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'WEDNESDAY', '9:00', '16:00'), + ('c3d5d2ae-a634-4fb2-a548-b1b65aa9c03f', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'THURSDAY', '9:00', '16:00'), + ('6d884176-31ea-451f-91c7-81a89d484611', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'FRIDAY', '9:00', '16:00'), + ('9f2b3a12-6d45-4a21-83b2-0a8b3b5f5f77', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'MONDAY', '7:00', '17:00'), + ('fa484b16-2651-49c4-99db-e6e5f8e34e46', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'TUESDAY', '7:00', '17:00'), + ('e96b5d50-562e-48cf-93a0-cd3b1144d186', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'WEDNESDAY', '7:00', '17:00'), + ('b5c4d3f2-946c-4007-9e87-91d86c40a07b', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'THURSDAY', '7:00', '17:00'), + ('a17b9c43-34ad-4fb1-9c2e-56e58e0b64e1', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'FRIDAY', '7:00', '17:00'), + ('cf98d8c5-3555-44e5-8dfd-5cbdb9c22f2b', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'SATURDAY', '7:00', '17:00'), + ('a3ac00c2-ab4a-42ff-b914-a636629afbbb', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8', 'SUNDAY', '7:00', '17:00'), + ('57ae2be7-0b21-4108-bdee-803e29d6dee4', '4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'MONDAY', '9:00', '15:30'), + ('83bea995-3313-4b0f-b237-18ea7d5b5644', '4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'TUESDAY', '9:00', '15:30'), + ('a65e28fb-470b-4d6d-9ef5-fc31984dcd39', '4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'WEDNESDAY', '9:00', '15:30'), + ('b9dc7047-128b-4854-acb6-7949ef0a7e8c', '4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'THURSDAY', '9:00', '15:30'), + ('18840544-29da-45e7-a531-b99c8e059263', '4a2a13c4-34be-4bef-82c3-a879c91bba5b', 'FRIDAY', '9:00', '15:30'), + ('da3b1bbc-c793-476a-bd6f-04b13ca4b47f', '76e4647b-cb56-460a-9f30-a6b3482fb93a', 'MONDAY', '8:00', '16:00'), + ('9077ec6a-fecf-4b1d-8e2f-c1ef0260d4b6', '76e4647b-cb56-460a-9f30-a6b3482fb93a', 'TUESDAY', '8:00', '16:00'), + ('a2ac6e3d-dfd2-492b-91f7-e631a952f256', '76e4647b-cb56-460a-9f30-a6b3482fb93a', 'WEDNESDAY', '8:00', '16:00'), + ('1a6ade0c-a184-4028-93a4-2dd9d75f0420', '76e4647b-cb56-460a-9f30-a6b3482fb93a', 'THURSDAY', '8:00', '16:00'), + ('e0ee6006-3a0f-4645-8fa1-2f533b72b18b', '76e4647b-cb56-460a-9f30-a6b3482fb93a', 'FRIDAY', '8:00', '16:00'), + ('79120ac2-032b-4610-bc62-340e1dacd896', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'MONDAY', '8:00', '17:00'), + ('c1e2dd8f-acf3-47a2-90a8-243523b96e3b', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'TUESDAY', '8:00', '17:00'), + ('0fd40668-1834-4351-bf6f-040836e2b82e', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'WEDNESDAY', '8:00', '17:00'), + ('47bbb917-4d97-4955-84f4-3dad31b81816', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'THURSDAY', '8:00', '17:00'), + ('416845b4-ee0e-4cb0-897c-110d05bba7b3', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866', 'FRIDAY', '8:00', '17:00') +ON CONFLICT (id) DO NOTHING; + +------------------------------------------------------------ +-- ACTIVE MENUS FOR EVERY RESTAURANT +------------------------------------------------------------ + +INSERT INTO daily_menu (id, date, status, restaurant_id) +VALUES + ('c1111111-aaaa-bbbb-cccc-111111111111', '2025-10-24', 'ACTIVE', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1'), + ('c2222222-aaaa-bbbb-cccc-222222222222', '2025-10-24', 'ACTIVE', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8'), + ('c3333333-aaaa-bbbb-cccc-333333333333', '2025-10-24', 'ACTIVE', '4a2a13c4-34be-4bef-82c3-a879c91bba5b'), + ('c4444444-aaaa-bbbb-cccc-444444444444', '2025-10-24', 'ACTIVE', '76e4647b-cb56-460a-9f30-a6b3482fb93a'), + ('c5555555-aaaa-bbbb-cccc-555555555555', '2025-10-24', 'ACTIVE', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866') +ON CONFLICT (id) DO NOTHING; + +------------------------------------------------------------ +-- DISHES +------------------------------------------------------------ + +INSERT INTO dish (id, name, category, amount, currency, restaurant_id) +VALUES + ('d1111111-aaaa-bbbb-cccc-000000000001', 'Potato Dumplings', 'MAIN_COURSE', 19.50, 'PLN', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1'), + ('d1111111-aaaa-bbbb-cccc-000000000002', 'Red Beet Soup', 'MAIN_COURSE', 8.00, 'PLN', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1'), + ('d1111111-aaaa-bbbb-cccc-000000000003', 'Pumpkin Cream Soup', 'MAIN_COURSE', 12.00, 'PLN', 'b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1'), + ('d2222222-aaaa-bbbb-cccc-000000000001', 'Chicken Teriyaki Bowl', 'MAIN_COURSE', 24.00, 'PLN', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8'), + ('d2222222-aaaa-bbbb-cccc-000000000002', 'Miso Soup', 'MAIN_COURSE', 10.00, 'PLN', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8'), + ('d2222222-aaaa-bbbb-cccc-000000000003', 'Salmon Rice Bowl', 'MAIN_COURSE', 9.50, 'PLN', 'e7c37f89-26b1-4cb5-9b43-6e2c15a0d9a8'), + ('d3333333-aaaa-bbbb-cccc-000000000001', 'Chicken Wrap', 'MAIN_COURSE', 18.00, 'PLN', '4a2a13c4-34be-4bef-82c3-a879c91bba5b'), + ('d3333333-aaaa-bbbb-cccc-000000000002', 'Tomato Cream Soup', 'MAIN_COURSE', 11.00, 'PLN', '4a2a13c4-34be-4bef-82c3-a879c91bba5b'), + ('d3333333-aaaa-bbbb-cccc-000000000003', 'Greek Salad', 'MAIN_COURSE', 14.50, 'PLN', '4a2a13c4-34be-4bef-82c3-a879c91bba5b'), + ('d4444444-aaaa-bbbb-cccc-000000000001', 'Pork Chop', 'MAIN_COURSE', 23.00, 'PLN', '76e4647b-cb56-460a-9f30-a6b3482fb93a'), + ('d4444444-aaaa-bbbb-cccc-000000000002', 'Chicken Broth Soup', 'MAIN_COURSE', 9.00, 'PLN', '76e4647b-cb56-460a-9f30-a6b3482fb93a'), + ('d4444444-aaaa-bbbb-cccc-000000000003', 'Boiled Potatoes', 'MAIN_COURSE', 6.00, 'PLN', '76e4647b-cb56-460a-9f30-a6b3482fb93a'), + ('d5555555-aaaa-bbbb-cccc-000000000001', 'Caesar Salad', 'MAIN_COURSE', 21.00, 'PLN', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866'), + ('d5555555-aaaa-bbbb-cccc-000000000002', 'Broccoli Cream Soup', 'MAIN_COURSE', 11.00, 'PLN', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866'), + ('d5555555-aaaa-bbbb-cccc-000000000003', 'Tuna Roll', 'MAIN_COURSE', 17.50, 'PLN', '1cbbef85-cac6-4eb4-afd5-feb2f88e5866') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO daily_menu_dishes (daily_menu_id, dish_id) +VALUES + ('c1111111-aaaa-bbbb-cccc-111111111111', 'd1111111-aaaa-bbbb-cccc-000000000001'), + ('c1111111-aaaa-bbbb-cccc-111111111111', 'd1111111-aaaa-bbbb-cccc-000000000002'), + ('c1111111-aaaa-bbbb-cccc-111111111111', 'd1111111-aaaa-bbbb-cccc-000000000003'), + ('c2222222-aaaa-bbbb-cccc-222222222222', 'd2222222-aaaa-bbbb-cccc-000000000001'), + ('c2222222-aaaa-bbbb-cccc-222222222222', 'd2222222-aaaa-bbbb-cccc-000000000002'), + ('c2222222-aaaa-bbbb-cccc-222222222222', 'd2222222-aaaa-bbbb-cccc-000000000003'), + ('c3333333-aaaa-bbbb-cccc-333333333333', 'd3333333-aaaa-bbbb-cccc-000000000001'), + ('c3333333-aaaa-bbbb-cccc-333333333333', 'd3333333-aaaa-bbbb-cccc-000000000002'), + ('c3333333-aaaa-bbbb-cccc-333333333333', 'd3333333-aaaa-bbbb-cccc-000000000003'), + ('c4444444-aaaa-bbbb-cccc-444444444444', 'd4444444-aaaa-bbbb-cccc-000000000001'), + ('c4444444-aaaa-bbbb-cccc-444444444444', 'd4444444-aaaa-bbbb-cccc-000000000002'), + ('c4444444-aaaa-bbbb-cccc-444444444444', 'd4444444-aaaa-bbbb-cccc-000000000003'), + ('c5555555-aaaa-bbbb-cccc-555555555555', 'd5555555-aaaa-bbbb-cccc-000000000001'), + ('c5555555-aaaa-bbbb-cccc-555555555555', 'd5555555-aaaa-bbbb-cccc-000000000002'), + ('c5555555-aaaa-bbbb-cccc-555555555555', 'd5555555-aaaa-bbbb-cccc-000000000003') +ON CONFLICT DO NOTHING; + +------------------------------------------------------------ +-- DISH ALLERGENS +------------------------------------------------------------ + +INSERT INTO dish_allergens (dish_id, allergen) +VALUES + ('d1111111-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), + ('d1111111-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), + ('d1111111-aaaa-bbbb-cccc-000000000002', 'LACTOSE'), + ('d2222222-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), + ('d2222222-aaaa-bbbb-cccc-000000000001', 'MEAT'), + ('d2222222-aaaa-bbbb-cccc-000000000002', 'GLUTEN'), + ('d2222222-aaaa-bbbb-cccc-000000000003', 'MEAT'), + ('d3333333-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), + ('d3333333-aaaa-bbbb-cccc-000000000001', 'MEAT'), + ('d3333333-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), + ('d3333333-aaaa-bbbb-cccc-000000000002', 'LACTOSE'), + ('d3333333-aaaa-bbbb-cccc-000000000003', 'LACTOSE'), + ('d4444444-aaaa-bbbb-cccc-000000000001', 'MEAT'), + ('d4444444-aaaa-bbbb-cccc-000000000002', 'MEAT'), + ('d5555555-aaaa-bbbb-cccc-000000000001', 'GLUTEN'), + ('d5555555-aaaa-bbbb-cccc-000000000001', 'LACTOSE'), + ('d5555555-aaaa-bbbb-cccc-000000000001', 'MEAT'), + ('d5555555-aaaa-bbbb-cccc-000000000002', 'LACTOSE'), + ('d5555555-aaaa-bbbb-cccc-000000000003', 'MEAT'), + ('d5555555-aaaa-bbbb-cccc-000000000003', 'GLUTEN') +ON CONFLICT DO NOTHING; + +------------------------------------------------------------ +-- VENDING MACHINES +------------------------------------------------------------ + +INSERT INTO location (id, latitude, longitude) +VALUES + ('550e8400-e29b-41d4-a716-446655440006', 50.03085967660663, 19.9076330797032), + ('550e8400-e29b-41d4-a716-446655440007', 50.0292711417798, 19.905728510392944), + ('550e8400-e29b-41d4-a716-446655440008', 50.0299355043595, 19.907602360960713) +ON CONFLICT (id) DO NOTHING; + +INSERT INTO facility (id, description, photo_path, location_id, facility_type, type) +VALUES + ('c3b6a5ef-9f40-5d4f-b62f-9d638df8f2b2', 'Snack vending machine with chips, cookies, and candy bars.', '/images/vending/snacks_01.jpg', '550e8400-e29b-41d4-a716-446655440006', 'VENDING_MACHINE', 'SNACKS'), + ('d4c7b6f0-0a51-6e5f-c73f-0e749ef9f3c3', 'Coffee machine with espresso, cappuccino, and hot chocolate.', '/images/vending/coffee_01.jpg', '550e8400-e29b-41d4-a716-446655440007', 'VENDING_MACHINE', 'COFFEE'), + ('e5d8c7f1-1b62-7f6f-d84f-1f850ff0f4d4', 'Lunch vending machine with sandwiches, salads, and wraps.', '/images/vending/lunch_01.jpg', '550e8400-e29b-41d4-a716-446655440008', 'VENDING_MACHINE', 'LUNCH') +ON CONFLICT (id) DO NOTHING; + +------------------------------------------------------------ +-- KEYCLOAK USERS +------------------------------------------------------------ + +INSERT INTO keycloak_user (id) +VALUES + ('e8efd725-8397-4aea-979f-3c096470d23b'), + ('17e0291d-75a1-40ae-ae78-7335ceadbfca') +ON CONFLICT (id) DO NOTHING; + +------------------------------------------------------------ +-- RESTAURANT OWNERS +------------------------------------------------------------ + +INSERT INTO restaurant_owners (restaurant_id, user_id) +VALUES ('b2a5f4de-8f39-4e3e-a51e-8c527ce7e1a1', 'e8efd725-8397-4aea-979f-3c096470d23b') +ON CONFLICT DO NOTHING; + +------------------------------------------------------------ +-- TEST RESTAURANT +------------------------------------------------------------ + +INSERT INTO location (id, latitude, longitude) +VALUES ('aaaaaaaa-1111-1111-1111-aaaaaaaaaaaa', 50.06143, 19.93658) +ON CONFLICT (id) DO NOTHING; + +INSERT INTO facility (id, description, photo_path, location_id, facility_type, name) +VALUES ('bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'Test restaurant for development', '/images/restaurants/test_restaurant.jpg', 'aaaaaaaa-1111-1111-1111-aaaaaaaaaaaa', 'RESTAURANT', 'TEST_RESTAURANT') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO opening_hours (id, restaurant_id, day_of_week, open_time, close_time) +VALUES + ('cccccccc-1111-1111-1111-cccccccccccc', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'MONDAY', '10:00', '18:00'), + ('cccccccc-2222-2222-2222-cccccccccccc', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'TUESDAY', '10:00', '18:00'), + ('cccccccc-3333-3333-3333-cccccccccccc', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'WEDNESDAY', '10:00', '18:00'), + ('cccccccc-4444-4444-4444-cccccccccccc', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'THURSDAY', '10:00', '18:00'), + ('cccccccc-5555-5555-5555-cccccccccccc', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', 'FRIDAY', '10:00', '18:00') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO daily_menu (id, date, status, restaurant_id) +VALUES ('dddddddd-1111-1111-1111-dddddddddddd', CURRENT_DATE, 'ACTIVE', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO dish (id, name, category, amount, currency, restaurant_id) +VALUES ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'Test Pasta', 'MAIN_COURSE', 25.00, 'PLN', 'bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO daily_menu_dishes (daily_menu_id, dish_id) +VALUES ('dddddddd-1111-1111-1111-dddddddddddd', 'eeeeeeee-1111-1111-1111-eeeeeeeeeeee') +ON CONFLICT DO NOTHING; + +INSERT INTO dish_allergens (dish_id, allergen) +VALUES + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'GLUTEN'), + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'LACTOSE'), + ('eeeeeeee-1111-1111-1111-eeeeeeeeeeee', 'MEAT') +ON CONFLICT DO NOTHING; + +INSERT INTO restaurant_owners (restaurant_id, user_id) +VALUES ('bbbbbbbb-2222-2222-2222-bbbbbbbbbbbb', '17e0291d-75a1-40ae-ae78-7335ceadbfca') +ON CONFLICT DO NOTHING; diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..19ab0fb --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,11 @@ +# H2 in-memory database for tests +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.defer-datasource-initialization=true + +# Flyway disabled for tests - Hibernate manages the schema +spring.flyway.enabled=false